[pypy-commit] lang-js default: move run code from JsCode to JsFunction

stepahn noreply at buildbot.pypy.org
Fri May 13 13:45:15 CEST 2011


Author: Stephan <stephan at stzal.com>
Branch: 
Changeset: r43:0d73a6637419
Date: 2011-05-12 15:06 +0200
http://bitbucket.org/pypy/lang-js/changeset/0d73a6637419/

Log:	move run code from JsCode to JsFunction

diff --git a/js/interpreter.py b/js/interpreter.py
--- a/js/interpreter.py
+++ b/js/interpreter.py
@@ -149,7 +149,8 @@
 
         bytecode = JsCode()
         node.emit(bytecode)
-        return bytecode.run(ctx, retlast=True)
+        func = bytecode.make_js_function()
+        return func.run(ctx, retlast = True)
 
 class W_ParseInt(W_NewBuiltin):
     length = 1
@@ -317,7 +318,8 @@
         ast = ASTBUILDER.dispatch(funcnode)
         bytecode = JsCode()
         ast.emit(bytecode)
-        return bytecode.run(ctx, retlast=True)
+        func = bytecode.make_js_function()
+        return func.run(ctx, retlast=True)
 
     def Construct(self, ctx, args=[]):
         return self.Call(ctx, args, this=None)
@@ -894,7 +896,8 @@
         if not we_are_translated():
             # debugging
             self._code = bytecode
+        func = bytecode.make_js_function()
         if interactive:
-            return bytecode.run(self.global_context, retlast=True)
+            return func.run(self.global_context, retlast=True)
         else:
-            bytecode.run(self.global_context)
+            func.run(self.global_context)
diff --git a/js/jscode.py b/js/jscode.py
--- a/js/jscode.py
+++ b/js/jscode.py
@@ -15,61 +15,6 @@
 class AlreadyRun(Exception):
     pass
 
-def run_bytecode(opcodes, ctx, stack, check_stack=True, retlast=False):
-    popped = False
-    if retlast:
-        if isinstance(opcodes[-1], POP):
-            opcodes.pop()
-            popped = True
-
-    i = 0
-    to_pop = 0
-    try:
-        while i < len(opcodes):
-            opcode = opcodes[i]
-            #if we_are_translated():
-            #    #this is an optimization strategy for translated code
-            #    #on top of cpython it destroys the performance
-            #    #besides, this code might be completely wrong
-            #    for name, op in opcode_unrolling:
-            #        opcode = hint(opcode, deepfreeze=True)
-            #        if isinstance(opcode, op):
-            #            result = opcode.eval(ctx, stack)
-            #            assert result is None
-            #            break
-            #else:
-            result = opcode.eval(ctx, stack)
-            assert result is None
-
-            if isinstance(opcode, BaseJump):
-                i = opcode.do_jump(stack, i)
-            else:
-                i += 1
-            if isinstance(opcode, WITH_START):
-                to_pop += 1
-            elif isinstance(opcode, WITH_END):
-                to_pop -= 1
-    finally:
-        for i in range(to_pop):
-            ctx.pop_object()
-
-    if retlast:
-        if popped:
-            assert len(stack) == 1
-            return stack[0]
-        else:
-            assert not stack
-            return w_Undefined
-    if check_stack:
-        assert not stack
-
-#def run_bytecode_unguarded(opcodes, ctx, stack, check_stack=True, retlast=False):
-#    try:
-#        run_bytecode(opcodes, ctx, stack, check_stack, retlast)
-#    except ThrowException:
-#        print
-#        raise
-
 class T(list):
     def append(self, element):
         assert isinstance(element, W_Root)
@@ -153,19 +98,10 @@
         self.opcodes.append(opcode)
         return opcode
 
-    def run(self, ctx, check_stack=True, retlast=False):
+    def make_js_function(self, name='__dont_care__', params=None):
         if self.has_labels:
             self.remove_labels()
-        if 1:
-            if we_are_translated():
-                stack = []
-            else:
-                stack = T()
-            return run_bytecode(self.opcodes, ctx, stack, check_stack,
-                                retlast)
-        else:
-            return run_bytecode_unguarded(self.opcodes, ctx, self,stack,
-                                          check_stack, retlast)
+        return JsFunction(name, params, self.opcodes)
 
     def _freeze_(self):
         if self.has_labels:
@@ -206,14 +142,64 @@
     def __init__(self, name, params, code):
         self.name = name
         self.params = params
-        self.code = code
+        self.opcodes = code
 
-    def run(self, ctx):
+    def run(self, ctx, check_stack=True, retlast=False):
+        if we_are_translated():
+            stack = []
+        else:
+            stack = T()
         try:
-            self.code.run(ctx)
+            return self.run_bytecode(ctx, stack, check_stack, retlast)
         except ReturnException, e:
             return e.value
-        return w_Undefined
+
+    def run_bytecode(self, ctx, stack, check_stack=True, retlast=False):
+        popped = False
+        if retlast and self.opcodes and isinstance(self.opcodes[-1], POP):
+            self.opcodes.pop()
+            popped = True
+
+        i = 0
+        to_pop = 0
+        try:
+            while i < len(self.opcodes):
+                opcode = self.opcodes[i]
+                #if we_are_translated():
+                #    #this is an optimization strategy for translated code
+                #    #on top of cpython it destroys the performance
+                #    #besides, this code might be completely wrong
+                #    for name, op in opcode_unrolling:
+                #        opcode = hint(opcode, deepfreeze=True)
+                #        if isinstance(opcode, op):
+                #            result = opcode.eval(ctx, stack)
+                #            assert result is None
+                #            break
+                #else:
+                result = opcode.eval(ctx, stack)
+                assert result is None
+
+                if isinstance(opcode, BaseJump):
+                    i = opcode.do_jump(stack, i)
+                else:
+                    i += 1
+                if isinstance(opcode, WITH_START):
+                    to_pop += 1
+                elif isinstance(opcode, WITH_END):
+                    to_pop -= 1
+        finally:
+            for i in range(to_pop):
+                ctx.pop_object()
+
+        if retlast:
+            if popped:
+                assert len(stack) == 1
+                return stack[0]
+            else:
+                assert not stack
+                return w_Undefined
+        if check_stack:
+            assert not stack
 
 class Opcode(object):
     def __init__(self):
