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
This commit is contained in:
parent
0464b33625
commit
16164471f3
@ -392,13 +392,8 @@ void MacroAssembler::EnterExitFrame() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::EnterApiExitFrame(int stack_space,
|
||||
int argc) {
|
||||
void MacroAssembler::EnterApiExitFrame(int argc) {
|
||||
EnterExitFramePrologue();
|
||||
|
||||
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
|
||||
lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset));
|
||||
|
||||
EnterExitFrameEpilogue(argc);
|
||||
}
|
||||
|
||||
@ -411,6 +406,13 @@ void MacroAssembler::LeaveExitFrame() {
|
||||
// Pop the arguments and the receiver from the caller stack.
|
||||
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.
|
||||
ExternalReference context_address(Top::k_context_address);
|
||||
mov(esi, Operand::StaticVariable(context_address));
|
||||
@ -418,15 +420,20 @@ void MacroAssembler::LeaveExitFrame() {
|
||||
mov(Operand::StaticVariable(context_address), Immediate(0));
|
||||
#endif
|
||||
|
||||
// Push the return address to get ready to return.
|
||||
push(ecx);
|
||||
|
||||
// Clear the top frame.
|
||||
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
|
||||
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,
|
||||
HandlerType type) {
|
||||
// Adjust this code if not the case.
|
||||
@ -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) {
|
||||
EnterApiExitFrame(stack_space, argc);
|
||||
EnterApiExitFrame(argc);
|
||||
// When handles as passed directly we don't have to allocate extra
|
||||
// space for and pass an out parameter.
|
||||
} else {
|
||||
// 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:
|
||||
//
|
||||
// n + 1: output cell
|
||||
@ -1177,11 +1178,19 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
|
||||
// Note that this is one more "argument" than the function expects
|
||||
// so the out cell will have to be popped explicitly after returning
|
||||
// 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.
|
||||
mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell.
|
||||
}
|
||||
|
||||
// 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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
|
||||
int stack_space) {
|
||||
ExternalReference next_address =
|
||||
ExternalReference::handle_scope_next_address();
|
||||
ExternalReference limit_address =
|
||||
@ -1230,8 +1239,8 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
|
||||
cmp(Operand::StaticVariable(scheduled_exception_address),
|
||||
Immediate(Factory::the_hole_value()));
|
||||
j(not_equal, &promote_scheduled_exception, not_taken);
|
||||
LeaveExitFrame();
|
||||
ret(0);
|
||||
LeaveApiExitFrame();
|
||||
ret(stack_space * kPointerSize);
|
||||
bind(&promote_scheduled_exception);
|
||||
MaybeObject* result =
|
||||
TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
|
||||
|
@ -123,13 +123,17 @@ class MacroAssembler: public Assembler {
|
||||
// to the first argument in register esi.
|
||||
void EnterExitFrame();
|
||||
|
||||
void EnterApiExitFrame(int stack_space, int argc);
|
||||
void EnterApiExitFrame(int argc);
|
||||
|
||||
// Leave the current exit frame. Expects the return value in
|
||||
// register eax:edx (untouched) and the pointer to the first
|
||||
// argument in register esi.
|
||||
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.
|
||||
void LoadContext(Register dst, int context_chain_length);
|
||||
|
||||
@ -499,12 +503,14 @@ class MacroAssembler: public Assembler {
|
||||
// Uses callee-saved esi to restore stack state after call. Arguments must be
|
||||
// stored in ApiParameterOperand(0), ApiParameterOperand(1) etc. Saves
|
||||
// context (esi).
|
||||
void PrepareCallApiFunction(int stack_space, int argc);
|
||||
void PrepareCallApiFunction(int argc, Register scratch);
|
||||
|
||||
// Calls an API function. Allocates HandleScope, extracts
|
||||
// returned value from handle and propagates exceptions.
|
||||
// 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.
|
||||
void JumpToExternalReference(const ExternalReference& ext);
|
||||
@ -603,6 +609,8 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
void EnterExitFramePrologue();
|
||||
void EnterExitFrameEpilogue(int argc);
|
||||
|
||||
void LeaveExitFrameEpilogue();
|
||||
|
||||
// Allocation support helpers.
|
||||
void LoadAllocationTopHelper(Register result,
|
||||
|
@ -499,8 +499,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm,
|
||||
// it's not controlled by GC.
|
||||
const int kApiStackSpace = 4;
|
||||
|
||||
__ PrepareCallApiFunction(argc + kFastApiCallArguments + 1,
|
||||
kApiArgc + kApiStackSpace);
|
||||
__ PrepareCallApiFunction(kApiArgc + kApiStackSpace, ebx);
|
||||
|
||||
__ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_.
|
||||
__ add(Operand(eax), Immediate(argc * kPointerSize));
|
||||
@ -518,7 +517,7 @@ static bool GenerateFastApiCall(MacroAssembler* masm,
|
||||
// garbage collection but instead return the allocation failure
|
||||
// object.
|
||||
MaybeObject* result =
|
||||
masm->TryCallApiFunctionAndReturn(&fun, kApiArgc + kApiStackSpace);
|
||||
masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1);
|
||||
if (result->IsFailure()) {
|
||||
*failure = Failure::cast(result);
|
||||
return false;
|
||||
@ -1109,7 +1108,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
|
||||
const int kStackSpace = 5;
|
||||
const int kApiArgc = 2;
|
||||
|
||||
__ PrepareCallApiFunction(kStackSpace, kApiArgc);
|
||||
__ PrepareCallApiFunction(kApiArgc, eax);
|
||||
__ mov(ApiParameterOperand(0), ebx); // name.
|
||||
__ add(Operand(ebx), Immediate(kPointerSize));
|
||||
__ mov(ApiParameterOperand(1), ebx); // arguments pointer.
|
||||
@ -1118,7 +1117,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
|
||||
// already generated). Do not allow the assembler to perform a
|
||||
// garbage collection but instead return the allocation failure
|
||||
// object.
|
||||
MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kApiArgc);
|
||||
MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
|
||||
if (result->IsFailure()) {
|
||||
*failure = Failure::cast(result);
|
||||
return false;
|
||||
@ -2169,7 +2168,10 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
||||
|
||||
if (depth != kInvalidProtoDepth) {
|
||||
__ 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.
|
||||
@ -2249,6 +2251,12 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
||||
|
||||
if (depth != kInvalidProtoDepth) {
|
||||
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);
|
||||
if (!success) {
|
||||
return failure;
|
||||
@ -2260,7 +2268,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
||||
// Handle call cache miss.
|
||||
__ bind(&miss);
|
||||
if (depth != kInvalidProtoDepth) {
|
||||
FreeSpaceForFastApiCall(masm(), eax);
|
||||
__ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
|
||||
}
|
||||
__ bind(&miss_in_smi_check);
|
||||
Object* obj;
|
||||
|
Loading…
Reference in New Issue
Block a user