X87: Switch full-codegen from StackHandlers to handler table.
authorchunyang.dai <chunyang.dai@intel.com>
Thu, 26 Mar 2015 13:06:47 +0000 (06:06 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 26 Mar 2015 13:06:56 +0000 (13:06 +0000)
port 38a719f965d0a83ddac04392d5b9c5abe214281c  (r27440)

original commit message:

    This switches full-codegen to no longer push and pop StackHandler
    markers onto the operand stack, but relies on a range-based handler
    table instead. We only use StackHandlers in JSEntryStubs to mark the
    transition from C to JS code.

    Note that this makes deoptimization and OSR from within any try-block
    work out of the box, makes the non-exception paths faster and should
    overall be neutral on the memory footprint (pros).

    On the other hand it makes the exception paths slower and actually
    throwing and exception more expensive (cons).

BUG=

Review URL: https://codereview.chromium.org/1030283003

Cr-Commit-Position: refs/heads/master@{#27478}

src/x87/code-stubs-x87.cc
src/x87/full-codegen-x87.cc
src/x87/macro-assembler-x87.cc
src/x87/macro-assembler-x87.h

index d5c362d76feeaa1484a01b2e5baa97fccb031a66..4e39ab86297a8e52f75f198763eacb4e6da7e9d8 100644 (file)
@@ -2248,9 +2248,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
   __ mov(esp, Operand::StaticVariable(pending_handler_sp_address));
   __ mov(ebp, Operand::StaticVariable(pending_handler_fp_address));
 
-  // If the handler is a JS frame, restore the context to the frame.
-  // (kind == ENTRY) == (ebp == 0) == (esi == 0), so we could test either
-  // ebp or esi.
+  // If the handler is a JS frame, restore the context to the frame. Note that
+  // the context will be set to (esi == 0) for non-JS frames.
   Label skip;
   __ test(esi, esi);
   __ j(zero, &skip, Label::kNear);
@@ -2311,10 +2310,9 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
   __ mov(eax, Immediate(isolate()->factory()->exception()));
   __ jmp(&exit);
 
-  // Invoke: Link this frame into the handler chain.  There's only one
-  // handler block in this code object, so its index is 0.
+  // Invoke: Link this frame into the handler chain.
   __ bind(&invoke);
-  __ PushTryHandler(StackHandler::JS_ENTRY, 0);
+  __ PushStackHandler();
 
   // Clear any pending exceptions.
   __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
@@ -2340,7 +2338,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
   __ call(edx);
 
   // Unlink this frame from the handler chain.
-  __ PopTryHandler();
+  __ PopStackHandler();
 
   __ bind(&exit);
   // Check if the current stack frame is marked as the outermost JS frame.
index 2d1a614ab21208796bcab51658f3bac5eed39dd5..59ff09f2db8f35e8821b5554064bd757c6eeded7 100644 (file)
@@ -95,7 +95,8 @@ class JumpPatchSite BASE_EMBEDDED {
 void FullCodeGenerator::Generate() {
   CompilationInfo* info = info_;
   handler_table_ =
-      isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
+      Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
+          HandlerTable::LengthForRange(function()->handler_count()), TENURED));
 
   profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
@@ -2108,7 +2109,6 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
 
       // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
       __ bind(&l_catch);
-      handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
       __ mov(load_name, isolate()->factory()->throw_string());  // "throw"
       __ push(load_name);                                       // "throw"
       __ push(Operand(esp, 2 * kPointerSize));                  // iter
@@ -2120,16 +2120,17 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       // re-boxing.
       __ bind(&l_try);
       __ pop(eax);                                       // result
-      __ PushTryHandler(StackHandler::CATCH, expr->index());
-      const int handler_size = StackHandlerConstants::kSize;
+      EnterTryBlock(expr->index(), &l_catch);
+      const int try_block_size = TryCatch::kElementCount * kPointerSize;
       __ push(eax);                                      // result
       __ jmp(&l_suspend);
       __ bind(&l_continuation);
       __ jmp(&l_resume);
       __ bind(&l_suspend);
-      const int generator_object_depth = kPointerSize + handler_size;
+      const int generator_object_depth = kPointerSize + try_block_size;
       __ mov(eax, Operand(esp, generator_object_depth));
       __ push(eax);                                      // g
+      __ push(Immediate(Smi::FromInt(expr->index())));   // handler-index
       DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
       __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
              Immediate(Smi::FromInt(l_continuation.pos())));
@@ -2137,13 +2138,13 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ mov(ecx, esi);
       __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
                           kDontSaveFPRegs);
