Exemple #1
0
    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)
Exemple #2
0
    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)
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
    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)
Exemple #7
0
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
Exemple #8
0
 def __init__(self, space):
     self.space = space
     self.no_specialized_storage = QuasiConstant(False)
     self.singleton_nodes = {}
     rstrat.StrategyFactory.__init__(self, AbstractStrategy)
Exemple #9
0
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)
Exemple #10
0
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)
Exemple #11
0
    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)
Exemple #12
0
 def __init__(self):
     self.counter_size = QuasiConstant(10000)
     self.interrupts_disabled = QuasiConstant(False)
     self.reset()
Exemple #13
0
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()"
Exemple #14
0
 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)
Exemple #15
0
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
Exemple #16
0
 def __init__(self):
     self.counter_size = QuasiConstant(10000)
     self.interrupts_disabled = QuasiConstant(False)
     self.reset()
Exemple #17
0
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