def __init__(self): # This is a hack; see compile_code() in main.py self.suppress_process_switch = QuasiConstant(False) self.headless = QuasiConstant(False) self.highdpi = QuasiConstant(False) self.software_renderer = QuasiConstant(False) self.no_display = QuasiConstant(False) self.silent = QuasiConstant(False) self.omit_printing_raw_bytes = QuasiConstant(False) self.image_loaded = QuasiConstant(False) self.is_spur = QuasiConstant(False) self.uses_block_contexts = QuasiConstant(False) self.simulate_numeric_primitives = QuasiConstant(False) self.system_attributes = {} self._system_attribute_version = QuasiConstant(Version()) self._executable_path = QuasiConstant("") self.title = QuasiConstant("RSqueak") self.altf4quit = QuasiConstant(False) from rsqueakvm.display import NullDisplay self._display = QuasiConstant(None, cls=NullDisplay) from rsqueakvm.interpreter import Interpreter self.interp = QuasiConstant(None, cls=Interpreter) self.make_special_objects() self.strategy_factory = storage.StrategyFactory(self)
def __new__(cls, name, bases, attrs): # import pdb; pdb.set_trace() if name != 'ForeignLanguageClassShadow': attrs['w_plugin_send'] = QuasiConstant(None, cls=W_PointersObject) attrs['w_foreign_class'] = QuasiConstant(None, cls=W_PointersObject) attrs['w_foreign_object_class'] = QuasiConstant( None, cls=W_PointersObject) return ExtendableStrategyMetaclass.__new__(cls, name, bases, attrs)
class InterruptCounter: def __init__(self): self.counter_size = QuasiConstant(10000) self.interrupts_disabled = QuasiConstant(False) self.reset() def setup(self): try: self.counter_size.set(int( os.environ.get('TOPAZ_CHECK_INTERVAL') or '10000')) self.interrupts_disabled.set(bool( os.environ.get('TOPAZ_DISABLE_INTERRUPTS'))) except: pass if self.interrupts_disabled.get(): log('TOPAZ_DISABLE_INTERRUPTS set.') else: log('TOPAZ_CHECK_INTERVAL set to %s.' % self.counter_size.get()) def reset(self): self._counter = self.counter_size.get() def triggers(self, decr_by=1): if self.interrupts_disabled.get(): return False self._counter -= decr_by if self._counter <= 0: self._counter = self.counter_size.get() return True return False
class InterruptCounter: def __init__(self): self.counter_size = QuasiConstant(10000) self.interrupts_disabled = QuasiConstant(False) self.reset() def setup(self): try: self.counter_size.set( int(os.environ.get('TOPAZ_CHECK_INTERVAL') or '10000')) self.interrupts_disabled.set( bool(os.environ.get('TOPAZ_DISABLE_INTERRUPTS'))) except: pass if self.interrupts_disabled.get(): log('TOPAZ_DISABLE_INTERRUPTS set.') else: log('TOPAZ_CHECK_INTERVAL set to %s.' % self.counter_size.get()) def reset(self): self._counter = self.counter_size.get() def triggers(self, decr_by=1): if self.interrupts_disabled.get(): return False self._counter -= decr_by if self._counter <= 0: self._counter = self.counter_size.get() return True return False
def patch_pypy(): # Patch-out virtualizables from PyPy so that translation works try: # TODO: what if first delattr fails? delattr(PyFrame, '_virtualizable_') delattr(PyPyJitDriver, 'virtualizables') except AttributeError: pass PyStdObjSpace.current_python_process = QuasiConstant(None, W_PythonProcess) PyStdObjSpace.getexecutioncontext = new_getexecutioncontext PyFrame.__init__ = __init__frame PyFrame.execute_frame = new_execute_frame PyFrame.block_handles_exception = block_handles_exception PyFrame.has_exception_handler = has_exception_handler PyFrame.handle_operation_error = new_handle_operation_error PyCode.__init__ = __init__pycode PyCode._immutable_fields_.extend(['_co_names[*]', 'co_source']) # Add app-level `co_source` to PyCode (this is hacky) w_code_type = py_space.fromcache(TypeCache).getorbuild(PyCode.typedef) w_code_type.dict_w['co_source'] = interp_attrproperty( 'co_source', cls=PyCode, wrapfn="newtext_or_none") PythonAstCompiler.compile = new_compile
def __new__(cls, name, bases, attrs): # import pdb; pdb.set_trace() if name != 'W_ForeignLanguageProcess': w_foreign_process_class = QuasiConstant(None, cls=W_PointersObject) def foreign_process_class(self): return w_foreign_process_class.get() attrs['w_foreign_process_class'] = w_foreign_process_class attrs['foreign_process_class'] = foreign_process_class return extendabletype.__new__(cls, name, bases, attrs)
def patch_topaz(): # Patch-out virtualizables from Topaz so that translation works try: delattr(topaz_frame.Frame, "_virtualizable_") delattr(TopazInterpreter.jitdriver, "virtualizables") except AttributeError: pass # this is fine W_CodeObject._immutable_fields_.append('source') topaz_frame.BaseFrame.get_code_source = base_frame_get_code_source topaz_frame.Frame.get_code_source = frame_get_code_source topaz_frame.BuiltinFrame.get_code_source = builtin_frame_get_code_source topaz_frame.Frame.has_exception_handler = has_exception_handler topaz_frame.Frame.block_handles_exception = block_handles_exception TopazInterpreter.handle_bytecode = new_handle_bytecode TopazInterpreter.handle_ruby_error = new_handle_ruby_error TopazInterpreter.jump = new_jump TopazObjectSpace.compile = new_compile TopazObjectSpace.current_ruby_process = QuasiConstant(None, W_RubyProcess) TopazObjectSpace.getexecutioncontext = new_getexecutioncontext
def __init__(self, space): self.space = space self.no_specialized_storage = QuasiConstant(False) self.singleton_nodes = {} rstrat.StrategyFactory.__init__(self, AbstractStrategy)
class StrategyFactory(rstrat.StrategyFactory): _immutable_fields_ = ["space", "no_specialized_storage"] def __init__(self, space): self.space = space self.no_specialized_storage = QuasiConstant(False) self.singleton_nodes = {} rstrat.StrategyFactory.__init__(self, AbstractStrategy) # XXX: copied and slightly modified to not set a singleton field on the strategy class def _create_strategy_instances(self, root_class, all_strategy_classes): for strategy_class in all_strategy_classes: if strategy_class._is_strategy: self.strategies.append(strategy_class) self._patch_strategy_class(strategy_class, root_class) self._order_strategies() # XXX: copied and slightly modified to include w_class for instantiation from rstrategies def switch_strategy(self, w_self, new_strategy_type, new_element=None): """ Switch the strategy of w_self to the new type. new_element can be given as as hint, purely for logging purposes. It should be the object that was added to w_self, causing the strategy switch. """ old_strategy = self.get_strategy(w_self) w_class = old_strategy.getclass() if new_strategy_type._is_singleton: new_strategy = self.strategy_singleton_instance(new_strategy_type, w_class) else: size = old_strategy.size(w_self) new_strategy = self.instantiate_strategy(new_strategy_type, w_class, w_self, size) self.set_strategy(w_self, new_strategy) old_strategy._convert_storage_to(w_self, new_strategy) new_strategy.strategy_switched(w_self) self.log(w_self, new_strategy, old_strategy, new_element) return new_strategy # XXX: copied and slightly modified to include w_class for instantiation from rstrategies def set_initial_strategy(self, w_self, strategy_type, w_class, size, elements=None): assert self.get_strategy(w_self) is None, "Strategy should not be initialized yet!" if strategy_type._is_singleton: strategy = self.strategy_singleton_instance(strategy_type, w_class) else: strategy = self.instantiate_strategy(strategy_type, w_class, w_self, size) self.set_strategy(w_self, strategy) strategy._initialize_storage(w_self, size) element = None if elements: strategy.store_all(w_self, elements) if len(elements) > 0: element = elements[0] strategy.strategy_switched(w_self) self.log(w_self, strategy, None, element) return strategy def strategy_singleton_instance(self, strategy_class, w_class=None): s = self.strategy_singleton_instance_from_cache(strategy_class, w_class) if s is None: s = self.instantiate_strategy(strategy_class, w_class) self.singleton_nodes[(strategy_class, w_class)] = s return s @jit.elidable def strategy_singleton_instance_from_cache(self, strategy_class, w_class): return self.singleton_nodes.get((strategy_class, w_class), None) def instantiate_strategy(self, strategy_type, w_class, w_self=None, initial_size=0): return strategy_type(self.space, w_self, initial_size, w_class) def strategy_type_for(self, objects, weak=False): if weak: return WeakListStrategy if self.no_specialized_storage.is_set(): return ListStrategy return rstrat.StrategyFactory.strategy_type_for(self, objects) def empty_storage_type(self, w_self, size, weak=False): if weak: return WeakListStrategy if self.no_specialized_storage.is_set(): return ListStrategy return AllNilStrategy def log(self, w_self, new_strategy, old_strategy=None, new_element=None): if not self.logger.active: return # Gather information to be logged image_loaded = self.space.image_loaded.is_set() size = new_strategy.size(w_self) new_strategy_str = new_strategy.repr_classname old_strategy_str = old_strategy.repr_classname if old_strategy else "" classname = w_self.guess_classname() if image_loaded else "" element_classname = new_element.guess_classname() if new_element and image_loaded else "" if image_loaded: cause = "Switched" if old_strategy else "Initialized" else: cause = "Filledin" self.logger.log(new_strategy_str, size, cause, old_strategy_str, classname, element_classname)
class W_ForeignLanguageProcess(W_AbstractObjectWithIdentityHash): __metaclass__ = ForeignLanguageProcessMeta _attrs_ = [ '_runner', '_done', 'w_result', 'w_error', '_space', 'w_rcvr', 'method_name', 'args_w', '_is_send', '_break_on_exceptions' ] repr_classname = 'W_ForeignLanguageProcess' eval_method = QuasiConstant(None, cls=W_PointersObject) resume_method = QuasiConstant(None, cls=W_PointersObject) def __init__(self, space, w_rcvr=None, method_name='', args_w=None, is_send=False, break_on_exceptions=False): W_AbstractObjectWithIdentityHash.__init__(self) self._space = space self.w_rcvr = w_rcvr self.method_name = method_name self.args_w = args_w or [] self._done = False self.w_result = None self.w_error = None self._is_send = is_send self._break_on_exceptions = break_on_exceptions def init_runner(self): if objectmodel.we_are_translated(): self._runner = runner.StackletLanguageRunner(self) else: self._runner = runner.GreenletLanguageRunner(self) def space(self): return self._space @staticmethod def load_special_objects(cls, language_name, space): language_process_class = space.smalltalk_at('%sProcess' % language_name) if language_process_class is None: # disable plugin? print '%s class not found.' % language_name cls.w_foreign_process_class.set(language_process_class) # this part is called twice -> make better foreign_class = space.smalltalk_at('ForeignLanguageProcess') if foreign_class is None: print 'ForeignLanguage class not found.' return language_process_class_s = language_process_class.as_class_get_shadow( space) eval_method_symbol = space.wrap_symbol('vmEval') eval_method = language_process_class_s.lookup(eval_method_symbol) if eval_method is None: print 'ForeignLanguageProcess>>vmEval method not found.' W_ForeignLanguageProcess.eval_method.set(eval_method) resume_method_symbol = space.wrap_symbol('vmResume') resume_method = language_process_class_s.lookup(resume_method_symbol) if resume_method is None: print 'ForeignLanguageProcess>>vmResume: method not found.' W_ForeignLanguageProcess.resume_method.set(resume_method) # W_AbstractObjectWithIdentityHash overrides def at0(self, space, index0): # import pdb; pdb.set_trace() return space.w_nil def atput0(self, space, index0, w_value): # import pdb; pdb.set_trace() pass def fetch(self, space, n0): # import pdb; pdb.set_trace() return space.w_nil def store(self, space, n0, w_value): # import pdb; pdb.set_trace() pass def getclass(self, space): return self.foreign_process_class() # Abstract methods def eval(self): raise NotImplementedError def send(self): raise NotImplementedError def pre_resume(self): # called on every switch to language process pass def post_resume(self): # called as soon as Smalltalk continues pass def w_top_frame(self): raise NotImplementedError # Helpers def safe_run(self): try: if self._is_send: self.guarded_send() else: self.eval() except Exception as e: print 'Unknown error in thread: %s' % e finally: self._done = True def guarded_send(self): if (self.w_rcvr is None or self.method_name == ''): error_msg = 'Invalid send (w_rcvr: %s, method: %s, args_w: %s)' % ( self.w_rcvr, self.method_name, self.args_w) print error_msg self.set_error(self.space().wrap_string(error_msg)) return self.send() def resume(self): if self.is_done(): # import pdb; pdb.set_trace() print 'The runner is done and cannot be resumed' return self.runner().resume() def error_detected(self): if not self.break_on_exceptions(): return False # pretend everything is ok and move on return self.get_error() is not None def runner(self): return self._runner def is_done(self): return self._done def fail(self, error_msg): print error_msg self.set_error(self.space().wrap_string(error_msg)) def get_result(self): return self.w_result def set_result(self, w_result): self.w_result = w_result def get_error(self): return self.w_error def set_error(self, w_error): self.w_error = w_error def reset_error(self): self.w_error = None def break_on_exceptions(self): return self._break_on_exceptions # Switching def switch_to_smalltalk(self, interp, s_frame, first_call=False): self.post_resume() log('Switching to Smalltalk...') if self.is_done(): return self._create_return_frame(interp.space) # import pdb; pdb.set_trace() if first_call: # attach s_frame with resume method for the first time s_resume_frame = self._build_resume_method(interp.space, is_eval=True) s_resume_frame.store_s_sender(s_frame) elif s_frame.w_method() is self.resume_method.get(): s_resume_frame = self._build_resume_method(interp.space) eval_frame = s_frame.s_sender() # Ensure #resume: method with closure = nil if (eval_frame.w_method() is self.eval_method.get() and eval_frame.closure is not None): # instead of chaining resume frames, store original sender s_resume_frame.store_s_sender(eval_frame) else: print('Unexpected eval_frame found:\n%s' % s_frame.print_stack()) s_resume_frame.store_s_sender(s_frame) else: print 'Unexpected s_frame found:\n%s' % s_frame.print_stack() s_resume_frame = s_frame interp.quick_check_for_interrupt(s_resume_frame, dec=interp.interrupt_counter_size) # this will raise a ProcessSwitch if there are interrupts or timers ... return s_resume_frame def _build_resume_method(self, space, is_eval=False): from rsqueakvm.storage_contexts import ContextPartShadow if is_eval: method = self.eval_method.get() else: method = self.resume_method.get() return ContextPartShadow.build_method_context(space, method, self) def _create_return_frame(self, space): from rsqueakvm.storage_contexts import ContextPartShadow log('Language has finished and returned a result.') # we want evalInThread and resumePython to return new frames, # so we don't build up stack, but we also don't raise to the # top-level loop all the time. # For resuming, we obviously need a new frame, because that's # how the Smalltalk scheduler knows how to continue back to Python. # Unfortunately, a primitive can only EITHER always return a new # frame OR a result. So when we get a result, we cannot simply # return it. Instead, we need to build a frame that simply returns # the result if space.is_spur.is_set(): w_cm = objectmodel.instantiate(W_SpurCompiledMethod) else: w_cm = objectmodel.instantiate(W_PreSpurCompiledMethod) w_resume_class = self.foreign_process_class() w_cm.header = 0 w_cm._primitive = 0 w_cm.literalsize = 3 w_cm.islarge = False w_cm._tempsize = 0 w_cm.argsize = 0 w_cm.compiledin_class = w_resume_class.getclass(space) w_cm.lookup_selector = 'fakeReturnResult' w_cm.bytes = [ chr(b) for b in [ 0x20, # push constant 0x7C, # return stack top ] ] w_cm.literals = [self.get_result(), space.w_nil, w_cm.compiledin_class] return ContextPartShadow.build_method_context(space, w_cm, w_resume_class)
def __init__(self): self.counter_size = QuasiConstant(10000) self.interrupts_disabled = QuasiConstant(False) self.reset()
from rsqueakvm.util.cells import QuasiConstant from rsqueakvm.plugins.vmdebugging.model import wrap_oplist, wrap_greenkey, wrap_debug_info from rpython.rlib.jit import JitHookInterface, Counters jit_iface_recursion = QuasiConstant(False) def make_hook(args, func): import inspect, re src = "\n".join([ re.sub("^\\s+", " " * 12, line) for line in inspect.getsource(func).split("\n")[1:] ]) code = [ "def f(%s):" % (args), " from rsqueakvm import constants", " from rsqueakvm.interpreter import jit_driver_name", " from rsqueakvm.model.variable import W_BytesObject", " if jitdriver.name != jit_driver_name: return", " space = self.space", " if jit_iface_recursion.is_set(): return", " interp = space.interp.get()", " w_jithook = space.w_jit_hook_selector()", " w_rcvr = space.w_jit_hook_receiver()", " if w_jithook and isinstance(w_jithook, W_BytesObject) and w_rcvr:", " w_method = w_rcvr.class_shadow(space).lookup(w_jithook)", " if w_method is None: return", " jit_iface_recursion.activate()", " try:", " args_w = func(%s)" % args, " interp.perform_headless(w_rcvr, w_jithook, [space.wrap_list(args_w)])", " finally:", " jit_iface_recursion.deactivate()"
def __init__(self): Plugin.__init__(self) self.w_ruby_object_class = QuasiConstant(None, cls=W_AbstractObjectWithIdentityHash) self.w_ruby_plugin_send = QuasiConstant(None, cls=W_AbstractObjectWithIdentityHash)
class ObjSpace(object): def __init__(self): # This is a hack; see compile_code() in main.py self.suppress_process_switch = QuasiConstant(False) self.headless = QuasiConstant(False) self.highdpi = QuasiConstant(False) self.software_renderer = QuasiConstant(False) self.no_display = QuasiConstant(False) self.silent = QuasiConstant(False) self.omit_printing_raw_bytes = QuasiConstant(False) self.image_loaded = QuasiConstant(False) self.is_spur = QuasiConstant(False) self.uses_block_contexts = QuasiConstant(False) self.simulate_numeric_primitives = QuasiConstant(False) self.system_attributes = {} self._system_attribute_version = QuasiConstant(Version()) self._executable_path = QuasiConstant("") self.title = QuasiConstant("RSqueak") self.altf4quit = QuasiConstant(False) from rsqueakvm.display import NullDisplay self._display = QuasiConstant(None, cls=NullDisplay) from rsqueakvm.interpreter import Interpreter self.interp = QuasiConstant(None, cls=Interpreter) self.make_special_objects() self.strategy_factory = storage.StrategyFactory(self) def make_special_objects(self): # These are used in the interpreter bytecodes self.w_minus_one = W_SmallInteger(-1) self.w_zero = W_SmallInteger(0) self.w_one = W_SmallInteger(1) self.w_two = W_SmallInteger(2) self.w_special_objects = empty_object() # no add all of those special objects that we assume constant while the image is running for name, (idx, t) in constants.constant_objects_in_special_object_table.items(): if t == "POINTERS": setattr(self, "w_" + name, empty_object()) elif t == "BYTES": setattr(self, "w_" + name, empty_symbol()) else: assert False def runtime_setup(self, interp, exepath, argv, image_name, image_args_idx): self.interp.set(interp) fullpath = exepath self._executable_path.set(fullpath) for i in range(image_args_idx, len(argv)): self.set_system_attribute(SYSTEM_ATTRIBUTE_IMAGE_ARGS_INDEX + i - image_args_idx, argv[i]) self.set_system_attribute(SYSTEM_ATTRIBUTE_IMAGE_NAME_INDEX, image_name) self.image_loaded.activate() self.init_system_attributes(argv) from rsqueakvm.plugins import PluginRegistry [p.startup(self, argv) for p in PluginRegistry.enabled_plugins] def init_system_attributes(self, argv): for i in xrange(1, len(argv)): self.set_system_attribute(-i, argv[i]) import platform from rsqueakvm.main import VERSION, BUILD_DATE from rpython.rlib.compilerinfo import get_compiler_info self.set_system_attribute(0, self._executable_path.get()) self.set_system_attribute(1001, platform.system()) # operating system self.set_system_attribute(1002, platform.version()) # operating system version self.set_system_attribute(1003, platform.processor()) # platform's processor type self.set_system_attribute(1004, VERSION) self.set_system_attribute(1006, "%s Compiler: %s" % (BUILD_DATE, get_compiler_info())) self.set_system_attribute(1007, "rsqueak") # interpreter class (invented for Cog) def get_system_attribute(self, idx): return self._pure_get_system_attribute(idx, self._system_attribute_version.get()) @jit.elidable def _pure_get_system_attribute(self, idx, version): return self.system_attributes[idx] def set_system_attribute(self, idx, value): self.system_attributes[idx] = value self._system_attribute_version.changed() # ============= Methods for wrapping and unwrapping stuff ============= @specialize.argtype(1) def wrap_int(self, val): if isinstance(val, rbigint.rbigint): return self.wrap_rbigint(val) elif isinstance(val, int): return self.wrap_smallint_unsafe(val) elif isinstance(val, r_uint): if val <= r_uint(constants.MAXINT): return self.wrap_smallint_unsafe(intmask(val)) else: return self.wrap_wordint_direct(val, self.w_LargePositiveInteger) elif IS_64BIT and isinstance(val, r_uint32): return self.wrap_smallint_unsafe(intmask(val)) elif isinstance(val, r_longlong) or isinstance(val, r_int64): # use '&' instead of 'and' in these checks, so we only generate 1 guard instead of two if (constants.MININT <= val) & (val <= constants.MAXINT): return self.wrap_smallint_unsafe(intmask(val)) elif (0 <= val) & (val <= r_longlong(constants.U_MAXINT)): return self.wrap_wordint_direct(r_uint(val), self.w_LargePositiveInteger) elif (0 > val) & (-r_longlong(constants.U_MAXINT) <= val): return self.wrap_wordint_direct(r_uint(-val), self.w_LargeNegativeInteger) else: return self.wrap_rbigint_direct(rbigint.rbigint.fromrarith_int(val)) elif isinstance(val, r_ulonglong): if val <= r_ulonglong(constants.MAXINT): return self.wrap_smallint_unsafe(intmask(val)) elif val <= constants.U_MAXINT: return self.wrap_wordint_direct(r_uint(val), self.w_LargePositiveInteger) else: return self.wrap_rbigint_direct(rbigint.rbigint.fromrarith_int(val)) else: raise WrappingError def wrap_smallint_unsafe(self, val): assert is_valid_int(val) return W_SmallInteger(intmask(val)) def wrap_rbigint(self, val): if val.sign >= 0: w_class = self.w_LargePositiveInteger else: w_class = self.w_LargeNegativeInteger # the logic below is an copied from rbigint.toint to make the guards inline better if val.numdigits() <= rbigint.MAX_DIGITS_THAT_CAN_FIT_IN_INT: try: uint = val._touint_helper() # this doesn't check the sign, which we want except OverflowError: return self.wrap_rbigint_direct(val, w_class) if val.sign >= 0: res = intmask(uint) if res >= 0: return self.wrap_smallint_unsafe(res) else: res = intmask(-uint) if res < 0: return self.wrap_smallint_unsafe(res) return self.wrap_wordint_direct(uint, w_class) return self.wrap_rbigint_direct(val, w_class) @always_inline def wrap_rbigint_direct(self, val, w_class=None): if w_class is None: if val.sign >= 0: w_class = self.w_LargePositiveInteger else: w_class = self.w_LargeNegativeInteger return W_LargeIntegerBig(self, w_class, val, 0) def wrap_wordint_direct(self, val, w_class): return W_LargeIntegerWord(self, w_class, val, constants.BYTES_PER_MACHINE_INT) def wrap_float(self, i): return W_Float(i) def wrap_string(self, string): w_inst = self.w_String.as_class_get_shadow(self).new(len(string)) assert isinstance(w_inst, W_BytesObject) w_inst.setbytes(list(string)) return w_inst def wrap_symbol(self, string): w_inst = self.wrap_string(string) w_inst.change_class(self, self.w_ByteSymbol) return w_inst def wrap_char(self, c): # return self.w_charactertable.fetch(self, ord(c)) return W_Character(ord(c)) def wrap_bool(self, b): if b: return self.w_true else: return self.w_false def wrap_list(self, lst_w): """ Converts a Python list of wrapped objects into a wrapped smalltalk array """ lstlen = len(lst_w) res = self.w_Array.as_class_get_shadow(self).new(lstlen) for i in range(lstlen): res.atput0(self, i, lst_w[i]) return res @jit.unroll_safe def wrap_list_unroll_safe(self, lst_w): lstlen = len(lst_w) res = self.w_Array.as_class_get_shadow(self).new(lstlen) for i in range(lstlen): res.atput0(self, i, lst_w[i]) return res def unwrap_int(self, w_value): return w_value.unwrap_int(self) def unwrap_uint(self, w_value): return w_value.unwrap_uint(self) def unwrap_positive_uint(self, w_value): if w_value.is_positive(self): return w_value.unwrap_uint(self) raise UnwrappingError def unwrap_int64(self, w_value): if IS_64BIT: return w_value.unwrap_int(self) else: return w_value.unwrap_int64(self) def unwrap_rbigint(self, w_value): return w_value.unwrap_rbigint(self) def unwrap_char_as_byte(self, w_char): return w_char.unwrap_char_as_byte(self) def unwrap_float(self, w_v): return w_v.unwrap_float(self) def unwrap_array(self, w_array): return w_array.unwrap_array(self) def unwrap_string(self, w_object): return w_object.unwrap_string(self) # ============= Access to static information ============= @specialize.arg(1) def get_special_selector(self, selector): i0 = constants.find_selectorindex(selector) self.w_special_selectors.as_cached_object_get_shadow(self) return self.w_special_selectors.fetch(self, i0) def executable_path(self): return self._executable_path.get() def get_image_name(self): return self.get_system_attribute(SYSTEM_ATTRIBUTE_IMAGE_NAME_INDEX) def window_title(self): title = self.title.get() imgpath = self.get_image_name() if len(title) == 0: title = "RSqueak (%s)" % imgpath else: title = "%s (%s)" % (self.title.get(), imgpath) return title def display(self): disp = self._display.get() if disp is None: # Create lazy to allow headless execution. if self.no_display.is_set(): disp = display.NullDisplay() print 'Attaching a dummy display...' else: disp = display.SDLDisplay( self.window_title(), self.highdpi.is_set(), self.software_renderer.is_set(), self.altf4quit.is_set() ) self._display.set(disp) return jit.promote(disp) def smalltalk_at(self, string): """A helper to find a class by name in modern Squeak images""" w_sd = self.w_smalltalkdict if w_sd.instsize() == 1: w_globals = w_sd.fetch(self, 0) if w_globals.instsize() == 6: w_bindings = w_globals.fetch(self, 2) if w_bindings.instsize() == 2: w_array = w_bindings.fetch(self, 1) size = w_array.varsize() for i in range(size): w_assoc = w_array.fetch(self, i) if w_assoc.instsize() == 2: try: if self.unwrap_string(w_assoc.fetch(self, 0)) == string: return w_assoc.fetch(self, 1) except UnwrappingError: pass elif w_globals.instsize() == 4: w_array = w_globals.fetch(self, 1) size = w_array.varsize() for i in range(size): w_assoc = w_array.fetch(self, i) if w_assoc.instsize() == 2: try: if self.unwrap_string(w_assoc.fetch(self, 0)) == string: return w_assoc.fetch(self, 1) except UnwrappingError: pass elif w_sd.instsize() == 2: w_array = w_sd.fetch(self, 1) size = w_array.varsize() for i in range(size): w_assoc = w_array.fetch(self, i) if w_assoc.instsize() == 2: try: if self.unwrap_string(w_assoc.fetch(self, 0)) == string: return w_assoc.fetch(self, 1) except UnwrappingError: pass # ============= Other Methods ============= def _freeze_(self): return True @jit.unroll_safe def newClosure(self, w_outer_ctxt, pc, numArgs, copiedValues): assert isinstance(w_outer_ctxt, W_PointersObject) w_method = w_outer_ctxt.as_context_get_shadow(self).w_method() pc_with_bytecodeoffset = pc + w_method.bytecodeoffset() + 1 numCopied = len(copiedValues) w_closure = W_BlockClosure(self, w_outer_ctxt, pc_with_bytecodeoffset, numArgs, numCopied) for i0 in range(numCopied): w_closure.atput0(self, i0, copiedValues[i0]) return w_closure
class ObjSpace(object): def __init__(self): # This is a hack; see compile_code() in main.py self.suppress_process_switch = QuasiConstant(False) self.headless = QuasiConstant(False) self.highdpi = QuasiConstant(False) self.software_renderer = QuasiConstant(False) self.no_display = QuasiConstant(False) self.silent = QuasiConstant(False) self.omit_printing_raw_bytes = QuasiConstant(False) self.image_loaded = QuasiConstant(False) self.is_spur = QuasiConstant(False) self.uses_block_contexts = QuasiConstant(False) self.simulate_numeric_primitives = QuasiConstant(False) self.system_attributes = {} self._system_attribute_version = QuasiConstant(Version()) self._executable_path = QuasiConstant("") self.title = QuasiConstant("RSqueak") self.altf4quit = QuasiConstant(False) from rsqueakvm.display import NullDisplay self._display = QuasiConstant(None, cls=NullDisplay) from rsqueakvm.interpreter import Interpreter self.interp = QuasiConstant(None, cls=Interpreter) self.make_special_objects() self.strategy_factory = storage.StrategyFactory(self) def make_special_objects(self): # These are used in the interpreter bytecodes self.w_minus_one = W_SmallInteger(-1) self.w_zero = W_SmallInteger(0) self.w_one = W_SmallInteger(1) self.w_two = W_SmallInteger(2) self.w_special_objects = empty_object() # no add all of those special objects that we assume constant while the image is running for name, (idx, t) in constants.constant_objects_in_special_object_table.items(): if t == "POINTERS": setattr(self, "w_" + name, empty_object()) elif t == "BYTES": setattr(self, "w_" + name, empty_symbol()) else: assert False def runtime_setup(self, interp, exepath, argv, image_name, image_args_idx): self.interp.set(interp) fullpath = exepath self._executable_path.set(fullpath) for i in range(image_args_idx, len(argv)): self.set_system_attribute(SYSTEM_ATTRIBUTE_IMAGE_ARGS_INDEX + i - image_args_idx, argv[i]) self.set_system_attribute(SYSTEM_ATTRIBUTE_IMAGE_NAME_INDEX, image_name) self.image_loaded.activate() self.init_system_attributes(argv) from rsqueakvm.plugins import PluginRegistry [p.startup(self, argv) for p in PluginRegistry.enabled_plugins] def init_system_attributes(self, argv): for i in xrange(1, len(argv)): self.set_system_attribute(-i, argv[i]) import platform from rsqueakvm.main import VERSION, BUILD_DATE from rpython.rlib.compilerinfo import get_compiler_info self.set_system_attribute(0, self._executable_path.get()) self.set_system_attribute(1001, platform.system()) # operating system self.set_system_attribute(1002, platform.version()) # operating system version self.set_system_attribute(1003, platform.processor()) # platform's processor type self.set_system_attribute(1004, VERSION) self.set_system_attribute(1006, "%s Compiler: %s" % (BUILD_DATE, get_compiler_info())) self.set_system_attribute(1007, "rsqueak") # interpreter class (invented for Cog) def get_system_attribute(self, idx): return self._pure_get_system_attribute(idx, self._system_attribute_version.get()) @jit.elidable def _pure_get_system_attribute(self, idx, version): return self.system_attributes[idx] def set_system_attribute(self, idx, value): self.system_attributes[idx] = value self._system_attribute_version.changed() # ============= Methods for wrapping and unwrapping stuff ============= @specialize.argtype(1) def wrap_int(self, val): if isinstance(val, rbigint.rbigint): return self.wrap_rbigint(val) elif isinstance(val, int): return self.wrap_smallint_unsafe(val) elif isinstance(val, r_uint): if val <= r_uint(constants.MAXINT): return self.wrap_smallint_unsafe(intmask(val)) else: return self.wrap_wordint_direct(val, self.w_LargePositiveInteger) elif IS_64BIT and isinstance(val, r_uint32): return self.wrap_smallint_unsafe(intmask(val)) elif isinstance(val, r_longlong) or isinstance(val, r_int64): # use '&' instead of 'and' in these checks, so we only generate 1 guard instead of two if (constants.MININT <= val) & (val <= constants.MAXINT): return self.wrap_smallint_unsafe(intmask(val)) elif (0 <= val) & (val <= r_longlong(constants.U_MAXINT)): return self.wrap_wordint_direct(r_uint(val), self.w_LargePositiveInteger) elif (0 > val) & (-r_longlong(constants.U_MAXINT) <= val): return self.wrap_wordint_direct(r_uint(-val), self.w_LargeNegativeInteger) else: return self.wrap_rbigint_direct(rbigint.rbigint.fromrarith_int(val)) elif isinstance(val, r_ulonglong): if val <= r_ulonglong(constants.MAXINT): return self.wrap_smallint_unsafe(intmask(val)) elif val <= constants.U_MAXINT: return self.wrap_wordint_direct(r_uint(val), self.w_LargePositiveInteger) else: return self.wrap_rbigint_direct(rbigint.rbigint.fromrarith_int(val)) else: raise WrappingError def wrap_smallint_unsafe(self, val): assert is_valid_int(val) return W_SmallInteger(intmask(val)) def wrap_rbigint(self, val): if val.sign >= 0: w_class = self.w_LargePositiveInteger else: w_class = self.w_LargeNegativeInteger # the logic below is an copied from rbigint.toint to make the guards inline better if val.numdigits() <= rbigint.MAX_DIGITS_THAT_CAN_FIT_IN_INT: try: uint = val._touint_helper() # this doesn't check the sign, which we want except OverflowError: return self.wrap_rbigint_direct(val, w_class) if val.sign >= 0: res = intmask(uint) if res >= 0: return self.wrap_smallint_unsafe(res) else: res = intmask(-uint) if res < 0: return self.wrap_smallint_unsafe(res) return self.wrap_wordint_direct(uint, w_class) return self.wrap_rbigint_direct(val, w_class) @always_inline def wrap_rbigint_direct(self, val, w_class=None): if w_class is None: if val.sign >= 0: w_class = self.w_LargePositiveInteger else: w_class = self.w_LargeNegativeInteger return W_LargeIntegerBig(self, w_class, val, 0) def wrap_wordint_direct(self, val, w_class): return W_LargeIntegerWord(self, w_class, val, constants.BYTES_PER_MACHINE_INT) def wrap_float(self, i): return W_Float(i) def wrap_string(self, string): w_inst = self.w_String.as_class_get_shadow(self).new(len(string)) assert isinstance(w_inst, W_BytesObject) w_inst.setbytes(list(string)) return w_inst def wrap_symbol(self, string): with ForceHeadless(self): return self.interp.get().perform(self.wrap_string(string), "asSymbol") def wrap_char(self, c): # return self.w_charactertable.fetch(self, ord(c)) return W_Character(ord(c)) def wrap_bool(self, b): if b: return self.w_true else: return self.w_false def wrap_list(self, lst_w): """ Converts a Python list of wrapped objects into a wrapped smalltalk array """ lstlen = len(lst_w) res = self.w_Array.as_class_get_shadow(self).new(lstlen) for i in range(lstlen): res.atput0(self, i, lst_w[i]) return res @jit.unroll_safe def wrap_list_unroll_safe(self, lst_w): lstlen = len(lst_w) res = self.w_Array.as_class_get_shadow(self).new(lstlen) for i in range(lstlen): res.atput0(self, i, lst_w[i]) return res def unwrap_int(self, w_value): return w_value.unwrap_int(self) def unwrap_uint(self, w_value): return w_value.unwrap_uint(self) def unwrap_positive_uint(self, w_value): if w_value.is_positive(self): return w_value.unwrap_uint(self) raise UnwrappingError def unwrap_int64(self, w_value): if IS_64BIT: return w_value.unwrap_int(self) else: return w_value.unwrap_int64(self) def unwrap_rbigint(self, w_value): return w_value.unwrap_rbigint(self) def unwrap_char_as_byte(self, w_char): return w_char.unwrap_char_as_byte(self) def unwrap_float(self, w_v): return w_v.unwrap_float(self) def unwrap_array(self, w_array): return w_array.unwrap_array(self) def unwrap_string(self, w_object): return w_object.unwrap_string(self) # ============= Access to static information ============= @specialize.arg(1) def get_special_selector(self, selector): i0 = constants.find_selectorindex(selector) self.w_special_selectors.as_cached_object_get_shadow(self) return self.w_special_selectors.fetch(self, i0) def executable_path(self): return self._executable_path.get() def get_image_name(self): return self.get_system_attribute(SYSTEM_ATTRIBUTE_IMAGE_NAME_INDEX) def window_title(self): title = self.title.get() imgpath = self.get_image_name() if len(title) == 0: title = "RSqueak (%s)" % imgpath else: title = "%s (%s)" % (self.title.get(), imgpath) return title def display(self): disp = self._display.get() if disp is None: # Create lazy to allow headless execution. if self.no_display.is_set(): disp = display.NullDisplay() print 'Attaching a dummy display...' else: disp = display.SDLDisplay( self.window_title(), self.highdpi.is_set(), self.software_renderer.is_set(), self.altf4quit.is_set() ) self._display.set(disp) return jit.promote(disp) def smalltalk_at(self, string): """A helper to find a class by name in modern Squeak images""" w_sd = self.w_smalltalkdict if w_sd.instsize() == 1: w_globals = w_sd.fetch(self, 0) if w_globals.instsize() == 6: w_bindings = w_globals.fetch(self, 2) if w_bindings.instsize() == 2: w_array = w_bindings.fetch(self, 1) size = w_array.varsize() for i in range(size): w_assoc = w_array.fetch(self, i) if w_assoc.instsize() == 2: try: if self.unwrap_string(w_assoc.fetch(self, 0)) == string: return w_assoc.fetch(self, 1) except UnwrappingError: pass elif w_globals.instsize() == 4: w_array = w_globals.fetch(self, 1) size = w_array.varsize() for i in range(size): w_assoc = w_array.fetch(self, i) if w_assoc.instsize() == 2: try: if self.unwrap_string(w_assoc.fetch(self, 0)) == string: return w_assoc.fetch(self, 1) except UnwrappingError: pass elif w_sd.instsize() == 2: w_array = w_sd.fetch(self, 1) size = w_array.varsize() for i in range(size): w_assoc = w_array.fetch(self, i) if w_assoc.instsize() == 2: try: if self.unwrap_string(w_assoc.fetch(self, 0)) == string: return w_assoc.fetch(self, 1) except UnwrappingError: pass # ============= Other Methods ============= def _freeze_(self): return True @jit.unroll_safe def newClosure(self, w_outer_ctxt, pc, numArgs, copiedValues): assert isinstance(w_outer_ctxt, W_PointersObject) w_method = w_outer_ctxt.as_context_get_shadow(self).w_method() pc_with_bytecodeoffset = pc + w_method.bytecodeoffset() + 1 numCopied = len(copiedValues) w_closure = W_BlockClosure(self, w_outer_ctxt, pc_with_bytecodeoffset, numArgs, numCopied) for i0 in range(numCopied): w_closure.atput0(self, i0, copiedValues[i0]) return w_closure