[pypy-svn] r68035 - pypy/trunk/pypy/jit/metainterp

arigo at codespeak.net arigo at codespeak.net
Wed Sep 30 16:20:33 CEST 2009


Author: arigo
Date: Wed Sep 30 16:20:33 2009
New Revision: 68035

Modified:
   pypy/trunk/pypy/jit/metainterp/codewriter.py
   pypy/trunk/pypy/jit/metainterp/pyjitpl.py
Log:
Remove the multiple IndirectCallsets and replace them all
with a single, global dictionary.


Modified: pypy/trunk/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/codewriter.py	Wed Sep 30 16:20:33 2009
@@ -42,35 +42,6 @@
         dump.dump_bytecode(self, file=file)
         print >> file
 
-class IndirectCallset(history.AbstractValue):
-    def __init__(self, codewriter, graphs):
-        self.keys = []
-        self.values = []
-        for graph in graphs:
-            fnptr = codewriter.rtyper.getcallable(graph)
-            fnaddress = codewriter.cpu.ts.cast_fnptr_to_root(fnptr)
-            self.keys.append(fnaddress)
-            self.values.append(codewriter.get_jitcode(graph))
-        self.dict = None
-
-    def bytecode_for_address(self, fnaddress):
-        if we_are_translated():
-            if self.dict is None:
-                # Build the dictionary at run-time.  This is needed
-                # because the keys are function addresses, so they
-                # can change from run to run.
-                self.dict = {}
-                keys = self.keys
-                values = self.values
-                for i in range(len(keys)):
-                    self.dict[keys[i]] = values[i]
-            return self.dict[fnaddress]
-        else:
-            for i in range(len(self.keys)):
-                if fnaddress == self.keys[i]:
-                    return self.values[i]
-            raise KeyError(fnaddress)
-
 class SwitchDict(history.AbstractValue):
     "Get a 'dict' attribute mapping integer values to bytecode positions."
 
@@ -83,7 +54,6 @@
     def __init__(self, metainterp_sd, policy):
         self.all_prebuilt_values = dict_equal_consts()
         self.all_graphs = {}
-        self.all_indirectcallsets = {}
         self.all_methdescrs = {}
         self.all_listdescs = {}
         self.unfinished_graphs = []
@@ -173,14 +143,15 @@
         calldescr = self.cpu.calldescrof(FUNC, tuple(NON_VOID_ARGS), FUNC.RESULT)
         return (cfnptr, calldescr)
 
-    def get_indirectcallset(self, graphs):
-        key = tuple(sorted(graphs))
-        try:
-            result = self.all_indirectcallsets[key]
-        except KeyError:
-            result = self.all_indirectcallsets[key] = \
-                                  IndirectCallset(self, graphs)
-        return result
+    def register_indirect_call_targets(self, op):
+        targets = self.policy.graphs_from(op, self.cpu.supports_floats)
+        assert targets is not None
+        for graph in targets:
+            fnptr = self.rtyper.getcallable(graph)
+            fnaddress = self.cpu.ts.cast_fnptr_to_root(fnptr)
+            jitcode = self.get_jitcode(graph)
+            self.metainterp_sd._register_indirect_call_target(fnaddress,
+                                                              jitcode)
 
     def get_methdescr(self, SELFTYPE, methname, attach_jitcodes):
         # use the type where the method is actually defined as a key. This way
@@ -1097,13 +1068,9 @@
     handle_residual_indirect_call = handle_residual_call
 
     def handle_regular_indirect_call(self, op):
-        targets = self.codewriter.policy.graphs_from(op,
-                                           self.codewriter.cpu.supports_floats)
-        assert targets is not None
+        self.codewriter.register_indirect_call_targets(op)
         self.minimize_variables()
-        indirectcallset = self.codewriter.get_indirectcallset(targets)
         self.emit('indirect_call')
-        self.emit(self.get_position(indirectcallset))
         self.emit(self.var_position(op.args[0]))
         self.emit_varargs([x for x in op.args[1:-1]
                              if x.concretetype is not lltype.Void])

Modified: pypy/trunk/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/pyjitpl.py	Wed Sep 30 16:20:33 2009
@@ -73,11 +73,6 @@
                     args += (bytecode, )
                 elif argspec == "orgpc":
                     args += (orgpc, )
-                elif argspec == "indirectcallset":
-                    indirectcallset = self.load_const_arg()
-                    assert isinstance(indirectcallset,
-                                      codewriter.IndirectCallset)
-                    args += (indirectcallset, )
                 elif argspec == "methdescr":
                     methdescr = self.load_const_arg()
                     assert isinstance(methdescr,
@@ -660,13 +655,12 @@
     def opimpl_residual_call_pure(self, calldescr, varargs):
         self.execute_varargs(rop.CALL_PURE, varargs, descr=calldescr, exc=False)
 
-
-    @arguments("orgpc", "indirectcallset", "box", "varargs")
-    def opimpl_indirect_call(self, pc, indirectcallset, box, varargs):
+    @arguments("orgpc", "box", "varargs")
+    def opimpl_indirect_call(self, pc, box, varargs):
         box = self.implement_guard_value(pc, box)
         cpu = self.metainterp.cpu
         key = cpu.ts.getaddr_for_box(cpu, box)
-        jitcode = indirectcallset.bytecode_for_address(key)
+        jitcode = self.metainterp.staticdata.bytecode_for_address(key)
         f = self.metainterp.newframe(jitcode)
         f.setup_call(varargs)
         return True
@@ -972,6 +966,9 @@
         self.opcode_names = []
         self.opname_to_index = {}
 
+        self.indirectcall_keys = []
+        self.indirectcall_values = []
+
         self.warmrunnerdesc = warmrunnerdesc
         self._op_goto_if_not = self.find_opcode('goto_if_not')
 
@@ -1023,6 +1020,26 @@
             self.portal_graph)
         self._class_sizes = self._codewriter.class_sizes
 
+    def bytecode_for_address(self, fnaddress):
+        if we_are_translated():
+            d = self.globaldata.indirectcall_dict
+            if d is None:
+                # Build the dictionary at run-time.  This is needed
+                # because the keys are function addresses, so they
+                # can change from run to run.
+                d = {}
+                keys = self.indirectcall_keys
+                values = self.indirectcall_values
+                for i in range(len(keys)):
+                    d[keys[i]] = values[i]
+                self.globaldata.indirectcall_dict = d
+            return d[fnaddress]
+        else:
+            for i in range(len(self.indirectcall_keys)):
+                if fnaddress == self.indirectcall_keys[i]:
+                    return self.indirectcall_values[i]
+            raise KeyError(fnaddress)
+
     # ---------- construction-time interface ----------
 
     def _register_opcode(self, opname):
@@ -1033,6 +1050,10 @@
         self.opcode_names.append(opname)
         self.opcode_implementations.append(getattr(MIFrame, name).im_func)
 
+    def _register_indirect_call_target(self, fnaddress, jitcode):
+        self.indirectcall_keys.append(fnaddress)
+        self.indirectcall_values.append(jitcode)
+
     def find_opcode(self, name):
         try:
             return self.opname_to_index[name]
@@ -1054,6 +1075,7 @@
 class MetaInterpGlobalData(object):
     def __init__(self, staticdata):
         self.initialized = False
+        self.indirectcall_dict = None
         #
         state = staticdata.state
         if state is not None:



More information about the Pypy-commit mailing list