[pypy-commit] lang-smalltalk storage-allocRemoval: Added an allocation-removal optimization for W_SmallInteger objects.

anton_gulenko noreply at buildbot.pypy.org
Wed Apr 2 09:44:37 CEST 2014


Author: Anton Gulenko <anton.gulenko at googlemail.com>
Branch: storage-allocRemoval
Changeset: r738:1efa7a6e3ddc
Date: 2014-04-02 09:44 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/1efa7a6e3ddc/

Log:	Added an allocation-removal optimization for W_SmallInteger objects.
	If a small-int is stored into a slot already containing a small-int,
	then the value will just be overwritten, without changing the
	object-reference. This means W_SmallInteger objects are not
	immutable. It also means the JIT can eliminate a lot of allocations.

diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -200,7 +200,6 @@
     # TODO can we tell pypy that its never larger then 31-bit?
     _attrs_ = ['value']
     __slots__ = ('value',)     # the only allowed slot here
-    _immutable_fields_ = ["value"]
     repr_classname = "W_SmallInteger"
     
     def __init__(self, value):
@@ -264,6 +263,18 @@
 
     def clone(self, space):
         return self
+        
+    def store_into_list(w_int, list_of_w_obj, index):
+        """This implements an allocation-removal optimization for Small Integers.
+        If some slot already contains a SmallInt, we simply store the new value.
+        This way, the JIT can eliminate lots of allocations of W_SmallInteger objects.
+        This must be used when storing into regular objects and also the stack/temps of contexts."""
+        # This code is duplicated in ContextPartShadow.stack_put
+        w_old = list_of_w_obj[index]
+        if isinstance(w_old, W_SmallInteger):
+            w_old.value = w_int.value
+        else:
+            list_of_w_obj[index] = W_SmallInteger(w_int.value)
 
 class W_AbstractObjectWithIdentityHash(W_Object):
     """Object with explicit hash (ie all except small
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -229,7 +229,11 @@
     def fetch(self, n0):
         return self.storage[n0]
     def store(self, n0, w_value):
-        self.storage[n0] = w_value
+        assert n0 >= 0
+        if isinstance(w_value, model.W_SmallInteger):
+            model.W_SmallInteger.store_into_list(w_value, self.storage, n0)
+        else:
+            self.storage[n0] = w_value
 
 class WeakListStorageShadow(AbstractStorageShadow):
     _attrs_ = ['storage']
@@ -835,8 +839,18 @@
     def stack_get(self, index0):
         return self._temps_and_stack[index0]
     
-    def stack_put(self, index0, w_val):
-        self._temps_and_stack[index0] = w_val
+    def stack_put(self, index0, w_value):
+        if isinstance(w_value, model.W_SmallInteger):
+            # This code is copied from W_SmallInteger.store_into_list
+            # Cannot use that method, because _temps_and_stack is virtualizable
+            # and is not allowed to be passed around.
+            w_old = self._temps_and_stack[index0]
+            if isinstance(w_old, model.W_SmallInteger):
+                w_old.value = w_value.value
+            else:
+                self._temps_and_stack[index0] = model.W_SmallInteger(w_value.value)
+        else:
+            self._temps_and_stack[index0] = w_value
     
     def stack(self):
         """NOT_RPYTHON""" # purely for testing
diff --git a/spyvm/squeakimage.py b/spyvm/squeakimage.py
--- a/spyvm/squeakimage.py
+++ b/spyvm/squeakimage.py
@@ -217,9 +217,6 @@
         # dictionary mapping old address to chunk object
         self.chunks = {}
         self.chunklist = []
-        # cache wrapper integers
-        self.intcache = {}
-
         self.lastWindowSize = 0
 
     def initialize(self):
@@ -440,12 +437,7 @@
         self.reader = reader
         self.value = value
         self.size = -1
-        if value in reader.intcache:
-            w_int = reader.intcache[value]
-        else:
-            w_int = self.space.wrap_int(value)
-            reader.intcache[value] = w_int
-        self.w_object = w_int
+        self.w_object = self.space.wrap_int(value)
         self.filled_in = True
 
     def initialize(self, chunk, reader):


More information about the pypy-commit mailing list