[pypy-commit] lang-smalltalk default: huge refactoring: remove the storage of the current frame on the interpreter.

cfbolz noreply at buildbot.pypy.org
Sat Feb 23 12:45:45 CET 2013


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: 
Changeset: r92:91aa1165c8e2
Date: 2013-02-23 12:45 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/91aa1165c8e2/

Log:	huge refactoring: remove the storage of the current frame on the
	interpreter. instead, just hand it around as an argument/result
	everywhere. this is a bit annoying in places, but makes the
	generated JIT code much better.

	 - the bytecode implementations now return the new frame, if they
	set one up
	 - the primitives now get and return a frame

diff too long, truncating to 2000 out of 2377 lines

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -33,24 +33,13 @@
     )
     
     def __init__(self, space, image=None, image_name=""):
-        self._w_active_context = None
         self.space = space
         self.image = image
         self.image_name = image_name
 
-    def w_active_context(self):
-        return self._w_active_context
-
-    def store_w_active_context(self, w_context):
-        assert isinstance(w_context, model.W_PointersObject)
-        self._w_active_context = w_context
-
-    def s_active_context(self):
-        return self.w_active_context().as_context_get_shadow(self.space)
-
-    def interpret(self):
+    def interpret_with_w_frame(self, w_frame):
         try:
-            self.loop()
+            self.loop(w_frame)
         except ReturnFromTopLevel, e:
             return e.object
 
@@ -61,10 +50,8 @@
             return conftest.option.bc_trace
         return conftest.option.prim_trace
 
-    def step(self, s_active_context=None):
+    def step(self, s_active_context):
         """NOT_RPYTHON: only for testing"""
-        if s_active_context is None:         # tests only
-            s_active_context = self.s_active_context()
         next = s_active_context.getbytecode()
         bytecodeimpl = BYTECODE_TABLE[next]
 
@@ -89,18 +76,20 @@
                 s_active_context.pc(),
                 next, bytecodeimpl.__name__,)
 
-        bytecodeimpl(s_active_context, self, next)
+        return bytecodeimpl(s_active_context, self, next)
 
-    def loop(self):
+    def loop(self, w_active_context):
+        s_active_context = w_active_context.as_context_get_shadow(self.space)
         while True:
-            s_active_context = self.s_active_context()
             pc = s_active_context._pc
             method = s_active_context.method()
 
             self.jit_driver.jit_merge_point(
                 pc=pc, self=self, method=method,
                 s_active_context=s_active_context)
-            self.step(s_active_context)
+            w_new_context = self.step(s_active_context)
+            if w_new_context is not None:
+                s_active_context = w_new_context.as_context_get_shadow(self.space)
 
     def perform(self, w_receiver, selector, *arguments_w):
         if selector == "asSymbol":
@@ -111,9 +100,8 @@
         w_method = s_class.lookup(w_selector)
         assert w_method
         w_frame = w_method.create_frame(self.space, w_receiver, list(arguments_w))
-        self.store_w_active_context(w_frame)
         try:
-            self.loop()
+            self.loop(w_frame)
         except ReturnFromTopLevel, e:
             return e.object
 
@@ -134,11 +122,10 @@
         # XXX move next line out of callPrimitive?
         func = primitives.prim_table[primitive]
         try:
-            func(interp, argcount)
-            return
+            return func(interp, self, argcount)
         except primitives.PrimitiveFailedError:
             pass
-        self._sendSelfSelectorSpecial(selector, argcount, interp)
+        return self._sendSelfSelectorSpecial(selector, argcount, interp)
     return callPrimitive
 
 # ___________________________________________________________________________
@@ -213,19 +200,19 @@
     def sendLiteralSelectorBytecode(self, interp, current_bytecode):
         w_selector = self.method().getliteral(current_bytecode & 15)
         argcount = ((current_bytecode >> 4) & 3) - 1
-        self._sendSelfSelector(w_selector, argcount, interp)
+        return self._sendSelfSelector(w_selector, argcount, interp)
 
     def _sendSelfSelector(self, w_selector, argcount, interp):
         receiver = self.peek(argcount)
-        self._sendSelector(w_selector, argcount, interp,
-                           receiver, receiver.shadow_of_my_class(self.space))
+        return self._sendSelector(w_selector, argcount, interp,
+                                  receiver, receiver.shadow_of_my_class(self.space))
 
     def _sendSuperSelector(self, w_selector, argcount, interp):
         w_compiledin = self.method().w_compiledin
         assert isinstance(w_compiledin, model.W_PointersObject)
         s_compiledin = w_compiledin.as_class_get_shadow(self.space)
-        self._sendSelector(w_selector, argcount, interp, self.w_receiver(),
-                           s_compiledin.s_superclass())
+        return self._sendSelector(w_selector, argcount, interp, self.w_receiver(),
+                                  s_compiledin.s_superclass())
 
     def _sendSelector(self, w_selector, argcount, interp,
                       receiver, receiverclassshadow):
@@ -247,50 +234,48 @@
                 for i, func in primitives.unrolling_prim_table:
                     if i == code:
                         try:
-                            func(interp, argcount)
-                            return
+                            return func(interp, self, argcount)
                         except primitives.PrimitiveFailedError:
                             break
             else:
                 func = primitives.prim_table[code]
                 try:
                     # note: argcount does not include rcvr
-                    func(interp, argcount)
-                    return
+                    return func(interp, self, argcount)
                 except primitives.PrimitiveFailedError:
                     if interp.should_trace(True):
                         print "PRIMITIVE FAILED: %d %s" % (method.primitive, w_selector.as_string(),)
                     pass # ignore this error and fall back to the Smalltalk version
         arguments = self.pop_and_return_n(argcount)
-        frame = method.create_frame(self.space, receiver, arguments,
-                                    self.w_self())
+        w_frame = method.create_frame(self.space, receiver, arguments,
+                                      self.w_self())
         self.pop()
-        interp.store_w_active_context(frame)
+        return w_frame
 
     def _return(self, object, interp, w_return_to):
         # for tests, when returning from the top-level context
         if w_return_to.is_same_object(self.space.w_nil):
             raise ReturnFromTopLevel(object)
         w_return_to.as_context_get_shadow(self.space).push(object)
-        interp.store_w_active_context(w_return_to)
+        return w_return_to
 
     def returnReceiver(self, interp, current_bytecode):
-        self._return(self.w_receiver(), interp, self.s_home().w_sender())
+        return self._return(self.w_receiver(), interp, self.s_home().w_sender())
 
     def returnTrue(self, interp, current_bytecode):
-        self._return(interp.space.w_true, interp, self.s_home().w_sender())
+        return self._return(interp.space.w_true, interp, self.s_home().w_sender())
 
     def returnFalse(self, interp, current_bytecode):
-        self._return(interp.space.w_false, interp, self.s_home().w_sender())
+        return self._return(interp.space.w_false, interp, self.s_home().w_sender())
 
     def returnNil(self, interp, current_bytecode):
-        self._return(interp.space.w_nil, interp, self.s_home().w_sender())
+        return self._return(interp.space.w_nil, interp, self.s_home().w_sender())
 
     def returnTopFromMethod(self, interp, current_bytecode):
-        self._return(self.top(), interp, self.s_home().w_sender())
+        return self._return(self.top(), interp, self.s_home().w_sender())
 
     def returnTopFromBlock(self, interp, current_bytecode):
-        self._return(self.top(), interp, self.w_sender())
+        return self._return(self.top(), interp, self.w_sender())
 
     def unknownBytecode(self, interp, current_bytecode):
         raise MissingBytecode("unknownBytecode")
@@ -339,7 +324,7 @@
 
     def singleExtendedSendBytecode(self, interp, current_bytecode):
         w_selector, argcount = self.getExtendedSelectorArgcount()
-        self._sendSelfSelector(w_selector, argcount, interp)
+        return self._sendSelfSelector(w_selector, argcount, interp)
 
     def doubleExtendedDoAnythingBytecode(self, interp, current_bytecode):
         second = self.getbytecode()
@@ -347,12 +332,12 @@
         opType = second >> 5
         if opType == 0:
             # selfsend
-            self._sendSelfSelector(self.method().getliteral(third),
-                                   second & 31, interp)
+            return self._sendSelfSelector(self.method().getliteral(third),
+                                          second & 31, interp)
         elif opType == 1:
             # supersend
-            self._sendSuperSelector(self.method().getliteral(third),
-                                    second & 31, interp)
+            return self._sendSuperSelector(self.method().getliteral(third),
+                                           second & 31, interp)
         elif opType == 2:
             # pushReceiver
             self.push(self.w_receiver().fetch(self.space, third))
@@ -375,13 +360,13 @@
 
     def singleExtendedSuperBytecode(self, interp, current_bytecode):
         w_selector, argcount = self.getExtendedSelectorArgcount()
-        self._sendSuperSelector(w_selector, argcount, interp)
+        return self._sendSuperSelector(w_selector, argcount, interp)
 
     def secondExtendedSendBytecode(self, interp, current_bytecode):
         descriptor = self.getbytecode()
         w_selector = self.method().getliteral(descriptor & 63)
         argcount = descriptor >> 6
-        self._sendSelfSelector(w_selector, argcount, interp)
+        return self._sendSelfSelector(w_selector, argcount, interp)
 
     def popStackBytecode(self, interp, current_bytecode):
         self.pop()
@@ -506,33 +491,33 @@
         # n.b.: depending on the type of the receiver, this may invoke
         # primitives.AT, primitives.STRING_AT, or something else for all
         # I know.
-        self._sendSelfSelectorSpecial("at:", 1, interp)
+        return self._sendSelfSelectorSpecial("at:", 1, interp)
 
     def bytecodePrimAtPut(self, interp, current_bytecode):
         # n.b. as above
