[pypy-commit] pypy default: For a "func-in-small-set" attribute, initialize the class vtable to
arigo
pypy.commits at gmail.com
Tue Mar 29 11:32:47 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r83421:1f344b91d8ab
Date: 2016-03-29 17:26 +0200
http://bitbucket.org/pypy/pypy/changeset/1f344b91d8ab/
Log: For a "func-in-small-set" attribute, initialize the class vtable to
'\xff' if there is no corresponding function, instead of the default
of 0 which will map to a random function.
diff --git a/rpython/rtyper/rclass.py b/rpython/rtyper/rclass.py
--- a/rpython/rtyper/rclass.py
+++ b/rpython/rtyper/rclass.py
@@ -310,10 +310,15 @@
# setup class attributes: for each attribute name at the level
# of 'r_parentcls', look up its value in the class
def assign(mangled_name, value):
- if (isinstance(value, Constant) and
- isinstance(value.value, staticmethod)):
- value = Constant(value.value.__get__(42)) # staticmethod => bare function
- llvalue = r.convert_desc_or_const(value)
+ if value is None:
+ llvalue = r.special_uninitialized_value()
+ if llvalue is None:
+ return
+ else:
+ if (isinstance(value, Constant) and
+ isinstance(value.value, staticmethod)):
+ value = Constant(value.value.__get__(42)) # staticmethod => bare function
+ llvalue = r.convert_desc_or_const(value)
setattr(vtable, mangled_name, llvalue)
for fldname in r_parentcls.clsfields:
@@ -321,8 +326,7 @@
if r.lowleveltype is Void:
continue
value = self.classdef.classdesc.read_attribute(fldname, None)
- if value is not None:
- assign(mangled_name, value)
+ assign(mangled_name, value)
# extra PBC attributes
for (access_set, attr), (mangled_name, r) in r_parentcls.pbcfields.items():
if self.classdef.classdesc not in access_set.descs:
@@ -330,8 +334,7 @@
if r.lowleveltype is Void:
continue
attrvalue = self.classdef.classdesc.read_attribute(attr, None)
- if attrvalue is not None:
- assign(mangled_name, attrvalue)
+ assign(mangled_name, attrvalue)
def fill_vtable_root(self, vtable):
"""Initialize the head of the vtable."""
diff --git a/rpython/rtyper/rmodel.py b/rpython/rtyper/rmodel.py
--- a/rpython/rtyper/rmodel.py
+++ b/rpython/rtyper/rmodel.py
@@ -125,6 +125,9 @@
self, value))
return value
+ def special_uninitialized_value(self):
+ return None
+
def get_ll_eq_function(self):
"""Return an eq(x,y) function to use to compare two low-level
values of this Repr.
diff --git a/rpython/rtyper/rpbc.py b/rpython/rtyper/rpbc.py
--- a/rpython/rtyper/rpbc.py
+++ b/rpython/rtyper/rpbc.py
@@ -431,10 +431,14 @@
if isinstance(value, types.MethodType) and value.im_self is None:
value = value.im_func # unbound method -> bare function
if value is None:
+ assert self.descriptions[0] is None
return chr(0)
funcdesc = self.rtyper.annotator.bookkeeper.getdesc(value)
return self.convert_desc(funcdesc)
+ def special_uninitialized_value(self):
+ return chr(0xFF)
+
def dispatcher(self, shape, index, argtypes, resulttype):
key = shape, index, tuple(argtypes), resulttype
if key in self._dispatch_cache:
diff --git a/rpython/rtyper/test/test_rpbc.py b/rpython/rtyper/test/test_rpbc.py
--- a/rpython/rtyper/test/test_rpbc.py
+++ b/rpython/rtyper/test/test_rpbc.py
@@ -1947,6 +1947,30 @@
kwds['config'] = self.config
return TestRPBC.interpret(fn, args, **kwds)
+ def test_class_missing_base_method_should_crash(self):
+ class Base(object):
+ pass # no method 'm' here
+ class A(Base):
+ def m(self):
+ return 42
+ class B(Base):
+ def m(self):
+ return 63
+ def g(n):
+ if n == 1:
+ return A()
+ elif n == 2:
+ return B()
+ else:
+ return Base()
+ def f(n):
+ return g(n).m()
+
+ assert self.interpret(f, [1]) == 42
+ assert self.interpret(f, [2]) == 63
+ e = py.test.raises(ValueError, self.interpret, f, [3])
+ assert str(e.value).startswith(r"exit case '\xff' not found")
+
def test_smallfuncsets_basic():
from rpython.translator.translator import TranslationContext, graphof
from rpython.config.translationoption import get_combined_translation_config
More information about the pypy-commit
mailing list