Author: Stephan <step...@stzal.com>
Branch: 
Changeset: r309:2481cfac22ff
Date: 2012-12-11 16:15 +0100
http://bitbucket.org/pypy/lang-js/changeset/2481cfac22ff/

Log:    cache resolved references in execution context

diff --git a/js/execution_context.py b/js/execution_context.py
--- a/js/execution_context.py
+++ b/js/execution_context.py
@@ -4,10 +4,13 @@
 
 class ExecutionContext(StackMixin):
     _immutable_fields_ = ['_stack_', '_stack_resize_', '_this_binding_', 
'_lexical_environment_', '_variable_environment_']
-    def __init__(self, stack_size=1):
+    _refs_resizable_ = True
+
+    def __init__(self, stack_size=1, refs_size=1):
         self._lexical_environment_ = None
         self._variable_environment_ = None
         self._this_binding_ = None
+        self._refs_ = [None] * refs_size
         self._init_stack_(size=stack_size, resize=False)
 
     def stack_append(self, value):
@@ -96,6 +99,7 @@
             arguments = self._argument_values_
             names = self._formal_parameters_
             args_obj = W_Arguments(func, names, arguments, env, strict)
+
             if strict is True:
                 env.create_immutable_bining(u'arguments')
                 env.initialize_immutable_binding(u'arguments', args_obj)
@@ -111,11 +115,36 @@
                 env.create_mutuable_binding(dn, configurable_bindings)
                 env.set_mutable_binding(dn, w_Undefined, False)
 
-    def get_ref(self, symbol):
-        ## TODO pre-bind symbols, work with idndex, does not work, see 
test_foo18
-        lex_env = self.lexical_environment()
-        ref = lex_env.get_identifier_reference(symbol)
-        return ref
+    def _get_refs(self, index):
+        assert index <= len(self._refs_)
+        return self._refs_[index]
+
+    def _set_refs(self, index, value):
+        assert index <= len(self._refs_)
+        self._refs_[index] = value
+
+    def get_ref(self, symbol, index=-1):
+        ## TODO pre-bind symbols, work with idndex, does not work, see 
test_foo19
+        if index == -1:
+            lex_env = self.lexical_environment()
+            ref = lex_env.get_identifier_reference(symbol)
+            return ref
+
+        if self._refs_resizable_ is True and index >= len(self._refs_):
+            self._refs_ += ([None] * (1 + index - len(self._refs_)))
+
+        if self._get_refs(index) is None:
+            lex_env = self.lexical_environment()
+            ref = lex_env.get_identifier_reference(symbol)
+            if ref.is_unresolvable_reference() is True:
+                return ref
+            self._set_refs(index, ref)
+
+        return self._get_refs(index)
+
+    def forget_ref(self, symbol, index):
+        self._set_refs(index, None)
+
 
 class GlobalExecutionContext(ExecutionContext):
     def __init__(self, code, global_object, strict=False):
@@ -159,19 +188,19 @@
 
 
 class FunctionExecutionContext(ExecutionContext):
+    _refs_resizable_ = False
     def __init__(self, code, formal_parameters=[], argv=[], this=w_Undefined, 
strict=False, scope=None, w_func=None):
         from js.jsobj import isnull_or_undefined, W_BasicObject
         from js.object_space import object_space
 
         stack_size = code.estimated_stack_size()
-        env_size = code.env_size()
+        env_size = code.env_size() + 1  # neet do add one for the arguments 
object
 
-        ExecutionContext.__init__(self, stack_size)
+        ExecutionContext.__init__(self, stack_size, env_size)
 
         self._code_ = code
         self._formal_parameters_ = formal_parameters
         self._argument_values_ = argv
-        self._this_ = this
         self._strict_ = strict
         self._scope_ = scope
         self._w_func_ = w_func
@@ -182,17 +211,18 @@
         self._lexical_environment_ = localEnv
         self._variable_environment_ = localEnv
 
-        from js.jsobj import isnull_or_undefined
-
         if strict:
             self._this_binding_ = this
-        elif this is None or isnull_or_undefined(this):
-            from js.object_space import object_space
-            self._this_binding_ = object_space.global_object
-        elif this.klass() is not 'Object':
-            self._this_binding_ = this.ToObject()
         else:
-            self._this_binding_ = this
+            if this is None or isnull_or_undefined(this):
+                self._this_binding_ = object_space.global_object
+            else:
+                assert isinstance(this, W_BasicObject)
+
+                if this.klass() is not 'Object':
+                    self._this_binding_ = this.ToObject()
+                else:
+                    self._this_binding_ = this
 
         self.declaration_binding_initialization()
 
diff --git a/js/opcodes.py b/js/opcodes.py
--- a/js/opcodes.py
+++ b/js/opcodes.py
@@ -143,8 +143,8 @@
     # 11.1.2
     def eval(self, ctx):
         # TODO put ref onto stack
-        ref = ctx.get_ref(self.identifier)
         value = ref.get_value()
+        ref = ctx.get_ref(self.identifier, self.index)
         ctx.stack_append(value)
 
     def __str__(self):
@@ -491,7 +491,7 @@
 
 
 class STORE(Opcode):
-    _immutable_fields_ = ['name']
+    _immutable_fields_ = ['identifier', 'index']
     _stack_change = 0
 
     def __init__(self, index, identifier):
@@ -501,8 +501,8 @@
 
     def eval(self, ctx):
         value = ctx.stack_top()
-        ref = ctx.get_ref(self.identifier)
         ref.put_value(value)
+        ref = ctx.get_ref(self.identifier, self.index)
 
     def __str__(self):
         return 'STORE "%s"' % (self.identifier)
@@ -900,15 +900,16 @@
 
 
 class DELETE(Opcode):
-    def __init__(self, name):
+    def __init__(self, name, index):
         self.name = name
+        self.index = index
 
     def eval(self, ctx):
         from js.lexical_environment import Reference
         from js.execution import JsSyntaxError
 
         # 11.4.1
-        ref = ctx.get_ref(self.name)
+        ref = ctx.get_ref(self.name, self.index)
         if not isinstance(ref, Reference):
             res = True
         if ref.is_unresolvable_reference():
@@ -923,6 +924,9 @@
                 raise JsSyntaxError()
             bindings = ref.base_env
             res = bindings.delete_binding(ref.get_referenced_name())
+
+        if res is True:
+            ctx.forget_ref(self.name, self.index)
         ctx.stack_append(_w(res))
 
 
diff --git a/js/operations.py b/js/operations.py
--- a/js/operations.py
+++ b/js/operations.py
@@ -576,7 +576,7 @@
     def emit(self, bytecode):
         what = self.what
         if isinstance(what, Identifier):
-            bytecode.emit('DELETE', what.name)
+            bytecode.emit('DELETE', what.name, what.index)
         elif isinstance(what, MemberDot):
             what.left.emit(bytecode)
             # XXX optimize
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to