Author: [email protected]
Date: Wed Feb 18 07:55:24 2009
New Revision: 1303

Added:
    branches/bleeding_edge/test/mjsunit/global-load-from-eval-in-with.js
       - copied unchanged from r1298,  
/branches/bleeding_edge/test/mjsunit/global-load-from-eval-in-with.js
    branches/bleeding_edge/test/mjsunit/local-load-from-eval.js
       - copied unchanged from r1298,  
/branches/bleeding_edge/test/mjsunit/local-load-from-eval.js
    branches/bleeding_edge/test/mjsunit/property-load-across-eval.js
       - copied unchanged from r1298,  
/branches/bleeding_edge/test/mjsunit/property-load-across-eval.js
Modified:
    branches/bleeding_edge/src/codegen-arm.h
    branches/bleeding_edge/src/codegen-ia32.h
    branches/bleeding_edge/src/contexts.cc
    branches/bleeding_edge/src/scopes.cc
    branches/bleeding_edge/src/scopes.h
    branches/bleeding_edge/src/variables.cc
    branches/bleeding_edge/src/variables.h

Log:
Not sure what happened, but my revert did not get everything out.  Fixing  
the problem instead.  The issue was using tmp instead of context in two  
places.

TBR=kasperl

Review URL: http://codereview.chromium.org/20459

Modified: branches/bleeding_edge/src/codegen-arm.h
==============================================================================
--- branches/bleeding_edge/src/codegen-arm.h    (original)
+++ branches/bleeding_edge/src/codegen-arm.h    Wed Feb 18 07:55:24 2009
@@ -256,6 +256,11 @@

    MemOperand SlotOperand(Slot* slot, Register tmp);

