Author: Stephan <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit