Revision: 13593
Author:   [email protected]
Date:     Tue Feb  5 00:09:32 2013
Log:      Support pass-through of stub caller arguments

Review URL: https://codereview.chromium.org/12093089
http://code.google.com/p/v8/source/detail?r=13593

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/deoptimizer-arm.cc
 /branches/bleeding_edge/src/arm/frames-arm.h
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/code-stubs-hydrogen.cc
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/deoptimizer.cc
 /branches/bleeding_edge/src/frames-inl.h
 /branches/bleeding_edge/src/frames.cc
 /branches/bleeding_edge/src/frames.h
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/deoptimizer-ia32.cc
 /branches/bleeding_edge/src/ia32/frames-ia32.h
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/src/x64/deoptimizer-x64.cc
 /branches/bleeding_edge/src/x64/frames-x64.h
 /branches/bleeding_edge/src/x64/lithium-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Tue Feb 5 00:09:32 2013
@@ -7879,7 +7879,12 @@
   bool save_fp_regs = CpuFeatures::IsSupported(VFP2);
   CEntryStub ces(1, save_fp_regs ? kSaveFPRegs : kDontSaveFPRegs);
   __ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
+  int parameter_count_offset =
+      StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
+  __ ldr(r1, MemOperand(fp, parameter_count_offset));
   masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
+  __ mov(r1, Operand(r1, LSL, kPointerSizeLog2));
+  __ add(sp, sp, r1);
   __ Ret();
 }

=======================================
--- /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Tue Feb 5 00:09:32 2013
@@ -466,13 +466,19 @@
   // v  +-------------------------+          +-------------------------|
   //    |   COMPILED_STUB marker  |          |   STUB_FAILURE marker   |
   //    +-------------------------+          +-------------------------+
-  //    |                         |          |     stub parameter 1    |
+  //    |                         |          |   caller args.length_   |
   //    | ...                     |          +-------------------------+
-  //    |                         |          |            ...          |
+  //    |                         |          |  caller args.arguments_ |
   //    |-------------------------|<-sp      +-------------------------+
-  //                                         |     stub parameter n    |
- // parameters in registers +-------------------------+<-sp
-  //       and spilled to stack              r0 = number of parameters
+  //                                         |  caller args pointer    |
+  //                                         +-------------------------+
+  //                                         |  caller stack param 1   |
+  //      parameters in registers            +-------------------------+
+  //       and spilled to stack              |           ....          |
+  //                                         +-------------------------+
+  //                                         |  caller stack param n   |
+ // +-------------------------+<-sp
+  //                                         r0 = number of parameters
   //                                         r1 = failure handler address
   //                                         fp = saved frame
   //                                         cp = JSFunction context
@@ -483,9 +489,15 @@
   CodeStubInterfaceDescriptor* descriptor =
       isolate_->code_stub_interface_descriptor(major_key);

+  // The output frame must have room for all pushed register parameters
+  // and the standard stack frame slots.
   int output_frame_size = StandardFrameConstants::kFixedFrameSize +
       kPointerSize * descriptor->register_param_count_;

+  // Include space for an argument object to the callee and optionally
+  // the space to pass the argument object to the stub failure handler.
+  output_frame_size += sizeof(Arguments) + kPointerSize;
+
   FrameDescription* output_frame =
       new(output_frame_size) FrameDescription(output_frame_size, 0);
   ASSERT(frame_index == 0);
@@ -497,12 +509,15 @@
       reinterpret_cast<intptr_t>(notify_failure->entry()));

   Code* trampoline = NULL;
-  StubFailureTrampolineStub().FindCodeInCache(&trampoline, isolate_);
+  int extra = descriptor->extra_expression_stack_count_;
+  StubFailureTrampolineStub(extra).FindCodeInCache(&trampoline, isolate_);
   ASSERT(trampoline != NULL);
   output_frame->SetPc(reinterpret_cast<intptr_t>(
       trampoline->instruction_start()));
   unsigned input_frame_size = input_->GetFrameSize();

+  intptr_t frame_ptr = input_->GetRegister(fp.code());
+
   // JSFunction continuation
   intptr_t input_frame_offset = input_frame_size - kPointerSize;
   intptr_t output_frame_offset = output_frame_size - kPointerSize;
@@ -528,6 +543,28 @@
       Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
   output_frame->SetFrameSlot(output_frame_offset, value);

+  int caller_arg_count = 0;
+  if (descriptor->stack_parameter_count_ != NULL) {
+    caller_arg_count =
+        input_->GetRegister(descriptor->stack_parameter_count_->code());
+  }
+
+ // Build the Arguments object for the caller's parameters and a pointer to it.
+  output_frame_offset -= kPointerSize;
+  value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
+      (caller_arg_count - 1) * kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, value);
+
+  output_frame->SetFrameSlot(output_frame_offset, value);
+  output_frame_offset -= kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, caller_arg_count);
+
+  value = frame_ptr - (output_frame_size - output_frame_offset) -
+      StandardFrameConstants::kMarkerOffset;
+  output_frame_offset -= kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, value);
+
+  // Copy the register parameters to the failure frame.
   for (int i = 0; i < descriptor->register_param_count_; ++i) {
     output_frame_offset -= kPointerSize;
     DoTranslateCommand(iterator, 0, output_frame_offset);
@@ -538,14 +575,17 @@
     output_frame->SetDoubleRegister(i, double_value);
   }

-  value = input_->GetRegister(fp.code());
-  output_frame->SetRegister(fp.code(), value);
-  output_frame->SetFp(value);
+  output_frame->SetRegister(fp.code(), frame_ptr);
+  output_frame->SetFp(frame_ptr);

   ApiFunction function(descriptor->deoptimization_handler_);
ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_);
   intptr_t handler = reinterpret_cast<intptr_t>(xref.address());
-  output_frame->SetRegister(r0.code(), descriptor->register_param_count_);
+  int params = descriptor->register_param_count_;
+  if (descriptor->stack_parameter_count_ != NULL) {
+    params++;
+  }
+  output_frame->SetRegister(r0.code(), params);
   output_frame->SetRegister(r1.code(), handler);
 }

=======================================
--- /branches/bleeding_edge/src/arm/frames-arm.h        Tue Jan 24 00:43:12 2012
+++ /branches/bleeding_edge/src/arm/frames-arm.h        Tue Feb  5 00:09:32 2013
@@ -134,20 +134,6 @@
 };


