Commit 16164471 authored by serya@chromium.org's avatar serya@chromium.org

API call code refactoring (ia32).

Review URL: http://codereview.chromium.org/5055004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5831 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0464b336
...@@ -392,13 +392,8 @@ void MacroAssembler::EnterExitFrame() { ...@@ -392,13 +392,8 @@ void MacroAssembler::EnterExitFrame() {
} }
void MacroAssembler::EnterApiExitFrame(int stack_space, void MacroAssembler::EnterApiExitFrame(int argc) {
int argc) {
EnterExitFramePrologue(); EnterExitFramePrologue();
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset));
EnterExitFrameEpilogue(argc); EnterExitFrameEpilogue(argc);
} }
...@@ -411,6 +406,13 @@ void MacroAssembler::LeaveExitFrame() { ...@@ -411,6 +406,13 @@ void MacroAssembler::LeaveExitFrame() {
// Pop the arguments and the receiver from the caller stack. // Pop the arguments and the receiver from the caller stack.
lea(esp, Operand(esi, 1 * kPointerSize)); lea(esp, Operand(esi, 1 * kPointerSize));
// Push the return address to get ready to return.
push(ecx);
LeaveExitFrameEpilogue();
}
void MacroAssembler::LeaveExitFrameEpilogue() {
// Restore current context from top and clear it in debug mode. // Restore current context from top and clear it in debug mode.
ExternalReference context_address(Top::k_context_address); ExternalReference context_address(Top::k_context_address);
mov(esi, Operand::StaticVariable(context_address)); mov(esi, Operand::StaticVariable(context_address));
...@@ -418,15 +420,20 @@ void MacroAssembler::LeaveExitFrame() { ...@@ -418,15 +420,20 @@ void MacroAssembler::LeaveExitFrame() {
mov(Operand::StaticVariable(context_address), Immediate(0)); mov(Operand::StaticVariable(context_address), Immediate(0));
#endif #endif
// Push the return address to get ready to return.
push(ecx);
// Clear the top frame. // Clear the top frame.
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
} }
void MacroAssembler::LeaveApiExitFrame() {
mov(esp, Operand(ebp));
pop(ebp);
LeaveExitFrameEpilogue();
}
void MacroAssembler::PushTryHandler(CodeLocation try_location, void MacroAssembler::PushTryHandler(CodeLocation try_location,
HandlerType type) { HandlerType type) {
// Adjust this code if not the case. // Adjust this code if not the case.
...@@ -1151,21 +1158,15 @@ Operand ApiParameterOperand(int index) { ...@@ -1151,21 +1158,15 @@ Operand ApiParameterOperand(int index) {
} }
void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) { void MacroAssembler::PrepareCallApiFunction(int argc, Register scratch) {
if (kPassHandlesDirectly) { if (kPassHandlesDirectly) {
EnterApiExitFrame(stack_space, argc); EnterApiExitFrame(argc);
// When handles as passed directly we don't have to allocate extra // When handles as passed directly we don't have to allocate extra
// space for and pass an out parameter. // space for and pass an out parameter.
} else { } else {
// We allocate two additional slots: return value and pointer to it. // We allocate two additional slots: return value and pointer to it.
EnterApiExitFrame(stack_space, argc + 2); EnterApiExitFrame(argc + 2);
}
}
MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
int argc) {
if (!kPassHandlesDirectly) {
// The argument slots are filled as follows: // The argument slots are filled as follows:
// //
// n + 1: output cell // n + 1: output cell
...@@ -1177,11 +1178,19 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, ...@@ -1177,11 +1178,19 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
// Note that this is one more "argument" than the function expects // Note that this is one more "argument" than the function expects
// so the out cell will have to be popped explicitly after returning // so the out cell will have to be popped explicitly after returning
// from the function. The out cell contains Handle. // from the function. The out cell contains Handle.
lea(eax, Operand(esp, (argc + 1) * kPointerSize)); // pointer to out cell.
mov(Operand(esp, 0 * kPointerSize), eax); // output. // pointer to out cell.
lea(scratch, Operand(esp, (argc + 1) * kPointerSize));
mov(Operand(esp, 0 * kPointerSize), scratch); // output.
if (FLAG_debug_code) {
mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell.
} }
}
}
MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
int stack_space) {
ExternalReference next_address = ExternalReference next_address =
ExternalReference::handle_scope_next_address(); ExternalReference::handle_scope_next_address();
ExternalReference limit_address = ExternalReference limit_address =
...@@ -1230,8 +1239,8 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, ...@@ -1230,8 +1239,8 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
cmp(Operand::StaticVariable(scheduled_exception_address), cmp(Operand::StaticVariable(scheduled_exception_address),
Immediate(Factory::the_hole_value())); Immediate(Factory::the_hole_value()));
j(not_equal, &promote_scheduled_exception, not_taken); j(not_equal, &promote_scheduled_exception, not_taken);
LeaveExitFrame(); LeaveApiExitFrame();
ret(0); ret(stack_space * kPointerSize);
bind(&promote_scheduled_exception); bind(&promote_scheduled_exception);
MaybeObject* result = MaybeObject* result =
TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
......
...@@ -123,13 +123,17 @@ class MacroAssembler: public Assembler { ...@@ -123,13 +123,17 @@ class MacroAssembler: public Assembler {
// to the first argument in register esi. // to the first argument in register esi.
void EnterExitFrame(); void EnterExitFrame();
void EnterApiExitFrame(int stack_space, int argc); void EnterApiExitFrame(int argc);
// Leave the current exit frame. Expects the return value in // Leave the current exit frame. Expects the return value in
// register eax:edx (untouched) and the pointer to the first // register eax:edx (untouched) and the pointer to the first
// argument in register esi. // argument in register esi.
void LeaveExitFrame(); void LeaveExitFrame();
// Leave the current exit frame. Expects the return value in
// register eax (untouched).
void LeaveApiExitFrame();
// Find the function context up the context chain. // Find the function context up the context chain.
void LoadContext(Register dst, int context_chain_length); void LoadContext(Register dst, int context_chain_length);
...@@ -499,12 +503,14 @@ class MacroAssembler: public Assembler { ...@@ -499,12 +503,14 @@ class MacroAssembler: public Assembler {
// Uses callee-saved esi to restore stack state after call. Arguments must be // Uses callee-saved esi to restore stack state after call. Arguments must be
// stored in ApiParameterOperand(0), ApiParameterOperand(1) etc. Saves // stored in ApiParameterOperand(0), ApiParameterOperand(1) etc. Saves
// context (esi). // context (esi).
void PrepareCallApiFunction(int stack_space, int argc); void PrepareCallApiFunction(int argc, Register scratch);
// Calls an API function. Allocates HandleScope, extracts // Calls an API function. Allocates HandleScope, extracts
// returned value from handle and propagates exceptions. // returned value from handle and propagates exceptions.
// Clobbers ebx, edi and caller-save registers. Restores context. // Clobbers ebx, edi and caller-save registers. Restores context.
MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function, int argc); // On return removes stack_space * kPointerSize (GCed).
MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function,
int stack_space);
// Jump to a runtime routine. // Jump to a runtime routine.
void JumpToExternalReference(const ExternalReference& ext); void JumpToExternalReference(const ExternalReference& ext);
...@@ -604,6 +610,8 @@ class MacroAssembler: public Assembler { ...@@ -604,6 +610,8 @@ class MacroAssembler: public Assembler {
void EnterExitFramePrologue(); void EnterExitFramePrologue();
void EnterExitFrameEpilogue(int argc); void EnterExitFrameEpilogue(int argc);
void LeaveExitFrameEpilogue();
// Allocation support helpers. // Allocation support helpers.
void LoadAllocationTopHelper(Register result, void LoadAllocationTopHelper(Register result,
Register result_end, Register result_end,
......
...@@ -499,8 +499,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm, ...@@ -499,8 +499,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm,
// it's not controlled by GC. // it's not controlled by GC.
const int kApiStackSpace = 4; const int kApiStackSpace = 4;
__ PrepareCallApiFunction(argc + kFastApiCallArguments + 1, __ PrepareCallApiFunction(kApiArgc + kApiStackSpace, ebx);
kApiArgc + kApiStackSpace);
__ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_.
__ add(Operand(eax), Immediate(argc * kPointerSize)); __ add(Operand(eax), Immediate(argc * kPointerSize));
...@@ -518,7 +517,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm, ...@@ -518,7 +517,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm,
// garbage collection but instead return the allocation failure // garbage collection but instead return the allocation failure
// object. // object.
MaybeObject* result = MaybeObject* result =
masm->TryCallApiFunctionAndReturn(&fun, kApiArgc + kApiStackSpace); masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1);
if (result->IsFailure()) { if (result->IsFailure()) {
*failure = Failure::cast(result); *failure = Failure::cast(result);
return false; return false;
...@@ -1109,7 +1108,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, ...@@ -1109,7 +1108,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
const int kStackSpace = 5; const int kStackSpace = 5;
const int kApiArgc = 2; const int kApiArgc = 2;
__ PrepareCallApiFunction(kStackSpace, kApiArgc); __ PrepareCallApiFunction(kApiArgc, eax);
__ mov(ApiParameterOperand(0), ebx); // name. __ mov(ApiParameterOperand(0), ebx); // name.
__ add(Operand(ebx), Immediate(kPointerSize)); __ add(Operand(ebx), Immediate(kPointerSize));
__ mov(ApiParameterOperand(1), ebx); // arguments pointer. __ mov(ApiParameterOperand(1), ebx); // arguments pointer.
...@@ -1118,7 +1117,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, ...@@ -1118,7 +1117,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
// already generated). Do not allow the assembler to perform a // already generated). Do not allow the assembler to perform a
// garbage collection but instead return the allocation failure // garbage collection but instead return the allocation failure
// object. // object.
MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kApiArgc); MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
if (result->IsFailure()) { if (result->IsFailure()) {
*failure = Failure::cast(result); *failure = Failure::cast(result);
return false; return false;
...@@ -2169,7 +2168,10 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2169,7 +2168,10 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
if (depth != kInvalidProtoDepth) { if (depth != kInvalidProtoDepth) {
__ IncrementCounter(&Counters::call_const_fast_api, 1); __ IncrementCounter(&Counters::call_const_fast_api, 1);
ReserveSpaceForFastApiCall(masm(), eax);
// Allocate space for v8::Arguments implicit values. Must be initialized
// before to call any runtime function.
__ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
} }
// Check that the maps haven't changed. // Check that the maps haven't changed.
...@@ -2249,6 +2251,12 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2249,6 +2251,12 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
if (depth != kInvalidProtoDepth) { if (depth != kInvalidProtoDepth) {
Failure* failure; Failure* failure;
// Move the return address on top of the stack.
__ mov(eax, Operand(esp, 3 * kPointerSize));
__ mov(Operand(esp, 0 * kPointerSize), eax);
// esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
// duplicate of return address and will be overwritten.
bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
if (!success) { if (!success) {
return failure; return failure;
...@@ -2260,7 +2268,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -2260,7 +2268,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
if (depth != kInvalidProtoDepth) { if (depth != kInvalidProtoDepth) {
FreeSpaceForFastApiCall(masm(), eax); __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
} }
__ bind(&miss_in_smi_check); __ bind(&miss_in_smi_check);
Object* obj; Object* obj;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment