MIPS: reland 16744: add context save for GenerateFastApiCall.
authorplind44@gmail.com <plind44@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 17 Sep 2013 19:10:48 +0000 (19:10 +0000)
committerplind44@gmail.com <plind44@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 17 Sep 2013 19:10:48 +0000 (19:10 +0000)
Port r16763 (968acfa)

BUG=
R=plind44@gmail.com

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

Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16778 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/mips/code-stubs-mips.cc
src/mips/macro-assembler-mips.cc
src/mips/macro-assembler-mips.h
src/mips/stub-cache-mips.cc

index e4f68f9..ee49b25 100644 (file)
@@ -2876,7 +2876,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
   // v0:v1: result
   // sp: stack pointer
   // fp: frame pointer
-  __ LeaveExitFrame(save_doubles_, s0, true);
+  __ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN);
 
   // Check if we should retry or throw exception.
   Label retry;
@@ -4156,7 +4156,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
   DirectCEntryStub stub;
   stub.GenerateCall(masm, t9);
 
-  __ LeaveExitFrame(false, no_reg);
+  __ LeaveExitFrame(false, no_reg, true);
 
   // v0: result
   // subject: subject string (callee saved)
index a85b0d8..465e8ab 100644 (file)
@@ -3847,12 +3847,14 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
 }
 
 
-void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
-                                              Address function_address,
-                                              ExternalReference thunk_ref,
-                                              Register thunk_last_arg,
-                                              int stack_space,
-                                              int return_value_offset_from_fp) {
+void MacroAssembler::CallApiFunctionAndReturn(
+    ExternalReference function,
+    Address function_address,
+    ExternalReference thunk_ref,
+    Register thunk_last_arg,
+    int stack_space,
+    MemOperand return_value_operand,
+    MemOperand* context_restore_operand) {
   ExternalReference next_address =
       ExternalReference::handle_scope_next_address(isolate());
   const int kNextOffset = 0;
@@ -3915,12 +3917,13 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
   }
 
   Label promote_scheduled_exception;
+  Label exception_handled;
   Label delete_allocated_handles;
   Label leave_exit_frame;
   Label return_value_loaded;
 
   // Load value from ReturnValue.
-  lw(v0, MemOperand(fp, return_value_offset_from_fp*kPointerSize));
+  lw(v0, return_value_operand);
   bind(&return_value_loaded);
 
   // No more valid handles (the result handle was the last one). Restore
@@ -3941,14 +3944,23 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
   li(at, Operand(ExternalReference::scheduled_exception_address(isolate())));
   lw(t1, MemOperand(at));
   Branch(&promote_scheduled_exception, ne, t0, Operand(t1));
+  bind(&exception_handled);
+
+  bool restore_context = context_restore_operand != NULL;
+  if (restore_context) {
+    lw(cp, *context_restore_operand);
+  }
   li(s0, Operand(stack_space));
-  LeaveExitFrame(false, s0, true);
+  LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN);
 
   bind(&promote_scheduled_exception);
-  TailCallExternalReference(
-      ExternalReference(Runtime::kPromoteScheduledException, isolate()),
-      0,
-      1);
+  {
+    FrameScope frame(this, StackFrame::INTERNAL);
+    CallExternalReference(
+        ExternalReference(Runtime::kPromoteScheduledException, isolate()),
+        0);
+  }
+  jmp(&exception_handled);
 
   // HandleScope limit has changed. Delete allocated extensions.
   bind(&delete_allocated_handles);
@@ -4684,6 +4696,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles,
 
 void MacroAssembler::LeaveExitFrame(bool save_doubles,
                                     Register argument_count,
+                                    bool restore_context,
                                     bool do_return) {
   // Optionally restore all double registers.
   if (save_doubles) {
@@ -4700,9 +4713,12 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles,
   sw(zero_reg, MemOperand(t8));
 
   // Restore current context from top and clear it in debug mode.
-  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
-  lw(cp, MemOperand(t8));
+  if (restore_context) {
+    li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
+    lw(cp, MemOperand(t8));
+  }
 #ifdef DEBUG
+  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
   sw(a3, MemOperand(t8));
 #endif
 
index 75ded88..2d9c950 100644 (file)
@@ -51,6 +51,12 @@ class JumpTarget;
 // MIPS generated code calls C code, it must be via t9 register.
 
 
+// Flags used for LeaveExitFrame function.
+enum LeaveExitFrameMode {
+  EMIT_RETURN = true,
+  NO_EMIT_RETURN = false
+};
+
 // Flags used for AllocateHeapNumber
 enum TaggingMode {
   // Tag the result.
@@ -848,7 +854,8 @@ class MacroAssembler: public Assembler {
   // Leave the current exit frame.
   void LeaveExitFrame(bool save_doubles,
                       Register arg_count,
-                      bool do_return = false);
+                      bool restore_context,
+                      bool do_return = NO_EMIT_RETURN);
 
   // Get the actual activation frame alignment for target environment.
   static int ActivationFrameAlignment();
@@ -1271,7 +1278,8 @@ class MacroAssembler: public Assembler {
                                 ExternalReference thunk_ref,
                                 Register thunk_last_arg,
                                 int stack_space,
-                                int return_value_offset_from_fp);
+                                MemOperand return_value_operand,
+                                MemOperand* context_restore_operand);
 
   // Jump to the builtin routine.
   void JumpToExternalReference(const ExternalReference& builtin,
index 97bd872..e0cf1b6 100644 (file)
@@ -829,23 +829,28 @@ static void FreeSpaceForFastApiCall(MacroAssembler* masm) {
 
 static void GenerateFastApiDirectCall(MacroAssembler* masm,
                                       const CallOptimization& optimization,
-                                      int argc) {
+                                      int argc,
+                                      bool restore_context) {
   // ----------- S t a t e -------------
-  //  -- sp[0]              : holder (set by CheckPrototypes)
-  //  -- sp[4]              : callee JS function
-  //  -- sp[8]              : call data
-  //  -- sp[12]             : isolate
-  //  -- sp[16]             : ReturnValue default value
-  //  -- sp[20]             : ReturnValue
-  //  -- sp[24]             : last JS argument
+  //  -- sp[0]              : context
+  //  -- sp[4]              : holder (set by CheckPrototypes)
+  //  -- sp[8]              : callee JS function
+  //  -- sp[12]             : call data
+  //  -- sp[16]             : isolate
+  //  -- sp[20]             : ReturnValue default value
+  //  -- sp[24]             : ReturnValue
+  //  -- sp[28]             : last JS argument
   //  -- ...
-  //  -- sp[(argc + 5) * 4] : first JS argument
-  //  -- sp[(argc + 6) * 4] : receiver
+  //  -- sp[(argc + 6) * 4] : first JS argument
+  //  -- sp[(argc + 7) * 4] : receiver
   // -----------------------------------
+  // Save calling context.
+  __ sw(cp, MemOperand(sp));
   // Get the function and setup the context.
   Handle<JSFunction> function = optimization.constant_function();
   __ LoadHeapObject(t1, function);
   __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset));
+  __ sw(t1, MemOperand(sp, 2 * kPointerSize));
 
   // Pass the additional arguments.
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
@@ -856,18 +861,18 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
   } else {
     __ li(t2, call_data);
   }
-
+  // Store call data.
+  __ sw(t2, MemOperand(sp, 3 * kPointerSize));
+  // Store isolate.
   __ li(t3, Operand(ExternalReference::isolate_address(masm->isolate())));
-  // Store JS function, call data, isolate ReturnValue default and ReturnValue.
-  __ sw(t1, MemOperand(sp, 1 * kPointerSize));
-  __ sw(t2, MemOperand(sp, 2 * kPointerSize));
-  __ sw(t3, MemOperand(sp, 3 * kPointerSize));
+  __ sw(t3, MemOperand(sp, 4 * kPointerSize));
+  // Store ReturnValue default and ReturnValue.
   __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
-  __ sw(t1, MemOperand(sp, 4 * kPointerSize));
   __ sw(t1, MemOperand(sp, 5 * kPointerSize));
+  __ sw(t1, MemOperand(sp, 6 * kPointerSize));
 
   // Prepare arguments.
-  __ Addu(a2, sp, Operand(5 * kPointerSize));
+  __ Addu(a2, sp, Operand((kFastApiCallArguments - 1) * kPointerSize));
 
   // Allocate the v8::Arguments structure in the arguments' space since
   // it's not controlled by GC.
@@ -906,12 +911,18 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
       masm->isolate());
 
   AllowExternalCallThatCantCauseGC scope(masm);
+  MemOperand context_restore_operand(
+      fp, 2 * kPointerSize);
+  MemOperand return_value_operand(
+      fp, (kFastApiCallArguments + 1) * kPointerSize);
   __ CallApiFunctionAndReturn(ref,
                               function_address,
                               thunk_ref,
                               a1,
                               kStackUnwindSpace,
-                              kFastApiCallArguments + 1);
+                              return_value_operand,
+                              restore_context ?
+                                  &context_restore_operand : NULL);
 }
 
 
@@ -926,10 +937,12 @@ static void GenerateFastApiCall(MacroAssembler* masm,
   ASSERT(!receiver.is(scratch));
 
   const int stack_space = kFastApiCallArguments + argc + 1;
+  const int kHolderIndex = kFastApiCallArguments +
+      FunctionCallbackArguments::kHolderIndex - 1;
   // Assign stack space for the call arguments.
   __ Subu(sp, sp, Operand(stack_space * kPointerSize));
   // Write holder to stack frame.
-  __ sw(receiver, MemOperand(sp, 0));
+  __ sw(receiver, MemOperand(sp, kHolderIndex * kPointerSize));
   // Write receiver to stack frame.
   int index = stack_space - 1;
   __ sw(receiver, MemOperand(sp, index * kPointerSize));
@@ -940,7 +953,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
     __ sw(receiver, MemOperand(sp, index-- * kPointerSize));
   }
 
-  GenerateFastApiDirectCall(masm, optimization, argc);
+  GenerateFastApiDirectCall(masm, optimization, argc, true);
 }
 
 
@@ -1054,7 +1067,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
 
     // Invoke function.
     if (can_do_fast_api_call) {
-      GenerateFastApiDirectCall(masm, optimization, arguments_.immediate());
+      GenerateFastApiDirectCall(
+          masm, optimization, arguments_.immediate(), false);
     } else {
       CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
           ? CALL_AS_FUNCTION
@@ -1181,6 +1195,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
                                        int save_at_depth,
                                        Label* miss,
                                        PrototypeCheckType check) {
+  const int kHolderIndex = kFastApiCallArguments +
+      FunctionCallbackArguments::kHolderIndex - 1;
   // Make sure that the type feedback oracle harvests the receiver map.
   // TODO(svenpanne) Remove this hack when all ICs are reworked.
   __ li(scratch1, Operand(Handle<Map>(object->map())));
@@ -1196,7 +1212,7 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
   int depth = 0;
 
   if (save_at_depth == depth) {
-    __ sw(reg, MemOperand(sp));
+    __ sw(reg, MemOperand(sp, kHolderIndex * kPointerSize));
   }
 
   // Check the maps in the prototype chain.
@@ -1254,7 +1270,7 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
     }
 
     if (save_at_depth == depth) {
-      __ sw(reg, MemOperand(sp));
+      __ sw(reg, MemOperand(sp, kHolderIndex * kPointerSize));
     }
 
     // Go to the next object in the prototype chain.
@@ -1454,7 +1470,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
   // (second argument - a1) = AccessorInfo&
   __ Addu(a1, sp, kPointerSize);
 
-  const int kStackUnwindSpace = kFastApiCallArguments + 1;
+  const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
   Address getter_address = v8::ToCData<Address>(callback->getter());
   ApiFunction fun(getter_address);
   ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
@@ -1471,7 +1487,8 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
                               thunk_ref,
                               a2,
                               kStackUnwindSpace,
-                              6);
+                              MemOperand(fp, 6 * kPointerSize),
+                              NULL);
 }
 
 
@@ -2554,7 +2571,7 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
   CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, name,
                   depth, &miss);
 
-  GenerateFastApiDirectCall(masm(), optimization, argc);
+  GenerateFastApiDirectCall(masm(), optimization, argc, false);
 
   __ bind(&miss);
   FreeSpaceForFastApiCall(masm());