[pypy-commit] lang-smalltalk default: (tfel, lwassermann):

lwassermann noreply at buildbot.pypy.org
Tue Jun 18 16:04:13 CEST 2013


Author: Lars Wassermann <lars.wassermann at gmail.com>
Branch: 
Changeset: r454:40875946b055
Date: 2013-06-14 16:54 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/40875946b055/

Log:	(tfel, lwassermann): added dynamic loading capabilities fixed
	problem with execution folder identification (adapted from topaz)
	fixed bool-function return values removed external bitblt hard link
	to now actually call external function 'copyBits'

diff --git a/spyvm/interpreter_proxy.py b/spyvm/interpreter_proxy.py
--- a/spyvm/interpreter_proxy.py
+++ b/spyvm/interpreter_proxy.py
@@ -94,8 +94,8 @@
                     raise NotImplementedError(
                         "InterpreterProxy: unknown result_type %s" % (result_type, ))
         wrapped.func_name = "wrapped_ipf_" + func.func_name
-        functions.append(("c_" + func.func_name, f_ptr, wrapped))
-        return func
+        functions.append((func.func_name, f_ptr, wrapped))
+        return wrapped
     return decorator
 
 @expose_on_virtual_machine_proxy([], int)
@@ -1005,8 +1005,7 @@
 # ##############################################################################
 
 VirtualMachine = lltype.Struct("VirtualMachine",
-        *map(lambda x: (x[0], x[1]), functions),
-        hints={'c_name': 'VirtualMachine'})
+        *map(lambda x: (x[0], x[1]), functions))
 VMPtr = Ptr(VirtualMachine)
 
 proxy_functions = unrolling_iterable(functions)
@@ -1023,6 +1022,10 @@
 
 # rffi.llexternal is supposed to represent c-functions.
 
+func_str_void = Ptr(FuncType([], sqStr))
+func_bool_vm = Ptr(FuncType([VMPtr], sqInt))
+func_bool_void = Ptr(FuncType([], sqInt))
+
 class _InterpreterProxy(object):
     _immutable_fields_ = ['vm_initialized?']
 
@@ -1032,6 +1035,7 @@
         self._next_oop = 0
         self.oop_map = {}
         self.object_map = {}
+        self.loaded_modules = {}
         self.remappable_objects = []
         self.reset()
 
@@ -1043,6 +1047,30 @@
         self.fail_reason = 0
 
     def call(self, signature, interp, s_frame, argcount, s_method):
+        from rpython.rlib.rdynload import dlsym
+        self.initialize_from_call(signature, interp, s_frame, argcount, s_method)
+        try:
+            if signature[0] not in self.loaded_modules:
+                module = self.load_and_initialize(signature[0])
+                print "Successfully loaded: %s" % signature[0]
+            else:
+                module = self.loaded_modules[signature[0]]
+
+            # call the correct function in it...
+            try:
+                _external_function = dlsym(module, signature[1])
+            except KeyError:
+                self.failed()
+            else:
+                external_function = rffi.cast(func_bool_void, _external_function)
+                external_function()
+
+            if not self.fail_reason == 0:
+                raise error.PrimitiveFailedError
+        finally:
+            self.reset()
+
+    def initialize_from_call(self, signature, interp, s_frame, argcount, s_method):
         self.interp = interp
         self.s_frame = s_frame
         self.argcount = argcount
@@ -1050,14 +1078,6 @@
         self.space = interp.space
         # ensure that space.w_nil gets the first possible oop
         self.object_to_oop(self.space.w_nil)
-        try:
-            # Load the correct DLL
-            self.failed()
-            # call the correct function in it...
-            if not self.fail_reason == 0:
-                raise error.PrimitiveFailedError
-        finally:
-            self.reset()
 
     def failed(self, reason=1):
         assert reason != 0
@@ -1094,6 +1114,57 @@
         self.remappable_objects.append(w_object)
         return w_object
 
