Author: Tim Felgentreff <[email protected]>
Branch: storage-refactoring-virtual-pc
Changeset: r869:6fb935c7c9b6
Date: 2014-07-03 16:21 +0200
http://bitbucket.org/pypy/lang-smalltalk/changeset/6fb935c7c9b6/
Log: start adding vrefs
diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -26,7 +26,7 @@
_immutable_fields_ = ["space", "image", "image_name",
"max_stack_depth", "interrupt_counter_size",
"startup_time", "evented", "interrupts"]
-
+
jit_driver = jit.JitDriver(
greens=['pc', 'self', 'method'],
reds=['s_context'],
@@ -38,7 +38,7 @@
trace=False, evented=True, interrupts=True,
max_stack_depth=constants.MAX_LOOP_DEPTH):
import time
-
+
# === Initialize immutable variables
self.space = space
self.image = image
@@ -54,7 +54,7 @@
self.interrupt_counter_size = int(os.environ["SPY_ICS"])
except KeyError:
self.interrupt_counter_size = constants.INTERRUPT_COUNTER_SIZE
-
+
# === Initialize mutable variables
self.interrupt_check_counter = self.interrupt_counter_size
self.current_stack_depth = 0
@@ -108,19 +108,25 @@
if jit.we_are_jitted():
self.jitted_check_for_interrupt(s_context)
self.jit_driver.can_enter_jit(pc=pc, self=self, method=method,
s_context=s_context)
-
+
# This is just a wrapper around loop_bytecodes that handles the stack
overflow protection mechanism
def stack_frame(self, s_new_frame, may_context_switch=True,
fresh_context=False):
if self.max_stack_depth > 0:
if self.current_stack_depth >= self.max_stack_depth:
raise StackOverflow(s_new_frame)
-
+
self.current_stack_depth += 1
+ s_sender = s_new_frame.s_sender()
+ assert s_sender
+ s_sender_ref = jit.virtual_ref(s_sender)
+ s_new_frame.store_s_sender(s_sender_ref, raiseError=False)
try:
self.loop_bytecodes(s_new_frame,
may_context_switch=may_context_switch, fresh_context=fresh_context)
finally:
+ jit.virtual_ref_finish(s_sender_ref, s_sender)
+ s_new_frame.restore_s_sender(s_sender)
self.current_stack_depth -= 1
-
+
def step(self, context, pc):
bytecode = context.fetch_bytecode(pc)
pc += 1
@@ -134,9 +140,9 @@
if start <= bytecode <= stop:
return getattr(context, methname)(self, bytecode, pc)
assert False, "unreachable"
-
+
# ============== Methods for handling user interrupts ==============
-
+
def jitted_check_for_interrupt(self, s_frame):
if not self.interrupts:
return
@@ -147,7 +153,7 @@
decr_by = int(trace_length // 100)
decr_by = max(decr_by, 1)
self.quick_check_for_interrupt(s_frame, decr_by)
-
+
def quick_check_for_interrupt(self, s_frame, dec=1):
if not self.interrupts:
return
@@ -183,7 +189,7 @@
return intmask(int((time.time() - self.startup_time) * 1000) &
constants.TAGGED_MASK)
# ============== Convenience methods for executing code ==============
-
+
def interpret_toplevel(self, w_frame):
try:
self.loop(w_frame)
@@ -199,7 +205,7 @@
"asSymbol")
else:
w_selector = selector
-
+
w_method = model.W_CompiledMethod(self.space, header=512)
w_method.literalatput0(self.space, 1, w_selector)
assert len(arguments_w) <= 7
@@ -208,10 +214,10 @@
s_frame = MethodContextShadow(self.space, None, w_method, w_receiver,
[])
s_frame.push(w_receiver)
s_frame.push_all(list(arguments_w))
-
+
self.interrupt_check_counter = self.interrupt_counter_size
return self.interpret_toplevel(s_frame.w_self())
-
+
def padding(self, symbol=' '):
return symbol * self.current_stack_depth
@@ -247,9 +253,20 @@
# jump=True means the pc is changed in an unpredictable way.
# The implementation method must additionally handle the pc.
# needs_pc=True means the bytecode implementation required the pc, but will
not change it.
+
+from rpython.rlib.unroll import SpecTag
+class unrolling_int(int, SpecTag):
+ def __add__(self, other):
+ return unrolling_int(int.__add__(self, other))
+ __radd__ = __add__
+ def __sub__(self, other):
+ return unrolling_int(int.__sub__(self, other))
+ def __rsub__(self, other):
+ return unrolling_int(int.__rsub__(self, other))
+unrolling_zero = unrolling_int(0)
+
def bytecode_implementation(parameter_bytes=0, jump=False, needs_pc=False):
def bytecode_implementation_decorator(actual_implementation_method):
- from rpython.rlib.unroll import unrolling_zero
@jit.unroll_safe
def bytecode_implementation_wrapper(self, interp, current_bytecode,
pc):
parameters = ()
@@ -351,9 +368,9 @@
# __extend__ adds new methods to the ContextPartShadow class
class __extend__(ContextPartShadow):
-
+
# ====== Push/Pop bytecodes ======
-
+
@bytecode_implementation()
def pushReceiverVariableBytecode(self, interp, current_bytecode):
index = current_bytecode & 15
@@ -432,7 +449,7 @@
@bytecode_implementation()
def popStackBytecode(self, interp, current_bytecode):
self.pop()
-
+
@bytecode_implementation(parameter_bytes=1)
def pushNewArrayBytecode(self, interp, current_bytecode, descriptor):
arraySize, popIntoArray = splitter[7, 1](descriptor)
@@ -442,9 +459,9 @@
else:
newArray =
interp.space.w_Array.as_class_get_shadow(interp.space).new(arraySize)
self.push(newArray)
-
+
# ====== Extended Push/Pop bytecodes ======
-
+
def _extendedVariableTypeAndIndex(self, descriptor):
return ((descriptor >> 6) & 3), (descriptor & 63)
@@ -480,16 +497,16 @@
@bytecode_implementation(parameter_bytes=1)
def extendedStoreBytecode(self, interp, current_bytecode, descriptor):
return self._extendedStoreBytecode(interp, current_bytecode,
descriptor)
-
+
@bytecode_implementation(parameter_bytes=1)
def extendedStoreAndPopBytecode(self, interp, current_bytecode,
descriptor):
self._extendedStoreBytecode(interp, current_bytecode, descriptor)
self.pop()
-
+
def _extract_index_and_temps(self, index_in_array, index_of_array):
w_indirectTemps = self.gettemp(index_of_array)
return index_in_array, w_indirectTemps
-
+
@bytecode_implementation(parameter_bytes=2)
def pushRemoteTempLongBytecode(self, interp, current_bytecode,
index_in_array, index_of_array):
index_in_array, w_indirectTemps =
self._extract_index_and_temps(index_in_array, index_of_array)
@@ -527,7 +544,7 @@
copiedValues: copiedValues).
self jump: blockSize
"""
-
+
space = self.space
numArgs, numCopied = splitter[4, 4](descriptor)
blockSize = (j << 8) | i
@@ -536,7 +553,7 @@
self.push(w_closure)
assert blockSize >= 0
return self._jump(blockSize, pc)
-
+
# ====== Helpers for send/return bytecodes ======
def _sendSelfSelector(self, w_selector, argcount, interp):
@@ -558,7 +575,7 @@
w_method = receiverclassshadow.lookup(w_selector)
except MethodNotFound:
return self._doesNotUnderstand(w_selector, argcount, interp,
receiver)
-
+
code = w_method.primitive()
if code:
try:
@@ -579,21 +596,21 @@
def _sendSelfSelectorSpecial(self, interp, selector, numargs):
w_selector = self.space.get_special_selector(selector)
return self._sendSelfSelector(w_selector, numargs, interp)
-
+
def _sendSpecialSelector(self, interp, receiver, special_selector,
w_args=[]):
w_special_selector = self.space.objtable["w_" + special_selector]
s_class = receiver.class_shadow(self.space)
w_method = s_class.lookup(w_special_selector)
s_frame = w_method.create_frame(interp.space, receiver, w_args, self)
-
+
#
######################################################################
if interp.trace:
print '%s %s %s: #%s' % (interp.padding('#'), special_selector,
s_frame.short_str(), w_args)
if not objectmodel.we_are_translated():
import pdb; pdb.set_trace()
-
+
return interp.stack_frame(s_frame)
-
+
def _doesNotUnderstand(self, w_selector, argcount, interp, receiver):
arguments = self.pop_and_return_n(argcount)
w_message_class = self.space.classtable["w_Message"]
@@ -603,7 +620,7 @@
w_message.store(self.space, 0, w_selector)
w_message.store(self.space, 1, self.space.wrap_list(arguments))
self.pop() # The receiver, already known.
-
+
try:
return self._sendSpecialSelector(interp, receiver,
"doesNotUnderstand", [w_message])
except MethodNotFound:
@@ -612,10 +629,10 @@
assert isinstance(s_class, ClassShadow)
print "Missing doesNotUnderstand in hierarchy of %s" %
s_class.getname()
raise
-
+
def _mustBeBoolean(self, interp, receiver):
return self._sendSpecialSelector(interp, receiver, "mustBeBoolean")
-
+
def _call_primitive(self, code, interp, argcount, w_method, w_selector):
# ##################################################################
if interp.trace:
@@ -635,11 +652,11 @@
def _return(self, return_value, interp, s_return_to):
# unfortunately, this assert is not true for some tests. TODO fix this.
# assert self._stack_ptr == self.tempsize()
-
+
# ##################################################################
if interp.trace:
print '%s<- %s' % (interp.padding(), return_value.as_repr_string())
-
+
if s_return_to is None:
# This should never happen while executing a normal image.
raise ReturnFromTopLevel(return_value)
@@ -736,7 +753,7 @@
return self._sendSelfSelector(w_selector, argcount, interp)
# ====== Misc ======
-
+
def _activate_unwind_context(self, interp, current_pc):
# TODO put the constant somewhere else.
# Primitive 198 is used in BlockClosure >> ensure:
@@ -754,11 +771,11 @@
raise nlr
finally:
self.mark_returned()
-
+
@bytecode_implementation()
def unknownBytecode(self, interp, current_bytecode):
raise MissingBytecode("unknownBytecode")
-
+
@bytecode_implementation()
def experimentalBytecode(self, interp, current_bytecode):
raise MissingBytecode("experimentalBytecode")
@@ -775,7 +792,7 @@
else:
w_alternative = interp.space.w_true
w_expected = interp.space.w_false
-
+
# Don't check the class, just compare with only two Boolean instances.
w_bool = self.pop()
if w_expected.is_same_object(w_bool):
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -1290,13 +1290,13 @@
s_new_context = shadow.BlockContextShadow(
interp.space, None, w_method_context, argcnt,
initialip)
return s_new_context.w_self()
-
+
def finalize_block_ctx(interp, s_block_ctx, s_frame):
from spyvm.error import SenderChainManipulation
# Set some fields
s_block_ctx.store_pc(s_block_ctx.initialip())
try:
- s_block_ctx.store_s_sender(s_frame)
+ s_block_ctx.store_s_sender(jit.non_virtual_ref(s_frame))
except SenderChainManipulation, e:
assert e.s_context == s_block_ctx
return s_block_ctx
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -20,7 +20,7 @@
_immutable_fields_ = ['space']
provides_getname = False
repr_classname = "AbstractShadow"
-
+
def __init__(self, space, w_self):
self.space = space
assert w_self is None or isinstance(w_self, model.W_PointersObject)
@@ -34,19 +34,19 @@
return "<%s %s>" % (self.repr_classname, self.getname())
else:
return "<%s>" % self.repr_classname
-
+
def fetch(self, n0):
raise NotImplementedError("Abstract class")
def store(self, n0, w_value):
raise NotImplementedError("Abstract class")
def size(self):
raise NotImplementedError("Abstract class")
-
+
def attach_shadow(self): pass
-
+
def copy_field_from(self, n0, other_shadow):
self.store(n0, other_shadow.fetch(n0))
-
+
# This can be overwritten to change the order of initialization.
def copy_from(self, other_shadow):
assert self.size() == other_shadow.size()
@@ -98,24 +98,24 @@
# Class must provide: wrap, unwrap, nil_value, is_nil_value, wrapper_class
_attrs_ = ['storage']
_immutable_fields_ = ['storage']
-
+
def __init__(self, space, w_self, size):
AbstractStorageShadow.__init__(self, space, w_self, size)
self.storage = [self.nil_value] * size
-
+
def size(self):
return len(self.storage)
-
+
def generalized_strategy_for(self, w_val):
return ListStorageShadow
-
+
def fetch(self, n0):
val = self.storage[n0]
if self.is_nil_value(val):
return self.space.w_nil
else:
return self.wrap(self.space, val)
-
+
def do_store(self, n0, w_val):
if w_val.is_nil(self.space):
self.storage[n0] = self.nil_value
@@ -134,7 +134,7 @@
nil_value = constants.MAXINT
wrapper_class = model.W_SmallInteger
import_from_mixin(AbstractValueOrNilStorageMixin)
-
+
@staticmethod
def static_can_contain(space, w_val):
return _value_or_nil_can_handle(SmallIntegerOrNilStorageShadow, space,
w_val)
@@ -153,7 +153,7 @@
nil_value = sys.float_info.max
wrapper_class = model.W_Float
import_from_mixin(AbstractValueOrNilStorageMixin)
-
+
@staticmethod
def static_can_contain(space, w_val):
return _value_or_nil_can_handle(FloatOrNilStorageShadow, space, w_val)
@@ -193,17 +193,17 @@
if float_can_handle and not
FloatOrNilStorageShadow.static_can_contain(space, w_obj):
float_can_handle = False
specialized_strategies = specialized_strategies - 1
-
+
if specialized_strategies <= 0:
return ListStorageShadow
-
+
if all_nil_can_handle:
return AllNilStorageShadow
if small_int_can_handle:
return SmallIntegerOrNilStorageShadow
if float_can_handle:
return FloatOrNilStorageShadow
-
+
# If this happens, please look for a bug in the code above.
assert False, "No strategy could be found for list..."
@@ -223,7 +223,7 @@
_immutable_fields_ = ['storage']
repr_classname = "ListStorageShadow"
import_from_mixin(ListStorageMixin)
-
+
def initialize_storage(self, size):
self.storage = [self.space.w_nil] * size
def fetch(self, n0):
@@ -236,7 +236,7 @@
_immutable_fields_ = ['storage']
repr_classname = "WeakListStorageShadow"
import_from_mixin(ListStorageMixin)
-
+
def initialize_storage(self, size):
self.storage = [weakref.ref(self.space.w_nil)] * size
def fetch(self, n0):
@@ -245,14 +245,14 @@
def store(self, n0, w_value):
assert w_value is not None
self.storage[n0] = weakref.ref(w_value)
-
+
class AbstractCachingShadow(ListStorageShadow):
_immutable_fields_ = ['version?']
_attrs_ = ['version']
repr_classname = "AbstractCachingShadow"
import_from_mixin(version.VersionMixin)
version = None
-
+
def __init__(self, space, w_self):
ListStorageShadow.__init__(self, space, w_self, 0)
self.changed()
@@ -284,7 +284,7 @@
_s_superclass = _s_methoddict = None
provides_getname = True
repr_classname = "ClassShadow"
-
+
def __init__(self, space, w_self):
self.subclass_s = {}
AbstractCachingShadow.__init__(self, space, w_self)
@@ -305,7 +305,7 @@
# 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)
instsize_lo = (classformat >> 1) & 0x3F
instsize_hi = (classformat >> (9 + 1)) & 0xC0
@@ -313,10 +313,10 @@
# 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:
@@ -356,7 +356,7 @@
return
# Some of the special info has changed -> Switch version.
self.changed()
-
+
def store_w_superclass(self, w_class):
superclass = self._s_superclass
if w_class is None or w_class.is_nil(self.space):
@@ -383,24 +383,24 @@
return
if methoddict: methoddict.s_class = None
self.store_s_methoddict(s_new_methoddict)
-
+
def store_s_methoddict(self, s_methoddict):
s_methoddict.s_class = self
s_methoddict.sync_method_cache()
self._s_methoddict = s_methoddict
-
+
def attach_s_class(self, s_other):
self.subclass_s[s_other] = None
def detach_s_class(self, s_other):
del self.subclass_s[s_other]
-
+
def store_w_name(self, w_name):
if isinstance(w_name, model.W_BytesObject):
self.name = w_name.as_string()
else:
self.name = None
-
+
@jit.unroll_safe
def flush_method_caches(self):
look_in_shadow = self
@@ -497,7 +497,7 @@
self.version = version
for s_class in self.subclass_s:
s_class.superclass_changed(version)
-
+
# _______________________________________________________________
# Methods used only in testing
@@ -532,7 +532,7 @@
_immutable_fields_ = ['invalid?', 's_class']
_attrs_ = ['methoddict', 'invalid', 's_class']
repr_classname = "MethodDictionaryShadow"
-
+
def __init__(self, space, w_self):
self.invalid = True
self.s_class = None
@@ -541,7 +541,7 @@
def update(self):
self.sync_method_cache()
-
+
def find_selector(self, w_selector):
if self.invalid:
return None # we may be invalid if Smalltalk code did not call
flushCache
@@ -593,7 +593,7 @@
class AbstractRedirectingShadow(AbstractShadow):
_attrs_ = ['_w_self_size']
repr_classname = "AbstractRedirectingShadow"
-
+
def __init__(self, space, w_self):
AbstractShadow.__init__(self, space, w_self)
if w_self is not None:
@@ -610,7 +610,7 @@
_attrs_ = ['_s_sender', '_pc', '_temps_and_stack',
'_stack_ptr', 'instances_w']
repr_classname = "ContextPartShadow"
-
+
_virtualizable_ = [
"_s_sender", "_pc",
"_temps_and_stack[*]", "_stack_ptr",
@@ -619,9 +619,9 @@
# ______________________________________________________________________
# Initialization
-
+
def __init__(self, space, w_self):
- self._s_sender = None
+ self._s_sender = jit.vref_None
AbstractRedirectingShadow.__init__(self, space, w_self)
self.instances_w = {}
@@ -630,26 +630,26 @@
AbstractRedirectingShadow.copy_field_from(self, n0, other_shadow)
except error.SenderChainManipulation, e:
assert e.s_context == self
-
+
def copy_from(self, other_shadow):
# Some fields have to be initialized before the rest, to ensure
correct initialization.
privileged_fields = self.fields_to_copy_first()
for n0 in privileged_fields:
self.copy_field_from(n0, other_shadow)
-
+
# Now the temp size will be known.
self.init_stack_and_temps()
-
+
for n0 in range(self.size()):
if n0 not in privileged_fields:
self.copy_field_from(n0, other_shadow)
-
+
def fields_to_copy_first(self):
return []
-
+
# ______________________________________________________________________
# Accessing object fields
-
+
def fetch(self, n0):
if n0 == constants.CTXPART_SENDER_INDEX:
return self.w_sender()
@@ -671,9 +671,9 @@
if n0 == constants.CTXPART_SENDER_INDEX:
assert isinstance(w_value, model.W_PointersObject)
if w_value.is_nil(self.space):
- self._s_sender = None
+ self._s_sender = jit.vref_None
else:
- self.store_s_sender(w_value.as_context_get_shadow(self.space))
+
self.store_s_sender(jit.non_virtual_ref(w_value.as_context_get_shadow(self.space)))
return
if n0 == constants.CTXPART_PC_INDEX:
return self.store_unwrap_pc(w_value)
@@ -688,24 +688,30 @@
else:
# XXX later should store tail out of known context part as well
raise error.WrapperException("Index in context out of bounds")
-
+
# === Sender ===
-
- def store_s_sender(self, s_sender):
- assert s_sender is None or isinstance(s_sender, ContextPartShadow)
+
+ def store_s_sender(self, s_sender, raiseError=True):
+ assert s_sender is jit.vref_None or isinstance(s_sender,
jit.DirectVRef)
self._s_sender = s_sender
- raise error.SenderChainManipulation(self)
-
+ if raiseError:
+ raise error.SenderChainManipulation(self)
+
+ def restore_s_sender(self, s_direct):
+ if self._s_sender is not jit.vref_None:
+ # virtual sender wasn't already cleared by e.g. mark_returned
+ self._s_sender = s_direct
+
def w_sender(self):
if self._s_sender is None:
return self.space.w_nil
return self._s_sender.w_self()
-
+
def s_sender(self):
- return self._s_sender
-
+ return self._s_sender()
+
# === Stack Pointer ===
-
+
def unwrap_store_stackpointer(self, w_sp1):
# the stackpointer in the W_PointersObject starts counting at the
# tempframe start
@@ -724,12 +730,12 @@
def stackdepth(self):
return rarithmetic.intmask(self._stack_ptr)
-
+
def wrap_stackpointer(self):
return self.space.wrap_int(self.stackdepth())
# === Program Counter ===
-
+
def store_unwrap_pc(self, w_pc):
if w_pc.is_nil(self.space):
self.store_pc(-1)
@@ -754,9 +760,9 @@
def store_pc(self, newpc):
assert newpc >= -1
self._pc = newpc
-
+
# === Subclassed accessors ===
-
+
def s_home(self):
raise NotImplementedError()
@@ -765,22 +771,22 @@
def w_receiver(self):
raise NotImplementedError()
-
+
def w_method(self):
raise NotImplementedError()
-
+
def tempsize(self):
raise NotImplementedError()
-
+
def is_closure_context(self):
raise NotImplementedError()
-
+
# === Other properties of Contexts ===
-
+
def mark_returned(self):
self.store_pc(-1)
try:
- self.store_s_sender(None)
+ self.store_s_sender(jit.vref_None)
except error.SenderChainManipulation, e:
assert self == e.s_context
@@ -789,25 +795,25 @@
def external_stackpointer(self):
return self.stackdepth() + self.stackstart()
-
+
def stackend(self):
# XXX this is incorrect when there is subclassing
return self._w_self_size
-
+
def fetch_next_bytecode(self):
pc = jit.promote(self._pc)
assert pc >= 0
self._pc += 1
return self.fetch_bytecode(pc)
-
+
def fetch_bytecode(self, pc):
bytecode = self.w_method().fetch_bytecode(pc)
return ord(bytecode)
-
+
# ______________________________________________________________________
# Temporary Variables
#
- # Every context has it's own stack. BlockContexts share their temps with
+ # Every context has it's own stack. BlockContexts share their temps with
# their home contexts. MethodContexts created from a BlockClosure get their
# temps copied from the closure upon activation. Changes are not
propagated back;
# this is handled by the compiler by allocating an extra Array for temps.
@@ -817,7 +823,7 @@
def settemp(self, index, w_value):
raise NotImplementedError()
-
+
# ______________________________________________________________________
# Stack Manipulation
@@ -831,13 +837,13 @@
for i in range(tempsize):
temps_and_stack[i] = self.space.w_nil
self._stack_ptr = rarithmetic.r_uint(tempsize) # we point after the
last element
-
+
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(self):
"""NOT_RPYTHON""" # purely for testing
return self._temps_and_stack[self.tempsize():self._stack_ptr]
@@ -892,7 +898,7 @@
# ______________________________________________________________________
# Primitive support
-
+
def store_instances_array(self, w_class, match_w):
# used for primitives 77 & 78
self.instances_w[w_class] = match_w
@@ -919,7 +925,7 @@
j += 1
retval += "\n---------------------"
return retval
-
+
def short_str(self):
arg_strings = self.argument_strings()
if len(arg_strings) > 0:
@@ -933,10 +939,10 @@
self.w_receiver().as_repr_string(),
args
)
-
+
def print_stack(self, method=True):
return self.print_padded_stack(method)[1]
-
+
def print_padded_stack(self, method):
padding = ret_str = ''
if self.s_sender() is not None:
@@ -950,9 +956,9 @@
class BlockContextShadow(ContextPartShadow):
_attrs_ = ['_w_home', '_initialip', '_eargc']
repr_classname = "BlockContextShadow"
-
+
# === Initialization ===
-
+
def __init__(self, space, w_self=None, w_home=None, argcnt=0, initialip=0):
self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
creating_w_self = w_self is None
@@ -972,40 +978,40 @@
def fields_to_copy_first(self):
return [ constants.BLKCTX_HOME_INDEX ]
-
+
# === Implemented accessors ===
-
+
def s_home(self):
return self._w_home.as_methodcontext_get_shadow(self.space)
-
+
def stackstart(self):
return constants.BLKCTX_STACK_START
def tempsize(self):
# A blockcontext doesn't have any temps
return 0
-
+
def w_receiver(self):
return self.s_home().w_receiver()
-
+
def w_method(self):
retval = self.s_home().w_method()
assert isinstance(retval, model.W_CompiledMethod)
return retval
-
+
def is_closure_context(self):
return True
-
+
# === Temporary variables ===
-
+
def gettemp(self, index):
return self.s_home().gettemp(index)
def settemp(self, index, w_value):
self.s_home().settemp(index, w_value)
-
+
# === Accessing object fields ===
-
+
def fetch(self, n0):
if n0 == constants.BLKCTX_HOME_INDEX:
return self._w_home
@@ -1025,11 +1031,11 @@
return self.unwrap_store_eargc(w_value)
else:
return ContextPartShadow.store(self, n0, w_value)
-
+
def store_w_home(self, w_home):
assert isinstance(w_home, model.W_PointersObject)
self._w_home = w_home
-
+
def unwrap_store_initialip(self, w_value):
initialip = self.space.unwrap_int(w_value)
initialip -= 1 + self.w_method().literalsize
@@ -1037,7 +1043,7 @@
def store_initialip(self, initialip):
self._initialip = initialip
-
+
def wrap_initialip(self):
initialip = self.initialip()
initialip += 1 + self.w_method().literalsize
@@ -1045,7 +1051,7 @@
def initialip(self):
return self._initialip
-
+
def unwrap_store_eargc(self, w_value):
self.store_expected_argument_count(self.space.unwrap_int(w_value))
@@ -1059,24 +1065,24 @@
self._eargc = argc
# === Stack Manipulation ===
-
+
def reset_stack(self):
self.pop_n(self.stackdepth())
# === Printing ===
-
+
def argument_strings(self):
return []
-
+
def method_str(self):
return '[] in %s' % self.w_method().get_identifier_string()
class MethodContextShadow(ContextPartShadow):
_attrs_ = ['closure', '_w_receiver', '_w_method']
repr_classname = "MethodContextShadow"
-
+
# === Initialization ===
-
+
@jit.unroll_safe
def __init__(self, space, w_self=None, w_method=None, w_receiver=None,
arguments=None, s_sender=None, closure=None,
pc=0):
@@ -1085,7 +1091,7 @@
self.store_w_receiver(w_receiver)
self.store_pc(pc)
self.closure = closure
-
+
if w_method:
self.store_w_method(w_method)
# The summand is needed, because we calculate i.a. our stackdepth
relative of the size of w_self.
@@ -1094,29 +1100,29 @@
self.init_stack_and_temps()
else:
self._w_method = None
-
+
if s_sender:
try:
- self.store_s_sender(s_sender)
+ self.store_s_sender(jit.non_virtual_ref(s_sender))
except error.SenderChainManipulation, e:
assert self == e.s_context
-
+
if arguments:
argc = len(arguments)
for i0 in range(argc):
self.settemp(i0, arguments[i0])
else:
argc = 0
-
+
if closure:
for i0 in range(closure.size()):
self.settemp(i0+argc, closure.at0(i0))
def fields_to_copy_first(self):
return [ constants.MTHDCTX_METHOD, constants.MTHDCTX_CLOSURE_OR_NIL ]
-
+
# === Accessing object fields ===
-
+
def fetch(self, n0):
if n0 == constants.MTHDCTX_METHOD:
return self.w_method()
@@ -1150,12 +1156,12 @@
return self.settemp(temp_i, w_value)
else:
return ContextPartShadow.store(self, n0, w_value)
-
+
def store_w_receiver(self, w_receiver):
self._w_receiver = w_receiver
-
+
# === Implemented Accessors ===
-
+
def s_home(self):
if self.is_closure_context():
# this is a context for a blockClosure
@@ -1168,31 +1174,31 @@
return s_outerContext.s_home()
else:
return self
-
+
def stackstart(self):
return constants.MTHDCTX_TEMP_FRAME_START
-
+
def store_w_method(self, w_method):
assert isinstance(w_method, model.W_CompiledMethod)
self._w_method = w_method
def w_receiver(self):
return self._w_receiver
-
+
def w_method(self):
retval = self._w_method
assert isinstance(retval, model.W_CompiledMethod)
return retval
-
+
def tempsize(self):
if not self.is_closure_context():
return self.w_method().tempsize()
else:
return self.closure.tempsize()
-
+
def is_closure_context(self):
return self.closure is not None
-
+
# ______________________________________________________________________
# Marriage of MethodContextShadows with PointerObjects only when required
@@ -1209,9 +1215,9 @@
self._w_self = w_self
self._w_self_size = w_self.size()
return w_self
-
+
# === Temporary variables ===
-
+
def gettemp(self, index0):
return self.stack_get(index0)
@@ -1219,7 +1225,7 @@
self.stack_put(index0, w_value)
# === Printing ===
-
+
def argument_strings(self):
argcount = self.w_method().argsize
tempsize = self.w_method().tempsize()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit