Version 3.0.8

Exposed heap size limit to the heap statistics gathered by the GetHeapStatistics API. 

Wrapped external pointers more carefully (issue 1037).

Hardened the implementation of error objects to avoid setters intercepting the properties set then throwing an error.

Avoided trashing the FPSCR when calculating Math.floor on ARM.

Performance improvements on the IA32 platform.


git-svn-id: http://v8.googlecode.com/svn/trunk@6346 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/scopes.cc b/src/scopes.cc
index 3565e11..58a10ee 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -112,68 +112,74 @@
 
 // Dummy constructor
 Scope::Scope(Type type)
-  : outer_scope_(NULL),
-    inner_scopes_(0),
-    type_(type),
-    scope_name_(Factory::empty_symbol()),
+  : inner_scopes_(0),
     variables_(false),
     temps_(0),
     params_(0),
-    dynamics_(NULL),
     unresolved_(0),
-    decls_(0),
-    receiver_(NULL),
-    function_(NULL),
-    arguments_(NULL),
-    arguments_shadow_(NULL),
-    illegal_redecl_(NULL),
-    scope_inside_with_(false),
-    scope_contains_with_(false),
-    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) {
+    decls_(0) {
+  SetDefaults(type, NULL, NULL);
+  ASSERT(!resolved());
 }
 
 
 Scope::Scope(Scope* outer_scope, Type type)
-  : outer_scope_(outer_scope),
-    inner_scopes_(4),
-    type_(type),
-    scope_name_(Factory::empty_symbol()),
+  : inner_scopes_(4),
+    variables_(),
     temps_(4),
     params_(4),
-    dynamics_(NULL),
     unresolved_(16),
-    decls_(4),
-    receiver_(NULL),
-    function_(NULL),
-    arguments_(NULL),
-    arguments_shadow_(NULL),
-    illegal_redecl_(NULL),
-    scope_inside_with_(false),
-    scope_contains_with_(false),
-    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) {
+    decls_(4) {
+  SetDefaults(type, outer_scope, NULL);
   // At some point we might want to provide outer scopes to
   // eval scopes (by walking the stack and reading the scope info).
   // In that case, the ASSERT below needs to be adjusted.
   ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
   ASSERT(!HasIllegalRedeclaration());
+  ASSERT(!resolved());
 }
 
 
+Scope::Scope(Scope* inner_scope, SerializedScopeInfo* scope_info)
+  : inner_scopes_(4),
+    variables_(),
+    temps_(4),
+    params_(4),
+    unresolved_(16),
+    decls_(4) {
+  ASSERT(scope_info != NULL);
+  SetDefaults(FUNCTION_SCOPE, inner_scope->outer_scope(), scope_info);
+  ASSERT(resolved());
+  InsertAfterScope(inner_scope);
+  if (scope_info->HasHeapAllocatedLocals()) {
+    num_heap_slots_ = scope_info_->NumberOfContextSlots();
+  }
+}
+
+
+
 bool Scope::Analyze(CompilationInfo* info) {
   ASSERT(info->function() != NULL);
   Scope* top = info->function()->scope();
+
+  // If we have a serialized scope info, reuse it.
+  if (!info->closure().is_null()) {
+    SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
+    if (scope_info != SerializedScopeInfo::Empty()) {
+      Scope* scope = top;
+      JSFunction* current = *info->closure();
+      do {
+        current = current->context()->closure();
+        SerializedScopeInfo* scope_info = current->shared()->scope_info();
+        if (scope_info != SerializedScopeInfo::Empty()) {
+          scope = new Scope(scope, scope_info);
+        } else {
+          ASSERT(current->context()->IsGlobalContext());
+        }
+      } while (!current->context()->IsGlobalContext());
+    }
+  }
+
   while (top->outer_scope() != NULL) top = top->outer_scope();
   top->AllocateVariables(info->calling_context());
 
@@ -191,6 +197,8 @@
 
 
 void Scope::Initialize(bool inside_with) {
+  ASSERT(!resolved());
+
   // Add this scope as a new inner scope of the outer scope.
   if (outer_scope_ != NULL) {
     outer_scope_->inner_scopes_.Add(this);
@@ -210,7 +218,7 @@
   Variable* var =
       variables_.Declare(this, Factory::this_symbol(), Variable::VAR,
                          false, Variable::THIS);
-  var->rewrite_ = new Slot(var, Slot::PARAMETER, -1);
+  var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
   receiver_ = var;
 
   if (is_function_scope()) {
@@ -224,7 +232,28 @@
 
 
 Variable* Scope::LocalLookup(Handle<String> name) {
-  return variables_.Lookup(name);
+  Variable* result = variables_.Lookup(name);
+  if (result != NULL || !resolved()) {
+    return result;
+  }
+  // If the scope is resolved, we can find a variable in serialized scope info.
+
+  // We should never lookup 'arguments' in this scope
+  // as it is impllicitly present in any scope.
+  ASSERT(*name != *Factory::arguments_symbol());
+
+  // Check context slot lookup.
+  Variable::Mode mode;
+  int index = scope_info_->ContextSlotIndex(*name, &mode);
+  if (index < 0) {
+    return NULL;
+  }
+
+  // Check that there is no local slot with the given name.
+  ASSERT(scope_info_->StackSlotIndex(*name) < 0);
+  Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL);
+  var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
+  return var;
 }
 
 
@@ -250,6 +279,7 @@
   // DYNAMIC variables are introduces during variable allocation,
   // INTERNAL variables are allocated explicitly, and TEMPORARY
   // variables are allocated via NewTemporary().
+  ASSERT(!resolved());
   ASSERT(mode == Variable::VAR || mode == Variable::CONST);
   return variables_.Declare(this, name, mode, true, Variable::NORMAL);
 }
@@ -273,6 +303,7 @@
   // Note that we must not share the unresolved variables with
   // the same name because they may be removed selectively via
   // RemoveUnresolved().
+  ASSERT(!resolved());
   VariableProxy* proxy = new VariableProxy(name, false, inside_with);
   unresolved_.Add(proxy);
   return proxy;
@@ -292,6 +323,7 @@
 
 
 Variable* Scope::NewTemporary(Handle<String> name) {
+  ASSERT(!resolved());
   Variable* var =
       new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL);
   temps_.Add(var);
@@ -550,7 +582,7 @@
     // Declare a new non-local.
     var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
     // Allocate it by giving it a dynamic lookup.
-    var->rewrite_ = new Slot(var, Slot::LOOKUP, -1);
+    var->set_rewrite(new Slot(var, Slot::LOOKUP, -1));
   }
   return var;
 }
@@ -612,8 +644,9 @@
   ASSERT(var != NULL);
 
   // If this is a lookup from an inner scope, mark the variable.
-  if (inner_lookup)
-    var->is_accessed_from_inner_scope_ = true;
+  if (inner_lookup) {
+    var->MarkAsAccessedFromInnerScope();
+  }
 
   // If the variable we have found is just a guess, invalidate the
   // result. If the found variable is local, record that fact so we
@@ -753,7 +786,7 @@
   // via an eval() call.  This is only possible if the variable has a
   // visible name.
   if ((var->is_this() || var->name()->length() > 0) &&
-      (var->is_accessed_from_inner_scope_ ||
+      (var->is_accessed_from_inner_scope() ||
        scope_calls_eval_ || inner_scope_calls_eval_ ||
        scope_contains_with_)) {
     var->set_is_used(true);
@@ -771,7 +804,7 @@
   // context.
   return
     var->mode() != Variable::TEMPORARY &&
-    (var->is_accessed_from_inner_scope_ ||
+    (var->is_accessed_from_inner_scope() ||
      scope_calls_eval_ || inner_scope_calls_eval_ ||
      scope_contains_with_ || var->is_global());
 }
@@ -787,12 +820,12 @@
 
 
 void Scope::AllocateStackSlot(Variable* var) {
-  var->rewrite_ = new Slot(var, Slot::LOCAL, num_stack_slots_++);
+  var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++));
 }
 
 
 void Scope::AllocateHeapSlot(Variable* var) {
-  var->rewrite_ = new Slot(var, Slot::CONTEXT, num_heap_slots_++);
+  var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++));
 }
 
 