-class StandardFrameConstants : public AllStatic {
- public:
-  // Fixed part of the frame consists of return address, caller fp,
-  // context and function.
-  static const int kFixedFrameSize    =  4 * kPointerSize;
-  static const int kExpressionsOffset = -3 * kPointerSize;
-  static const int kMarkerOffset      = -2 * kPointerSize;
-  static const int kContextOffset     = -1 * kPointerSize;
-  static const int kCallerFPOffset    =  0 * kPointerSize;
-  static const int kCallerPCOffset    =  1 * kPointerSize;
-  static const int kCallerSPOffset    =  2 * kPointerSize;
-};
-
-
 class JavaScriptFrameConstants : public AllStatic {
  public:
   // FP-relative.
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Mon Feb  4 04:01:59 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Tue Feb  5 00:09:32 2013
@@ -2257,7 +2257,7 @@

 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
   LParameter* result = new(zone()) LParameter;
-  if (info()->IsOptimizing()) {
+  if (instr->kind() == HParameter::STACK_PARAMETER) {
     int spill_index = chunk()->GetParameterStackSlot(instr->index());
     return DefineAsSpilled(result, spill_index);
   } else {
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Feb 5 00:09:32 2013
@@ -102,7 +102,8 @@
   HGraph* graph = this->graph();
   Zone* zone = this->zone();
   for (int i = 0; i < descriptor->register_param_count_; ++i) {
-    HParameter* param = new(zone) HParameter(i);
+    HParameter* param =
+        new(zone) HParameter(i, HParameter::REGISTER_PARAMETER);
     AddInstruction(param);
     graph->start_environment()->Push(param);
     parameters_[i] = param;
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc   Fri Jan 25 03:55:29 2013
+++ /branches/bleeding_edge/src/code-stubs.cc   Tue Feb  5 00:09:32 2013
@@ -604,6 +604,14 @@
   masm->bind(&fail);
   KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
 }
+
+
+void StubFailureTrampolineStub::GenerateAheadOfTime() {
+  int i = 0;
+ for (; i <= StubFailureTrampolineStub::kMaxExtraExpressionStackCount; ++i) {
+    StubFailureTrampolineStub(i).GetCode();
+  }
+}


 FunctionEntryHook ProfileEntryHookStub::entry_hook_ = NULL;
=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Mon Feb  4 07:40:50 2013
+++ /branches/bleeding_edge/src/code-stubs.h    Tue Feb  5 00:09:32 2013
@@ -253,8 +253,12 @@
 struct CodeStubInterfaceDescriptor {
   CodeStubInterfaceDescriptor()
       : register_param_count_(-1),
+        stack_parameter_count_(NULL),
+        extra_expression_stack_count_(0),
         register_params_(NULL) { }
   int register_param_count_;
+  const Register* stack_parameter_count_;
+  int extra_expression_stack_count_;
   Register* register_params_;
   Address deoptimization_handler_;
 };
@@ -1420,14 +1424,23 @@

 class StubFailureTrampolineStub : public PlatformCodeStub {
  public:
-  StubFailureTrampolineStub() {}
+  static const int kMaxExtraExpressionStackCount = 1;
+
+  explicit StubFailureTrampolineStub(int extra_expression_stack_count)
+      : extra_expression_stack_count_(extra_expression_stack_count) {}
+
+  virtual bool IsPregenerated() { return true; }
+
+  static void GenerateAheadOfTime();

  private:
   Major MajorKey() { return StubFailureTrampoline; }
-  int MinorKey() { return 0; }
+  int MinorKey() { return extra_expression_stack_count_; }

   void Generate(MacroAssembler* masm);

+  int extra_expression_stack_count_;
+
   DISALLOW_COPY_AND_ASSIGN(StubFailureTrampolineStub);
 };

=======================================
--- /branches/bleeding_edge/src/deoptimizer.cc  Tue Jan 29 01:12:20 2013
+++ /branches/bleeding_edge/src/deoptimizer.cc  Tue Feb  5 00:09:32 2013
@@ -1497,10 +1497,9 @@
     // size matches with the stack height we can compute based on the
     // environment at the OSR entry. The code for that his built into
     // the DoComputeOsrOutputFrame function for now.
-  } else {
+  } else if (compiled_code_->kind() != Code::COMPILED_STUB) {
     unsigned stack_slots = compiled_code_->stack_slots();
-    unsigned outgoing_size = compiled_code_->kind() == Code::COMPILED_STUB
-        ? 0 : ComputeOutgoingArgumentSize();
+    unsigned outgoing_size = ComputeOutgoingArgumentSize();
ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
   }
 #endif
=======================================
--- /branches/bleeding_edge/src/frames-inl.h    Tue Jan 29 01:12:20 2013
+++ /branches/bleeding_edge/src/frames-inl.h    Tue Feb  5 00:09:32 2013
@@ -256,7 +256,7 @@


 inline StubFailureTrampolineFrame::StubFailureTrampolineFrame(
-    StackFrameIterator* iterator) : InternalFrame(iterator) {
+    StackFrameIterator* iterator) : StandardFrame(iterator) {
 }


=======================================
--- /branches/bleeding_edge/src/frames.cc       Tue Jan 29 01:12:20 2013
+++ /branches/bleeding_edge/src/frames.cc       Tue Feb  5 00:09:32 2013
@@ -1304,12 +1304,39 @@


 void StubFailureTrampolineFrame::Iterate(ObjectVisitor* v) const {
-  const int offset = StandardFrameConstants::kContextOffset;
   Object** base = &Memory::Object_at(sp());
-  Object** limit = &Memory::Object_at(fp() + offset) + 1;
+  Object** limit = &Memory::Object_at(fp() +
+                                      kFirstRegisterParameterFrameOffset);
+  v->VisitPointers(base, limit);
+  base = &Memory::Object_at(fp() + StandardFrameConstants::kMarkerOffset);
+  const int offset = StandardFrameConstants::kContextOffset;
+  limit = &Memory::Object_at(fp() + offset) + 1;
   v->VisitPointers(base, limit);
   IteratePc(v, pc_address(), LookupCode());
 }
+
+
+Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
+  return fp() + StandardFrameConstants::kCallerSPOffset;
+}
+
+
+Code* StubFailureTrampolineFrame::unchecked_code() const {
+  int i = 0;
+ for (; i <= StubFailureTrampolineStub::kMaxExtraExpressionStackCount; ++i) {
+    Code* trampoline;
+    StubFailureTrampolineStub(i).FindCodeInCache(&trampoline, isolate());
+    ASSERT(trampoline != NULL);
+    Address current_pc = pc();
+    Address code_start = trampoline->instruction_start();
+    Address code_end = code_start + trampoline->instruction_size();
+    if (code_start <= current_pc && current_pc < code_end) {
+      return trampoline;
+    }
+  }
+  UNREACHABLE();
+  return NULL;
+}


// -------------------------------------------------------------------------
=======================================
--- /branches/bleeding_edge/src/frames.h        Tue Jan 29 01:12:20 2013
+++ /branches/bleeding_edge/src/frames.h        Tue Feb  5 00:09:32 2013
@@ -143,6 +143,22 @@
   V(ARGUMENTS_ADAPTOR,       ArgumentsAdaptorFrame)


+class StandardFrameConstants : public AllStatic {
+ public:
+  // Fixed part of the frame consists of return address, caller fp,
+  // context and function.
+ // StandardFrame::IterateExpressions assumes that kContextOffset is the last
+  // object pointer.
+  static const int kFixedFrameSize    =  4 * kPointerSize;
+  static const int kExpressionsOffset = -3 * kPointerSize;
+  static const int kMarkerOffset      = -2 * kPointerSize;
+  static const int kContextOffset     = -1 * kPointerSize;
+  static const int kCallerFPOffset    =  0 * kPointerSize;
+  static const int kCallerPCOffset    = +1 * kPointerSize;
+  static const int kCallerSPOffset    = +2 * kPointerSize;
+};
+
+
 // Abstract base class for all stack frames.
 class StackFrame BASE_EMBEDDED {
  public:
@@ -672,9 +688,21 @@
 };


-class StubFailureTrampolineFrame: public InternalFrame {
+class StubFailureTrampolineFrame: public StandardFrame {
  public:
+  // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the
+  // presubmit script complains about using sizeof() on a type.
+  static const int kFirstRegisterParameterFrameOffset =
+      StandardFrameConstants::kMarkerOffset - 3 * kPointerSize;
+
+  static const int kCallerStackParameterCountFrameOffset =
+      StandardFrameConstants::kMarkerOffset - 2 * kPointerSize;
+
   virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; }
+
+  // Get the code associated with this frame.
+  // This method could be called during marking phase of GC.
+  virtual Code* unchecked_code() const;

   virtual void Iterate(ObjectVisitor* v) const;

@@ -682,6 +710,8 @@
   inline explicit StubFailureTrampolineFrame(
       StackFrameIterator* iterator);

+  virtual Address GetCallerStackPointer() const;
+
  private:
   friend class StackFrameIterator;
 };
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/hydrogen-instructions.h Tue Feb 5 00:09:32 2013
@@ -4010,11 +4010,20 @@

 class HParameter: public HTemplateInstruction<0> {
  public:
-  explicit HParameter(unsigned index) : index_(index) {
+  enum ParameterKind {
+    STACK_PARAMETER,
+    REGISTER_PARAMETER
+  };
+
+  explicit HParameter(unsigned index,
+                      ParameterKind kind = STACK_PARAMETER)
+      : index_(index),
+        kind_(kind) {
     set_representation(Representation::Tagged());
   }

   unsigned index() const { return index_; }
+  ParameterKind kind() const { return kind_; }

   virtual void PrintDataTo(StringStream* stream);

@@ -4026,6 +4035,7 @@

  private:
   unsigned index_;
+  ParameterKind kind_;
 };


=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Tue Feb 5 00:09:32 2013
@@ -48,6 +48,7 @@
   static Register registers[] = { edx, ecx };
   descriptor->register_param_count_ = 2;
   descriptor->register_params_ = registers;
+  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
 }
@@ -7646,8 +7647,14 @@
   bool save_fp_regs = CpuFeatures::IsSupported(SSE2);
   CEntryStub ces(1, save_fp_regs ? kSaveFPRegs : kDontSaveFPRegs);
   __ call(ces.GetCode(), RelocInfo::CODE_TARGET);
+  int parameter_count_offset =
+      StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
+  __ mov(ebx, MemOperand(ebp, parameter_count_offset));
   masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
-  __ ret(0);  // Return to IC Miss stub, continuation still on stack.
+  __ pop(ecx);
+  __ lea(esp, MemOperand(esp, ebx, times_pointer_size,
+                         extra_expression_stack_count_ * kPointerSize));
+  __ jmp(ecx);  // Return to IC Miss stub, continuation still on stack.
 }


