Version 3.6.1

Fixed a bug in abrupt exit from with or catch inside finally.

Fixed possible crash in FixedDoubleArray::Initialize() (Chromium issue 95113).

Fixed a bug in Page::GetRegionMaskForSpan (Chromium issue 94425).

Fixed a few clang warnings (which -Werror treated as errors).

Performance improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@9173 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 0f44cf2..d810bb3 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -190,9 +190,9 @@
 void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
   // If assigning to a property (including a global property) the assignment is
   // breakable.
-  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
+  VariableProxy* proxy = expr->target()->AsVariableProxy();
   Property* prop = expr->target()->AsProperty();
-  if (prop != NULL || (var != NULL && var->is_global())) {
+  if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
     is_breakable_ = true;
     return;
   }
@@ -395,26 +395,6 @@
 }
 
 
-int FullCodeGenerator::SlotOffset(Slot* slot) {
-  ASSERT(slot != NULL);
-  // Offset is negative because higher indexes are at lower addresses.
-  int offset = -slot->index() * kPointerSize;
-  // Adjust by a (parameter or local) base offset.
-  switch (slot->type()) {
-    case Slot::PARAMETER:
-      offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
-      break;
-    case Slot::LOCAL:
-      offset += JavaScriptFrameConstants::kLocal0Offset;
-      break;
-    case Slot::CONTEXT:
-    case Slot::LOOKUP:
-      UNREACHABLE();
-  }
-  return offset;
-}
-
-
 bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
   // Inline smi case inside loops, but not division and modulo which
   // are too complicated and take up too much space.
@@ -529,34 +509,21 @@
 void FullCodeGenerator::VisitDeclarations(
     ZoneList<Declaration*>* declarations) {
   int length = declarations->length();
-  int globals = 0;
+  int global_count = 0;
   for (int i = 0; i < length; i++) {
     Declaration* decl = declarations->at(i);
-    Variable* var = decl->proxy()->var();
-    Slot* slot = var->AsSlot();
-
-    // If it was not possible to allocate the variable at compile
-    // time, we need to "declare" it at runtime to make sure it
-    // actually exists in the local context.
-    if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
-      VisitDeclaration(decl);
-    } else {
-      // Count global variables and functions for later processing
-      globals++;
-    }
+    EmitDeclaration(decl->proxy(), decl->mode(), decl->fun(), &global_count);
   }
 
-  // Compute array of global variable and function declarations.
-  // Do nothing in case of no declared global functions or variables.
-  if (globals > 0) {
+  // Batch declare global functions and variables.
+  if (global_count > 0) {
     Handle<FixedArray> array =
-        isolate()->factory()->NewFixedArray(2 * globals, TENURED);
+        isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
     for (int j = 0, i = 0; i < length; i++) {
       Declaration* decl = declarations->at(i);
       Variable* var = decl->proxy()->var();
-      Slot* slot = var->AsSlot();
 
-      if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) {
+      if (var->IsUnallocated()) {
         array->set(j++, *(var->name()));
         if (decl->fun() == NULL) {
           if (var->mode() == Variable::CONST) {
@@ -578,7 +545,7 @@
       }
     }
     // Invoke the platform-dependent code generator to do the actual
-    // declaration the global variables and functions.
+    // declaration the global functions and variables.
     DeclareGlobals(array);
   }
 }
@@ -851,10 +818,11 @@
 
 void FullCodeGenerator::VisitBlock(Block* stmt) {
   Comment cmnt(masm_, "[ Block");
-  Breakable nested_statement(this, stmt);
+  NestedBlock nested_block(this, stmt);
   SetStatementPosition(stmt);
 
   Scope* saved_scope = scope();
+  // Push a block context when entering a block with block scoped variables.
   if (stmt->block_scope() != NULL) {
     { Comment cmnt(masm_, "[ Extend block context");
       scope_ = stmt->block_scope();
@@ -871,8 +839,16 @@
   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
   VisitStatements(stmt->statements());
   scope_ = saved_scope;
-  __ bind(nested_statement.break_label());
+  __ bind(nested_block.break_label());
   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
+
+  // Pop block context if necessary.
+  if (stmt->block_scope() != NULL) {
+    LoadContextField(context_register(), Context::PREVIOUS_INDEX);
+    // Update local stack frame context field.
+    StoreToFrameField(StandardFrameConstants::kContextOffset,
+                      context_register());
+  }
 }
 
 
@@ -1345,25 +1321,6 @@
 }
 
 
-FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
-    int* stack_depth,
-    int* context_length) {
-  // The macros used here must preserve the result register.
-  __ Drop(*stack_depth);
-  __ PopTryHandler();
-  *stack_depth = 0;
-
-  Register context = FullCodeGenerator::context_register();
-  while (*context_length > 0) {
-    codegen_->LoadContextField(context, Context::PREVIOUS_INDEX);
-    --(*context_length);
-  }
-
-  __ Call(finally_entry_);
-  return previous_;
-}
-
-
 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
     int* stack_depth,
     int* context_length) {