@@ -857,7 +890,7 @@
           // It is ok to set this only now, because arguments is a local
           // variable that is allocated after the parameters have been
           // allocated.
-          arguments_shadow_->is_accessed_from_inner_scope_ = true;
+          arguments_shadow_->MarkAsAccessedFromInnerScope();
         }
         Property* rewrite =
             new Property(new VariableProxy(arguments_shadow_),
@@ -865,7 +898,7 @@
                          RelocInfo::kNoPosition,
                          Property::SYNTHETIC);
         rewrite->set_is_arguments_access(true);
-        var->rewrite_ = rewrite;
+        var->set_rewrite(rewrite);
       }
     }
 
@@ -880,23 +913,23 @@
       ASSERT(var->scope() == this);
       if (MustAllocate(var)) {
         if (MustAllocateInContext(var)) {
-          ASSERT(var->rewrite_ == NULL ||
+          ASSERT(var->rewrite() == NULL ||
                  (var->AsSlot() != NULL &&
                   var->AsSlot()->type() == Slot::CONTEXT));
-          if (var->rewrite_ == NULL) {
+          if (var->rewrite() == NULL) {
             // Only set the heap allocation if the parameter has not
             // been allocated yet.
             AllocateHeapSlot(var);
           }
         } else {
-          ASSERT(var->rewrite_ == NULL ||
+          ASSERT(var->rewrite() == NULL ||
                  (var->AsSlot() != NULL &&
                   var->AsSlot()->type() == Slot::PARAMETER));
           // Set the parameter index always, even if the parameter
           // was seen before! (We need to access the actual parameter
           // supplied for the last occurrence of a multiply declared
           // parameter.)
-          var->rewrite_ = new Slot(var, Slot::PARAMETER, i);
+          var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
         }
       }
     }
@@ -906,10 +939,10 @@
 
 void Scope::AllocateNonParameterLocal(Variable* var) {
   ASSERT(var->scope() == this);
-  ASSERT(var->rewrite_ == NULL ||
+  ASSERT(var->rewrite() == NULL ||
          (!var->IsVariable(Factory::result_symbol())) ||
          (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL));
-  if (var->rewrite_ == NULL && MustAllocate(var)) {
+  if (var->rewrite() == NULL && MustAllocate(var)) {
     if (MustAllocateInContext(var)) {
       AllocateHeapSlot(var);
     } else {
@@ -943,15 +976,18 @@
 
 
 void Scope::AllocateVariablesRecursively() {
-  // The number of slots required for variables.
-  num_stack_slots_ = 0;
-  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
-
   // Allocate variables for inner scopes.
   for (int i = 0; i < inner_scopes_.length(); i++) {
     inner_scopes_[i]->AllocateVariablesRecursively();
   }
 
+  // If scope is already resolved, we still need to allocate
+  // variables in inner scopes which might not had been resolved yet.
+  if (resolved()) return;
+  // The number of slots required for variables.
+  num_stack_slots_ = 0;
+  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
+
   // Allocate variables for this scope.
   // Parameters must be allocated first, if any.
   if (is_function_scope()) AllocateParameterLocals();