=======================================
--- /branches/bleeding_edge/src/ia32/deoptimizer-ia32.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/ia32/deoptimizer-ia32.cc Tue Feb 5 00:09:32 2013
@@ -573,13 +573,19 @@
   // v  +-------------------------+          +-------------------------|
   //    |   COMPILED_STUB marker  |          |   STUB_FAILURE marker   |
   //    +-------------------------+          +-------------------------+
-  //    |                         |          |     stub parameter 1    |
+  //    |                         |          |   caller args.length_   |
   //    | ...                     |          +-------------------------+
-  //    |                         |          |            ...          |
+  //    |                         |          |  caller args.arguments_ |
   //    |-------------------------|<-esp     +-------------------------+
-  //                                         |     stub parameter n    |
- // parameters in registers +-------------------------+<-esp
-  //       and spilled to stack              eax = number of parameters
+  //                                         |  caller args pointer    |
+  //                                         +-------------------------+
+  //                                         |  caller stack param 1   |
+  //      parameters in registers            +-------------------------+
+  //       and spilled to stack              |           ....          |
+  //                                         +-------------------------+
+  //                                         |  caller stack param n   |
+ // +-------------------------+<-esp
+  //                                         eax = number of parameters
   //                                         ebx = failure handler address
   //                                         ebp = saved frame
   //                                         esi = JSFunction context
@@ -590,9 +596,15 @@
   CodeStubInterfaceDescriptor* descriptor =
       isolate_->code_stub_interface_descriptor(major_key);

+  // The output frame must have room for all pushed register parameters
+  // and the standard stack frame slots.
   int output_frame_size = StandardFrameConstants::kFixedFrameSize +
       kPointerSize * descriptor->register_param_count_;

+  // Include space for an argument object to the callee and optionally
+  // the space to pass the argument object to the stub failure handler.
+  output_frame_size += sizeof(Arguments) + kPointerSize;
+
   FrameDescription* output_frame =
       new(output_frame_size) FrameDescription(output_frame_size, 0);
   ASSERT(frame_index == 0);
@@ -604,12 +616,15 @@
       reinterpret_cast<intptr_t>(notify_failure->entry()));

   Code* trampoline = NULL;
-  StubFailureTrampolineStub().FindCodeInCache(&trampoline, isolate_);
+  int extra = descriptor->extra_expression_stack_count_;
+  StubFailureTrampolineStub(extra).FindCodeInCache(&trampoline, isolate_);
   ASSERT(trampoline != NULL);
   output_frame->SetPc(reinterpret_cast<intptr_t>(
       trampoline->instruction_start()));
   unsigned input_frame_size = input_->GetFrameSize();

+  intptr_t frame_ptr = input_->GetRegister(ebp.code());
+
   // JSFunction continuation
   intptr_t input_frame_offset = input_frame_size - kPointerSize;
   intptr_t output_frame_offset = output_frame_size - kPointerSize;
@@ -635,14 +650,35 @@
       Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
   output_frame->SetFrameSlot(output_frame_offset, value);

+  int caller_arg_count = 0;
+  if (descriptor->stack_parameter_count_ != NULL) {
+    caller_arg_count =
+        input_->GetRegister(descriptor->stack_parameter_count_->code());
+  }
+
+ // Build the Arguments object for the caller's parameters and a pointer to it.
+  output_frame_offset -= kPointerSize;
+  value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
+      (caller_arg_count - 1) * kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, value);
+
+  output_frame->SetFrameSlot(output_frame_offset, value);
+  output_frame_offset -= kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, caller_arg_count);
+
+  value = frame_ptr - (output_frame_size - output_frame_offset) -
+      StandardFrameConstants::kMarkerOffset;
+  output_frame_offset -= kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, value);
+
+  // Copy the register parameters to the failure frame.
   for (int i = 0; i < descriptor->register_param_count_; ++i) {
     output_frame_offset -= kPointerSize;
     DoTranslateCommand(iterator, 0, output_frame_offset);
   }

-  value = input_->GetRegister(ebp.code());
-  output_frame->SetRegister(ebp.code(), value);
-  output_frame->SetFp(value);
+  output_frame->SetRegister(ebp.code(), frame_ptr);
+  output_frame->SetFp(frame_ptr);

   for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
     double double_value = input_->GetDoubleRegister(i);
@@ -651,7 +687,11 @@

   intptr_t handler =
       reinterpret_cast<intptr_t>(descriptor->deoptimization_handler_);
-  output_frame->SetRegister(eax.code(), descriptor->register_param_count_);
+  int params = descriptor->register_param_count_;
+  if (descriptor->stack_parameter_count_ != NULL) {
+    params++;
+  }
+  output_frame->SetRegister(eax.code(), params);
   output_frame->SetRegister(ebx.code(), handler);
 }

=======================================
--- /branches/bleeding_edge/src/ia32/frames-ia32.h      Tue Jun 12 03:22:33 2012
+++ /branches/bleeding_edge/src/ia32/frames-ia32.h      Tue Feb  5 00:09:32 2013
@@ -97,22 +97,6 @@
 };


-class StandardFrameConstants : public AllStatic {
- public:
-  // Fixed part of the frame consists of return address, caller fp,
-  // context and function.
- // StandardFrame::IterateExpressions assumes that kContextOffset is the last
-  // object pointer.
-  static const int kFixedFrameSize    =  4 * kPointerSize;
-  static const int kExpressionsOffset = -3 * kPointerSize;
-  static const int kMarkerOffset      = -2 * kPointerSize;
-  static const int kContextOffset     = -1 * kPointerSize;
-  static const int kCallerFPOffset    =  0 * kPointerSize;
-  static const int kCallerPCOffset    = +1 * kPointerSize;
-  static const int kCallerSPOffset    = +2 * kPointerSize;
-};
-
-
 class JavaScriptFrameConstants : public AllStatic {
  public:
   // FP-relative.
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Feb 5 00:09:32 2013
@@ -2346,7 +2346,7 @@

 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
   LParameter* result = new(zone()) LParameter;
-  if (info()->IsOptimizing()) {
+  if (instr->kind() == HParameter::STACK_PARAMETER) {
     int spill_index = chunk()->GetParameterStackSlot(instr->index());
     return DefineAsSpilled(result, spill_index);
   } else {
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Thu Jan 31 06:23:36 2013
+++ /branches/bleeding_edge/src/isolate.cc      Tue Feb  5 00:09:32 2013
@@ -2120,7 +2120,7 @@
     // Ensure that the stub failure trampoline has been generated.
     HandleScope scope(this);
     CodeStub::GenerateFPStubs();
-    StubFailureTrampolineStub().GetCode();
+    StubFailureTrampolineStub::GenerateAheadOfTime();
   }

   if (FLAG_parallel_recompilation) optimizing_compiler_thread_.Start();
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Mon Feb  4 12:24:11 2013
+++ /branches/bleeding_edge/src/runtime.cc      Tue Feb  5 00:09:32 2013
@@ -78,6 +78,9 @@
   RUNTIME_ASSERT(args[index]->Is##Type());                           \
   Handle<Type> name = args.at<Type>(index);

+#define CONVERT_ARG_STUB_CALLER_ARGS(name)                           \
+  Arguments* name = reinterpret_cast<Arguments*>(args[0]);
+
 // Cast the given object to a boolean and store it in a variable with
 // the given name.  If the object is not a boolean call IllegalOperation
 // and return.
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue Feb 5 00:09:32 2013
@@ -45,6 +45,7 @@
   static Register registers[] = { rdx, rax };
   descriptor->register_param_count_ = 2;
   descriptor->register_params_ = registers;
+  descriptor->stack_parameter_count_ = NULL;
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure);
 }
@@ -6635,8 +6636,14 @@
   ASSERT(!Serializer::enabled());
   CEntryStub ces(1, kSaveFPRegs);
   __ Call(ces.GetCode(), RelocInfo::CODE_TARGET);
+  int parameter_count_offset =
+      StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
+  __ movq(rbx, MemOperand(rbp, parameter_count_offset));
   masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
-  __ ret(0);  // Return to IC Miss stub, continuation still on stack.
+  __ pop(rcx);
+  __ lea(rsp, MemOperand(rsp, rbx, times_pointer_size,
+                         extra_expression_stack_count_ * kPointerSize));
+  __ jmp(rcx);  // Return to IC Miss stub, continuation still on stack.
 }


=======================================
--- /branches/bleeding_edge/src/x64/deoptimizer-x64.cc Mon Feb 4 04:01:59 2013 +++ /branches/bleeding_edge/src/x64/deoptimizer-x64.cc Tue Feb 5 00:09:32 2013
@@ -462,13 +462,19 @@
   // v  +-------------------------+          +-------------------------|
   //    |   COMPILED_STUB marker  |          |   STUB_FAILURE marker   |
   //    +-------------------------+          +-------------------------+
-  //    |                         |          |     stub parameter 1    |
+  //    |                         |          |   caller args.length_   |
   //    | ...                     |          +-------------------------+
-  //    |                         |          |            ...          |
+  //    |                         |          |  caller args.arguments_ |
   //    |-------------------------|<-rsp     +-------------------------+
-  //                                         |     stub parameter n    |
- // parameters in registers +-------------------------+<-rsp
-  //       and spilled to stack              rax = number of parameters
+  //                                         |  caller args pointer    |
+  //                                         +-------------------------+
+  //                                         |  caller stack param 1   |
+  //      parameters in registers            +-------------------------+
+  //       and spilled to stack              |           ....          |
+  //                                         +-------------------------+
+  //                                         |  caller stack param n   |
+ // +-------------------------+<-rsp
+  //                                         rax = number of parameters
   //                                         rbx = failure handler address
   //                                         rbp = saved frame
   //                                         rsi = JSFunction context
@@ -479,9 +485,15 @@
   CodeStubInterfaceDescriptor* descriptor =
       isolate_->code_stub_interface_descriptor(major_key);

+  // The output frame must have room for all pushed register parameters
+  // and the standard stack frame slots.
   int output_frame_size = StandardFrameConstants::kFixedFrameSize +
       kPointerSize * descriptor->register_param_count_;

+  // Include space for an argument object to the callee and optionally
+  // the space to pass the argument object to the stub failure handler.
+  output_frame_size += sizeof(Arguments) + kPointerSize;
+
   FrameDescription* output_frame =
       new(output_frame_size) FrameDescription(output_frame_size, 0);
   ASSERT(frame_index == 0);
@@ -493,12 +505,15 @@
       reinterpret_cast<intptr_t>(notify_failure->entry()));

   Code* trampoline = NULL;
