Version 3.5.5.

Fixed bugs involving negative zero and the optimizing compiler.
Fixed optimized version of Function.apply(x, arguments). (issue 1592)
Eliminated uses of deprecated ARM instructions.
Sped up Math.floor by using SSE 4.1 roundsd instruction on ia32.
Removed restriction on the size of disassembled code that is printed.
Review URL: http://codereview.chromium.org/7618040

git-svn-id: http://v8.googlecode.com/svn/trunk@8933 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index e5375fc..732a8fe 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -35,6 +35,7 @@
 #include "macro-assembler.h"
 #include "prettyprinter.h"
 #include "scopes.h"
+#include "scopeinfo.h"
 #include "stub-cache.h"
 
 namespace v8 {
@@ -90,8 +91,7 @@
 }
 
 
-void BreakableStatementChecker::VisitEnterWithContextStatement(
-    EnterWithContextStatement* stmt) {
+void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
   Visit(stmt->expression());
 }
 
@@ -317,7 +317,6 @@
   // field, and then a sequence of entries.  Each entry is a pair of AST id
   // and code-relative pc offset.
   masm()->Align(kIntSize);
-  masm()->RecordComment("[ Stack check table");
   unsigned offset = masm()->pc_offset();
   unsigned length = stack_checks_.length();
   __ dd(length);
@@ -325,7 +324,6 @@
     __ dd(stack_checks_[i].id);
     __ dd(stack_checks_[i].pc_and_state);
   }
-  masm()->RecordComment("]");
   return offset;
 }
 
@@ -847,8 +845,23 @@
   Breakable nested_statement(this, stmt);
   SetStatementPosition(stmt);
 
+  Scope* saved_scope = scope();
+  if (stmt->block_scope() != NULL) {
+    { Comment cmnt(masm_, "[ Extend block context");
+      scope_ = stmt->block_scope();
+      __ Push(scope_->GetSerializedScopeInfo());
+      PushFunctionArgumentForContextAllocation();
+      __ CallRuntime(Runtime::kPushBlockContext, 2);
+      StoreToFrameField(StandardFrameConstants::kContextOffset,
+                        context_register());
+    }
+    { Comment cmnt(masm_, "[ Declarations");
+      VisitDeclarations(scope_->declarations());
+    }
+  }
   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
   VisitStatements(stmt->statements());
+  scope_ = saved_scope;
   __ bind(nested_statement.break_target());
   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
 }
@@ -900,16 +913,24 @@
   SetStatementPosition(stmt);
   NestedStatement* current = nesting_stack_;
   int stack_depth = 0;
+  int context_length = 0;
   // When continuing, we clobber the unpredictable value in the accumulator
   // with one that's safe for GC.  If we hit an exit from the try block of
   // try...finally on our way out, we will unconditionally preserve the
   // accumulator on the stack.
   ClearAccumulator();
   while (!current->IsContinueTarget(stmt->target())) {
-    stack_depth = current->Exit(stack_depth);
-    current = current->outer();
+    current = current->Exit(&stack_depth, &context_length);
   }
   __ Drop(stack_depth);
+  if (context_length > 0) {
+    while (context_length > 0) {
+      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
+      --context_length;
+    }
+    StoreToFrameField(StandardFrameConstants::kContextOffset,
+                      context_register());
+  }
 
   Iteration* loop = current->AsIteration();
   __ jmp(loop->continue_target());
@@ -921,16 +942,24 @@
   SetStatementPosition(stmt);
   NestedStatement* current = nesting_stack_;
   int stack_depth = 0;
+  int context_length = 0;
   // When breaking, we clobber the unpredictable value in the accumulator
   // with one that's safe for GC.  If we hit an exit from the try block of
   // try...finally on our way out, we will unconditionally preserve the
   // accumulator on the stack.
   ClearAccumulator();
   while (!current->IsBreakTarget(stmt->target())) {
-    stack_depth = current->Exit(stack_depth);
-    current = current->outer();
+    current = current->Exit(&stack_depth, &context_length);
   }
   __ Drop(stack_depth);
+  if (context_length > 0) {
+    while (context_length > 0) {
+      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
+      --context_length;
+    }
+    StoreToFrameField(StandardFrameConstants::kContextOffset,
+                      context_register());
+  }
 
   Breakable* target = current->AsBreakable();
   __ jmp(target->break_target());
@@ -946,9 +975,9 @@
   // Exit all nested statements.
   NestedStatement* current = nesting_stack_;
   int stack_depth = 0;
+  int context_length = 0;
   while (current != NULL) {
-    stack_depth = current->Exit(stack_depth);
-    current = current->outer();
+    current = current->Exit(&stack_depth, &context_length);
   }
   __ Drop(stack_depth);
 
@@ -956,9 +985,8 @@
 }
 
 
-void FullCodeGenerator::VisitEnterWithContextStatement(
-    EnterWithContextStatement* stmt) {
-  Comment cmnt(masm_, "[ EnterWithContextStatement");
+void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
+  Comment cmnt(masm_, "[ WithStatement");
   SetStatementPosition(stmt);
 
   VisitForStackValue(stmt->expression());
@@ -966,6 +994,15 @@
   __ CallRuntime(Runtime::kPushWithContext, 2);
   decrement_stack_height();
   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
+
+  { WithOrCatch body(this);
+    Visit(stmt->statement());
+  }
+
+  // Pop context.
+  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
+  // Update local stack frame context field.
+  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
 }
 
 
@@ -1124,7 +1161,9 @@
   Scope* saved_scope = scope();
   scope_ = stmt->scope();
   ASSERT(scope_->declarations()->is_empty());
-  Visit(stmt->catch_block());
+  { WithOrCatch body(this);
+    Visit(stmt->catch_block());
+  }
   scope_ = saved_scope;
   __ jmp(&done);
 
@@ -1170,8 +1209,8 @@
   Label try_handler_setup;
   const int original_stack_height = stack_height();
   const int finally_block_stack_height = original_stack_height + 2;
-  const int try_block_stack_height = original_stack_height + 4;
-  STATIC_ASSERT(StackHandlerConstants::kSize / kPointerSize == 4);
+  const int try_block_stack_height = original_stack_height + 5;
+  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
 
   // Setup the try-handler chain. Use a call to
   // Jump to try-handler setup and try-block code. Use call to put try-handler
@@ -1300,20 +1339,33 @@
 }
 
 
-int FullCodeGenerator::TryFinally::Exit(int stack_depth) {
+FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
+    int* stack_depth,
+    int* context_length) {
   // The macros used here must preserve the result register.
-  __ Drop(stack_depth);
+  __ 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 0;
+  return previous_;
 }
 
 
-int FullCodeGenerator::TryCatch::Exit(int stack_depth) {
+FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
+    int* stack_depth,
+    int* context_length) {
   // The macros used here must preserve the result register.
-  __ Drop(stack_depth);
+  __ Drop(*stack_depth);
   __ PopTryHandler();
-  return 0;
+  *stack_depth = 0;
+  return previous_;
 }