def on_enter_jit(self, invariants, reds, bytecode, pos): # Now some strange code that makes a copy of the 'args' list in # a complicated way... this is a workaround forcing the whole 'args' # list to be virtual. It is a way to tell the JIT compiler that it # doesn't have to worry about the 'args' list being unpredictably # modified. oldloops = invariants oldargs = reds.args argcount = promote(len(oldargs)) args = [] n = 0 while n < argcount: hint(n, concrete=True) args.append(oldargs[n]) n += 1 reds.args = args # turn the green 'loops' from 'invariants' into a virtual list oldloops = hint(oldloops, deepfreeze=True) argcount = len(oldloops) loops = [] n = 0 while n < argcount: hint(n, concrete=True) loops.append(oldloops[n]) n += 1 reds.loops = loops
def f(v): hint(None, global_merge_point=True) l = [1, 10] v.l = l g(v) l2 = v.l return l[0] * 2 + l[1] + l2[0] * 2 + l2[1]
def f(v): hint(None, global_merge_point=True) s = S(1, 10) v.s = s g(v) s2 = v.s return s.x * 2 + s.y + s2.x * 2 + s2.y
def ll_function(n): hint(None, global_merge_point=True) s = lltype.malloc(S) c = ll_two(n, s) k = hint(s.x, promote=True) k += c return hint(k, variable=True)
def f(x): hint(None, global_merge_point=True) lst = g(x) try: return lst[0] except IndexError: return -42
def ll_three(s, k): k = hint(k, promote=True) if s.x > 6: k *= hint(s.y, promote=True) return k else: return hint(1, concrete=True)
def ll_function(a, i): a = hint(a, deepfreeze=True) res = a[i] res = hint(res, concrete=True) res = hint(res, variable=True) return res
def copy(self, heap, memo): hint(self, concrete=True) try: return memo[self] except KeyError: newvar = memo[self] = heap.newvar() return newvar
def call_valuestack(self, w_func, nargs, frame): if not self.config.objspace.disable_call_speedhacks: # XXX start of hack for performance from pypy.interpreter.function import Function, Method hint(w_func.__class__, promote=True) if isinstance(w_func, Method): w_inst = w_func.w_instance if w_inst is not None: w_func = w_func.w_function # reuse callable stack place for w_inst frame.settopvalue(w_inst, nargs) nargs += 1 elif nargs > 0 and (self.abstract_isinstance_w( frame.peekvalue(nargs - 1), # :-( w_func.w_class)): w_func = w_func.w_function if isinstance(w_func, Function): return w_func.funccall_valuestack(nargs, frame) # XXX end of hack for performance args = frame.make_arguments(nargs) try: return self.call_args(w_func, args) finally: if isinstance(args, ArgumentsFromValuestack): args.frame = None
def f(x): while x > 0: myjitdriver.can_enter_jit(x=x) myjitdriver.jit_merge_point(x=x) a = A() hint(a, promote=True) x -= 1
def dispatch_jit(self, pycode, next_instr, ec): hint(None, global_merge_point=True) pycode = hint(pycode, deepfreeze=True) entry_fastlocals_w = self.jit_enter_frame(pycode, next_instr) # For the sequel, force 'next_instr' to be unsigned for performance next_instr = r_uint(next_instr) co_code = pycode.co_code try: try: while True: hint(None, global_merge_point=True) next_instr = self.handle_bytecode(co_code, next_instr, ec) except Return: w_result = self.popvalue() self.blockstack = None self.valuestack_w = None return w_result except Yield: w_result = self.popvalue() return w_result finally: self.jit_leave_frame(pycode, entry_fastlocals_w)
def copy_and_basic_unify(self, other, heap, memo): hint(self, concrete=True) if isinstance(other, Atom) and (self is other or other.name == self.name): return self else: raise UnificationFailed
def call_valuestack(self, w_func, nargs, frame): if not self.config.objspace.disable_call_speedhacks: # XXX start of hack for performance from pypy.interpreter.function import Function, Method hint(w_func.__class__, promote=True) if isinstance(w_func, Method): w_inst = w_func.w_instance if w_inst is not None: func = w_func.w_function if isinstance(func, Function): return func.funccall_obj_valuestack(w_inst, nargs, frame) elif nargs > 0 and self.is_true( self.abstract_isinstance(frame.peekvalue(nargs-1), # :-( w_func.w_class)): w_func = w_func.w_function if isinstance(w_func, Function): return w_func.funccall_valuestack(nargs, frame) # XXX end of hack for performance args = frame.make_arguments(nargs) try: return self.call_args(w_func, args) finally: if isinstance(args, ArgumentsFromValuestack): args.frame = None
def ll_function(n): hint(None, global_merge_point=True) s = lltype.malloc(S) s.x = n k = hint(n, promote=True) k = ll_two(k) return hint(k, variable=True) + s.x
def pushrevvalues(self, n, values_w): # n should be len(values_w) while True: n -= 1 if n < 0: break hint(n, concrete=True) self.pushvalue(values_w[n])
def f(n): hint(None, global_merge_point=True) v = V([100]) h = l[n & 1] n += 10 res = h(v, n) return res - v.v.pop()
def interpret(bytecode, args): """The interpreter's entry point and portal function. """ loops = [] stack = empty_stack() pos = 0 while True: tinyjitdriver.jit_merge_point(args=args, loops=loops, stack=stack, bytecode=bytecode, pos=pos) bytecode = hint(bytecode, deepfreeze=True) if pos >= len(bytecode): break opcode = bytecode[pos] hint(opcode, concrete=True) # same as in tiny1.py pos += 1 if opcode == 'ADD': stack = op2(stack, func_add_int, func_add_str) elif opcode == 'SUB': stack = op2(stack, func_sub_int, func_sub_str) elif opcode == 'MUL': stack = op2(stack, func_mul_int, func_mul_str) elif opcode[0] == '#': n = myint(opcode, start=1) stack = Stack(args[n - 1], stack) elif opcode.startswith('->#'): n = myint(opcode, start=3) if n > len(args): raise IndexError stack, args[n - 1] = stack.pop() elif opcode == '{': loops.append(pos) elif opcode == '}': stack, flag = stack.pop() if flag.as_int() == 0: loops.pop() else: pos = loops[-1] # A common problem when interpreting loops or jumps: the 'pos' # above is read out of a list, so the hint-annotator thinks # it must be red (not a compile-time constant). But the # hint(opcode, concrete=True) in the next iteration of the # loop requires all variables the 'opcode' depends on to be # green, including this 'pos'. We promote 'pos' to a green # here, as early as possible. Note that in practice the 'pos' # read out of the 'loops' list will be a compile-time constant # because it was pushed as a compile-time constant by the '{' # case above into 'loops', which is a virtual list, so the # promotion below is just a way to make the colors match. pos = hint(pos, promote=True) tinyjitdriver.can_enter_jit(args=args, loops=loops, stack=stack, bytecode=bytecode, pos=pos) else: stack = Stack(StrBox(opcode), stack) return stack
def interpret(bytecode, args): """The interpreter's entry point and portal function. """ loops = [] stack = empty_stack() pos = 0 while True: tinyjitdriver.jit_merge_point(args=args, loops=loops, stack=stack, bytecode=bytecode, pos=pos) bytecode = hint(bytecode, deepfreeze=True) if pos >= len(bytecode): break opcode = bytecode[pos] hint(opcode, concrete=True) # same as in tiny1.py pos += 1 if opcode == "ADD": stack = op2(stack, func_add_int, func_add_float) elif opcode == "SUB": stack = op2(stack, func_sub_int, func_sub_float) elif opcode == "MUL": stack = op2(stack, func_mul_int, func_mul_float) elif opcode[0] == "#": n = myint(opcode, start=1) stack = Stack(args[n - 1], stack) elif opcode.startswith("->#"): n = myint(opcode, start=3) if n > len(args): raise IndexError stack, args[n - 1] = stack.pop() elif opcode == "{": loops.append(pos) elif opcode == "}": stack, flag = stack.pop() if flag.as_int() == 0: loops.pop() else: pos = loops[-1] # A common problem when interpreting loops or jumps: the 'pos' # above is read out of a list, so the hint-annotator thinks # it must be red (not a compile-time constant). But the # hint(opcode, concrete=True) in the next iteration of the # loop requires all variables the 'opcode' depends on to be # green, including this 'pos'. We promote 'pos' to a green # here, as early as possible. Note that in practice the 'pos' # read out of the 'loops' list will be a compile-time constant # because it was pushed as a compile-time constant by the '{' # case above into 'loops', which is a virtual list, so the # promotion below is just a way to make the colors match. pos = promote(pos) tinyjitdriver.can_enter_jit(args=args, loops=loops, stack=stack, bytecode=bytecode, pos=pos) else: try: try: v = IntBox(int(opcode)) except ValueError: v = FloatBox(myfloat(opcode)) stack = Stack(v, stack) except ValueError: pass # ignore rest return stack
def ll_function(n, total): while n > 0: hint(None, global_merge_point=True) k = hint(n, promote=True) k = ll_two(k) total += hint(k, variable=True) n -= 1 return total
def f(e): hint(None, global_merge_point=True) xy = e.xy y = xy_get_y(xy) newy = 2 * y xy_set_y(xy, newy) g(e) return xy.x
def ll_function(x): mylist = hint(lst, deepfreeze=True) try: z = mylist[x] except IndexError: return -42 hint(z, concrete=True) return z
def ll_function(n): hint(None, global_merge_point=True) k = n if k > 5: k //= 2 k = hint(k, promote=True) k *= 17 return hint(k, variable=True)
def ll_function(n): a = getinstance(n) a = hint(a, promote=True) a = hint(a, deepfreeze=True) if isinstance(a, B): return a return None
def f(n): hint(n, concrete=True) if n == 0: s = "abc" else: s = "123" a = h1(s) return a
def set_semiconstant(self, name, val, local_only=False): self = hint(self, promote=True) sc_version = hint(self.semiconstant_version, promote=True) self._set_intern(name, val, local_only) if not self._is_semiconstant(name, sc_version): self.semiconstants.append(name) self.semiconstant_version = VersionTag()
def set(self, name, val, local_only=False): self = hint(self, promote=True) sc_version = hint(self.semiconstant_version, promote=True) if self._is_semiconstant(name, sc_version): self.set_semiconstant(name, val) else: self._set_intern(name, val, local_only)
def get(self, name): self = hint(self, promote=True) sc_version = hint(self.semiconstant_version, promote=True) if self._is_semiconstant(name, sc_version): return self._get_semiconstant(name, sc_version) else: return self._get_intern(name)
def ll_function(n, i): d = getdict(n) d = hint(d, deepfreeze=True) res = d[i] res = hint(res, concrete=True) res = hint(res, variable=True) return res
def dupvalues(self, n): delta = n-1 while True: n -= 1 if n < 0: break hint(n, concrete=True) w_value = self.peekvalue(delta) self.pushvalue(w_value)
def get_next_structure(self, key): # jit helper self = hint(self, promote=True) key = hint(key, promote=True) newstruct = _get_next_structure_shared(self, key) if not we_are_jitted(): self._size_estimate -= self.size_estimate() self._size_estimate += newstruct.size_estimate() return newstruct
def lookup_where_with_method_cache(w_self, name): space = w_self.space w_self = hint(w_self, promote=True) assert space.config.objspace.std.withmethodcache version_tag = hint(w_self.version_tag(), promote=True) if version_tag is None: tup = w_self._lookup_where(name) return tup return w_self._pure_lookup_where_with_method_cache(name, version_tag)
def ll_function(n, i): l = getlist(n) l = hint(l, deepfreeze=True) res = l[i] res = hint(res, concrete=True) res = hint(res, variable=True) return res
def f(x): l = [a1] * 100 + [a2] * 100 + [b] * 100 while x > 0: myjitdriver.can_enter_jit(x=x, l=l) myjitdriver.jit_merge_point(x=x, l=l) a = l[x] x = a.g(x) hint(a, promote=True) return x
def _try_rule(self, rule, query, continuation): rule = hint(rule, deepfreeze=True) hint(self, concrete=True) # standardizing apart nextcall = rule.clone_and_unify_head(self.heap, query) if nextcall is not None: return self.call(nextcall, continuation, choice_point=False) else: return continuation.call(self, choice_point=False)
def popvalues(self, n): values_w = [None] * n while True: n -= 1 if n < 0: break hint(n, concrete=True) values_w[n] = self.popvalue() return values_w
def ll_two(n): s = lltype.malloc(S) if n < 0: s.x = 10 else: s.x = 20 k = hint(s.x, promote=True) k *= 17 return hint(k, variable=True)
def _call(self, query, continuation): signature = query.signature from pypy.lang.prolog.builtin import builtins builtins = hint(builtins, deepfreeze=True) signature = hint(signature, promote=True) for bsig, builtin in unrolling_builtins: if signature == bsig: return builtin.call(self, query, continuation) return self.user_call(query, continuation, choice_point=False)