Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 9 commits
  • 4 files changed
  • 0 commit comments
  • 2 contributors
Commits on Mar 12, 2012
@ltratt A minimal patch to try and (roughly) emulate PyPy's fixed size slots …
…for objects.

As it stands, this patch leads to upto a 10% slowdown.
109051a
Commits on Mar 13, 2012
@ltratt Use fixed size arrays instead of arbitrarily sized lists for extra_sl…
…ots.
55bc446
Commits on Mar 14, 2012
Carl Friedrich Bolz promote the index used to read out of the stack.
this helps inlined functions a lot
b5f80e7
Carl Friedrich Bolz split the Class.instantiated builtin into two parts, one seen by the
JIT (because it has no loop), one not
0f736a6
Carl Friedrich Bolz only cast from float to int if really necessary
the constructor of Con_Int always takes an int now. The caller is
responsible for doing the necessary cast
e8c1f1b
Carl Friedrich Bolz make get_slice not elidable
it does not quite make sense to do so, because get_slice is rarely
called with all constant arguments and in that case the JIT is much
better at optimizing away the content of it, because it can look inside.
82dd10f
@cfbolz cfbolz improve Class.instantiated more
Class.instantiated can be implemented with a subclass check, which is
pure, because the inheritance hierarchy cannot change.
5717e04
@ltratt Merge https://github.com/cfbolz/converge into small_objects 9e0a5f3
@ltratt Minor build fix.
This is needed for (at least) OpenBSD amd64; it may effect other OSs /
architectures too.
bb9f31d
Showing with 116 additions and 60 deletions.
  1. +105 −55 vm/Builtins.py
  2. +4 −3 vm/Modules/Con_Array.py
  3. +2 −2 vm/Modules/Con_C_Time.py
  4. +5 −0 vm/VM.py
