Author: Anton Gulenko <[email protected]>
Branch: storage
Changeset: r775:493897022dac
Date: 2014-04-04 16:59 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/493897022dac/
Log: Small consistency fixed in W_CompiledMethod and ClassShadow,
regarding versioning. Made sure that each time a variable guarded by
@constant_for_version is changed, self.changed() is called. Using
jit.elide_promoted() for @constant_for_version. Added descriptive
funtion name.
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -16,7 +16,7 @@
"""
import sys, weakref
from spyvm import constants, error, version, storage_statistics
-from spyvm.version import elidable_for_version, constant_for_version
+from spyvm.version import elidable_for_version, constant_for_version,
constant_for_version_arg
from rpython.rlib import rrandom, objectmodel, jit, signature
from rpython.rlib.rarithmetic import intmask, r_uint, r_int
@@ -1164,6 +1164,8 @@
header (4 bytes)
literals (4 bytes each)
bytecodes (variable)
+
+ An optional method trailer can be part of the bytecodes part.
"""
repr_classname = "W_CompiledMethod"
@@ -1176,22 +1178,12 @@
# Additional info about the method
"_likely_methodname", "w_compiledin" ]
-### Extension from Squeak 3.9 doc, which we do not implement:
-### trailer (variable)
-### The trailer has two variant formats. In the first variant, the last
-### byte is at least 252 and the last four bytes represent a source pointer
-### into one of the sources files (see #sourcePointer). In the second
-### variant, the last byte is less than 252, and the last several bytes
-### are a compressed version of the names of the method's temporary
-### variables. The number of bytes used for this purpose is the value of
-### the last byte in the method.
-
_likely_methodname = "<unknown>"
import_from_mixin(version.VersionMixin)
def __init__(self, space, bytecount=0, header=0):
+ self.bytes = ["\x00"] * bytecount
self.setheader(space, header)
- self.bytes = ["\x00"] * bytecount
def fillin(self, space, g_self):
# Implicitely sets the header, including self.literalsize
@@ -1200,7 +1192,7 @@
self.setbytes(g_self.get_bytes()[self.bytecodeoffset():])
# === Setters ===
-
+
def setheader(self, space, header):
_primitive, literalsize, islarge, tempsize, argsize =
constants.decode_compiled_method_header(header)
self.literalsize = literalsize
@@ -1215,15 +1207,15 @@
def setliteral(self, index, w_lit):
self.literals[index] = w_lit
- self.changed()
if index == len(self.literals):
self.w_compiledin = None
+ self.changed()
def setliterals(self, literals):
"""NOT RPYTHON""" # Only for testing, not safe.
self.literals = literals
+ self.w_compiledin = None
self.changed()
- self.w_compiledin = None
def setbytes(self, bytes):
self.bytes = bytes
@@ -1262,7 +1254,7 @@
def getheader(self):
return self.header
- @constant_for_version
+ @constant_for_version_arg
def getliteral(self, index):
return self.literals[index]
@@ -1276,7 +1268,7 @@
# mc for methods with islarge flag turned on 32
return 16 + self.islarge * 40 + self.argsize
- @constant_for_version
+ @constant_for_version_arg
def getbytecode(self, pc):
assert pc >= 0 and pc < len(self.bytes)
return self.bytes[pc]
@@ -1368,6 +1360,7 @@
copy = W_CompiledMethod(space, 0, self.getheader())
copy.bytes = list(self.bytes)
copy.literals = list(self.literals)
+ copy.changed()
return copy
def invariant(self):
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -1,6 +1,6 @@
import sys, weakref
from spyvm import model, constants, error, wrapper, version
-from spyvm.version import elidable_for_version, constant_for_version
+from spyvm.version import elidable_for_version, constant_for_version,
constant_for_version_arg
from rpython.tool.pairtype import extendabletype
from rpython.rlib import rarithmetic, objectmodel, jit, longlong2float
from rpython.rlib.objectmodel import import_from_mixin
@@ -305,14 +305,18 @@
# In Slang the value is read directly as a boxed integer, so that
# the code gets a "pointer" whose bits are set as above, but
# shifted one bit to the left and with the lowest bit set to 1.
-
- # compute the instance size (really the size, not the number of
bytes)
+
+ # Compute the instance size (really the size, not the number of
bytes)
instsize_lo = (classformat >> 1) & 0x3F
instsize_hi = (classformat >> (9 + 1)) & 0xC0
self._instance_size = (instsize_lo | instsize_hi) - 1 # subtract
hdr
# decode the instSpec
format = (classformat >> 7) & 15
self.instance_varsized = format >= 2
+
+ # In case of raised exception below.
+ self.changed()
+
if format < 4:
self.instance_kind = POINTERS
elif format == 4:
@@ -470,14 +474,16 @@
# _______________________________________________________________
# Other Methods
- @constant_for_version
+ @constant_for_version_arg
def lookup(self, w_selector):
look_in_shadow = self
while look_in_shadow is not None:
w_method = look_in_shadow.s_methoddict().find_selector(w_selector)
if w_method is not None:
# Old images don't store compiledin-info in literals.
- w_method.w_compiledin = look_in_shadow.w_self()
+ if not w_method.w_compiledin:
+ w_method.w_compiledin = look_in_shadow.w_self()
+ w_method.changed()
return w_method
look_in_shadow = look_in_shadow._s_superclass
raise MethodNotFound(self, w_selector)
diff --git a/spyvm/version.py b/spyvm/version.py
--- a/spyvm/version.py
+++ b/spyvm/version.py
@@ -17,13 +17,24 @@
# be used in situations where the receiver is very unlikely to change in the
same
# context of the interpreted program (like classes or compiled methods).
def constant_for_version(func):
- @jit.elidable
- def elidable_func(self, version, *args):
- return func(self, *args)
- def meth(self, *args):
- self = jit.promote(self)
- version = jit.promote(self.version)
- return elidable_func(self, version, *args)
+ def versioned_func(self, version):
+ return func(self)
+ versioned_func.func_name = "constant_" + func.func_name
+ elidable_func = jit.elidable_promote()(versioned_func)
+ def meth(self):
+ return elidable_func(self, self.version)
+ meth.func_name = "constant_meth_" + func.func_name
+ return meth
+
+# Same as constant_for_version, but allows for one additional argument.
+def constant_for_version_arg(func):
+ def versioned_func(self, version, arg):
+ return func(self, arg)
+ versioned_func.func_name = "constant_" + func.func_name
+ elidable_func = jit.elidable_promote()(versioned_func)
+ def meth(self, arg):
+ return elidable_func(self, self.version, arg)
+ meth.func_name = "constant_meth_" + func.func_name
return meth
class Version(object):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit