def eval_arithmetic(self, engine): from prolog.interpreter.arithmetic import get_arithmetic_function func = get_arithmetic_function(self.signature()) jit.promote(func) if func is None: error.throw_type_error("evaluable", self.get_prolog_signature()) return func(engine, self)
def pop_n(self, n): #assert n == 0 or self._stack_ptr - n >= self.tempsize() jit.promote(self._stack_ptr) while n > 0: n -= 1 self._stack_ptr -= 1 self.stack_put(self._stack_ptr, self.space.w_nil)
def pop_n(self, n): #assert n == 0 or self._stack_ptr - n >= self.tempsize() jit.promote(self._stack_ptr) while n > 0: n -= 1 self._stack_ptr -= 1 self._temps_and_stack[self._stack_ptr] = None
def getbytecode(self): jit.promote(self._pc) assert self._pc >= 0 bytecode = self.s_method().getbytecode(self._pc) currentBytecode = ord(bytecode) self._pc += 1 return currentBytecode
def constr_proc_wrapper_cont(self, field_values, struct_type_name, issuper, app, env, cont, _vals): from pycket.interpreter import return_multi_vals, jump guard_values = _vals.get_all_values() type = jit.promote(self.type) if guard_values: field_values = guard_values super_type = jit.promote(type.super) if isinstance(super_type, W_StructType): split_position = len(field_values) - type.init_field_cnt super_auto = super_type.constr.type.auto_values assert split_position >= 0 field_values = self._splice(field_values, len(field_values),\ split_position, super_auto, len(super_auto)) if issuper: return super_type.constr.code(field_values[:split_position], struct_type_name, True, env, cont, app) else: return super_type.constr.code(field_values[:split_position], struct_type_name, True, env, self.constr_proc_cont(field_values, env, cont), app) else: if issuper: return return_multi_vals(values.Values.make(field_values), env, cont) else: return jump(env, self.constr_proc_cont(field_values, env, cont))
def pop_n(self, n): jit.promote(self.stack_ptr()) while n > 0: n -= 1 assert self.stack_ptr() >= 1, "stack pointer reduced to < 1 in pop_n" self.store_stack_ptr(self.stack_ptr() - 1) self.stack_put(self.stack_ptr(), self.space.w_nil)
def descr_call(self, space, __args__): promote(self) # invoke the __new__ of the type if not we_are_jitted(): # note that the annotator will figure out that self.w_new_function # can only be None if the newshortcut config option is not set w_newfunc = self.w_new_function else: # for the JIT it is better to take the slow path because normal lookup # is nicely optimized, but the self.w_new_function attribute is not # known to the JIT w_newfunc = None if w_newfunc is None: w_newtype, w_newdescr = self.lookup_where('__new__') w_newfunc = space.get(w_newdescr, self) if (space.config.objspace.std.newshortcut and not we_are_jitted() and isinstance(w_newtype, W_TypeObject)): self.w_new_function = w_newfunc w_newobject = space.call_obj_args(w_newfunc, self, __args__) call_init = space.isinstance_w(w_newobject, self) # maybe invoke the __init__ of the type if (call_init and not (space.is_w(self, space.w_type) and not __args__.keywords and len(__args__.arguments_w) == 1)): w_descr = space.lookup(w_newobject, '__init__') w_result = space.get_and_call_args(w_descr, w_newobject, __args__) if not space.is_w(w_result, space.w_None): raise oefmt(space.w_TypeError, "__init__() should return None") return w_newobject
def mutate(self, struct, field, val, env, cont, app): assert isinstance(struct, W_RootStruct) jit.promote(self) offset = struct.struct_type().get_offset(self.type) if offset == -1: raise SchemeException("cannot reference an identifier before its definition") return struct.set_with_extra_info(field + offset, val, app, env, cont)
def impl_functor(engine, heap, t, functor, arity): if helper.is_atomic(t): functor.unify(t, heap) arity.unify(term.Number(0), heap) elif helper.is_term(t): assert isinstance(t, term.Callable) sig = t.signature() atom = term.Callable.build(t.name(), signature=sig.atom_signature) functor.unify(atom, heap) arity.unify(term.Number(t.argument_count()), heap) elif isinstance(t, term.Var): if isinstance(functor, term.Var): error.throw_instantiation_error() a = helper.unwrap_int(arity) jit.promote(a) if a < 0: error.throw_domain_error("not_less_than_zero", arity) else: functor = helper.ensure_atomic(functor) if a == 0: t.unify(functor, heap) else: jit.promote(functor) name = helper.unwrap_atom(functor) t.unify( term.Callable.build(name, [heap.newvar() for i in range(a)]), heap)
def make_cont(self, env, prev, i=0): jit.promote(self) jit.promote(i) if i == len(self.body) - 1: return self.body[i], env, prev else: return self.body[i], env, SequenceContinuation(self, i+1, env, prev)
def toplevel_lookup(self, sym): from pycket.values import W_Cell jit.promote(self) w_res = self._lookup(sym, jit.promote(self.version)) if isinstance(w_res, W_Cell): w_res = w_res.get_val() return w_res
def fn(n): a1 = (n, ) g.a = a1 a2 = (n - 1, ) g.a = a2 jit.promote(n) return a1[0] + a2[0] + gn(a1, a2)
def plug_reduce(self, v): assert isinstance(v, MultiValue) new_env_s = create_new_env_structure(self.let_ast.top_env_s, self.env_s) jit.promote(new_env_s) return ExpState(self.let_ast.body, new_env_s, EnvironmentValues(v.values, self.env_v), self.k)
def __init__(self, func, names, args, env, strict=False): from js.object_space import _w W__Object.__init__(self) self.strict = strict _len = len(args) put_property(self, u'length', _w(_len), writable=True, enumerable=False, configurable=True) from js.object_space import object_space _map = object_space.new_obj() mapped_names = new_map() jit.promote(_len) indx = _len - 1 while indx >= 0: val = args[indx] put_property(self, unicode(str(indx)), val, writable=True, enumerable=True, configurable=True) if indx < len(names): name = names[indx] if strict is False and not mapped_names.contains(name): mapped_names = mapped_names.add(name) g = make_arg_getter(name, env) p = make_arg_setter(name, env) desc = PropertyDescriptor(setter=p, getter=g, configurable=True) _map.define_own_property(unicode(str(indx)), desc, False) indx = indx - 1 if not mapped_names.empty(): self._paramenter_map_ = _map if strict is False: put_property(self, u'callee', _w(func), writable=True, enumerable=False, configurable=True) else: # 10.6 14 thrower pass
def next(self, state, mutate=False): assert state.iterator is self index = state.index if self.track_index: index += 1 indices = state._indices offset = state.offset if self.contiguous: elsize = self.array.dtype.elsize jit.promote(elsize) offset += elsize elif self.ndim_m1 == 0: stride = self.strides[0] jit.promote(stride) offset += stride else: for i in xrange(self.ndim_m1, -1, -1): idx = indices[i] if idx < self.shape_m1[i]: indices[i] = idx + 1 offset += self.strides[i] break else: indices[i] = 0 offset -= self.backstrides[i] if not mutate: return IterState(self, index, indices, offset) state.index = index state.offset = offset
def fn(n): jit.promote(n) try: n = ovfcheck(n + 1) except OverflowError: return 12 else: return n
def __init__(self, closure, k, env_s, prev_env_v): assert isinstance(closure, Closure) self.closure = closure self.k = k self.env_s = env_s jit.promote(self.env_s) self.prev_env_v = prev_env_v self.plug_loop = False
def make_arity_list(arity, extra=None): jit.promote(arity) acc = values.w_null if extra is not None: acc = values.W_Cons.make(extra, acc) for item in reversed(arity.arity_list): i = values.W_Fixnum(item) acc = values.W_Cons.make(i, acc) return acc
def get_global(self, name): # Return the global with the given name if it's in the dictionary of globals # if not, return None jit.promote(self) assoc = self._get_global(name) if assoc: return assoc.get_value() else: return None
def lookup(self, sym, env_structure): jit.promote(env_structure) for i, s in enumerate(env_structure.elems): if s is sym: v = self._get_list(i) assert v is not None return v prev = self.get_prev(env_structure) return prev.lookup(sym, env_structure.prev)
def __init__(self, code, frame, globals): self.code = code self.env = Environment(frame, globals, self.code.localSize(), promote(self.code.maxDepth), promote(self.code.maxHandlerDepth)) # For vat checkpointing. from typhon.vats import currentVat self.vat = currentVat.get()
def code(self, field_values, issuper, env, cont): from pycket.interpreter import jump if self.type.guard is values.w_false: return jump(env, self.constr_proc_wrapper_cont(field_values, issuper, env, cont)) else: guard_args = field_values + [values.W_Symbol.make(self.type.name)] jit.promote(self) return self.type.guard.call(guard_args, env, self.constr_proc_wrapper_cont(field_values, issuper, env, cont))
def mutate(self, struct, field, val, env, cont, app): self = jit.promote(self) st = jit.promote(struct.struct_type()) if st is None: raise SchemeException("%s got %s" % (self.tostring(), struct.tostring())) offset = st.get_offset(self.type) if offset == -1: raise SchemeException("cannot reference an identifier before its definition") return struct.set_with_extra_info(field + offset, val, app, env, cont)
def eq(self, other): # slightly evil if jit.isconstant(self): jit.promote(other) elif jit.isconstant(other): jit.promote(self) return self is other or ( self.numargs == other.numargs and self.name == other.name)
def invoke_Ef(self, args): new_env = self._env x = 0 arg_names = jit.promote(self._arg_names) while x < args.arg_count(): new_env = new_env.with_locals(arg_names[x], args.get_arg(x)) x += 1 new_env = new_env.with_locals(jit.promote(self._name), self) ast = self._w_code return thunk_tailcall_Ef(ast, new_env)
def fn(n, i): res = 0 obj = A() while i > 0: myjitdriver.can_enter_jit(i=i, obj=obj) myjitdriver.jit_merge_point(i=i, obj=obj) promote(obj) res = obj.foo() i-=1 return res
def issubtype(w_self, w_type): promote(w_self) promote(w_type) if w_self.space.config.objspace.std.withtypeversion and we_are_jitted(): version_tag1 = w_self.version_tag() version_tag2 = w_type.version_tag() if version_tag1 is not None and version_tag2 is not None: res = _pure_issubtype(w_self, w_type, version_tag1, version_tag2) return res return _issubtype(w_self, w_type)
def fn(i): if i < 0: g.a1 = [7, 8, 9] g.a2 = [7, 8, 9, 10] jit.promote(i) a1 = g.a1 a1[i + 1] = 15 # make lists mutable a2 = g.a2 a2[i + 1] = 19 return a1[i] + a2[i] + a1[i] + a2[i]
def prep_exb(self, args): size = jit.promote(self._cd.exchange_size) exb = rffi.cast(rffi.VOIDP, lltype.malloc(rffi.CCHARP.TO, size, flavor="raw")) tokens = [None] * len(args) for i, tp in enumerate(self._arg_types): offset_p = rffi.ptradd(exb, jit.promote(self._cd.exchange_args[i])) tokens[i] = tp.ffi_set_value(offset_p, args[i]) return exb, tokens
def f(n, a, i): stufflist = StuffList() stufflist.lst = [Stuff(a), Stuff(3)] while n > 0: myjitdriver.can_enter_jit(n=n, i=i, stufflist=stufflist) myjitdriver.jit_merge_point(n=n, i=i, stufflist=stufflist) promote(i) v = Stuff(i) n -= stufflist.lst[v.x].x return n
def call_with_extra_info(self, args, env, cont, calling_app): jit.promote(self) return self.closure.call_with_extra_info(args, env, cont, calling_app)
def _stack_pointer(self): return jit.promote(self._stack_pointer_)
def getclass(self, space): return jit.promote(self.map).find(mapdict.ClassNode).getclass()
def find_instance_var(self, space, name): node = jit.promote(self.map).find(mapdict.AttributeNode, name) if node is None: return None return node.read(space, self)
def unset_flag(self, space, name): node = jit.promote(self.map).find(mapdict.FlagNode, name) # Flags are by default unset, no need to add if unsetting if node is not None: node.write(space, self, space.w_false)
def set_instance_var(self, space, name, w_value): idx = jit.promote(self.map).find_set_attr(space, name) if idx == -1: idx = self.map.add_attr(space, self, name) self.storage[idx] = w_value
def set_instance_var(self, space, name, w_value): node = jit.promote(self.map).find(mapdict.AttributeNode, name) if node is None: self.map = node = self.map.add(space, mapdict.AttributeNode.select_type(space, w_value), name, self) node.write(space, self, w_value)
def find_instance_var(self, space, name): idx = jit.promote(self.map).find_attr(space, name) if idx == -1: return None return self.storage[idx]
def get_flag(self, space, name): node = jit.promote(self.map).find(mapdict.FlagNode, name) return space.w_false if node is None else node.read(space, self)
def test(a, b): a = promote(a) b = promote(b) return compare(a, b)
def equal_func_unroll_n(a, b, info, env, cont, n): # n says how many times to call equal_func before going through loop label if n > 0: jit.promote(n) return equal_func_impl(a, b, info, env, cont, n - 1) return equal_func_loop(a, b, info, env, cont)
def unset_flag(self, space, name): idx = jit.promote(self.map).find_flag(space, name) if idx != -1: # Flags are by default unset, no need to add if unsetting self.storage[idx] = space.w_false
def getclass(self, space): return jit.promote(self.w_class)
def callAtom(self, atom, arguments, namedArgsMap): """ This method is used to reuse atoms without having to rebuild them. """ from typhon.objects.collections.maps import EMPTY_MAP # Promote the atom, on the basis that atoms are generally reused. atom = promote(atom) # Log the atom to the JIT log. Don't do this if the atom's not # promoted; it'll be slow. jit_debug(atom.repr) try: return self.recvNamed(atom, arguments, namedArgsMap) except Refused as r: # This block of method implementations is Typhon's Miranda # protocol. ~ C. if atom is _CONFORMTO_1: # Welcome to _conformTo/1. # to _conformTo(_): return self return self if atom is _GETALLEGEDINTERFACE_0: # Welcome to _getAllegedInterface/0. interface = self.optInterface() if interface is None: from typhon.objects.interfaces import ComputedInterface interface = ComputedInterface(self) return interface if atom is _PRINTON_1: # Welcome to _printOn/1. from typhon.objects.constants import NullObject self.printOn(arguments[0]) return NullObject if atom is _RESPONDSTO_2: from typhon.objects.constants import wrapBool from typhon.objects.data import unwrapInt, unwrapStr verb = unwrapStr(arguments[0]) arity = unwrapInt(arguments[1]) atom = getAtom(verb, arity) result = (atom in self.respondingAtoms() or atom in mirandaAtoms) return wrapBool(result) if atom is _SEALEDDISPATCH_1: # to _sealedDispatch(_): return null from typhon.objects.constants import NullObject return NullObject if atom is _UNCALL_0: from typhon.objects.constants import NullObject return NullObject if atom is _WHENMORERESOLVED_1: # Welcome to _whenMoreResolved. # This method's implementation, in Monte, should be: # to _whenMoreResolved(callback): callback<-(self) from typhon.vats import currentVat vat = currentVat.get() vat.sendOnly(arguments[0], RUN_1, [self], EMPTY_MAP) from typhon.objects.constants import NullObject return NullObject addTrail(r, self, atom, arguments) raise except UserException as ue: addTrail(ue, self, atom, arguments) raise except MemoryError: ue = userError(u"Memory corruption or exhausted heap") addTrail(ue, self, atom, arguments) raise ue except StackOverflow: check_stack_overflow() ue = userError(u"Stack overflow") addTrail(ue, self, atom, arguments) raise ue
def class_shadow(self, space): """Return internal representation of Squeak class.""" w_class = jit.promote(self.getclass(space)) return w_class.as_class_get_shadow(space)
def invoke(self, args): self = jit.promote(self) return self._invoke(args)
def call(self, args, env, cont): jit.promote(self) return self.closure.call(args, env, cont)
def interpret(bytecode, args): """The interpreter's entry point and portal function. """ # ------------------------------ # First a lot of JIT hints... # # A portal needs a "global merge point" at the beginning, for # technical reasons, if it uses promotion hints: hint(None, global_merge_point=True) # An important hint: 'bytecode' is a list, which is in theory # mutable. Let's tell the JIT compiler that it can assume that the # list is entirely frozen, i.e. immutable and only containing immutable # objects. Otherwise, it cannot do anything - it would have to assume # that the list can unpredictably change at runtime. bytecode = hint(bytecode, deepfreeze=True) # 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. oldargs = args argcount = promote(len(oldargs)) args = [] n = 0 while n < argcount: hint(n, concrete=True) args.append(oldargs[n]) n += 1 # ------------------------------ # the real code starts here loops = [] stack = [] pos = 0 while pos < len(bytecode): # It is a good idea to put another 'global merge point' at the # start of each iteration in the interpreter's main loop. The # JIT compiler keeps a table of all the times it passed through # the global merge point. It allows it to detect when it can # stop compiling and generate a jump back to some machine code # that was already generated earlier. hint(None, global_merge_point=True) opcode = bytecode[pos] hint(opcode, concrete=True) # same as in tiny1.py pos += 1 if opcode == 'ADD': op2(stack, func_add_int, func_add_str) elif opcode == 'SUB': op2(stack, func_sub_int, func_sub_str) elif opcode == 'MUL': op2(stack, func_mul_int, func_mul_str) elif opcode[0] == '#': n = myint(opcode, start=1) stack.append(args[n - 1]) elif opcode.startswith('->#'): n = myint(opcode, start=3) if n > len(args): raise IndexError args[n - 1] = stack.pop() elif opcode == '{': loops.append(pos) elif opcode == '}': if stack.pop().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 promote(pos) else: stack.append(StrBox(opcode)) return stack
def get_prev(self, env_structure): jit.promote(env_structure) if env_structure.elems: return self._prev return self
def get_w_globals(self): debugdata = self.getdebug() if debugdata is not None: return debugdata.w_globals return jit.promote(self.pycode).w_globals
def get_method(self): return jit.promote(self._method)
def set_flag(self, space, name): node = jit.promote(self.map).find(mapdict.FlagNode, name) if node is None: self.map = node = self.map.add(space, mapdict.FlagNode, name, self) node.write(space, self, space.w_true)
def get_ret_val_from_buffer(self, exb): cd = self._c_fn_type.get_cd() offset_p = rffi.ptradd(exb, jit.promote(cd.exchange_result)) ret_val = self._c_fn_type._ret_type.ffi_get_value(offset_p) return ret_val
def set_flag(self, space, name): idx = jit.promote(self.map).find_flag(space, name) if idx == -1: self.map.add_flag(space, self, name) else: self.storage[idx] = space.w_true
def getcode(self): if jit.we_are_jitted(): if not self.can_change_code: return _get_immutable_code(self) return jit.promote(self.code) return self.code
def call_with_extra_info(self, args, env, cont, extra_call_info): jit.promote(self) return self.code(args, env, cont, extra_call_info)
def getclass(self, space): return jit.promote(self.map).get_class()
def get_flag(self, space, name): idx = jit.promote(self.map).find_flag(space, name) if idx == -1: return space.w_false return self.storage[idx]
def equal_func_impl(a, b, info, env, cont, n): from pycket.interpreter import return_value for_chaperone = jit.promote(info.for_chaperone) if a.eqv(b): return return_value(values.w_true, env, cont) if (for_chaperone >= EqualInfo.CHAPERONE and b.is_non_interposing_chaperone()): return equal_func_unroll_n(a, b.get_proxied(), info, env, cont, n) # Enter into chaperones/impersonators if we have permission to do so if ((for_chaperone == EqualInfo.CHAPERONE and a.is_chaperone()) or (for_chaperone == EqualInfo.IMPERSONATOR and a.is_impersonator())): return equal_func_unroll_n(a.get_proxied(), b, info, env, cont, n) # If we are doing a chaperone/impersonator comparison, then we do not have # a chaperone-of/impersonator-of relation if `a` is not a proxy and # `b` is a proxy. if for_chaperone != EqualInfo.BASIC and not a.is_proxy() and b.is_proxy(): return return_value(values.w_false, env, cont) if isinstance(a, values_string.W_String) and isinstance(b, values_string.W_String): is_chaperone = for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) return return_value(values.W_Bool.make(a.equal(b)), env, cont) if isinstance(a, values.W_Bytes) and isinstance(b, values.W_Bytes): is_chaperone = info.for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) return return_value(values.W_Bool.make(a.equal(b)), env, cont) if isinstance(a, values.W_Cons) and isinstance(b, values.W_Cons): cont = equal_car_cont(a.cdr(), b.cdr(), info, env, cont) return equal_func_unroll_n(a.car(), b.car(), info, env, cont, n) if isinstance(a, values.W_MCons) and isinstance(b, values.W_MCons): cont = equal_car_cont(a.cdr(), b.cdr(), info, env, cont) return equal_func_unroll_n(a.car(), b.car(), info, env, cont, n) if isinstance(a, values.W_Box) and isinstance(b, values.W_Box): is_chaperone = for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) return a.unbox(env, equal_unbox_right_cont(b, info, env, cont)) if isinstance(a, values.W_MVector) and isinstance(b, values.W_MVector): is_chaperone = for_chaperone == EqualInfo.CHAPERONE if is_chaperone and (not a.immutable() or not b.immutable()): return return_value(values.w_false, env, cont) if a.length() != b.length(): return return_value(values.w_false, env, cont) return equal_vec_func(a, b, values.W_Fixnum(0), info, env, cont) if isinstance(a, values_struct.W_RootStruct) and isinstance(b, values_struct.W_RootStruct): a_type = a.struct_type() b_type = b.struct_type() w_prop = a_type.read_prop(values_struct.w_prop_equal_hash) if w_prop: w_prop = b_type.read_prop(values_struct.w_prop_equal_hash) if w_prop: w_equal_proc, w_hash_proc, w_hash2_proc = equal_hash_args(w_prop) # FIXME: it should work with cycles properly and be an equal?-recur w_equal_recur = equalp.w_prim return w_equal_proc.call([a, b, w_equal_recur], env, cont) if not a.struct_type().isopaque and not b.struct_type().isopaque: # This is probably not correct even if struct2vector were done # correct, due to side effects, but it is close enough for now. # Though the racket documentation says that `equal?` can elide # impersonator/chaperone handlers. a_imm = len(a_type.immutables) == a_type.total_field_cnt b_imm = len(b_type.immutables) == b_type.total_field_cnt a = values_struct.struct2vector(a, immutable=a_imm) b = values_struct.struct2vector(b, immutable=b_imm) return equal_func_unroll_n(a, b, info, env, cont, n) if a.equal(b): return return_value(values.w_true, env, cont) return return_value(values.w_false, env, cont)
def get_fn(self, tp1, tp2, _rev): d1 = self._dict.get(tp1, None) if d1 is None: return self._default_fn fn = d1.get(tp2, self._default_fn) return promote(fn)