View
160 vm/Builtins.py
@@ -125,43 +125,58 @@ def extend(self, n):
return self.other_maps[n]
+ @jit.elidable
+ def size(self):
+ return len(self.index_map)
+
+
_EMPTY_MAP = _Con_Map()
+BASIC_SLOTS_SIZE = 4
+
class Con_Boxed_Object(Con_Object):
- __slots__ = ("instance_of", "slots_map", "slots")
+ __slots__ = ("instance_of", "slots_map", "s1", "s2", "s3", "s4", "extra_slots")
def __init__(self, vm, instance_of=None):
if instance_of is None:
- self.instance_of = vm.get_builtin(BUILTIN_OBJECT_CLASS)
- else:
- self.instance_of = instance_of
+ instance_of = vm.get_builtin(BUILTIN_OBJECT_CLASS)
self.slots_map = _EMPTY_MAP
- self.slots = None
+ self.s1 = self.s2 = self.s3 = self.s4 = None
+ if isinstance(instance_of, Con_Class) and instance_of.extra_slots_size > 0:
+ self.extra_slots = [None] * instance_of.extra_slots_size
+ debug.make_sure_not_resized(self.extra_slots)
+ else:
+ self.extra_slots = None
+ self.instance_of = instance_of
def has_slot(self, vm, n):
- if self.slots is not None:
- m = jit.promote(self.slots_map)
- i = m.find(n)
- if i != -1:
- return True
+ m = jit.promote(self.slots_map)
+ i = m.find(n)
+ if i != -1:
+ return True
return False
def find_slot(self, vm, n):
- o = None
- if self.slots is not None:
- m = jit.promote(self.slots_map)
- i = m.find(n)
- if i != -1:
- o = self.slots[i]
-
- if o is None:
+ m = jit.promote(self.slots_map)
+ i = m.find(n)
+ if i == 0:
+ o = self.s1
+ elif i == 1:
+ o = self.s2
+ elif i == 2:
+ o = self.s3
+ elif i == 3:
+ o = self.s4
+ elif i != -1:
+ o = self.extra_slots[i - BASIC_SLOTS_SIZE]
+ else:
o = self.instance_of.find_field(vm, n)
if o is None:
if n == "instance_of":
@@ -176,14 +191,19 @@ def find_slot(self, vm, n):
def get_slot(self, vm, n):
- o = None
- if self.slots is not None:
- m = jit.promote(self.slots_map)
- i = m.find(n)
- if i != -1:
- o = self.slots[i]
-
- if o is None:
+ m = jit.promote(self.slots_map)
+ i = m.find(n)
+ if i == 0:
+ o = self.s1
+ elif i == 1:
+ o = self.s2
+ elif i == 2:
+ o = self.s3
+ elif i == 3:
+ o = self.s4
+ elif i != -1:
+ o = self.extra_slots[i - BASIC_SLOTS_SIZE]
+ else:
o = self.instance_of.find_field(vm, n)
if o is None:
if n == "instance_of":
@@ -197,20 +217,42 @@ def get_slot(self, vm, n):
return o
-
def set_slot(self, vm, n, o):
assert o is not None
m = jit.promote(self.slots_map)
- if self.slots is not None:
- i = m.find(n)
- if i == -1:
- self.slots_map = m.extend(n)
- self.slots.append(o)
- else:
- self.slots[i] = o
- else:
+ i = m.find(n)
+ if i == -1:
self.slots_map = m.extend(n)
- self.slots = [o]
+ i = self.slots_map.size() - 1
+
+ assert i != -1
+ if i == 0:
+ self.s1 = o
+ elif i == 1:
+ self.s2 = o
+ elif i == 2:
+ self.s3 = o
+ elif i == 3:
+ self.s4 = o
+ else:
+ extra_slots = self.extra_slots
+ off = i - BASIC_SLOTS_SIZE
+ if isinstance(extra_slots, list) and off < len(self.extra_slots):
+ self.extra_slots[off] = o
+ return
+
+ instance_of = self.instance_of
+ assert isinstance(instance_of, Con_Class)
+ if self.extra_slots is None:
+ if instance_of.extra_slots_size == 0:
+ instance_of.extra_slots_size = 1
+ self.extra_slots = [o]
+ debug.make_sure_not_resized(self.extra_slots)
+ else:
+ if instance_of.extra_slots_size == i - BASIC_SLOTS_SIZE:
+ instance_of.extra_slots_size += 1
+ self.extra_slots = self.extra_slots + [o]
+ debug.make_sure_not_resized(self.extra_slots)
def is_(self, o):
@@ -407,7 +449,8 @@ def bootstrap_con_object(vm):
#
class Con_Class(Con_Boxed_Object):
- __slots__ = ("supers", "fields_map", "fields", "new_func", "version", "dependents")
+ __slots__ = ("supers", "fields_map", "fields", "new_func", "version",
+ "dependents", "extra_slots_size")
_immutable_fields = ("supers", "fields", "dependents")
@@ -439,8 +482,9 @@ def __init__(self, vm, name, supers, container, instance_of=None, new_func=None)
self.supers = supers
self.fields_map = _EMPTY_MAP
self.fields = []
+ self.extra_slots_size = 0
- # To optimise slot lookups, we need to be a little more cunning. We make a (reasonable)
+ # To optimise field lookups, we need to be a little more cunning. We make a (reasonable)
# assumption that classes rarely change their fields (most classes never change their fields
# after their initial creation at all), so that in general we can simply elide field
# lookups entirely. When a field is changed, all subsequent field lookups on that class and
@@ -615,24 +659,31 @@ def _Con_Class_instantiated(vm):
assert isinstance(self, Con_Class)
assert isinstance(o, Con_Boxed_Object)
- if o.instance_of is self:
+ jit.promote(self)
+ cls = jit.promote(o.instance_of)
+ if cls is self:
# We optimise the easy case.
return vm.get_builtin(BUILTIN_NULL_OBJ)
- else:
- # What we do now is to put 'instance_of' onto a stack; if the current class on the stack
- # does not match 'self', we push all the class's superclasses onto the stack.
- #
- # If we run off the end of the stack then there is no match.
- stack = [o.instance_of]
- while len(stack) > 0:
- cnd = stack.pop()
- assert isinstance(cnd, Con_Class)
- if cnd is self:
- return vm.get_builtin(BUILTIN_NULL_OBJ)
- stack.extend(cnd.supers)
-
+ elif _Con_Class_is_subclass(self, cls):
+ return vm.get_builtin(BUILTIN_NULL_OBJ)
return vm.get_builtin(BUILTIN_FAIL_OBJ)
+@jit.elidable
+def _Con_Class_is_subclass(self, subcls):
+ # What we do is to put 'subcls' onto a stack; if the current class on the stack
+ # does not match 'self', we push all the class's superclasses onto the stack.
+ #
+ # If we run off the end of the stack then there is no match.
+ stack = [subcls]
+ while len(stack) > 0:
+ cnd = stack.pop()
+ assert isinstance(cnd, Con_Class)
+ if cnd is self:
+ return True
+ stack.extend(cnd.supers)
+
+ return False
+
def bootstrap_con_class(vm):
class_class = vm.get_builtin(BUILTIN_CLASS_CLASS)
@@ -1166,7 +1217,7 @@ def __init__(self, vm, v, instance_of=None):
instance_of = vm.get_builtin(BUILTIN_INT_CLASS)
Con_Number.__init__(self, vm, instance_of)
assert v is not None
- self.v = rffi.cast(lltype.Signed, v)
+ self.v = v
def as_int(self):
@@ -1300,7 +1351,7 @@ def _new_func_Con_Int(vm):
vm.raise_helper("Number_Exception", [o_o])
return Con_Int(vm, v)
elif isinstance(o_o, Con_Float):
- return Con_Int(vm, o_o.v)
+ return Con_Int(vm, int(o_o.v))
else:
vm.raise_helper("Type_Exception", [Con_String(vm, "Number | String"), o_o])
@@ -1776,7 +1827,6 @@ def gt(self, vm, o):
return self.v > o.v
- @jit.elidable
def get_slice(self, vm, i, j):
i, j = translate_slice_idxs(vm, i, j, len(self.v))
return Con_String(vm, self.v[i:j])
View
7 vm/Modules/Con_Array.py
@@ -334,9 +334,10 @@ def _check_room(vm, self, i):
def _get_obj(vm, self, i):
if self.type == TYPE_I64:
- return Con_Int(vm, rffi.cast(rffi.LONGP, self.data)[i])
+ value = rffi.cast(rffi.LONGP, self.data)[i]
+ return Con_Int(vm, rffi.cast(lltype.Signed, value))
elif self.type == TYPE_I32:
- return Con_Int(vm, rffi.cast(rffi.LONG, rffi.cast(rffi.INTP, self.data)[i]))
+ return Con_Int(vm, rffi.cast(lltype.Signed, rffi.cast(rffi.INTP, self.data)[i]))
elif self.type == TYPE_F:
return Con_Float(vm, rffi.cast(rffi.DOUBLE, rffi.cast(rffi.DOUBLEP, self.data)[i]))
else:
@@ -369,4 +370,4 @@ def bootstrap_array_class(vm, mod):
new_c_con_func_for_class(vm, "len_bytes", Array_len_bytes, array_class)
new_c_con_func_for_class(vm, "serialize", Array_serialize, array_class)
new_c_con_func_for_class(vm, "set", Array_set, array_class)
- new_c_con_func_for_class(vm, "to_str", Array_to_str, array_class)
+ new_c_con_func_for_class(vm, "to_str", Array_to_str, array_class)
View
4 vm/Modules/Con_C_Time.py
@@ -81,8 +81,8 @@ def current(vm):
with lltype.scoped_alloc(TIMEVAL) as tp:
if gettimeofday(tp, lltype.nullptr(TIMEZONEP.TO)) != 0:
raise Exception("XXX")
- sec = rarithmetic.r_int(tp.c_tv_sec)
- usec = rarithmetic.r_int(tp.c_tv_usec)
+ sec = int(tp.c_tv_sec)
+ usec = int(tp.c_tv_usec)
return Con_List(vm, [Con_Int(vm, sec), Con_Int(vm, usec * 1000)])
View
5 vm/VM.py
@@ -747,6 +747,7 @@ def _instr_apply(self, instr, cf):
for j in range(0, num_args):
k = i + num_args - j - 1
assert k >= 0
+ jit.promote(k)
new_cf.stack[k] = cf.stack_pop()
new_cf.stackpe = i + num_args
@@ -1167,6 +1168,7 @@ def __init__(self, parent, func, pc, max_stack_size, nargs, bc_off, closure):
def stack_get(self, i):
assert i >= 0
+ jit.promote(i)
return self.stack[i]
@@ -1175,6 +1177,7 @@ def stack_get_slice(self, i, j):
assert i >= 0 and j >= i
l = [None] * (j - i)
a = 0
+ jit.promote(i)
for k in range(i, j):
l[a] = self.stack[k]
a += 1
@@ -1186,6 +1189,7 @@ def stack_get_slice_del(self, i):
assert i >= 0
l = [None] * (self.stackpe - i)
a = 0
+ jit.promote(i)
for k in range(i, self.stackpe):
l[a] = self.stack[k]
self.stack[k] = None
@@ -1196,6 +1200,7 @@ def stack_get_slice_del(self, i):
def stack_set(self, i, o):
assert i >= 0
+ jit.promote(i)
self.stack[i] = o

No commit comments for this range

Something went wrong with that request. Please try again.