-      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
+      __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 2);
       __ mov(context_register(),
              Operand(ebp, StandardFrameConstants::kContextOffset));
       __ pop(eax);                                       // result
       EmitReturnSequence();
       __ bind(&l_resume);                                // received in eax
-      __ PopTryHandler();
+      ExitTryBlock(expr->index());
 
       // receiver = iter; f = iter.next; arg = received;
       __ bind(&l_next);
@@ -5266,33 +5267,6 @@ void FullCodeGenerator::ExitFinallyBlock() {
 }
 
 
-#undef __
-
-#define __ ACCESS_MASM(masm())
-
-FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
-    int* stack_depth,
-    int* context_length) {
-  // The macros used here must preserve the result register.
-
-  // Because the handler block contains the context of the finally
-  // code, we can restore it directly from there for the finally code
-  // rather than iteratively unwinding contexts via their previous
-  // links.
-  __ Drop(*stack_depth);  // Down to the handler block.
-  if (*context_length > 0) {
-    // Restore the context to its dedicated register and the stack.
-    __ mov(esi, Operand(esp, StackHandlerConstants::kContextOffset));
-    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
-  }
-  __ PopTryHandler();
-  __ call(finally_entry_);
-
-  *stack_depth = 0;
-  *context_length = 0;
-  return previous_;
-}
-
 #undef __
 
 
index b6befebf67ecefe251a4b0446143f17775136898..5cc41b793efc4259ca069baf31807e01cca18573 100644 (file)
@@ -987,34 +987,21 @@ void MacroAssembler::LeaveApiExitFrame(bool restore_context) {
 }
 
 
-void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
-                                    int handler_index) {
+void MacroAssembler::PushStackHandler() {
   // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 3 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kSize == 1 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
-  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
-
-  // We will build up the handler from the bottom by pushing on the stack.
-  // First push the context.
-  if (kind == StackHandler::JS_ENTRY) {
-    push(Immediate(Smi::FromInt(0)));  // No context.
-  } else {
-    push(esi);
-  }
-
-  // Push the index.
-  push(Immediate(handler_index));
 
   // Link the current handler as the next handler.
   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   push(Operand::StaticVariable(handler_address));
+
   // Set this new handler as the current one.
   mov(Operand::StaticVariable(handler_address), esp);
 }
 
 
-void MacroAssembler::PopTryHandler() {
+void MacroAssembler::PopStackHandler() {
   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
   ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
   pop(Operand::StaticVariable(handler_address));
index e801bf52f80958c2d9982d3984c1fb59f57a769f..c392598c91bf9750df72f82d3d2a7f7b19796656 100644 (file)
@@ -535,11 +535,11 @@ class MacroAssembler: public Assembler {
   // ---------------------------------------------------------------------------
   // Exception handling
 
-  // Push a new try handler and link it into try handler chain.
-  void PushTryHandler(StackHandler::Kind kind, int handler_index);
+  // Push a new stack handler and link it into stack handler chain.
+  void PushStackHandler();
 
-  // Unlink the stack handler on top of the stack from the try handler chain.
-  void PopTryHandler();
+  // Unlink the stack handler on top of the stack from the stack handler chain.
+  void PopStackHandler();
 
   // ---------------------------------------------------------------------------
   // Inline caching support