[pypy-commit] lang-js default: moved stack into ExecutionContext

stepahn noreply at buildbot.pypy.org
Fri Dec 28 11:32:00 CET 2012


Author: Stephan <stephan at stzal.com>
Branch: 
Changeset: r105:00760baa5669
Date: 2011-07-04 15:52 +0200
http://bitbucket.org/pypy/lang-js/changeset/00760baa5669/

Log:	moved stack into ExecutionContext

diff --git a/js/jscode.py b/js/jscode.py
--- a/js/jscode.py
+++ b/js/jscode.py
@@ -14,7 +14,7 @@
     except IndexError:
         return "???"
 
-jitdriver = JitDriver(greens=['pc', 'self'], reds=['to_pop', 'stack', 'ctx'], get_printable_location = get_printable_location, virtualizables=['stack'])
+jitdriver = JitDriver(greens=['pc', 'self'], reds=['to_pop', 'ctx'], get_printable_location = get_printable_location, virtualizables=['ctx'])
 
 class AlreadyRun(Exception):
     pass
@@ -135,6 +135,21 @@
     def __repr__(self):
         return "\n".join([repr(i) for i in self.opcodes])
 
+ at jit.dont_look_inside
+def _save_stack(ctx, size):
+    old_stack = ctx.stack
+    old_stack_pointer = ctx.stack_pointer
+
+    ctx.stack_pointer = 0
+    ctx.stack = [None] * size
+    return old_stack, old_stack_pointer
+
+ at jit.dont_look_inside
+def _restore_stack(ctx, state):
+    old_stack, old_stack_pointer = state
+    ctx.stack_pointer = old_stack_pointer
+    ctx.stack = old_stack
+
 class JsFunction(object):
     _immutable_fields_ = ["opcodes[*]"]
 
@@ -145,10 +160,12 @@
         self.opcodes = make_sure_not_resized(code)
 
     def run(self, ctx, check_stack=True):
-        from js.utils import Stack
-        stack = Stack(len(self.opcodes) * 2)
+        state = _save_stack(ctx, len(self.opcodes) * 2)
+
         try:
-            return self.run_bytecode(ctx, stack, check_stack)
+            r = self.run_bytecode(ctx, check_stack)
+            _restore_stack(ctx, state)
+            return r
         except ReturnException, e:
             return e.value
 
@@ -156,12 +173,12 @@
         assert pc >= 0
         return self.opcodes[pc]
 
-    def run_bytecode(self, ctx, stack, check_stack=True):
+    def run_bytecode(self, ctx, check_stack=True):
         pc = 0
         to_pop = 0
         try:
             while True:
-                jitdriver.jit_merge_point(pc=pc, stack=stack, self=self, ctx=ctx, to_pop=to_pop)
+                jitdriver.jit_merge_point(pc=pc, self=self, ctx=ctx, to_pop=to_pop)
                 if pc >= len(self.opcodes):
                     break
 
@@ -177,15 +194,15 @@
                 #            assert result is None
                 #            break
                 #else:
-                result = opcode.eval(ctx, stack)
+                result = opcode.eval(ctx)
                 assert result is None
 
                 if isinstance(opcode, BaseJump):
-                    new_pc = opcode.do_jump(stack, pc)
+                    new_pc = opcode.do_jump(ctx, pc)
                     condition = new_pc < pc
                     pc = new_pc
                     if condition:
-                        jitdriver.can_enter_jit(pc=pc, stack=stack, self=self, ctx=ctx, to_pop=to_pop)
+                        jitdriver.can_enter_jit(pc=pc, self=self, ctx=ctx, to_pop=to_pop)
                     continue
                 else:
                     pc += 1
@@ -198,5 +215,5 @@
                 ctx.pop_object()
 
         if check_stack:
-            stack.check()
-        return stack.top()
+            ctx.check_stack()
+        return ctx.top()
diff --git a/js/jsobj.py b/js/jsobj.py
--- a/js/jsobj.py
+++ b/js/jsobj.py
@@ -2,16 +2,18 @@
 from pypy.rpython.lltypesystem import rffi
 from pypy.rlib.rarithmetic import r_uint, intmask, ovfcheck_float_to_int
 from pypy.rlib.rfloat import isnan, isinf, NAN, formatd
-from js.execution import ThrowException, JsTypeError,\
-     RangeError, ReturnException
+from js.execution import ThrowException, JsTypeError, RangeError, ReturnException
+
+from pypy.rlib.jit import hint
+from pypy.rlib import jit, debug
+from js.utils import StackMixin
+
 import string
 DE = 1
 DD = 2
 RO = 4
 IT = 8
 
-from pypy.rlib import jit
-
 class SeePage(NotImplementedError):
     pass
 
@@ -571,7 +573,7 @@
     def __repr__(self):
         return 'W_List(%s)' % (self.list_w,)
 
-class ExecutionContext(object):
+class ExecutionContext(StackMixin):
     def __init__(self, scope, this=None, variable=None,
                     debug=False, jsproperty=None):
         assert scope is not None
@@ -592,6 +594,7 @@
             self.property = jsproperty
         self.local_identifiers = []
         self.local_values = []
+        StackMixin.__init__(self)
 
     def __str__(self):
         return "<ExCtx %s, var: %s>"%(self.scope, self.variable)
diff --git a/js/opcodes.py b/js/opcodes.py
--- a/js/opcodes.py
+++ b/js/opcodes.py
@@ -12,7 +12,7 @@
     def __init__(self):
         pass
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         """ Execute in context ctx
         """
         raise NotImplementedError
@@ -21,43 +21,43 @@
         return self.__class__.__name__
 
 class BaseBinaryComparison(Opcode):
-    def eval(self, ctx, stack):
-        s4 = stack.pop()
-        s2 = stack.pop()
-        stack.append(self.decision(ctx, s2, s4))
+    def eval(self, ctx):
+        s4 = ctx.pop()
+        s2 = ctx.pop()
+        ctx.append(self.decision(ctx, s2, s4))
 
     def decision(self, ctx, op1, op2):
         raise NotImplementedError
 
 class BaseBinaryBitwiseOp(Opcode):
-    def eval(self, ctx, stack):
-        s5 = stack.pop().ToInt32(ctx)
-        s6 = stack.pop().ToInt32(ctx)
-        stack.append(self.operation(ctx, s5, s6))
+    def eval(self, ctx):
+        s5 = ctx.pop().ToInt32(ctx)
+        s6 = ctx.pop().ToInt32(ctx)
+        ctx.append(self.operation(ctx, s5, s6))
 
     def operation(self, ctx, op1, op2):
         raise NotImplementedError
 
 class BaseBinaryOperation(Opcode):
-    def eval(self, ctx, stack):
-        right = stack.pop()
-        left = stack.pop()
-        stack.append(self.operation(ctx, left, right))
+    def eval(self, ctx):
+        right = ctx.pop()
+        left = ctx.pop()
+        ctx.append(self.operation(ctx, left, right))
 
 class BaseUnaryOperation(Opcode):
     pass
 
 class Undefined(Opcode):
-    def eval(self, ctx, stack):
-        stack.append(w_Undefined)
+    def eval(self, ctx):
+        ctx.append(w_Undefined)
 
 class LOAD_INTCONSTANT(Opcode):
     _immutable_fields_ = ['w_intvalue']
     def __init__(self, value):
         self.w_intvalue = W_IntNumber(int(value))
 
-    def eval(self, ctx, stack):
-        stack.append(self.w_intvalue)
+    def eval(self, ctx):
+        ctx.append(self.w_intvalue)
 
     def __repr__(self):
         return 'LOAD_INTCONSTANT %s' % (self.w_intvalue.intval,)
@@ -66,15 +66,15 @@
     def __init__(self, value):
         self.boolval = value
 
-    def eval(self, ctx, stack):
-        stack.append(newbool(self.boolval))
+    def eval(self, ctx):
+        ctx.append(newbool(self.boolval))
 
 class LOAD_FLOATCONSTANT(Opcode):
     def __init__(self, value):
         self.w_floatvalue = W_FloatNumber(float(value))
 
-    def eval(self, ctx, stack):
-        stack.append(self.w_floatvalue)
+    def eval(self, ctx):
+        ctx.append(self.w_floatvalue)
 
     def __repr__(self):
         return 'LOAD_FLOATCONSTANT %s' % (self.w_floatvalue.floatval,)
@@ -84,8 +84,8 @@
     def __init__(self, value):
         self.w_stringvalue = W_String(value)
 
-    def eval(self, ctx, stack):
-        stack.append(self.w_stringvalue)
+    def eval(self, ctx):
+        ctx.append(self.w_stringvalue)
 
     #def get_literal(self, ctx):
     #    return W_String(self.strval).ToString(ctx)
@@ -94,20 +94,20 @@
         return 'LOAD_STRINGCONSTANT "%s"' % (self.w_stringvalue.strval,)
 
 class LOAD_UNDEFINED(Opcode):
-    def eval(self, ctx, stack):
-        stack.append(w_Undefined)
+    def eval(self, ctx):
+        ctx.append(w_Undefined)
 
 class LOAD_NULL(Opcode):
-    def eval(self, ctx, stack):
-        stack.append(w_Null)
+    def eval(self, ctx):
+        ctx.append(w_Null)
 
 class LOAD_VARIABLE(Opcode):
     _immutable_fields_ = ['identifier']
     def __init__(self, identifier):
         self.identifier = identifier
 
-    def eval(self, ctx, stack):
-        stack.append(ctx.resolve_identifier(ctx, self.identifier))
+    def eval(self, ctx):
+        ctx.append(ctx.resolve_identifier(ctx, self.identifier))
 
     def __repr__(self):
         return 'LOAD_VARIABLE "%s"' % (self.identifier,)
@@ -117,7 +117,7 @@
         self.depth = depth
         self.identifier = identifier
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         raise NotImplementedError()
         # XXX
         # scope = ctx.scope[self.depth]
@@ -131,12 +131,12 @@
     def __init__(self, counter):
         self.counter = counter
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         proto = ctx.get_global().Get(ctx, 'Array').Get(ctx, 'prototype')
         array = W_Array(ctx, Prototype=proto, Class = proto.Class)
         for i in range(self.counter):
-            array.Put(ctx, str(self.counter - i - 1), stack.pop())
-        stack.append(array)
+            array.Put(ctx, str(self.counter - i - 1), ctx.pop())
+        ctx.append(array)
 
     def __repr__(self):
         return 'LOAD_ARRAY %d' % (self.counter,)
@@ -146,9 +146,9 @@
     def __init__(self, counter):
         self.counter = counter
 
-    def eval(self, ctx, stack):
-        list_w = stack.pop_n(self.counter)[:] # pop_n returns a non-resizable list
-        stack.append(W_List(list_w))
+    def eval(self, ctx):
+        list_w = ctx.pop_n(self.counter)[:] # pop_n returns a non-resizable list
+        ctx.append(W_List(list_w))
 
     def __repr__(self):
         return 'LOAD_LIST %d' % (self.counter,)
@@ -157,7 +157,7 @@
     def __init__(self, funcobj):
         self.funcobj = funcobj
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         proto = ctx.get_global().Get(ctx, 'Function').Get(ctx, 'prototype')
         w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function',
                           callfunc=self.funcobj)
@@ -165,7 +165,7 @@
         w_obj = create_object(ctx, 'Object')
         w_obj.Put(ctx, 'constructor', w_func, flags = jsobj.DE)
         w_func.Put(ctx, 'prototype', w_obj)
-        stack.append(w_func)
+        ctx.append(w_func)
 
     def __repr__(self):
         return 'LOAD_FUNCTION' # XXX
@@ -186,28 +186,28 @@
     def __init__(self, counter):
         self.counter = counter
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         w_obj = create_object(ctx, 'Object')
         for _ in range(self.counter):
-            name = stack.pop().ToString(ctx)
-            w_elem = stack.pop()
+            name = ctx.pop().ToString(ctx)
+            w_elem = ctx.pop()
             w_obj.Put(ctx, name, w_elem)
-        stack.append(w_obj)
+        ctx.append(w_obj)
 
     def __repr__(self):
         return 'LOAD_OBJECT %d' % (self.counter,)
 
 class LOAD_MEMBER(Opcode):
-    def eval(self, ctx, stack):
-        w_obj = stack.pop().ToObject(ctx)
-        name = stack.pop().ToString(ctx)
-        stack.append(w_obj.Get(ctx, name))
+    def eval(self, ctx):
+        w_obj = ctx.pop().ToObject(ctx)
+        name = ctx.pop().ToString(ctx)
+        ctx.append(w_obj.Get(ctx, name))
 
 class COMMA(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        one = stack.pop()
-        stack.pop()
-        stack.append(one)
+    def eval(self, ctx):
+        one = ctx.pop()
+        ctx.pop()
+        ctx.append(one)
         # XXX
 
 class SUB(BaseBinaryOperation):
@@ -222,20 +222,20 @@
         return newbool(right.HasProperty(name))
 
 class TYPEOF(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        one = stack.pop()
-        stack.append(W_String(one.type()))
+    def eval(self, ctx):
+        one = ctx.pop()
+        ctx.append(W_String(one.type()))
 
 class TYPEOF_VARIABLE(Opcode):
     def __init__(self, name):
         self.name = name
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         try:
             var = ctx.resolve_identifier(ctx, self.name)
-            stack.append(W_String(var.type()))
+            ctx.append(W_String(var.type()))
         except ThrowException:
-            stack.append(W_String('undefined'))
+            ctx.append(W_String('undefined'))
 
 #class Typeof(UnaryOp):
 #    def eval(self, ctx):
@@ -261,28 +261,28 @@
         return W_IntNumber(op1|op2)
 
 class BITNOT(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        op = stack.pop().ToInt32(ctx)
-        stack.append(W_IntNumber(~op))
+    def eval(self, ctx):
+        op = ctx.pop().ToInt32(ctx)
+        ctx.append(W_IntNumber(~op))
 
 class URSH(BaseBinaryBitwiseOp):
-    def eval(self, ctx, stack):
-        op2 = stack.pop().ToUInt32(ctx)
-        op1 = stack.pop().ToUInt32(ctx)
+    def eval(self, ctx):
+        op2 = ctx.pop().ToUInt32(ctx)
+        op1 = ctx.pop().ToUInt32(ctx)
         # XXX check if it could fit into int
-        stack.append(W_FloatNumber(op1 >> (op2 & 0x1F)))
+        ctx.append(W_FloatNumber(op1 >> (op2 & 0x1F)))
 
 class RSH(BaseBinaryBitwiseOp):
-    def eval(self, ctx, stack):
-        op2 = stack.pop().ToUInt32(ctx)
-        op1 = stack.pop().ToInt32(ctx)
-        stack.append(W_IntNumber(op1 >> intmask(op2 & 0x1F)))
+    def eval(self, ctx):
+        op2 = ctx.pop().ToUInt32(ctx)
+        op1 = ctx.pop().ToInt32(ctx)
+        ctx.append(W_IntNumber(op1 >> intmask(op2 & 0x1F)))
 
 class LSH(BaseBinaryBitwiseOp):
-    def eval(self, ctx, stack):
-        op2 = stack.pop().ToUInt32(ctx)
-        op1 = stack.pop().ToInt32(ctx)
-        stack.append(W_IntNumber(op1 << intmask(op2 & 0x1F)))
+    def eval(self, ctx):
+        op2 = ctx.pop().ToUInt32(ctx)
+        op1 = ctx.pop().ToInt32(ctx)
+        ctx.append(W_IntNumber(op1 << intmask(op2 & 0x1F)))
 
 class MUL(BaseBinaryOperation):
     def operation(self, ctx, op1, op2):
@@ -297,32 +297,32 @@
         return mod(ctx, op1, op2)
 
 class UPLUS(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        if isinstance(stack.top(), W_IntNumber):
+    def eval(self, ctx):
+        if isinstance(ctx.top(), W_IntNumber):
             return
-        if isinstance(stack.top(), W_FloatNumber):
+        if isinstance(ctx.top(), W_FloatNumber):
             return
-        stack.append(W_FloatNumber(stack.pop().ToNumber(ctx)))
+        ctx.append(W_FloatNumber(ctx.pop().ToNumber(ctx)))
 
 class UMINUS(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        stack.append(uminus(stack.pop(), ctx))
+    def eval(self, ctx):
+        ctx.append(uminus(ctx.pop(), ctx))
 
 class NOT(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        stack.append(newbool(not stack.pop().ToBoolean()))
+    def eval(self, ctx):
+        ctx.append(newbool(not ctx.pop().ToBoolean()))
 
 class INCR(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        value = stack.pop()
+    def eval(self, ctx):
+        value = ctx.pop()
         newvalue = increment(ctx, value)
-        stack.append(newvalue)
+        ctx.append(newvalue)
 
 class DECR(BaseUnaryOperation):
-    def eval(self, ctx, stack):
-        value = stack.pop()
+    def eval(self, ctx):
+        value = ctx.pop()
         newvalue = decrement(ctx, value)
-        stack.append(newvalue)
+        ctx.append(newvalue)
 
 class GT(BaseBinaryComparison):
     def decision(self, ctx, op1, op2):
@@ -357,21 +357,21 @@
         return newbool(not StrictEC(ctx, op1, op2))
 
 class STORE_MEMBER(Opcode):
-    def eval(self, ctx, stack):
-        left = stack.pop()
-        member = stack.pop()
-        value = stack.pop()
+    def eval(self, ctx):
+        left = ctx.pop()
+        member = ctx.pop()
+        value = ctx.pop()
         name = member.ToString(ctx)
         left.ToObject(ctx).Put(ctx, name, value)
-        stack.append(value)
+        ctx.append(value)
 
 class STORE(Opcode):
     _immutable_fields_ = ['name']
     def __init__(self, name):
         self.name = name
 
-    def eval(self, ctx, stack):
-        value = stack.top()
+    def eval(self, ctx):
+        value = ctx.top()
         ctx.assign(self.name, value)
 
     def __repr__(self):
@@ -390,60 +390,60 @@
         self.where = where
         self.decision = False
 
-    def do_jump(self, stack, pos):
+    def do_jump(self, ctx, pos):
         return 0
 
     def __repr__(self):
         return '%s %d' % (self.__class__.__name__, self.where)
 
 class JUMP(BaseJump):
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         pass
 
-    def do_jump(self, stack, pos):
+    def do_jump(self, ctx, pos):
         return self.where
 
 class BaseIfJump(BaseJump):
-    def eval(self, ctx, stack):
-        value = stack.pop()
+    def eval(self, ctx):
+        value = ctx.pop()
         self.decision = value.ToBoolean()
 
 class BaseIfNopopJump(BaseJump):
-    def eval(self, ctx, stack):
-        value = stack.top()
+    def eval(self, ctx):
+        value = ctx.top()
         self.decision = value.ToBoolean()
 
 class JUMP_IF_FALSE(BaseIfJump):
-    def do_jump(self, stack, pos):
+    def do_jump(self, ctx, pos):
         if self.decision:
             return pos + 1
         return self.where
 
 class JUMP_IF_FALSE_NOPOP(BaseIfNopopJump):
-    def do_jump(self, stack, pos):
+    def do_jump(self, ctx, pos):
         if self.decision:
-            stack.pop()
+            ctx.pop()
             return pos + 1
         return self.where
 
 class JUMP_IF_TRUE(BaseIfJump):
-    def do_jump(self, stack, pos):
+    def do_jump(self, ctx, pos):
         if self.decision:
             return self.where
         return pos + 1
 
 class JUMP_IF_TRUE_NOPOP(BaseIfNopopJump):
-    def do_jump(self, stack, pos):
+    def do_jump(self, ctx, pos):
         if self.decision:
             return self.where
-        stack.pop()
+        ctx.pop()
         return pos + 1
 
 class DECLARE_FUNCTION(Opcode):
     def __init__(self, funcobj):
         self.funcobj = funcobj
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         # function declaration actyally don't run anything
         proto = ctx.get_global().Get(ctx, 'Function').Get(ctx, 'prototype')
         w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self.funcobj)
@@ -467,19 +467,19 @@
     def __init__(self, name):
         self.name = name
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         ctx.declare_variable(self.name)
 
     def __repr__(self):
         return 'DECLARE_VAR "%s"' % (self.name,)
 
 class RETURN(Opcode):
-    def eval(self, ctx, stack):
-        raise ReturnException(stack.pop())
+    def eval(self, ctx):
+        raise ReturnException(ctx.pop())
 
 class POP(Opcode):
-    def eval(self, ctx, stack):
-        stack.pop()
+    def eval(self, ctx):
+        ctx.pop()
 
 def common_call(ctx, r1, args, this, name):
     if not isinstance(r1, W_PrimitiveObject):
@@ -491,45 +491,29 @@
     return res
 
 class CALL(Opcode):
-    def eval(self, ctx, stack):
-        r1 = stack.pop()
-        args = stack.pop()
+    def eval(self, ctx):
+        r1 = ctx.pop()
+        args = ctx.pop()
         name = r1.ToString(ctx)
         #XXX hack, this should be comming from context
-        stack.append(common_call(ctx, r1, args, ctx.scope[-1], name))
+        ctx.append(common_call(ctx, r1, args, ctx.scope[-1], name))
 
 class CALL_METHOD(Opcode):
-    def eval(self, ctx, stack):
-        method = stack.pop()
-        what = stack.pop().ToObject(ctx)
-        args = stack.pop()
+    def eval(self, ctx):
+        method = ctx.pop()
+        what = ctx.pop().ToObject(ctx)
+        args = ctx.pop()
         name = method.ToString(ctx)
         r1 = what.Get(ctx, name)
-        stack.append(common_call(ctx, r1, args, what, name))
-
-#class CALL_BASEOP(Opcode):
-    #def __init__(self, baseop):
-        #self.baseop = baseop
-
-    #def eval(self, ctx, stack):
-        #from js.baseop import get_baseop_func
-        #func = get_baseop_func(self.baseop)
-        #args = stack.pop_n(func.argcount)
-        #kwargs = {'ctx':ctx}
-        #val = func(*args, **kwargs)
-        #stack.append(val)
-
-    #def __repr__(self):
-        #from js.baseop import get_baseop_name, get_baseop_func
-        #return "CALL_BASEOP %s (%d)" % (get_baseop_name(self.baseop), self.baseop)
+        ctx.append(common_call(ctx, r1, args, what, name))
 
 class DUP(Opcode):
-    def eval(self, ctx, stack):
-        stack.append(stack.top())
+    def eval(self, ctx):
+        ctx.append(ctx.top())
 
 class THROW(Opcode):
-    def eval(self, ctx, stack):
-        val = stack.pop()
+    def eval(self, ctx):
+        val = ctx.pop()
         raise ThrowException(val)
 
 class TRYCATCHBLOCK(Opcode):
@@ -539,7 +523,7 @@
         self.catchparam  = catchparam
         self.finallyfunc = finallyfunc
 
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         try:
             try:
                 self.tryfunc.run(ctx)
@@ -567,32 +551,32 @@
         return "TRYCATCHBLOCK" # XXX shall we add stuff here???
 
 class NEW(Opcode):
-    def eval(self, ctx, stack):
-        y = stack.pop()
-        x = stack.pop()
+    def eval(self, ctx):
+        y = ctx.pop()
+        x = ctx.pop()
         assert isinstance(y, W_List)
         args = y.get_args()
-        stack.append(commonnew(ctx, x, args))
+        ctx.append(commonnew(ctx, x, args))
 
 class NEW_NO_ARGS(Opcode):
-    def eval(self, ctx, stack):
-        x = stack.pop()
-        stack.append(commonnew(ctx, x, []))
+    def eval(self, ctx):
+        x = ctx.pop()
+        ctx.append(commonnew(ctx, x, []))
 
 # ------------ iterator support ----------------
 
 class LOAD_ITERATOR(Opcode):
-    def eval(self, ctx, stack):
-        obj = stack.pop().ToObject(ctx)
+    def eval(self, ctx):
+        obj = ctx.pop().ToObject(ctx)
         props = [prop.value for prop in obj.propdict.values() if not prop.flags & jsobj.DE]
-        stack.append(W_Iterator(props))
+        ctx.append(W_Iterator(props))
 
 class JUMP_IF_ITERATOR_EMPTY(BaseJump):
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         pass
 
-    def do_jump(self, stack, pos):
-        iterator = stack.top()
+    def do_jump(self, ctx, pos):
+        iterator = ctx.top()
         assert isinstance(iterator, W_Iterator)
         if iterator.empty():
             return self.where
@@ -602,20 +586,20 @@
     def __init__(self, name):
         self.name = name
 
-    def eval(self, ctx, stack):
-        iterator = stack.top()
+    def eval(self, ctx):
+        iterator = ctx.top()
         assert isinstance(iterator, W_Iterator)
         ctx.assign(self.name, iterator.next())
 
 # ---------------- with support ---------------------
 
 class WITH_START(Opcode):
-    def eval(self, ctx, stack):
-        obj = stack.pop().ToObject(ctx)
+    def eval(self, ctx):
+        obj = ctx.pop().ToObject(ctx)
         ctx.push_object(obj)
 
 class WITH_END(Opcode):
-    def eval(self, ctx, stack):
+    def eval(self, ctx):
         ctx.pop_object()
 
 # ------------------ delete -------------------------
@@ -624,22 +608,22 @@
     def __init__(self, name):
         self.name = name
 
-    def eval(self, ctx, stack):
-        stack.append(newbool(ctx.delete_identifier(self.name)))
+    def eval(self, ctx):
+        ctx.append(newbool(ctx.delete_identifier(self.name)))
 
 class DELETE_MEMBER(Opcode):
-    def eval(self, ctx, stack):
-        what = stack.pop().ToString(ctx)
-        obj = stack.pop().ToObject(ctx)
-        stack.append(newbool(obj.Delete(what)))
+    def eval(self, ctx):
+        what = ctx.pop().ToString(ctx)
+        obj = ctx.pop().ToObject(ctx)
+        ctx.append(newbool(obj.Delete(what)))
 
 class LOAD_LOCAL(Opcode):
     _immutable_fields_ = ['local']
     def __init__(self, local):
         self.local = local
 
-    def eval(self, ctx, stack):
-        stack.append(ctx.get_local_value(self.local))
+    def eval(self, ctx):
+        ctx.append(ctx.get_local_value(self.local))
 
     def __repr__(self):
         return 'LOAD_LOCAL %d' % (self.local,)
@@ -649,8 +633,8 @@
     def __init__(self, local):
         self.local = local
 
-    def eval(self, ctx, stack):
-        value = stack.top()
+    def eval(self, ctx):
+        value = ctx.top()
         ctx.assign_local(self.local, value)
 
     def __repr__(self):
diff --git a/js/test/test_stack.py b/js/test/test_stack.py
--- a/js/test/test_stack.py
+++ b/js/test/test_stack.py
@@ -1,30 +1,35 @@
 import py
 
-from js.utils import Stack
+from js.utils import StackMixin
 from js.jsobj import W_IntNumber
 
 one   = W_IntNumber(1)
 two   = W_IntNumber(2)
 three = W_IntNumber(3)
 
+class Stack(StackMixin):
+    def __init__(self, size):
+        StackMixin.__init__(self)
+        self.stack = [None] * size
+
 def test_stack_push():
     s = Stack(99)
-    assert len(s.content) == 99
-    assert s.content == [None] * 99
+    assert len(s.stack) == 99
+    assert s.stack == [None] * 99
 
     s = Stack(99)
     s.append(one)
-    assert s.content[0] == one
-    assert s.pointer == 1
+    assert s.stack[0] == one
+    assert s.stack_pointer == 1
 
     s = Stack(99)
     s.append(one)
     s.append(two)
     s.append(three)
-    assert s.content[0] == one
-    assert s.content[1] == two
-    assert s.content[2] == three
-    assert s.pointer == 3
+    assert s.stack[0] == one
+    assert s.stack[1] == two
+    assert s.stack[2] == three
+    assert s.stack_pointer == 3
 
 def test_stack_pop():
     s = Stack(99)
@@ -32,8 +37,8 @@
     s.append(two)
     s.append(three)
     assert s.pop() == three
-    assert s.pointer == 2
-    assert s.content[2] == None
+    assert s.stack_pointer == 2
+    assert s.stack[2] == None
 
     s = Stack(99)
     s.append(one)
@@ -61,9 +66,9 @@
     s.append(three)
     x = s.pop_n(2)
     assert x == [two, three]
-    assert s.pointer == 1
-    assert s.content[1] == None
-    assert s.content[2] == None
+    assert s.stack_pointer == 1
+    assert s.stack[1] == None
+    assert s.stack[2] == None
 
 def test_stack_max():
     s = Stack(2)
diff --git a/js/utils.py b/js/utils.py
--- a/js/utils.py
+++ b/js/utils.py
@@ -1,38 +1,34 @@
 # encoding: utf-8
-from js.jsobj import W_Root
 from pypy.rlib.jit import hint
 from pypy.rlib import jit, debug
 
-class Stack(object):
-    _virtualizable2_ = ['content[*]', 'pointer']
-    def __init__(self, size):
-        self = hint(self, access_directly = True, fresh_virtualizable = True)
-        self.content = [None] * size
-        self.pointer = 0
-
-    def __repr__(self):
-        return "<Stack %(content)s@%(pointer)d>" % {'pointer': self.pointer, 'content': self.content}
+class StackMixin(object):
+    _mixin_ = True
+    def __init__(self):
+        self.stack = [None]
+        self.stack_pointer = 0
 
     def pop(self):
         e = self.top()
-        i = self.pointer - 1
+        i = self.stack_pointer - 1
         assert i >= 0
-        self.content[i] = None
-        self.pointer = i
+        self.stack[i] = None
+        self.stack_pointer = i
         return e
 
     def top(self):
-        i = self.pointer - 1
+        i = self.stack_pointer - 1
         if i < 0:
             raise IndexError
-        return self.content[i]
+        return self.stack[i]
 
     def append(self, element):
+        from js.jsobj import W_Root
         assert isinstance(element, W_Root)
-        i = self.pointer
+        i = self.stack_pointer
         assert i >= 0
-        self.content[i] = element
-        self.pointer = i + 1
+        self.stack[i] = element
+        self.stack_pointer = i + 1
 
     @jit.unroll_safe
     def pop_n(self, n):
@@ -42,5 +38,5 @@
         debug.make_sure_not_resized(l)
         return l
 
-    def check(self):
-        assert self.pointer == 1
+    def check_stack(self):
+        assert self.stack_pointer == 1


More information about the pypy-commit mailing list