-  StubFailureTrampolineStub().FindCodeInCache(&trampoline, isolate_);
+  int extra = descriptor->extra_expression_stack_count_;
+  StubFailureTrampolineStub(extra).FindCodeInCache(&trampoline, isolate_);
   ASSERT(trampoline != NULL);
   output_frame->SetPc(reinterpret_cast<intptr_t>(
       trampoline->instruction_start()));
   unsigned input_frame_size = input_->GetFrameSize();

+  intptr_t frame_ptr = input_->GetRegister(rbp.code());
+
   // JSFunction continuation
   unsigned input_frame_offset = input_frame_size - kPointerSize;
   unsigned output_frame_offset = output_frame_size - kPointerSize;
@@ -524,14 +539,35 @@
       Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
   output_frame->SetFrameSlot(output_frame_offset, value);

+  int caller_arg_count = 0;
+  if (descriptor->stack_parameter_count_ != NULL) {
+    caller_arg_count =
+        input_->GetRegister(descriptor->stack_parameter_count_->code());
+  }
+
+ // Build the Arguments object for the caller's parameters and a pointer to it.
+  output_frame_offset -= kPointerSize;
+  value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
+      (caller_arg_count - 1) * kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, value);
+
+  output_frame->SetFrameSlot(output_frame_offset, value);
+  output_frame_offset -= kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, caller_arg_count);
+
+  value = frame_ptr - (output_frame_size - output_frame_offset) -
+      StandardFrameConstants::kMarkerOffset;
+  output_frame_offset -= kPointerSize;
+  output_frame->SetFrameSlot(output_frame_offset, value);
+
+  // Copy the register parameters to the failure frame.
   for (int i = 0; i < descriptor->register_param_count_; ++i) {
     output_frame_offset -= kPointerSize;
     DoTranslateCommand(iterator, 0, output_frame_offset);
   }

-  value = input_->GetRegister(rbp.code());
-  output_frame->SetRegister(rbp.code(), value);
-  output_frame->SetFp(value);
+  output_frame->SetRegister(rbp.code(), frame_ptr);
+  output_frame->SetFp(frame_ptr);

   for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
     double double_value = input_->GetDoubleRegister(i);
@@ -540,7 +576,11 @@

   intptr_t handler =
       reinterpret_cast<intptr_t>(descriptor->deoptimization_handler_);
-  output_frame->SetRegister(rax.code(), descriptor->register_param_count_);
+  int params = descriptor->register_param_count_;
+  if (descriptor->stack_parameter_count_ != NULL) {
+    params++;
+  }
+  output_frame->SetRegister(rax.code(), params);
   output_frame->SetRegister(rbx.code(), handler);
 }

=======================================
--- /branches/bleeding_edge/src/x64/frames-x64.h        Tue Jan 24 00:43:12 2012
+++ /branches/bleeding_edge/src/x64/frames-x64.h        Tue Feb  5 00:09:32 2013
@@ -85,20 +85,6 @@
 };


-class StandardFrameConstants : public AllStatic {
- public:
-  // Fixed part of the frame consists of return address, caller fp,
-  // context and function.
-  static const int kFixedFrameSize    =  4 * kPointerSize;
-  static const int kExpressionsOffset = -3 * kPointerSize;
-  static const int kMarkerOffset      = -2 * kPointerSize;
-  static const int kContextOffset     = -1 * kPointerSize;
-  static const int kCallerFPOffset    =  0 * kPointerSize;
-  static const int kCallerPCOffset    = +1 * kPointerSize;
-  static const int kCallerSPOffset    = +2 * kPointerSize;
-};
-
-
 class JavaScriptFrameConstants : public AllStatic {
  public:
   // FP-relative.
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc      Mon Feb  4 04:01:59 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Tue Feb  5 00:09:32 2013
@@ -2200,7 +2200,7 @@

 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
   LParameter* result = new(zone()) LParameter;
-  if (info()->IsOptimizing()) {
+  if (instr->kind() == HParameter::STACK_PARAMETER) {
     int spill_index = chunk()->GetParameterStackSlot(instr->index());
     return DefineAsSpilled(result, spill_index);
   } else {

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to