+    def top_remappable(self):
+        if len(self.remappable_objects) == 0:
+            raise ProxyFunctionFailed
+        return self.remappable_objects[-1]
+
+    def load_and_initialize(self, module_name):
+        from rpython.rlib.rdynload import dlopen, dlsym, dlclose, DLOpenError
+        import os
+        c_name = rffi.str2charp(os.path.join(IProxy.space.executable_path(), module_name))
+        try:
+            module = dlopen(c_name)
+        except DLOpenError, e:
+            print "Missing library: %s" % e
+            raise error.PrimitiveFailedError
+        try:
+            try:
+                _getModuleName = dlsym(module, "getModuleName")
+            except KeyError:
+                pass # the method does not need to exist
+            else:
+                getModuleName = rffi.cast(func_str_void, _getModuleName)
+                if not rffi.charp2str(getModuleName()).startswith(module_name):
+                    raise error.PrimitiveFailedError
+
+            try:
+                _setInterpreter = dlsym(module, "setInterpreter")
+            except KeyError:
+                raise error.PrimitiveFailedError
+            else:
+                setInterpreter = rffi.cast(func_bool_vm, _setInterpreter)
+                if not setInterpreter(sqGetInterpreterProxy()):
+                    print "Failed setting interpreter on: %s" % module_name
+                    raise error.PrimitiveFailedError
+
+            try:
+                _initialiseModule = dlsym(module, "initialiseModule")
+            except KeyError:
+                pass # the method does not need to exist
+            else:
+                initialiseModule = rffi.cast(func_bool_void, _initialiseModule)
+                if not initialiseModule():
+                    print "Failed initialization of: %s" % module_name
+                    raise error.PrimitiveFailedError
+
+            self.loaded_modules[module_name] = module
+            return module
+        except error.PrimitiveFailedError:
+            dlclose(module)
+            raise
+
+
 IProxy = _InterpreterProxy()
 
 # # Class extensions for Array conversion
diff --git a/spyvm/objspace.py b/spyvm/objspace.py
--- a/spyvm/objspace.py
+++ b/spyvm/objspace.py
@@ -1,15 +1,40 @@
+import os
+
 from spyvm import constants, model, shadow, wrapper
 from spyvm.error import UnwrappingError, WrappingError, PrimitiveFailedError
-from rpython.rlib import jit
+from rpython.rlib import jit, rpath
 from rpython.rlib.objectmodel import instantiate, specialize
 from rpython.rlib.rarithmetic import intmask, r_uint, int_between
 
 class ObjSpace(object):
     def __init__(self):
         self.classtable = {}
+        self._executable_path = [""] # XXX: we cannot set the attribute
+                                  # directly on the frozen objectspace
         self.make_bootstrap_classes()
         self.make_bootstrap_objects()
 
+    def find_executable(self, executable):
+        if os.sep in executable or (os.name == "nt" and ":" in executable):
+            return executable
+        path = os.environ.get("PATH")
+        if path:
+            for dir in path.split(os.pathsep):
+                f = os.path.join(dir, executable)
+                if os.path.isfile(f):
+                    executable = f
+                    break
+        return rpath.rabspath(executable)
+
+    def runtime_setup(self, executable):
+        fullpath = rpath.rabspath(self.find_executable(executable))
+        i = fullpath.rfind(os.path.sep) + 1
+        assert i > 0
+        self._executable_path[0] = fullpath[:i]
+
+    def executable_path(self):
+        return self._executable_path[0]
+
     def make_bootstrap_classes(self):
         def define_core_cls(name, w_superclass, w_metaclass):
             assert name.startswith('w_')
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -839,9 +839,9 @@
         raise PrimitiveFailedError
     signature = (w_modulename.as_string(), w_functionname.as_string())
 
-    if signature == ('BitBltPlugin', 'primitiveCopyBits'):
-        return prim_holder.prim_table[BITBLT_COPY_BITS](interp, s_frame, argcount, s_method)
-    elif signature[0] == "SocketPlugin":
+    # if signature == ('BitBltPlugin', 'primitiveCopyBits'):
+    #     return prim_holder.prim_table[BITBLT_COPY_BITS](interp, s_frame, argcount, s_method)
+    if signature[0] == "SocketPlugin":
         from spyvm.plugins.socket import SocketPlugin
         return SocketPlugin.call(signature[1], interp, s_frame, argcount, s_method)
     elif signature[0] == "FilePlugin":
@@ -994,7 +994,7 @@
 
 @expose_primitive(VM_PATH, unwrap_spec=[object])
 def func(interp, s_frame, w_receiver):
-    return interp.space.wrap_string(os.path.join(os.getcwd(), ''))
+    return interp.space.wrap_string("%s%s" % (interp.space.executable_path(), os.path.sep))
 
 @expose_primitive(SHORT_AT, unwrap_spec=[object, index1_0])
 def func(interp, s_frame, w_receiver, n0):
diff --git a/targetimageloadingsmalltalk.py b/targetimageloadingsmalltalk.py
--- a/targetimageloadingsmalltalk.py
+++ b/targetimageloadingsmalltalk.py
@@ -136,6 +136,7 @@
     image_reader = squeakimage.reader_for_image(space, squeakimage.Stream(data=imagedata))
     image = create_image(space, image_reader)
     interp = interpreter.Interpreter(space, image, image_name=path, trace=trace)
+    space.runtime_setup(argv[0])
     if benchmark is not None:
         return _run_benchmark(interp, number, benchmark)
     else:


More information about the pypy-commit mailing list