+  MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
+                                               Register tmp,
+                                               Register tmp2,
+                                               Label* slow);
+
    // Expressions
    MemOperand GlobalObject() const  {
      return ContextOperand(cp, Context::GLOBAL_INDEX);
@@ -272,6 +277,11 @@

    // Read a value from a slot and leave it on top of the expression stack.
    void LoadFromSlot(Slot* slot, TypeofState typeof_state);
+  void LoadFromGlobalSlotCheckExtensions(Slot* slot,
+                                         TypeofState typeof_state,
+                                         Register tmp,
+                                         Register tmp2,
+                                         Label* slow);

    // Special code for typeof expressions: Unfortunately, we must
    // be careful when loading the expression in 'typeof'

Modified: branches/bleeding_edge/src/codegen-ia32.h
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.h   (original)
+++ branches/bleeding_edge/src/codegen-ia32.h   Wed Feb 18 07:55:24 2009
@@ -267,6 +267,9 @@

    Operand SlotOperand(Slot* slot, Register tmp);

+  Operand ContextSlotOperandCheckExtensions(Slot* slot,
+                                            Register tmp,
+                                            Label* slow);

    // Expressions
    Operand GlobalObject() const {
@@ -284,6 +287,10 @@

    // Read a value from a slot and leave it on top of the expression stack.
    void LoadFromSlot(Slot* slot, TypeofState typeof_state);
+  void LoadFromGlobalSlotCheckExtensions(Slot* slot,
+                                         TypeofState typeof_state,
+                                         Register tmp,
+                                         Label* slow);

    // Special code for typeof expressions: Unfortunately, we must
    // be careful when loading the expression in 'typeof'

Modified: branches/bleeding_edge/src/contexts.cc
==============================================================================
--- branches/bleeding_edge/src/contexts.cc      (original)
+++ branches/bleeding_edge/src/contexts.cc      Wed Feb 18 07:55:24 2009
@@ -134,10 +134,12 @@
          // declared variables that were introduced through declaration  
nodes)
          // must not appear here.
          switch (mode) {
-          case Variable::INTERNAL :  // fall through
-          case Variable::VAR      : *attributes = NONE; break;
-          case Variable::CONST    : *attributes = READ_ONLY; break;
-          case Variable::DYNAMIC  : UNREACHABLE(); break;
+          case Variable::INTERNAL:  // fall through
+          case Variable::VAR: *attributes = NONE; break;
+          case Variable::CONST: *attributes = READ_ONLY; break;
+          case Variable::DYNAMIC: UNREACHABLE(); break;
+          case Variable::DYNAMIC_GLOBAL: UNREACHABLE(); break;
+          case Variable::DYNAMIC_LOCAL: UNREACHABLE(); break;
            case Variable::TEMPORARY: UNREACHABLE(); break;
          }
          return context;

Modified: branches/bleeding_edge/src/scopes.cc
==============================================================================
--- branches/bleeding_edge/src/scopes.cc        (original)
+++ branches/bleeding_edge/src/scopes.cc        Wed Feb 18 07:55:24 2009
@@ -139,6 +139,7 @@
      scope_calls_eval_(false),
      outer_scope_calls_eval_(false),
      inner_scope_calls_eval_(false),
+    outer_scope_is_eval_scope_(false),
      force_eager_compilation_(false),
      num_stack_slots_(0),
      num_heap_slots_(0) {
@@ -312,7 +313,8 @@
    // and assume they may invoke eval themselves. Eventually we could  
capture
    // this information in the ScopeInfo and then use it here (by traversing
    // the call chain stack, at compile time).
-  PropagateScopeInfo(is_eval_scope());
+  bool eval_scope = is_eval_scope();
+  PropagateScopeInfo(eval_scope, eval_scope);

    // 2) Resolve variables.
    Scope* global_scope = NULL;
@@ -442,6 +444,9 @@
    if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
    if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");
    if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
+  if (outer_scope_is_eval_scope_) {
+    Indent(n1, "// outer scope is 'eval' scope\n");
+  }
    if (num_stack_slots_ > 0) { Indent(n1, "// ");
    PrintF("%d stack slots\n", num_stack_slots_); }
    if (num_heap_slots_ > 0) { Indent(n1, "// ");
@@ -482,20 +487,18 @@
  #endif  // DEBUG


-Variable* Scope::NonLocal(Handle<String> name) {
-  // Space optimization: reuse existing non-local with the same name.
+Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
+  // Space optimization: reuse existing non-local with the same name
+  // and mode.
    for (int i = 0; i < nonlocals_.length(); i++) {
      Variable* var = nonlocals_[i];
-    if (var->name().is_identical_to(name)) {
-      ASSERT(var->mode() == Variable::DYNAMIC);
+    if (var->name().is_identical_to(name) && var->mode() == mode) {
        return var;
      }
    }

-  // Otherwise create a new new-local and add it to the list.
-  Variable* var = new Variable(
-    NULL /* we don't know the scope */,
-    name, Variable::DYNAMIC, true, false);
+  // Otherwise create a new non-local and add it to the list.
+  Variable* var = new Variable(NULL, name, mode, true, false);
    nonlocals_.Add(var);

    // Allocate it by giving it a dynamic lookup.
@@ -511,7 +514,9 @@
  // because the variable is just a guess (and may be shadowed by another
  // variable that is introduced dynamically via an 'eval' call or a 'with'
  // statement).
-Variable* Scope::LookupRecursive(Handle<String> name, bool inner_lookup) {
+Variable* Scope::LookupRecursive(Handle<String> name,
+                                 bool inner_lookup,
+                                 Variable** invalidated_local) {
    // If we find a variable, but the current scope calls 'eval', the found
    // variable may not be the correct one (the 'eval' may introduce a
    // property with the same name). In that case, remember that the variable
@@ -542,7 +547,7 @@
        var = function_;

      } else if (outer_scope_ != NULL) {
-      var = outer_scope_->LookupRecursive(name, true /* inner lookup */);
+      var = outer_scope_->LookupRecursive(name, true, invalidated_local);
        // We may have found a variable in an outer scope. However, if
        // the current scope is inside a 'with', the actual variable may
        // be a property introduced via the 'with' statement. Then, the
@@ -563,8 +568,10 @@
      var->is_accessed_from_inner_scope_ = true;

    // If the variable we have found is just a guess, invalidate the result.
-  if (guess)
+  if (guess) {
+    *invalidated_local = var;
      var = NULL;
+  }

    return var;
  }
@@ -578,7 +585,8 @@
    if (proxy->var() != NULL) return;

    // Otherwise, try to resolve the variable.
-  Variable* var = LookupRecursive(proxy->name(), false);
+  Variable* invalidated_local = NULL;
+  Variable* var = LookupRecursive(proxy->name(), false,  
&invalidated_local);

    if (proxy->inside_with()) {
      // If we are inside a local 'with' statement, all bets are off
@@ -587,7 +595,7 @@
      // Note that we must do a lookup anyway, because if we find one,
      // we must mark that variable as potentially accessed from this
      // inner scope (the property may not be in the 'with' object).
-    var = NonLocal(proxy->name());
+    var = NonLocal(proxy->name(), Variable::DYNAMIC);

    } else {
      // We are not inside a local 'with' statement.
@@ -601,11 +609,22 @@
        // or we don't know about the outer scope (because we are
        // in an eval scope).
        if (!is_global_scope() &&
-          (is_eval_scope() || outer_scope_calls_eval_ ||
-           scope_calls_eval_ || scope_inside_with_)) {
-        // We must look up the variable at runtime, and we don't
-        // know anything else.
-        var = NonLocal(proxy->name());
+          (scope_inside_with_ || outer_scope_is_eval_scope_)) {
+        // If we are inside a with statement or the code is executed
+        // using eval, we give up and look up the variable at runtime.
+        var = NonLocal(proxy->name(), Variable::DYNAMIC);
+
+      } else if (!is_global_scope() &&
+                 (scope_calls_eval_ || outer_scope_calls_eval_)) {
+        // If the code is not executed using eval and there are no
+        // with scopes, either we have a local or a global variable
+        // that might be shadowed by an eval-introduced variable.
+        if (invalidated_local != NULL) {
+          var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
+          var->set_local_if_not_shadowed(invalidated_local);
+        } else {
+          var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
+        }

        } else {
          // We must have a global variable.
@@ -643,15 +662,21 @@
  }


-bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval) {
+bool Scope::PropagateScopeInfo(bool outer_scope_calls_eval,
+                               bool outer_scope_is_eval_scope) {
    if (outer_scope_calls_eval) {
      outer_scope_calls_eval_ = true;
    }

-  bool b = scope_calls_eval_ || outer_scope_calls_eval_;
+  if (outer_scope_is_eval_scope) {
+    outer_scope_is_eval_scope_ = true;
+  }
+
+  bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_;
+  bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_;
    for (int i = 0; i < inner_scopes_.length(); i++) {
      Scope* inner_scope = inner_scopes_[i];
-    if (inner_scope->PropagateScopeInfo(b)) {
+    if (inner_scope->PropagateScopeInfo(calls_eval, is_eval)) {
        inner_scope_calls_eval_ = true;
      }
      if (inner_scope->force_eager_compilation_) {

Modified: branches/bleeding_edge/src/scopes.h
==============================================================================
--- branches/bleeding_edge/src/scopes.h (original)
+++ branches/bleeding_edge/src/scopes.h Wed Feb 18 07:55:24 2009
@@ -166,10 +166,13 @@
    bool is_function_scope() const  { return type_ == FUNCTION_SCOPE; }
    bool is_global_scope() const  { return type_ == GLOBAL_SCOPE; }

+  // Information about which scopes calls eval.
+  bool calls_eval() const  { return scope_calls_eval_; }
+  bool outer_scope_calls_eval() const  { return outer_scope_calls_eval_; }
+
    // The scope immediately surrounding this scope, or NULL.
    Scope* outer_scope() const  { return outer_scope_; }

-
    //  
---------------------------------------------------------------------------
    // Accessors.

@@ -290,6 +293,7 @@
    // Computed via PropagateScopeInfo.
    bool outer_scope_calls_eval_;
    bool inner_scope_calls_eval_;
+  bool outer_scope_is_eval_scope_;
    bool force_eager_compilation_;

    // Computed via AllocateVariables; function scopes only.
@@ -298,15 +302,18 @@

    // Create a non-local variable with a given name.
    // These variables are looked up dynamically at runtime.
-  Variable* NonLocal(Handle<String> name);
+  Variable* NonLocal(Handle<String> name, Variable::Mode mode);

    // Variable resolution.
-  Variable* LookupRecursive(Handle<String> name, bool inner_lookup);
+  Variable* LookupRecursive(Handle<String> name,
+                            bool inner_lookup,
+                            Variable** invalidated_local);
    void ResolveVariable(Scope* global_scope, VariableProxy* proxy);
    void ResolveVariablesRecursively(Scope* global_scope);

    // Scope analysis.
-  bool PropagateScopeInfo(bool outer_scope_calls_eval);
+  bool PropagateScopeInfo(bool outer_scope_calls_eval,
+                          bool outer_scope_is_eval_scope);
    bool HasTrivialContext() const;

    // Predicates.

Modified: branches/bleeding_edge/src/variables.cc
==============================================================================
--- branches/bleeding_edge/src/variables.cc     (original)
+++ branches/bleeding_edge/src/variables.cc     Wed Feb 18 07:55:24 2009
@@ -110,6 +110,8 @@
      case VAR: return "VAR";
      case CONST: return "CONST";
      case DYNAMIC: return "DYNAMIC";
+    case DYNAMIC_GLOBAL: return "DYNAMIC_GLOBAL";
+    case DYNAMIC_LOCAL: return "DYNAMIC_LOCAL";
      case INTERNAL: return "INTERNAL";
      case TEMPORARY: return "TEMPORARY";
    }
@@ -143,6 +145,7 @@
      mode_(mode),
      is_valid_LHS_(is_valid_LHS),
      is_this_(is_this),
+    local_if_not_shadowed_(NULL),
      is_accessed_from_inner_scope_(false),
      rewrite_(NULL) {
    // names must be canonicalized for fast equality checks
@@ -155,6 +158,5 @@
    // activation frame.
    return mode_ != TEMPORARY && scope_ != NULL && scope_->is_global_scope();
  }
-

  } }  // namespace v8::internal

Modified: branches/bleeding_edge/src/variables.h
==============================================================================
--- branches/bleeding_edge/src/variables.h      (original)
+++ branches/bleeding_edge/src/variables.h      Wed Feb 18 07:55:24 2009
@@ -113,13 +113,27 @@
    enum Mode {
      // User declared variables:
      VAR,       // declared via 'var', and 'function' declarations
+
      CONST,     // declared via 'const' declarations

      // Variables introduced by the compiler:
-    DYNAMIC,   // always require dynamic lookup (we don't know the  
declaration)
-    INTERNAL,  // like VAR, but not user-visible (may or may not be in a
-               // context)
-    TEMPORARY  // temporary variables (not user-visible), never in a  
context
+    DYNAMIC,         // always require dynamic lookup (we don't know
+                     // the declaration)
+
+    DYNAMIC_GLOBAL,  // requires dynamic lookup, but we know that the
+                     // variable is global unless it has been shadowed
+                     // by an eval-introduced variable
+
+    DYNAMIC_LOCAL,   // requires dynamic lookup, but we know that the
+                     // variable is local and where it is unless it
+                     // has been shadowed by an eval-introduced
+                     // variable
+
+    INTERNAL,        // like VAR, but not user-visible (may or may not
+                     // be in a context)
+
+    TEMPORARY        // temporary variables (not user-visible), never
+                     // in a context
    };

    // Printing support
@@ -150,9 +164,24 @@
      return !is_this() && name().is_identical_to(n);
    }

+  bool is_dynamic() const {
+    return (mode_ == DYNAMIC ||
+            mode_ == DYNAMIC_GLOBAL ||
+            mode_ == DYNAMIC_LOCAL);
+  }
+
    bool is_global() const;
    bool is_this() const { return is_this_; }

+  Variable* local_if_not_shadowed() const {
+    ASSERT(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL);
+    return local_if_not_shadowed_;
+  }
+
+  void set_local_if_not_shadowed(Variable* local) {
+    local_if_not_shadowed_ = local;
+  }
+
    Expression* rewrite() const  { return rewrite_; }
    Slot* slot() const;

@@ -167,6 +196,8 @@
    Mode mode_;
    bool is_valid_LHS_;
    bool is_this_;
+
+  Variable* local_if_not_shadowed_;

    // Usage info.
    bool is_accessed_from_inner_scope_;  // set by variable resolver

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to