@@ -804,7 +790,7 @@
             name = ""
         else:
             name = funcobj.name + " "
-        codestr = '\n'.join(['  %r' % (op,) for op in funcobj.code.opcodes])
+        codestr = '\n'.join(['  %r' % (op,) for op in funcobj.opcodes])
         return 'DECLARE_FUNCTION %s%r [\n%s\n]' % (name, funcobj.params, codestr)
 
 class DECLARE_VAR(Opcode):
@@ -861,34 +847,34 @@
         raise ThrowException(val)
 
 class TRYCATCHBLOCK(Opcode):
-    def __init__(self, trycode, catchparam, catchcode, finallycode):
-        self.trycode     = trycode
-        self.catchcode   = catchcode
+    def __init__(self, tryfunc, catchparam, catchfunc, finallyfunc):
+        self.tryfunc     = tryfunc
+        self.catchfunc   = catchfunc
         self.catchparam  = catchparam
-        self.finallycode = finallycode
+        self.finallyfunc = finallyfunc
 
     def eval(self, ctx, stack):
         try:
             try:
-                self.trycode.run(ctx)
+                self.tryfunc.run(ctx)
             except ThrowException, e:
-                if self.catchcode is not None:
+                if self.catchfunc is not None:
                     # XXX just copied, I don't know if it's right
                     obj = W_Object()
                     obj.Put(ctx, self.catchparam, e.exception)
                     ctx.push_object(obj)
                     try:
-                        self.catchcode.run(ctx)
+                        self.catchfunc.run(ctx)
                     finally:
                         ctx.pop_object()
-                if self.finallycode is not None:
-                    self.finallycode.run(ctx)
-                if not self.catchcode:
+                if self.finallyfunc is not None:
+                    self.finallyfunc.run(ctx)
+                if not self.catchfunc:
                     raise
         except ReturnException:
             # we run finally block here and re-raise the exception
-            if self.finallycode is not None:
-                self.finallycode.run(ctx)
+            if self.finallyfunc is not None:
+                self.finallyfunc.run(ctx)
             raise
 
     def __repr__(self):
diff --git a/js/jsobj.py b/js/jsobj.py
--- a/js/jsobj.py
+++ b/js/jsobj.py
@@ -147,7 +147,7 @@
         w_Arguments = W_Arguments(self, args)
         act.Put(ctx, 'arguments', w_Arguments)
         newctx = function_context(self.Scope, act, this)
-        val = self.callfunc.run(ctx=newctx)
+        val = self.callfunc.run(ctx=newctx, retlast=True)
         return val
 
     def Construct(self, ctx, args=[]):
diff --git a/js/operations.py b/js/operations.py
--- a/js/operations.py
+++ b/js/operations.py
@@ -313,7 +313,7 @@
         code = JsCode()
         if self.body is not None:
             self.body.emit(code)
-        funcobj = JsFunction(self.name, self.params, code)
+        funcobj = code.make_js_function(self.name, self.params)
         bytecode.emit('DECLARE_FUNCTION', funcobj)
         if self.name is None:
             bytecode.emit('LOAD_FUNCTION', funcobj)
@@ -648,18 +648,20 @@
         # a bit naive operator for now
         trycode = JsCode()
         self.tryblock.emit(trycode)
+        tryfunc = trycode.make_js_function()
         if self.catchblock:
             catchcode = JsCode()
             self.catchblock.emit(catchcode)
+            catchfunc = catchcode.make_js_function()
+            finallyfunc = finallycode.make_js_function()
         else:
-            catchcode = None
+            catchfunc = None
         if self.finallyblock:
             finallycode = JsCode()
             self.finallyblock.emit(finallycode)
         else:
-            finallycode = None
-        bytecode.emit('TRYCATCHBLOCK', trycode, self.catchparam.get_literal(),
-                      catchcode, finallycode)    
+            finallyfunc = None
+        bytecode.emit('TRYCATCHBLOCK', tryfunc, self.catchparam.get_literal(), catchfunc, finallyfunc)
 
 class VariableDeclaration(Expression):
     def __init__(self, pos, identifier, expr=None):
diff --git a/js/test/test_interp.py b/js/test/test_interp.py
--- a/js/test/test_interp.py
+++ b/js/test/test_interp.py
@@ -13,7 +13,8 @@
     bytecode.emit('LOAD_FLOATCONSTANT', 4)
     bytecode.emit('ADD')
     bytecode.emit('POP')
-    res = bytecode.run(ExecutionContext([W_Object()]), check_stack=False, retlast=True)
+    func = bytecode.make_js_function()
+    res = func.run(ExecutionContext([W_Object()]), check_stack=False, retlast=True)
     assert res.ToNumber(None) == 6.0
 
 def assertp(code, prints):
@@ -37,7 +38,8 @@
     try:
         bytecode = JsCode()
         interpreter.load_source(code, '').emit(bytecode)
-        code_val = bytecode.run(ExecutionContext([ctx]), retlast=True)
+        func = bytecode.make_js_function()
+        code_val = func.run(ExecutionContext([ctx]), retlast=True)
     except ThrowException, excpt:
         code_val = excpt.exception
     print code_val, value


More information about the pypy-commit mailing list