-        self._sendSelfSelectorSpecial("at:put:", 2, interp)
+        return self._sendSelfSelectorSpecial("at:put:", 2, interp)
 
     def bytecodePrimSize(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("size", 0, interp)
+        return self._sendSelfSelectorSpecial("size", 0, interp)
 
     def bytecodePrimNext(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("next", 0, interp)
+        return self._sendSelfSelectorSpecial("next", 0, interp)
 
     def bytecodePrimNextPut(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("nextPut:", 1, interp)
+        return self._sendSelfSelectorSpecial("nextPut:", 1, interp)
 
     def bytecodePrimAtEnd(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("atEnd", 0, interp)
+        return self._sendSelfSelectorSpecial("atEnd", 0, interp)
 
     def bytecodePrimEquivalent(self, interp, current_bytecode):
         # short-circuit: classes cannot override the '==' method,
         # which cannot fail
-        primitives.prim_table[primitives.EQUIVALENT](interp, 1)
+        primitives.prim_table[primitives.EQUIVALENT](interp, self, 1)
 
     def bytecodePrimClass(self, interp, current_bytecode):
         # short-circuit: classes cannot override the 'class' method,
         # which cannot fail
-        primitives.prim_table[primitives.CLASS](interp, 0)
+        primitives.prim_table[primitives.CLASS](interp, self, 0)
 
 
     bytecodePrimBlockCopy = make_call_primitive_bytecode(primitives.BLOCK_COPY, "blockCopy:", 1)
@@ -540,19 +525,19 @@
     bytecodePrimValueWithArg = make_call_primitive_bytecode(primitives.VALUE, "value:", 1)
 
     def bytecodePrimDo(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("do:", 1, interp)
+        return self._sendSelfSelectorSpecial("do:", 1, interp)
 
     def bytecodePrimNew(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("new", 0, interp)
+        return self._sendSelfSelectorSpecial("new", 0, interp)
 
     def bytecodePrimNewWithArg(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("new:", 1, interp)
+        return self._sendSelfSelectorSpecial("new:", 1, interp)
 
     def bytecodePrimPointX(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("x", 0, interp)
+        return self._sendSelfSelectorSpecial("x", 0, interp)
 
     def bytecodePrimPointY(self, interp, current_bytecode):
-        self._sendSelfSelectorSpecial("y", 0, interp)
+        return self._sendSelfSelectorSpecial("y", 0, interp)
 
 BYTECODE_RANGES = [
             (  0,  15, "pushReceiverVariableBytecode"),
@@ -680,7 +665,7 @@
         cond = " or ".join(["bytecode == %s" % (i, )
                                 for i in numbers])
         code.append("    %sif %s:" % (prefix, cond, ))
-        code.append("        context.%s(self, bytecode)" % (entry[-1], ))
+        code.append("        return context.%s(self, bytecode)" % (entry[-1], ))
         prefix = "el"
     code.append("bytecode_step_translated._always_inline_ = True")
     source = py.code.Source("\n".join(code))
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -26,7 +26,7 @@
 # arguments, an interp and an argument_count
 # completes, and returns a result, or throws a PrimitiveFailedError.
 def make_failing(code):
-    def raise_failing_default(interp, argument_count):
+    def raise_failing_default(interp, s_frame, argument_count):
 #        print "Primitive failed", code
         raise PrimitiveFailedError
     return raise_failing_default
@@ -43,7 +43,7 @@
 index1_0 = object()
 char = object()
 
-def expose_primitive(code, unwrap_spec=None, no_result=False):
+def expose_primitive(code, unwrap_spec=None, no_result=False, result_is_new_frame=False):
     # some serious magic, don't look
     from rpython.rlib.unroll import unrolling_iterable
     # heuristics to give it a nice name
@@ -56,6 +56,7 @@
             else:
                 name = key
 
+    assert not (no_result and result_is_new_frame)
     # Because methods always have a receiver, an unwrap_spec of [] is a bug
     assert unwrap_spec is None or unwrap_spec
 
@@ -63,21 +64,20 @@
         assert code not in prim_table
         func.func_name = "prim_" + name
         if unwrap_spec is None:
-            def wrapped(interp, argument_count_m1):
-                w_result = func(interp, argument_count_m1)
+            def wrapped(interp, s_frame, argument_count_m1):
+                w_result = func(interp, s_frame, argument_count_m1)
+                if result_is_new_frame:
+                    return w_result
                 if not no_result:
                     assert w_result is not None
-                    interp.s_active_context().push(w_result)
-                return w_result
+                    s_frame.push(w_result)
         else:
             len_unwrap_spec = len(unwrap_spec)
             assert (len_unwrap_spec == len(inspect.getargspec(func)[0]) + 1,
                     "wrong number of arguments")
             unrolling_unwrap_spec = unrolling_iterable(enumerate(unwrap_spec))
-            def wrapped(interp, argument_count_m1):
+            def wrapped(interp, s_frame, argument_count_m1):
                 argument_count = argument_count_m1 + 1 # to account for the rcvr
-                frame = interp.w_active_context()
-                s_frame = frame.as_context_get_shadow(interp.space)
                 assert argument_count == len_unwrap_spec
                 if s_frame.stackdepth() < len_unwrap_spec:
                     # XXX shouldn't this be a crash instead?
@@ -105,14 +105,15 @@
                     else:
                         raise NotImplementedError(
                             "unknown unwrap_spec %s" % (spec, ))
-                w_result = func(interp, *args)
+                w_result = func(interp, s_frame, *args)
                 # After calling primitive, reload context-shadow in case it
                 # needs to be updated
-                new_s_frame = interp.s_active_context()
-                frame.as_context_get_shadow(interp.space).pop_n(len_unwrap_spec)   # only if no exception occurs!
-                if not no_result:
+                s_frame.pop_n(len_unwrap_spec)   # only if no exception occurs!
+                if result_is_new_frame:
+                    return w_result
+                elif not no_result:
                     assert w_result is not None
-                    new_s_frame.push(w_result)
+                    s_frame.push(w_result)
         wrapped.func_name = "wrap_prim_" + name
         prim_table[code] = wrapped
         prim_table_implemented_only.append((code, wrapped))
@@ -143,7 +144,7 @@
 for (code,op) in math_ops.items():
     def make_func(op):
         @expose_primitive(code, unwrap_spec=[int, int])
-        def func(interp, receiver, argument):
+        def func(interp, s_frame, receiver, argument):
             try:
                 res = rarithmetic.ovfcheck(op(receiver, argument))
             except OverflowError:
@@ -159,14 +160,14 @@
 for (code,op) in bitwise_binary_ops.items():
     def make_func(op):
         @expose_primitive(code, unwrap_spec=[int, int])
-        def func(interp, receiver, argument):
+        def func(interp, s_frame, receiver, argument):
             res = op(receiver, argument)
             return interp.space.wrap_int(res)
     make_func(op)
 
 # #/ -- return the result of a division, only succeed if the division is exact
 @expose_primitive(DIVIDE, unwrap_spec=[int, int])
-def func(interp, receiver, argument):
+def func(interp, s_frame, receiver, argument):
     if argument == 0:
         raise PrimitiveFailedError()
     if receiver % argument != 0:
@@ -175,28 +176,28 @@
 
 # #\\ -- return the remainder of a division
 @expose_primitive(MOD, unwrap_spec=[int, int])
-def func(interp, receiver, argument):
+def func(interp, s_frame, receiver, argument):
     if argument == 0:
         raise PrimitiveFailedError()
     return interp.space.wrap_int(receiver % argument)
 
 # #// -- return the result of a division, rounded towards negative zero
 @expose_primitive(DIV, unwrap_spec=[int, int])
-def func(interp, receiver, argument):
+def func(interp, s_frame, receiver, argument):
     if argument == 0:
         raise PrimitiveFailedError()
     return interp.space.wrap_int(receiver // argument)
     
 # #// -- return the result of a division, rounded towards negative infinite
 @expose_primitive(QUO, unwrap_spec=[int, int])
-def func(interp, receiver, argument):
+def func(interp, s_frame, receiver, argument):
     if argument == 0:
         raise PrimitiveFailedError()
     return interp.space.wrap_int(receiver // argument)
     
 # #bitShift: -- return the shifted value
 @expose_primitive(BIT_SHIFT, unwrap_spec=[int, int])
-def func(interp, receiver, argument):
+def func(interp, s_frame, receiver, argument):
 
     # TODO: 1 << 100 will overflow to 0. Catch this gracefully by Primitive
     # Failing! Use ovfcheck_lfshift
@@ -242,40 +243,40 @@
 for (code,op) in math_ops.items():
     def make_func(op):
         @expose_primitive(code, unwrap_spec=[float, float])
-        def func(interp, v1, v2):
+        def func(interp, s_frame, v1, v2):
             w_res = interp.space.wrap_float(op(v1, v2))
             return w_res
     make_func(op)
 
 @expose_primitive(FLOAT_TRUNCATED, unwrap_spec=[float])
-def func(interp, f): 
+def func(interp, s_frame, f):
     w_res = interp.space.wrap_int(int(f))
     return w_res
 
 @expose_primitive(FLOAT_TIMES_TWO_POWER, unwrap_spec=[float, int])
-def func(interp, rcvr, arg): 
+def func(interp, s_frame, rcvr, arg):
     w_res = interp.space.wrap_float(math.ldexp(rcvr, arg))
     return w_res
 
 @expose_primitive(FLOAT_SQUARE_ROOT, unwrap_spec=[float])
-def func(interp, f): 
+def func(interp, s_frame, f):
     if f < 0.0:
         raise PrimitiveFailedError
     w_res = interp.space.wrap_float(math.sqrt(f))
     return w_res
 
 @expose_primitive(FLOAT_SIN, unwrap_spec=[float])
-def func(interp, f): 
+def func(interp, s_frame, f):
     w_res = interp.space.wrap_float(math.sin(f))
     return w_res
 
 @expose_primitive(FLOAT_ARCTAN, unwrap_spec=[float])
-def func(interp, f): 
+def func(interp, s_frame, f):
     w_res = interp.space.wrap_float(math.atan(f))
     return w_res
 
 @expose_primitive(FLOAT_LOG_N, unwrap_spec=[float])
-def func(interp, f): 
+def func(interp, s_frame, f):
     if f == 0:
         res = -rfloat.INFINITY
     elif f < 0:
@@ -285,14 +286,14 @@
     return interp.space.wrap_float(res)
 
 @expose_primitive(FLOAT_EXP, unwrap_spec=[float])
-def func(interp, f): 
+def func(interp, s_frame, f):
     w_res = interp.space.wrap_float(math.exp(f))
     return w_res
 
 MAKE_POINT = 18
 
 @expose_primitive(MAKE_POINT, unwrap_spec=[int, int])
-def func(interp, x, y):
+def func(interp, s_frame, x, y):
     w_res = interp.space.w_Point.as_class_get_shadow(interp.space).new(2)
     point = wrapper.PointWrapper(interp.space, w_res)
     point.store_x(x)
@@ -315,24 +316,24 @@
 STRING_AT_PUT = 64
 
 @expose_primitive(AT, unwrap_spec=[object, index1_0])
-def func(interp, w_obj, n0):
+def func(interp, s_frame, w_obj, n0):
     n0 = assert_valid_index(interp.space, n0, w_obj)
     return w_obj.at0(interp.space, n0)
 
 @expose_primitive(AT_PUT, unwrap_spec=[object, index1_0, object])
-def func(interp, w_obj, n0, w_val):
+def func(interp, s_frame, w_obj, n0, w_val):
     n0 = assert_valid_index(interp.space, n0, w_obj)
     w_obj.atput0(interp.space, n0, w_val)
     return w_val
 
 @expose_primitive(SIZE, unwrap_spec=[object])
-def func(interp, w_obj):
+def func(interp, s_frame, w_obj):
     if not w_obj.shadow_of_my_class(interp.space).isvariable():
         raise PrimitiveFailedError()
     return interp.space.wrap_int(w_obj.primsize(interp.space))
 
 @expose_primitive(STRING_AT, unwrap_spec=[object, index1_0])
-def func(interp, w_obj, n0):
+def func(interp, s_frame, w_obj, n0):
     n0 = assert_valid_index(interp.space, n0, w_obj)
     # XXX I am not sure this is correct, but it un-breaks translation:
     # make sure that getbyte is only performed on W_BytesObjects
@@ -341,7 +342,7 @@
     return interp.space.wrap_char(w_obj.getchar(n0))
 
 @expose_primitive(STRING_AT_PUT, unwrap_spec=[object, index1_0, object])
-def func(interp, w_obj, n0, w_val):
+def func(interp, s_frame, w_obj, n0, w_val):
     val = interp.space.unwrap_char(w_val)
     n0 = assert_valid_index(interp.space, n0, w_obj)
     if not (isinstance(w_obj, model.W_CompiledMethod) or
@@ -374,13 +375,13 @@
 NEW_METHOD = 79
 
 @expose_primitive(OBJECT_AT, unwrap_spec=[object, index1_0])
-def func(interp, w_rcvr, n0):
+def func(interp, s_frame, w_rcvr, n0):
     if not isinstance(w_rcvr, model.W_CompiledMethod):
         raise PrimitiveFailedError()
     return w_rcvr.literalat0(interp.space, n0)
 
 @expose_primitive(OBJECT_AT_PUT, unwrap_spec=[object, index1_0, object])
-def func(interp, w_rcvr, n0, w_value):
+def func(interp, s_frame, w_rcvr, n0, w_value):
     if not isinstance(w_rcvr, model.W_CompiledMethod):
         raise PrimitiveFailedError()
     #assert_bounds(n0, 0, len(w_rcvr.literals))
@@ -388,7 +389,7 @@
     return w_value
 
 @expose_primitive(NEW, unwrap_spec=[object])
-def func(interp, w_cls):
+def func(interp, s_frame, w_cls):
     assert isinstance(w_cls, model.W_PointersObject)
     s_class = w_cls.as_class_get_shadow(interp.space)
     if s_class.isvariable():
@@ -396,7 +397,7 @@
     return s_class.new()
 
 @expose_primitive(NEW_WITH_ARG, unwrap_spec=[object, int])
-def func(interp, w_cls, size):
+def func(interp, s_frame, w_cls, size):
     assert isinstance(w_cls, model.W_PointersObject)
     s_class = w_cls.as_class_get_shadow(interp.space)
     if not s_class.isvariable():
@@ -404,11 +405,11 @@
     return s_class.new(size)
 
 @expose_primitive(ARRAY_BECOME_ONE_WAY, unwrap_spec=[object, object])
-def func(interp, w_obj1, w_obj2):
+def func(interp, s_frame, w_obj1, w_obj2):
     raise PrimitiveNotYetWrittenError
 
 @expose_primitive(INST_VAR_AT, unwrap_spec=[object, index1_0])
-def func(interp, w_rcvr, n0):
+def func(interp, s_frame, w_rcvr, n0):
     "Fetches a fixed field from the object, and fails otherwise"
     s_class = w_rcvr.shadow_of_my_class(interp.space)
     assert_bounds(n0, 0, s_class.instsize())
@@ -418,7 +419,7 @@
     return w_rcvr.fetch(interp.space, n0)
 
 @expose_primitive(INST_VAR_AT_PUT, unwrap_spec=[object, index1_0, object])
-def func(interp, w_rcvr, n0, w_value):
+def func(interp, s_frame, w_rcvr, n0, w_value):
     "Stores a value into a fixed field from the object, and fails otherwise"
     s_class = w_rcvr.shadow_of_my_class(interp.space)
     assert_bounds(n0, 0, s_class.instsize())
@@ -428,32 +429,32 @@
     return w_value
 
 @expose_primitive(AS_OOP, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     if isinstance(w_rcvr, model.W_SmallInteger):
         raise PrimitiveFailedError()
     return interp.space.wrap_int(w_rcvr.gethash())
 
 @expose_primitive(STORE_STACKP, unwrap_spec=[object, object])
-def func(interp, w_obj1, w_obj2):
+def func(interp, s_frame, w_obj1, w_obj2):
     # This primitive seems to resize the stack.  I don't think this is
     # really relevant in our implementation.
     raise PrimitiveNotYetWrittenError()
 
 @expose_primitive(SOME_INSTANCE, unwrap_spec=[object])
-def func(interp, w_class):
+def func(interp, s_frame, w_class):
     # This primitive returns some instance of the class on the stack.
     # Not sure quite how to do this; maintain a weak list of all
     # existing instances or something?
     raise PrimitiveNotYetWrittenError()
 
 @expose_primitive(NEXT_INSTANCE, unwrap_spec=[object])
-def func(interp, w_obj):
+def func(interp, s_frame, w_obj):
     # This primitive is used to iterate through all instances of a class:
     # it returns the "next" instance after w_obj.
     raise PrimitiveNotYetWrittenError()
 
 @expose_primitive(NEW_METHOD, unwrap_spec=[object, int, int])
-def func(interp, w_class, bytecount, header):
+def func(interp, s_frame, w_class, bytecount, header):
     # We ignore w_class because W_CompiledMethod is special
     w_method = model.W_CompiledMethod(bytecount, header)
     return w_method
@@ -484,19 +485,19 @@
 
 
 @expose_primitive(BE_CURSOR, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     # TODO: Use info from cursor object.
     interp.space.objtable['w_cursor'] = w_rcvr
     return w_rcvr
 
 
 @expose_primitive(BE_DISPLAY, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     interp.space.objtable['w_display'] = w_rcvr
     return w_rcvr
 
 @expose_primitive(SCREEN_SIZE, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     # XXX get the real screen size
     w_res = interp.space.w_Point.as_class_get_shadow(interp.space).new(2)
     point = wrapper.PointWrapper(interp.space, w_res)
@@ -515,27 +516,27 @@
 CHANGE_CLASS = 115      # Blue Book: primitiveOopsLeft
 
 @expose_primitive(EQUIVALENT, unwrap_spec=[object, object])
-def func(interp, w_arg, w_rcvr):
+def func(interp, s_frame, w_arg, w_rcvr):
     return interp.space.wrap_bool(w_arg.is_same_object(w_rcvr))
 
 @expose_primitive(CLASS, unwrap_spec=[object])
-def func(interp, w_obj):
+def func(interp, s_frame, w_obj):
     return w_obj.getclass(interp.space)
 
 @expose_primitive(BYTES_LEFT, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     raise PrimitiveNotYetWrittenError()
 
 @expose_primitive(QUIT, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     raise PrimitiveNotYetWrittenError()
 
 @expose_primitive(EXIT_TO_DEBUGGER, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     raise PrimitiveNotYetWrittenError()
 
 @expose_primitive(CHANGE_CLASS, unwrap_spec=[object, object], no_result=True)
-def func(interp, w_arg, w_rcvr):
+def func(interp, s_frame, w_arg, w_rcvr):
     w_arg_class = w_arg.getclass(interp.space)
     w_rcvr_class = w_rcvr.getclass(interp.space)
 
@@ -572,22 +573,22 @@
 SIGNAL_AT_BYTES_LEFT = 125
 
 @expose_primitive(IMAGE_NAME)
-def func(interp, argument_count):
+def func(interp, s_frame, argument_count):
     if argument_count == 0:
-        interp.s_active_context().pop()
+        s_frame.pop()
         return interp.space.wrap_string(interp.image_name)        
     elif argument_count == 1:
         pass # XXX
     raise PrimitiveFailedError
 
 @expose_primitive(LOW_SPACE_SEMAPHORE, unwrap_spec=[object, object])
-def func(interp, w_reciver, i):
+def func(interp, s_frame, w_reciver, i):
     # dont know when the space runs out
     return w_reciver
 
 
 @expose_primitive(SIGNAL_AT_BYTES_LEFT, unwrap_spec=[object, int])
-def func(interp, w_reciver, i):
+def func(interp, s_frame, w_reciver, i):
     # dont know when the space runs out
     return w_reciver
 
@@ -600,7 +601,7 @@
 CLONE = 148
 
 @expose_primitive(BECOME, unwrap_spec=[object, object])
-def func(interp, w_rcvr, w_new):
+def func(interp, s_frame, w_rcvr, w_new):
     if w_rcvr.size() != w_new.size():
         raise PrimitiveFailedError
     w_lefts = []
@@ -623,13 +624,13 @@
 @expose_primitive(INC_GC, unwrap_spec=[object])
 @expose_primitive(FULL_GC, unwrap_spec=[object])
 @jit.dont_look_inside
-def func(interp, w_arg): # Squeak pops the arg and ignores it ... go figure
+def func(interp, s_frame, w_arg): # Squeak pops the arg and ignores it ... go figure
     from rpython.rlib import rgc
     rgc.collect()
     return fake_bytes_left(interp)
 
 @expose_primitive(CLONE, unwrap_spec=[object])
-def func(interp, w_arg):
+def func(interp, s_frame, w_arg):
     return w_arg.clone(interp.space)
 
 #____________________________________________________________________________
@@ -638,7 +639,7 @@
 SECONDS_CLOCK = 137
 
 @expose_primitive(MILLISECOND_CLOCK, unwrap_spec=[object])
-def func(interp, w_arg):
+def func(interp, s_frame, w_arg):
     import time
     import math
     return interp.space.wrap_int(int(math.fmod(time.time()*1000, constants.TAGGED_MAXINT/2)))
@@ -647,7 +648,7 @@
 secs_between_1901_and_1970 = rarithmetic.r_uint((69 * 365 + 17) * 24 * 3600)
 
 @expose_primitive(SECONDS_CLOCK, unwrap_spec=[object])
-def func(interp, w_arg):
+def func(interp, s_frame, w_arg):
     import time
     sec_since_epoch = rarithmetic.r_uint(time.time())
     sec_since_1901 = sec_since_epoch + secs_between_1901_and_1970
@@ -674,7 +675,7 @@
 
 
 @expose_primitive(DIRECTORY_DELIMITOR, unwrap_spec=[object])
-def func(interp, _):
+def func(interp, s_frame, _):
     import os.path
     return interp.space.wrap_char(os.path.sep)
 
@@ -707,7 +708,7 @@
 for (code,op) in bool_ops.items():
     def make_func(op):
         @expose_primitive(code, unwrap_spec=[int, int])
-        def func(interp, v1, v2):
+        def func(interp, s_frame, v1, v2):
             res = op(v1, v2)
             w_res = interp.space.wrap_bool(res)
             return w_res
@@ -716,7 +717,7 @@
 for (code,op) in bool_ops.items():
     def make_func(op):
         @expose_primitive(code+_FLOAT_OFFSET, unwrap_spec=[float, float])
-        def func(interp, v1, v2):
+        def func(interp, s_frame, v1, v2):
             res = op(v1, v2)
             w_res = interp.space.wrap_bool(res)
             return w_res
@@ -735,14 +736,15 @@
 PUSH_TWO = 263
 
 @expose_primitive(PUSH_SELF, unwrap_spec=[object])
-def func(interp, w_self):
+def func(interp, s_frame, w_self):
     # no-op really
     return w_self
 
 def make_push_const_func(code, name):
     @expose_primitive(code, unwrap_spec=[object])
-    def func(interp, w_ignored):
+    def func(interp, s_frame, w_ignored):
         return getattr(interp.space, name)
+    return func
 
 for (code, name) in [
     (PUSH_TRUE, "w_true"),
@@ -770,8 +772,7 @@
 FLUSH_CACHE = 89
 
 @expose_primitive(BLOCK_COPY, unwrap_spec=[object, int])
-def func(interp, w_context, argcnt):
-    frame = interp.s_active_context()
+def func(interp, s_frame, w_context, argcnt):
 
     # From B.B.: If receiver is a MethodContext, then it becomes
     # the new BlockContext's home context.  Otherwise, the home
@@ -782,31 +783,28 @@
 
     # The block bytecodes are stored inline: so we skip past the
     # byteodes to invoke this primitive to find them (hence +2)
-    initialip = frame.pc() + 2
+    initialip = s_frame.pc() + 2
     w_new_context = shadow.BlockContextShadow.make_context(
         interp.space,
         w_method_context, interp.space.w_nil, argcnt, initialip)
     return w_new_context
 
-def finalize_block_ctx(interp, s_block_ctx, frame):
+def finalize_block_ctx(interp, s_block_ctx, w_frame):
     # Set some fields
     s_block_ctx.store_pc(s_block_ctx.initialip())
-    s_block_ctx.store_w_sender(frame)
-    interp.store_w_active_context(s_block_ctx.w_self())
-    
- at expose_primitive(VALUE, no_result=True)
-def func(interp, argument_count):
+    s_block_ctx.store_w_sender(w_frame)
+    return s_block_ctx.w_self()
+
+ at expose_primitive(VALUE, result_is_new_frame=True)
+def func(interp, s_frame, argument_count):
     # argument_count does NOT include the receiver.
     # This means that for argument_count == 3 the stack looks like:
     #  3      2       1      Top
     #  Rcvr | Arg 0 | Arg1 | Arg 2
     #
-    
-    frame = interp.s_active_context()
-    
     # Validate that we have a block on the stack and that it received
     # the proper number of arguments:
-    w_block_ctx = frame.peek(argument_count)
+    w_block_ctx = s_frame.peek(argument_count)
 
     # XXX need to check this since VALUE is called on all sorts of objects.
     if not w_block_ctx.getclass(interp.space).is_same_object(
@@ -823,18 +821,18 @@
 
     # Initialize the block stack with the arguments that were
     # pushed.  Also pop the receiver.
-    block_args = frame.pop_and_return_n(exp_arg_cnt)
+    block_args = s_frame.pop_and_return_n(exp_arg_cnt)
 
     # Reset stack of blockcontext to []
     s_block_ctx.reset_stack()
     s_block_ctx.push_all(block_args)
 
-    frame.pop()
-    finalize_block_ctx(interp, s_block_ctx, frame.w_self())
-    
+    s_frame.pop()
+    return finalize_block_ctx(interp, s_block_ctx, s_frame.w_self())
+
 @expose_primitive(VALUE_WITH_ARGS, unwrap_spec=[object, list],
-                  no_result=True)
-def func(interp, w_block_ctx, args_w):
+                  result_is_new_frame=True)
+def func(interp, s_frame, w_block_ctx, args_w):
 
     assert isinstance(w_block_ctx, model.W_PointersObject)
     s_block_ctx = w_block_ctx.as_blockcontext_get_shadow(interp.space)
@@ -849,63 +847,63 @@
 
     # XXX Check original logic. Image does not test this anyway
     # because falls back to value + internal implementation
-    finalize_block_ctx(interp, s_block_ctx, interp.w_active_context())
+    return finalize_block_ctx(interp, s_block_ctx, s_frame.w_self())
 
 @expose_primitive(PERFORM)
-def func(interp, argcount):
+def func(interp, s_frame, argcount):
     raise PrimitiveFailedError()
 
 @expose_primitive(PERFORM_WITH_ARGS,
                   unwrap_spec=[object, object, object],
-                  no_result=True)
-def func(interp, w_rcvr, w_sel, w_args):
+                  result_is_new_frame=True)
+def func(interp, s_frame, w_rcvr, w_sel, w_args):
     w_method = w_rcvr.shadow_of_my_class(interp.space).lookup(w_sel)
     assert w_method
 
     w_frame = w_method.create_frame(interp.space, w_rcvr,
         [w_args.fetch(interp.space, i) for i in range(w_args.size())])
 
-    w_frame.as_context_get_shadow(interp.space).store_w_sender(interp.w_active_context())
-    interp.store_w_active_context(w_frame)
+    w_frame.as_context_get_shadow(interp.space).store_w_sender(s_frame.w_self())
+    return w_frame
 
 @expose_primitive(SIGNAL, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     # XXX we might want to disable this check
     if not w_rcvr.getclass(interp.space).is_same_object(
         interp.space.w_Semaphore):
         raise PrimitiveFailedError()
-    wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(interp)
-    return w_rcvr
-    
+    s_frame.push(w_rcvr) # w_rcvr is the result in the old frame
+    return wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(s_frame.w_self())
+
 @expose_primitive(WAIT, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     # XXX we might want to disable this check
     if not w_rcvr.getclass(interp.space).is_same_object(
         interp.space.w_Semaphore):
         raise PrimitiveFailedError()
-    wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(interp)
-    return w_rcvr
-    
- at expose_primitive(RESUME, unwrap_spec=[object])
-def func(interp, w_rcvr,):
+    s_frame.push(w_rcvr) # w_rcvr is the result in the old frame
+    return wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(s_frame.w_self())
+
+ at expose_primitive(RESUME, unwrap_spec=[object], result_is_new_frame=True)
+def func(interp, s_frame, w_rcvr,):
     # XXX we might want to disable this check
     if not w_rcvr.getclass(interp.space).is_same_object(
         interp.space.w_Process):
         raise PrimitiveFailedError()
-    wrapper.ProcessWrapper(interp.space, w_rcvr).resume(interp)
-    return w_rcvr
- 
+    s_frame.push(w_rcvr) # w_rcvr is the result in the old frame
+    return wrapper.ProcessWrapper(interp.space, w_rcvr).resume(s_frame.w_self())
+
 @expose_primitive(SUSPEND, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr, result_is_new_frame=True):
     # XXX we might want to disable this check
     if not w_rcvr.getclass(interp.space).is_same_object(
         interp.space.w_Process):
         raise PrimitiveFailedError()
-    wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(interp)
-    return w_rcvr
- 
+    s_frame.push(w_rcvr) # w_rcvr is the result in the old frame
+    return wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(s_frame.w_self())
+
 @expose_primitive(FLUSH_CACHE, unwrap_spec=[object])
-def func(interp, w_rcvr):
+def func(interp, s_frame, w_rcvr):
     # XXX we currently don't care about bad flushes :) XXX
     # raise PrimitiveNotYetWrittenError()
     return w_rcvr
@@ -924,14 +922,13 @@
 CLOSURE_VALUE_NO_CONTEXT_SWITCH_ = 222
 
 @expose_primitive(CLOSURE_COPY_WITH_COPIED_VALUES, unwrap_spec=[object, int, list])
-def func(interp, outerContext, numArgs, copiedValues):
-    frame = interp.s_active_context()
-    w_context = interp.space.newClosure(outerContext, frame.pc(), 
+def func(interp, s_frame, outerContext, numArgs, copiedValues):
+    w_context = interp.space.newClosure(outerContext, s_frame.pc(),
                                                         numArgs, copiedValues)
     return w_context
 
 
-def activateClosure(interp, w_block, args_w, mayContextSwitch=True):
+def activateClosure(interp, s_frame, w_block, args_w, mayContextSwitch=True):
     space = interp.space
     if not w_block.getclass(space).is_same_object(
             space.w_BlockClosure):
@@ -948,46 +945,46 @@
     # additionally to the smalltalk implementation, this also pushes
     # args and copiedValues
     w_new_frame = block.asContextWithSender(
-                            interp.w_active_context(), args_w)
+                            s_frame.w_self(), args_w)
     w_closureMethod = w_new_frame.get_shadow(space).w_method()
 
     assert isinstance(w_closureMethod, model.W_CompiledMethod)
     assert w_block is not block.outerContext()
 
-    interp.store_w_active_context(w_new_frame)
+    return w_new_frame
 
 
- at expose_primitive(CLOSURE_VALUE, unwrap_spec=[object], no_result=True)
-def func(interp, w_block_closure):
-    activateClosure(interp, w_block_closure, [])
+ at expose_primitive(CLOSURE_VALUE, unwrap_spec=[object], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure):
+    return activateClosure(interp, s_frame, w_block_closure, [])
 
- at expose_primitive(CLOSURE_VALUE_, unwrap_spec=[object, object], no_result=True)
-def func(interp, w_block_closure, w_a0):
-    activateClosure(interp, w_block_closure, [w_a0])
+ at expose_primitive(CLOSURE_VALUE_, unwrap_spec=[object, object], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure, w_a0):
+    return activateClosure(interp, s_frame, w_block_closure, [w_a0])
 
- at expose_primitive(CLOSURE_VALUE_VALUE, unwrap_spec=[object, object, object], no_result=True)
-def func(interp, w_block_closure, w_a0, w_a1):
-    activateClosure(interp, w_block_closure, [w_a0, w_a1])
+ at expose_primitive(CLOSURE_VALUE_VALUE, unwrap_spec=[object, object, object], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure, w_a0, w_a1):
+    return activateClosure(interp, s_frame, w_block_closure, [w_a0, w_a1])
 
- at expose_primitive(CLOSURE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object], no_result=True)
-def func(interp, w_block_closure, w_a0, w_a1, w_a2):
-    activateClosure(interp, w_block_closure, [w_a0, w_a1, w_a2])
+ at expose_primitive(CLOSURE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure, w_a0, w_a1, w_a2):
+    return activateClosure(interp, s_frame, w_block_closure, [w_a0, w_a1, w_a2])
 
- at expose_primitive(CLOSURE_VALUE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object, object], no_result=True)
-def func(interp, w_block_closure, w_a0, w_a1, w_a2, w_a3):
-    activateClosure(interp, w_block_closure, [w_a0, w_a1, w_a2, w_a3])
+ at expose_primitive(CLOSURE_VALUE_VALUE_VALUE_VALUE, unwrap_spec=[object, object, object, object, object], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure, w_a0, w_a1, w_a2, w_a3):
+    return activateClosure(interp, s_frame, w_block_closure, [w_a0, w_a1, w_a2, w_a3])
 
- at expose_primitive(CLOSURE_VALUE_WITH_ARGS, unwrap_spec=[object, list], no_result=True)
-def func(interp, w_block_closure, args_w):
-    activateClosure(interp, w_block_closure, args_w)
+ at expose_primitive(CLOSURE_VALUE_WITH_ARGS, unwrap_spec=[object, list], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure, args_w):
+    return activateClosure(interp, s_frame, w_block_closure, args_w)
 
- at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH, unwrap_spec=[object], no_result=True)
-def func(interp, w_block_closure):
-    activateClosure(interp, w_block_closure, [], mayContextSwitch=False)
+ at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH, unwrap_spec=[object], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure):
+    return activateClosure(interp, s_frame, w_block_closure, [], mayContextSwitch=False)
 
- at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH_, unwrap_spec=[object, object], no_result=True)
-def func(interp, w_block_closure, w_a0):
-    activateClosure(interp, w_block_closure, [w_a0], mayContextSwitch=False)
+ at expose_primitive(CLOSURE_VALUE_NO_CONTEXT_SWITCH_, unwrap_spec=[object, object], result_is_new_frame=True)
+def func(interp, s_frame, w_block_closure, w_a0):
+    return activateClosure(interp, s_frame, w_block_closure, [w_a0], mayContextSwitch=False)
 
 # ___________________________________________________________________________
 # PrimitiveLoadInstVar
@@ -1002,7 +999,7 @@
 for i in range(264, 520):
     def make_prim(i):
         @expose_primitive(i, unwrap_spec=[object])
-        def func(interp, w_object):
+        def func(interp, s_frame, w_object):
             return w_object.fetch(interp.space, i - 264)
     globals()["INST_VAR_AT_%d" % (i-264)] = i
     make_prim(i)
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -502,7 +502,7 @@
 
     def peek(self, idx):
         rpos = rarithmetic.r_uint(idx)
-        return self._temps_and_stack[self._stack_ptr + ~rpos]
+        return self._temps_and_stack[jit.promote(self._stack_ptr) + ~rpos]
 
     @jit.unroll_safe
     def pop_n(self, n):
diff --git a/spyvm/test/jit.py b/spyvm/test/jit.py
--- a/spyvm/test/jit.py
+++ b/spyvm/test/jit.py
@@ -65,9 +65,8 @@
         s_class = w_object.shadow_of_my_class(space)
         w_method = s_class.lookup(w_selector)
         w_frame = w_method.create_frame(space, w_object, [])
-        interp.store_w_active_context(w_frame)
 
         def interp_w():
-            interp.loop()
+            interp.loop(w_frame)
 
         self.meta_interp(interp_w, [], listcomp=True, listops=True, backendopt=True)
diff --git a/spyvm/test/test_interpreter.py b/spyvm/test/test_interpreter.py
--- a/spyvm/test/test_interpreter.py
+++ b/spyvm/test/test_interpreter.py
@@ -5,6 +5,7 @@
 mockclass = objspace.bootstrap_class
 
 space = objspace.ObjSpace()
+interp = interpreter.Interpreter(space)
 
 # expose the bytecode's values as global constants.
 # Bytecodes that have a whole range are exposed as global functions:
@@ -76,7 +77,7 @@
         return lit
     return [fakeliteral(lit) for lit in literals]
 
-def new_interpreter(bytes, receiver=space.w_nil, space=space):
+def new_frame(bytes, receiver=space.w_nil, space=space):
     assert isinstance(bytes, str)
     w_method = model.W_CompiledMethod(len(bytes))
     w_method.islarge = 1
@@ -85,9 +86,7 @@
     w_method.tempsize=8
     w_method.setliterals([model.W_PointersObject(None, 2)])
     w_frame = w_method.create_frame(space, receiver, ["foo", "bar"])
-    interp = interpreter.Interpreter(space)
-    interp.store_w_active_context(w_frame)
-    return interp
+    return w_frame, w_frame.as_context_get_shadow(space)
 
 def test_create_frame():
     w_method = model.W_CompiledMethod(len("hello"))
@@ -108,8 +107,7 @@
     assert s_frame.getbytecode() == ord("l")
 
 def test_push_pop():
-    interp = new_interpreter("")
-    frame = interp.s_active_context()
+    _, frame = new_frame("")
     frame.push(12)
     frame.push(34)
     frame.push(56)
@@ -123,15 +121,15 @@
     assert frame.top() == 12
 
 def test_unknownBytecode():
-    interp = new_interpreter(unknownBytecode)
-    py.test.raises(interpreter.MissingBytecode, interp.interpret)
+    w_frame, s_frame = new_frame(unknownBytecode)
+    py.test.raises(interpreter.MissingBytecode, interp.step, s_frame)
 
 # push bytecodes
 def test_pushReceiverBytecode():
-    interp = new_interpreter(pushReceiverBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().top().is_same_object(
-            interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver())
+    w_frame, s_frame = new_frame(pushReceiverBytecode)
+    interp.step(s_frame)
+    assert s_frame.top().is_same_object(
+            s_frame.w_receiver())
 
 def test_pushReceiverVariableBytecode(bytecode = (pushReceiverVariableBytecode(0) +
                                                   pushReceiverVariableBytecode(1) +
@@ -140,31 +138,33 @@
     w_demo.store(space, 0, "egg")
     w_demo.store(space, 1, "bar")
     w_demo.store(space, 2, "baz")
-    interp = new_interpreter(bytecode, receiver = w_demo)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == ["egg", "bar", "baz"]
+    w_frame, s_frame = new_frame(bytecode, receiver = w_demo)
+    s_frame = w_frame.as_context_get_shadow(space)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.stack() == ["egg", "bar", "baz"]
 
 def test_pushTemporaryVariableBytecode(bytecode=(pushTemporaryVariableBytecode(0) +
                                                  pushTemporaryVariableBytecode(1) +
                                                  pushTemporaryVariableBytecode(2))):
-    interp = new_interpreter(bytecode)
-    interp.w_active_context().as_methodcontext_get_shadow(space).settemp(2, "temp")
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == ["foo", "bar", "temp"]
+    w_frame, s_frame = new_frame(bytecode)
+    s_frame = w_frame.as_context_get_shadow(space)
+    s_frame.settemp(2, "temp")
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.stack() == ["foo", "bar", "temp"]
 
 def test_pushLiteralConstantBytecode(bytecode=pushLiteralConstantBytecode(0) +
                                               pushLiteralConstantBytecode(1) +
                                               pushLiteralConstantBytecode(2)):
-    interp = new_interpreter(bytecode)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, "a", "b", "c"))
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == [fakesymbol("a"),
+    w_frame, s_frame = new_frame(bytecode)
+    s_frame.w_method().setliterals(fakeliterals(space, "a", "b", "c"))
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.stack() == [fakesymbol("a"),
                                              fakesymbol("b"),
                                              fakesymbol("c")]
 
@@ -172,24 +172,24 @@
     w_association = mockclass(space, 2).as_class_get_shadow(space).new()
     w_association.store(space, 0, "mykey")
     w_association.store(space, 1, "myvalue")
-    interp = new_interpreter(bytecode)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals( fakeliterals(space, w_association))
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == ["myvalue"]
+    w_frame, s_frame = new_frame(bytecode)
+    s_frame.w_method().setliterals( fakeliterals(space, w_association))
+    interp.step(s_frame)
+    assert s_frame.stack() == ["myvalue"]
 
 def test_storeAndPopReceiverVariableBytecode(bytecode=storeAndPopReceiverVariableBytecode,
                                              popped=True):
     shadow = mockclass(space, 8).as_class_get_shadow(space)
     for index in range(8):
         w_object = shadow.new()
-        interp = new_interpreter(pushConstantTrueBytecode + bytecode(index))
-        interp.w_active_context().as_methodcontext_get_shadow(space).store_w_receiver(w_object)
-        interp.step(interp.s_active_context())
-        interp.step(interp.s_active_context())
+        w_frame, s_frame = new_frame(pushConstantTrueBytecode + bytecode(index))
+        s_frame.store_w_receiver(w_object)
+        interp.step(s_frame)
+        interp.step(s_frame)
         if popped:
-            assert interp.s_active_context().stack() == []
+            assert s_frame.stack() == []
         else:
-            assert interp.s_active_context().stack() == [space.w_true]
+            assert s_frame.stack() == [space.w_true]
 
         for test_index in range(8):
             if test_index == index:
@@ -199,171 +199,170 @@
 
 def test_storeAndPopTemporaryVariableBytecode(bytecode=storeAndPopTemporaryVariableBytecode):
     for index in range(8):
-        interp = new_interpreter(pushConstantTrueBytecode + bytecode(index))
-        #interp.w_active_context().as_methodcontext_get_shadow(space).temps = [None] * 8
-        interp.step(interp.s_active_context())
-        interp.step(interp.s_active_context())
-        assert interp.s_active_context().stack() == []
-        interp.w_active_context().as_methodcontext_get_shadow(space)
+        w_frame, s_frame = new_frame(pushConstantTrueBytecode + bytecode(index))
+        #s_frame.temps = [None] * 8
+        interp.step(s_frame)
+        interp.step(s_frame)
+        assert s_frame.stack() == []
         for test_index in range(8):
-            print interp.w_active_context()._vars
+            print w_frame._vars
             if test_index == index:
-                assert interp.s_active_context().gettemp(test_index) == space.w_true
+                assert s_frame.gettemp(test_index) == space.w_true
             else:
-                assert interp.s_active_context().gettemp(test_index) != space.w_true
+                assert s_frame.gettemp(test_index) != space.w_true
 
 def test_pushConstantTrueBytecode():
-    interp = new_interpreter(pushConstantTrueBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().is_same_object(space.w_true)
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantTrueBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop().is_same_object(space.w_true)
+    assert s_frame.stack() == []
 
 def test_pushConstantFalseBytecode():
-    interp = new_interpreter(pushConstantFalseBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().is_same_object(space.w_false)
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantFalseBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop().is_same_object(space.w_false)
+    assert s_frame.stack() == []
 
 def test_pushConstantNilBytecode():
-    interp = new_interpreter(pushConstantNilBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().is_same_object(space.w_nil)
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantNilBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop().is_same_object(space.w_nil)
+    assert s_frame.stack() == []
 
 def test_pushConstantMinusOneBytecode():
-    interp = new_interpreter(pushConstantMinusOneBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().is_same_object(space.w_minus_one)
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantMinusOneBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop().is_same_object(space.w_minus_one)
+    assert s_frame.stack() == []
 
 def test_pushConstantZeroBytecode():
-    interp = new_interpreter(pushConstantZeroBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().is_same_object(space.w_zero)
-    assert interp.s_active_context().stack() == []
-    
+    w_frame, s_frame = new_frame(pushConstantZeroBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop().is_same_object(space.w_zero)
+    assert s_frame.stack() == []
+
 def test_pushConstantOneBytecode():
-    interp = new_interpreter(pushConstantOneBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().is_same_object(space.w_one)
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantOneBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop().is_same_object(space.w_one)
+    assert s_frame.stack() == []
 
 def test_pushConstantTwoBytecode():
-    interp = new_interpreter(pushConstantTwoBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().is_same_object(space.w_two)
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantTwoBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop().is_same_object(space.w_two)
+    assert s_frame.stack() == []
 
 def test_pushActiveContextBytecode():
-    interp = new_interpreter(pushActiveContextBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop() == interp.w_active_context()
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushActiveContextBytecode)
+    interp.step(s_frame)
+    assert s_frame.pop() == w_frame
+    assert s_frame.stack() == []
     
 def test_duplicateTopBytecode():
-    interp = new_interpreter(pushConstantZeroBytecode + duplicateTopBytecode)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == [space.w_zero, space.w_zero]
+    w_frame, s_frame = new_frame(pushConstantZeroBytecode + duplicateTopBytecode)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.stack() == [space.w_zero, space.w_zero]
     
 def test_bytecodePrimBitAnd():
-    interp = new_interpreter(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitAnd)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == 0
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitAnd)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == 0
+    assert s_frame.stack() == []
     
 def test_bytecodePrimBitOr():
-    interp = new_interpreter(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitOr)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == 3
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitOr)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == 3
+    assert s_frame.stack() == []
 
 def test_bytecodePrimBitShift():
-    interp = new_interpreter(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitShift)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == 4
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitShift)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == 4
+    assert s_frame.stack() == []
     
 def test_bytecodePrimClass():
-    interp = new_interpreter(pushConstantOneBytecode + bytecodePrimClass)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop() == space.w_SmallInteger
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantOneBytecode + bytecodePrimClass)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop() == space.w_SmallInteger
+    assert s_frame.stack() == []
     
 def test_bytecodePrimSubtract():
-    interp = new_interpreter(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimSubtract)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == -1
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimSubtract)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == -1
+    assert s_frame.stack() == []
 
 def test_bytecodePrimMultiply():
-    interp = new_interpreter(pushConstantMinusOneBytecode + pushConstantTwoBytecode + bytecodePrimMultiply)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == -2
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantMinusOneBytecode + pushConstantTwoBytecode + bytecodePrimMultiply)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == -2
+    assert s_frame.stack() == []
     
 def test_bytecodePrimDivide():
-    interp = new_interpreter(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimDivide)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == -2    
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimDivide)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == -2    
+    assert s_frame.stack() == []
     
 def test_bytecodePrimDiv():
-    interp = new_interpreter(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimDiv)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == -2
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimDiv)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == -2
+    assert s_frame.stack() == []
 
 def test_bytecodePrimMod():
-    interp = new_interpreter(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimMod)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop().value == 0
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimMod)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop().value == 0
+    assert s_frame.stack() == []
 
 def test_bytecodePrimEquivalent():
-    interp = new_interpreter(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimEquivalent)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop() == space.w_false
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantTwoBytecode + pushConstantMinusOneBytecode + bytecodePrimEquivalent)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop() == space.w_false
+    assert s_frame.stack() == []
     
-    interp = new_interpreter(pushConstantOneBytecode + pushConstantOneBytecode + bytecodePrimEquivalent)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pop() == space.w_true
-    assert interp.s_active_context().stack() == []
+    w_frame, s_frame = new_frame(pushConstantOneBytecode + pushConstantOneBytecode + bytecodePrimEquivalent)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    assert s_frame.pop() == space.w_true
+    assert s_frame.stack() == []
     
 def test_bytecodePrimNew():
     w_fakeclassclass = mockclass(space, 10, name='fakeclassclass')
     w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=False,
                             w_metaclass=w_fakeclassclass)
-    interp = new_interpreter(bytecodePrimNew)
-    interp.s_active_context().push(w_fakeclass)
+    w_frame, s_frame = new_frame(bytecodePrimNew)
+    s_frame.push(w_fakeclass)
     run_with_faked_primitive_methods(
         [[w_fakeclassclass, primitives.NEW, 0, "new"]],
         interp.step,
-        interp.s_active_context())
-    w_fakeinst = interp.s_active_context().pop()
-    assert interp.s_active_context().stack() == []
+        s_frame)
+    w_fakeinst = s_frame.pop()
+    assert s_frame.stack() == []
     assert w_fakeinst.getclass(space).is_same_object(w_fakeclass)
     assert w_fakeinst.size() == 1
     
@@ -371,29 +370,29 @@
     w_fakeclassclass = mockclass(space, 10, name='fakeclassclass')
     w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=True,
                             w_metaclass=w_fakeclassclass)
-    interp = new_interpreter(bytecodePrimNewWithArg)
-    interp.s_active_context().push(w_fakeclass)
-    interp.s_active_context().push(space.w_two)
+    w_frame, s_frame = new_frame(bytecodePrimNewWithArg)
+    s_frame.push(w_fakeclass)
+    s_frame.push(space.w_two)
     run_with_faked_primitive_methods(
         [[w_fakeclassclass, primitives.NEW_WITH_ARG, 1, "new:"]],
         interp.step,
-        interp.s_active_context())
-    w_fakeinst = interp.s_active_context().pop()
-    assert interp.s_active_context().stack() == []
+        s_frame)
+    w_fakeinst = s_frame.pop()
+    assert s_frame.stack() == []
     assert w_fakeinst.getclass(space).is_same_object(w_fakeclass)
     assert w_fakeinst.size() == 3
  
 def test_bytecodePrimSize():
     w_fakeclass = mockclass(space, 2, name='fakeclass', varsized=True)
     w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(5)
-    interp = new_interpreter(bytecodePrimSize)
-    interp.s_active_context().push(w_fakeinst)
+    w_frame, s_frame = new_frame(bytecodePrimSize)
+    s_frame.push(w_fakeinst)
     run_with_faked_primitive_methods(
         [[w_fakeclass, primitives.SIZE, 0, "size"]],
         interp.step,
-        interp.s_active_context())
-    assert interp.s_active_context().pop().value == 5
-    assert interp.s_active_context().stack() == []
+        s_frame)
+    assert s_frame.pop().value == 5
+    assert s_frame.stack() == []
 
 # w_class - the class from which the method is going to be called
 # (and on which it is going to be installed)
@@ -411,20 +410,21 @@
         literals = fakeliterals(space, "foo")
         w_foo = literals[0]
         shadow.installmethod(w_foo, w_method)
-        interp = new_interpreter(bytecodes)
-        interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(literals)
-        interp.s_active_context().push(w_object)
-        callerContext = interp.w_active_context()
-        interp.step(interp.s_active_context())
-        assert interp.s_active_context().w_sender() == callerContext
-        assert interp.s_active_context().stack() == []
-        assert interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver().is_same_object(w_object)
-        assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method().is_same_object(shadow.s_methoddict().methoddict[w_foo])
-        assert callerContext.as_context_get_shadow(space).stack() == []
-        interp.step(interp.s_active_context())
-        interp.step(interp.s_active_context())
-        assert interp.w_active_context() == callerContext
-        assert interp.s_active_context().stack() == [result]
+        w_frame, s_frame = new_frame(bytecodes)
+        s_frame.w_method().setliterals(literals)
+        s_frame.push(w_object)
+        w_active_context = interp.step(s_frame)
+        s_active_context = w_active_context.as_context_get_shadow(space)
+        assert s_active_context.w_sender() == w_frame
+        assert s_active_context.stack() == []
+        assert w_active_context.as_methodcontext_get_shadow(space).w_receiver().is_same_object(w_object)
+        assert w_active_context.as_methodcontext_get_shadow(space).w_method().is_same_object(shadow.s_methoddict().methoddict[w_foo])
+        assert s_frame.stack() == []
+        interp.step(s_active_context)
+        w_active_context = interp.step(s_active_context)
+        s_active_context = w_active_context.as_context_get_shadow(space)
+        assert w_active_context == w_frame
+        assert s_active_context.stack() == [result]
 
 def test_sendLiteralSelectorBytecode():
     w_class = mockclass(space, 0)
@@ -443,25 +443,24 @@
     method.setliterals(literals)
     shadow.installmethod(literals[0], method)
     w_object = shadow.new()
-    interp = new_interpreter(sendLiteralSelectorBytecode(16) + returnTopFromMethod)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(literals)
-    interp.s_active_context().push(w_object)
-    interp.s_active_context().push(space.wrap_int(8))
-    result = interp.interpret()
+    w_frame, s_frame = new_frame(sendLiteralSelectorBytecode(16) + returnTopFromMethod)
+    s_frame.w_method().setliterals(literals)
+    s_frame.push(w_object)
+    s_frame.push(space.wrap_int(8))
+    result = interp.interpret_with_w_frame(w_frame)
     assert space.unwrap_int(result) == 34
 
 def test_send_to_primitive():
 
     def test():
-        interp = new_interpreter(sendLiteralSelectorBytecode(1 + 16))
-        interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, "foo", "-"))
-        interp.s_active_context().push(space.wrap_int(50))
-        interp.s_active_context().push(space.wrap_int(8))
-        callerContext = interp.w_active_context()
-        interp.step(interp.s_active_context())
-        assert interp.w_active_context() is callerContext
-        assert len(interp.s_active_context().stack()) == 1
-        w_result = interp.s_active_context().pop()
+        w_frame, s_frame = new_frame(sendLiteralSelectorBytecode(1 + 16))
+        s_frame.w_method().setliterals(fakeliterals(space, "foo", "-"))
+        s_frame.push(space.wrap_int(50))
+        s_frame.push(space.wrap_int(8))
+        w_new_frame = interp.step(s_frame)
+        assert w_new_frame is None
+        assert len(s_frame.stack()) == 1
+        w_result = s_frame.pop()
         assert space.unwrap_int(w_result) == 42
         
     run_with_faked_primitive_methods(
@@ -470,72 +469,72 @@
         test)
 
 def test_makePoint():
-    interp = new_interpreter(pushConstantZeroBytecode +
+    w_frame, s_frame = new_frame(pushConstantZeroBytecode +
                              pushConstantOneBytecode +
                              bytecodePrimMakePoint)
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
-    w_point = interp.s_active_context().top()
+    interp.step(s_frame)
+    interp.step(s_frame)
+    interp.step(s_frame)
+    w_point = s_frame.top()
     from spyvm.wrapper import PointWrapper
     point = PointWrapper(interp.space, w_point)
     assert point.x() == 0
     assert point.y() == 1
 
 def test_longJumpIfTrue():
-    interp = new_interpreter(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15))
-    interp.s_active_context().push(space.w_false)
-    pc = interp.s_active_context().pc() + 2
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc
-    interp.s_active_context().push(space.w_true)
-    pc = interp.s_active_context().pc() + 2
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc + 15
+    w_frame, s_frame = new_frame(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15))
+    s_frame.push(space.w_false)
+    pc = s_frame.pc() + 2
+    interp.step(s_frame)
+    assert s_frame.pc() == pc
+    s_frame.push(space.w_true)
+    pc = s_frame.pc() + 2
+    interp.step(s_frame)
+    assert s_frame.pc() == pc + 15
 
 def test_longJumpIfFalse():
-    interp = new_interpreter(pushConstantTrueBytecode + longJumpIfFalse(0) + chr(15) +
+    w_frame, s_frame = new_frame(pushConstantTrueBytecode + longJumpIfFalse(0) + chr(15) +
                              pushConstantFalseBytecode + longJumpIfFalse(0) + chr(15))
-    interp.step(interp.s_active_context())
-    pc = interp.s_active_context().pc() + 2
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc
-    interp.step(interp.s_active_context())
-    pc = interp.s_active_context().pc() + 2
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc + 15
+    interp.step(s_frame)
+    pc = s_frame.pc() + 2
+    interp.step(s_frame)
+    assert s_frame.pc() == pc
+    interp.step(s_frame)
+    pc = s_frame.pc() + 2
+    interp.step(s_frame)
+    assert s_frame.pc() == pc + 15
 
 def test_longUnconditionalJump():
-    interp = new_interpreter(longUnconditionalJump(4) + chr(15))
-    pc = interp.s_active_context().pc() + 2
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc + 15
+    w_frame, s_frame = new_frame(longUnconditionalJump(4) + chr(15))
+    pc = s_frame.pc() + 2
+    interp.step(s_frame)
+    assert s_frame.pc() == pc + 15
 
 def test_shortUnconditionalJump():
-    interp = new_interpreter(chr(145))
-    pc = interp.s_active_context().pc() + 1
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc + 2
+    w_frame, s_frame = new_frame(chr(145))
+    pc = s_frame.pc() + 1
+    interp.step(s_frame)
+    assert s_frame.pc() == pc + 2
 
 def test_shortConditionalJump():
-    interp = new_interpreter(pushConstantTrueBytecode + shortConditionalJump(3) +
+    w_frame, s_frame = new_frame(pushConstantTrueBytecode + shortConditionalJump(3) +
                              pushConstantFalseBytecode + shortConditionalJump(3))
-    interp.step(interp.s_active_context())
-    pc = interp.s_active_context().pc() + 1
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc
-    interp.step(interp.s_active_context())
-    pc = interp.s_active_context().pc() + 1
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().pc() == pc + 4
+    interp.step(s_frame)
+    pc = s_frame.pc() + 1
+    interp.step(s_frame)
+    assert s_frame.pc() == pc
+    interp.step(s_frame)
+    pc = s_frame.pc() + 1
+    interp.step(s_frame)
+    assert s_frame.pc() == pc + 4
 
 def test_popStackBytecode():
-    interp = new_interpreter(pushConstantTrueBytecode +
+    w_frame, s_frame = new_frame(pushConstantTrueBytecode +
                              popStackBytecode)
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == [space.w_true]
-    interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == []
+    interp.step(s_frame)
+    assert s_frame.stack() == [space.w_true]
+    interp.step(s_frame)
+    assert s_frame.stack() == []
 
 def test_extendedPushBytecode():
     test_pushReceiverVariableBytecode(extendedPushBytecode + chr((0<<6) + 0) +
@@ -556,10 +555,10 @@
     w_association = mockclass(space, 2).as_class_get_shadow(space).new()
     w_association.store(space, 0, "mykey")
     w_association.store(space, 1, "myvalue")
-    interp = new_interpreter(pushConstantOneBytecode + bytecode)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(fakeliterals(space, w_association))
-    interp.step(interp.s_active_context())
-    interp.step(interp.s_active_context())
+    w_frame, s_frame = new_frame(pushConstantOneBytecode + bytecode)
+    s_frame.w_method().setliterals(fakeliterals(space, w_association))
+    interp.step(s_frame)
+    interp.step(s_frame)
     assert w_association.fetch(space, 1).is_same_object(space.w_one)
 
 def test_extendedStoreAndPopBytecode():
@@ -574,7 +573,7 @@
     storeAssociation(extendedStoreAndPopBytecode + chr((3<<6) + 0))
 
 def test_callPrimitiveAndPush_fallback():
-    interp = new_interpreter(bytecodePrimAdd)
+    w_frame, s_frame = new_frame(bytecodePrimAdd)
     shadow = mockclass(space, 0).as_class_get_shadow(space)
     w_method = model.W_CompiledMethod(0)
     w_method.argsize = 1
@@ -586,26 +585,27 @@
     space.w_special_selectors.atput0(space, constants.find_selectorindex("+"), w_symbol)
 
     w_object = shadow.new()
-    interp.s_active_context().push(w_object)
-    interp.s_active_context().push(space.w_one)
-    interp.step(interp.s_active_context())
-    assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method() == shadow.s_methoddict().methoddict[w_symbol]
-    assert interp.s_active_context().w_receiver() is w_object
-    assert interp.w_active_context().as_methodcontext_get_shadow(space).gettemp(0).is_same_object(space.w_one)
-    assert interp.s_active_context().stack() == []
+    s_frame.push(w_object)
+    s_frame.push(space.w_one)
+    w_active_context = interp.step(s_frame)
+    s_active_context = w_active_context.as_context_get_shadow(space)
+    assert w_active_context.as_methodcontext_get_shadow(space).w_method() == shadow.s_methoddict().methoddict[w_symbol]
+    assert s_active_context.w_receiver() is w_object
+    assert w_active_context.as_methodcontext_get_shadow(space).gettemp(0).is_same_object(space.w_one)
+    assert s_active_context.stack() == []
 
 def test_bytecodePrimBool():
-    interp = new_interpreter(bytecodePrimLessThan +
+    w_frame, s_frame = new_frame(bytecodePrimLessThan +
                              bytecodePrimGreaterThan +
                              bytecodePrimLessOrEqual +
                              bytecodePrimGreaterOrEqual +
                              bytecodePrimEqual +
                              bytecodePrimNotEqual)
     for i in range(6):
-        interp.s_active_context().push(space.w_one)
-        interp.s_active_context().push(space.w_two)
-        interp.step(interp.s_active_context())
-    assert interp.s_active_context().stack() == [space.w_true, space.w_false,
+        s_frame.push(space.w_one)
+        s_frame.push(space.w_two)
+        interp.step(s_frame)
+    assert s_frame.stack() == [space.w_true, space.w_false,
                                           space.w_true, space.w_false,
                                           space.w_false, space.w_true]
 
@@ -635,20 +635,23 @@
     w_super.as_class_get_shadow(space).installmethod(foo, meth2)
     meth3 = model.W_CompiledMethod(0)
     w_supersuper.as_class_get_shadow(space).installmethod(foo, meth3)
-    interp = new_interpreter(bytecodes)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(literals)
-    interp.s_active_context().push(w_object)
-    interp.step(interp.s_active_context())
+    w_frame, s_frame = new_frame(bytecodes)
+    s_frame.w_method().setliterals(literals)
+    s_frame.push(w_object)
+    w_active_context = interp.step(s_frame)
+    s_active_context = w_active_context.as_context_get_shadow(space)
     for w_specificclass in [w_super, w_supersuper]:
-        callerContext = interp.w_active_context()
-        interp.step(interp.s_active_context())
-        interp.step(interp.s_active_context())
-        assert interp.s_active_context().w_sender() == callerContext
-        assert interp.s_active_context().stack() == []
-        assert interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver() == w_object
+        w_caller_context = w_active_context
+        s_caller_context = s_active_context
+        interp.step(s_active_context)
+        w_active_context = interp.step(s_active_context)
+        s_active_context = w_active_context.as_context_get_shadow(space)
+        assert s_active_context.w_sender() == w_caller_context
+        assert s_active_context.stack() == []
+        assert w_active_context.as_methodcontext_get_shadow(space).w_receiver() == w_object
         meth = w_specificclass.as_class_get_shadow(space).s_methoddict().methoddict[foo]
-        assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method() == meth
-        assert callerContext.as_context_get_shadow(space).stack() == []
+        assert s_active_context.w_method() == meth
+        assert s_caller_context.stack() == []
 
 def test_secondExtendedSendBytecode():
     w_class = mockclass(space, 0)
@@ -681,9 +684,9 @@
 
 def interpret_bc(bcodes, literals, receiver=space.w_nil):
     bcode = "".join([chr(x) for x in bcodes])
-    interp = new_interpreter(bcode, receiver=receiver)
-    interp.w_active_context().as_methodcontext_get_shadow(space).w_method().setliterals(literals)
-    return interp.interpret()
+    w_frame, s_frame = new_frame(bcode, receiver=receiver)
+    s_frame.w_method().setliterals(literals)
+    return interp.interpret_with_w_frame(w_frame)
 
 # tests: bytecodePrimValue & bytecodePrimValueWithArg
 def test_bc_3_plus_4():
@@ -849,44 +852,39 @@
 
 # Closure Bytecodes
 def test_bc_pushNewArrayBytecode(bytecode=pushNewArrayBytecode):
-    interp = new_interpreter(bytecode + chr(0x83))
-    context = interp.s_active_context()
-    context.push(fakeliterals(space, "egg"))
-    context.push(fakeliterals(space, "bar"))
-    context.push(fakeliterals(space, "baz"))
-    interp.step(interp.s_active_context())
-    array = context.pop()
+    w_frame, s_frame = new_frame(bytecode + chr(0x83))
+    s_frame.push(fakeliterals(space, "egg"))
+    s_frame.push(fakeliterals(space, "bar"))
+    s_frame.push(fakeliterals(space, "baz"))
+    interp.step(s_frame)
+    array = s_frame.pop()
     assert array.at0(space, 0) == fakeliterals(space, "egg")
     assert array.at0(space, 1) == fakeliterals(space, "bar")
     assert array.at0(space, 2) == fakeliterals(space, "baz")
 
 def test_bc_pushNewArray(bytecode=pushNewArrayBytecode):
-    interp = new_interpreter(bytecode + chr(0x07))
-    context = interp.s_active_context()
-    interp.step(interp.s_active_context())
-    array = context.pop()
+    w_frame, s_frame = new_frame(bytecode + chr(0x07))
+    interp.step(s_frame)
+    array = s_frame.pop()
     assert array.size() == 7
     assert array.at0(space, 0) == space.w_nil
 
 def test_bc_pushRemoteTempLongBytecode(bytecode = pushRemoteTempLongBytecode):
-    interp = new_interpreter(bytecode + chr(0) + chr(0))
-    context = interp.s_active_context()
-    context.push(fakeliterals(space, "jam"))
-    context.settemp(0, space.w_Array.as_class_get_shadow(interp.space).new(2))
-    interp.step(interp.s_active_context())
-    assert context.top() == space.w_nil
+    w_frame, s_frame = new_frame(bytecode + chr(0) + chr(0))
+    s_frame.settemp(0, space.w_Array.as_class_get_shadow(interp.space).new(2))
+    interp.step(s_frame)
+    assert s_frame.top() == space.w_nil
 
 def setupTempArrayAndContext(bytecode):
     # both indizes are 0-relative
-    interp = new_interpreter(bytecode + chr(2) + chr(1))
-    context = interp.s_active_context()
-    context.push(fakeliterals(space, "english"))
-    context.push(fakeliterals(space, "bar"))
+    w_frame, s_frame = new_frame(bytecode + chr(2) + chr(1))
+    s_frame.push(fakeliterals(space, "english"))
+    s_frame.push(fakeliterals(space, "bar"))
     temp_array = space.w_Array.as_class_get_shadow(interp.space).new(3)
     temp_array.atput0(space, 2, fakeliterals(space, "pub"))
-    context.settemp(1, temp_array)
-    interp.step(context)
-    return context, temp_array
+    s_frame.settemp(1, temp_array)
+    interp.step(s_frame)
+    return s_frame, temp_array
 
 def test_bc_pushRemoteTempLongBytecode2(bytecode = pushRemoteTempLongBytecode):
     context, _ = setupTempArrayAndContext(bytecode)
@@ -904,26 +902,24 @@
 
 def test_bc_pushClosureCopyCopied0ValuesBytecode(bytecode = pushClosureCopyCopiedValuesBytecode):
     for i in (0, 0xF0, 0x0FF0, 0xFFF0):
-        interp = new_interpreter(bytecode + chr(2) + chr(i >> 8) + chr(i & 0xFF))
-        context = interp.s_active_context()
-        pc = context.pc()
+        w_frame, s_frame = new_frame(bytecode + chr(2) + chr(i >> 8) + chr(i & 0xFF))
+        pc = s_frame.pc()
         # create/find a method with an appropriate blockClosure
-        interp.step(context)
-        assert context.pc() == pc + 4 + i
-        closure = wrapper.BlockClosureWrapper(space, context.top())
+        interp.step(s_frame)
+        assert s_frame.pc() == pc + 4 + i
+        closure = wrapper.BlockClosureWrapper(space, s_frame.top())
         assert closure.startpc() == pc + 4
-        assert closure.outerContext() is context._w_self
+        assert closure.outerContext() is s_frame._w_self
 
 def test_bc_pushClosureCopyCopied2ValuesBytecode(bytecode = pushClosureCopyCopiedValuesBytecode):
-    interp = new_interpreter(bytecode + chr(0x23) + chr(0) + chr(0))
-    context = interp.s_active_context()
-    context.push("english")
-    context.push("bar")
-    pc = context.pc()
-    interp.step(context)
-    assert context.pc() == pc + 4
-    closure = wrapper.BlockClosureWrapper(space, context.top())
+    w_frame, s_frame = new_frame(bytecode + chr(0x23) + chr(0) + chr(0))
+    s_frame.push("english")
+    s_frame.push("bar")
+    pc = s_frame.pc()
+    interp.step(s_frame)
+    assert s_frame.pc() == pc + 4
+    closure = wrapper.BlockClosureWrapper(space, s_frame.top())
     assert closure.startpc() == pc + 4
-    assert closure.outerContext() is context._w_self
+    assert closure.outerContext() is s_frame._w_self
     assert closure.at0(0) == "english"
     assert closure.at0(1) == "bar"
diff --git a/spyvm/test/test_miniimage.py b/spyvm/test/test_miniimage.py
--- a/spyvm/test/test_miniimage.py
+++ b/spyvm/test/test_miniimage.py
@@ -211,12 +211,11 @@
     py.test.skip("This method actually runs an image. Fails since no graphical primitives yet")
     from spyvm import wrapper
     ap = wrapper.ProcessWrapper(space, wrapper.scheduler(space).active_process())
-    s_ctx = ap.suspended_context().as_methodcontext_get_shadow(space)
+    w_ctx = ap.suspended_context()
     ap.store_suspended_context(space.w_nil)
 
     interp = interpreter.Interpreter(space)
-    interp.store_w_active_context(s_ctx.w_self())
-    interp.interpret()
+    interp.interpret_with_w_frame(w_ctx)
 
 def test_compile_method():
     sourcecode = """fib 


More information about the pypy-commit mailing list