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