Index: src/ia32/stub-cache-ia32.cc |
=================================================================== |
--- src/ia32/stub-cache-ia32.cc (revision 5789) |
+++ src/ia32/stub-cache-ia32.cc (working copy) |
@@ -413,6 +413,10 @@ |
} |
+// Amount of pointers to be reserved on stack for v8::Arguments::implicit_args_. |
antonm
2010/11/09 13:56:19
I am not a native speaker, but I would rather say
antonm
2010/11/09 13:56:19
'v8::Arguments::implicit_args_': should either be
|
+static const int kFastApiCallArguments = 3; |
+ |
+ |
// Reserves space for the extra arguments to FastHandleApiCall in the |
// caller's frame. |
// |
@@ -423,10 +427,9 @@ |
// -- esp[4] : last argument in the internal frame of the caller |
// ----------------------------------- |
__ pop(scratch); |
- __ push(Immediate(Smi::FromInt(0))); |
- __ push(Immediate(Smi::FromInt(0))); |
- __ push(Immediate(Smi::FromInt(0))); |
- __ push(Immediate(Smi::FromInt(0))); |
+ for (int i = 0; i < kFastApiCallArguments; i++) { |
+ __ push(Immediate(Smi::FromInt(0))); |
+ } |
__ push(scratch); |
} |
@@ -434,75 +437,81 @@ |
// Undoes the effects of ReserveSpaceForFastApiCall. |
static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { |
// ----------- S t a t e ------------- |
- // -- esp[0] : return address |
- // -- esp[4] : last fast api call extra argument |
+ // -- esp[0] : return address. |
+ // -- esp[4] : last fast api call extra argument. |
// -- ... |
- // -- esp[16] : first fast api call extra argument |
- // -- esp[20] : last argument in the internal frame |
+ // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument. |
+ // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal |
+ // frame. |
// ----------------------------------- |
__ pop(scratch); |
- __ add(Operand(esp), Immediate(kPointerSize * 4)); |
+ __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments)); |
__ push(scratch); |
} |
// Generates call to FastHandleApiCall builtin. |
-static void GenerateFastApiCall(MacroAssembler* masm, |
+static bool GenerateFastApiCall(MacroAssembler* masm, |
const CallOptimization& optimization, |
- int argc) { |
+ int argc, |
+ Failure** failure) { |
// ----------- S t a t e ------------- |
// -- esp[0] : return address |
// -- esp[4] : object passing the type check |
// (last fast api call extra argument, |
// set by CheckPrototypes) |
- // -- esp[8] : api call data |
- // -- esp[12] : api callback |
- // -- esp[16] : api function |
+ // -- esp[8] : api function |
// (first fast api call extra argument) |
- // -- esp[20] : last argument |
+ // -- esp[12] : api call data |
+ // -- esp[16] : last argument |
// -- ... |
- // -- esp[(argc + 5) * 4] : first argument |
- // -- esp[(argc + 6) * 4] : receiver |
+ // -- esp[(argc + 3) * 4] : first argument |
+ // -- esp[(argc + 4) * 4] : receiver |
// ----------------------------------- |
- |
// Get the function and setup the context. |
JSFunction* function = optimization.constant_function(); |
__ mov(edi, Immediate(Handle<JSFunction>(function))); |
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
// Pass the additional arguments FastHandleApiCall expects. |
- __ mov(Operand(esp, 4 * kPointerSize), edi); |
- bool info_loaded = false; |
- Object* callback = optimization.api_call_info()->callback(); |
- if (Heap::InNewSpace(callback)) { |
- info_loaded = true; |
- __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info())); |
- __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset)); |
- __ mov(Operand(esp, 3 * kPointerSize), ebx); |
- } else { |
- __ mov(Operand(esp, 3 * kPointerSize), Immediate(Handle<Object>(callback))); |
- } |
+ __ mov(Operand(esp, 2 * kPointerSize), edi); |
Object* call_data = optimization.api_call_info()->data(); |
+ Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); |
if (Heap::InNewSpace(call_data)) { |
- if (!info_loaded) { |
- __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info())); |
- } |
+ __ mov(ecx, api_call_info_handle); |
__ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); |
- __ mov(Operand(esp, 2 * kPointerSize), ebx); |
+ __ mov(Operand(esp, 3 * kPointerSize), ebx); |
} else { |
- __ mov(Operand(esp, 2 * kPointerSize), |
+ __ mov(Operand(esp, 3 * kPointerSize), |
Immediate(Handle<Object>(call_data))); |
} |
- // Set the number of arguments. |
- __ mov(eax, Immediate(argc + 4)); |
+ // Prepare arguments for ApiCallEntryStub. |
+ __ lea(eax, Operand(esp, 3 * kPointerSize)); |
+ __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize)); |
+ __ Set(edx, Immediate(argc)); |
- // Jump to the fast api call builtin (tail call). |
- Handle<Code> code = Handle<Code>( |
- Builtins::builtin(Builtins::FastHandleApiCall)); |
- ParameterCount expected(0); |
- __ InvokeCode(code, expected, expected, |
- RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
+ Object* callback = optimization.api_call_info()->callback(); |
+ Address api_function_address = v8::ToCData<Address>(callback); |
+ ApiFunction fun(api_function_address); |
+ |
+ ApiCallEntryStub stub(api_call_info_handle, &fun); |
+ |
+ __ EnterInternalFrame(); |
+ |
+ // Emitting a stub call may try to allocate (if the code is not |
+ // already generated). Do not allow the assembler to perform a |
+ // garbage collection but instead return the allocation failure |
+ // object. |
+ MaybeObject* result = masm->TryCallStub(&stub); |
+ if (result->IsFailure()) { |
+ *failure = Failure::cast(result); |
+ return false; |
+ } |
+ |
+ __ LeaveInternalFrame(); |
+ __ ret((argc + 4) * kPointerSize); |
+ return true; |
} |
@@ -515,7 +524,7 @@ |
arguments_(arguments), |
name_(name) {} |
- void Compile(MacroAssembler* masm, |
+ bool Compile(MacroAssembler* masm, |
JSObject* object, |
JSObject* holder, |
String* name, |
@@ -524,7 +533,8 @@ |
Register scratch1, |
Register scratch2, |
Register scratch3, |
- Label* miss) { |
+ Label* miss, |
+ Failure** failure) { |
ASSERT(holder->HasNamedInterceptor()); |
ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
@@ -535,17 +545,18 @@ |
CallOptimization optimization(lookup); |
if (optimization.is_constant_call()) { |
- CompileCacheable(masm, |
- object, |
- receiver, |
- scratch1, |
- scratch2, |
- scratch3, |
- holder, |
- lookup, |
- name, |
- optimization, |
- miss); |
+ return CompileCacheable(masm, |
+ object, |
+ receiver, |
+ scratch1, |
+ scratch2, |
+ scratch3, |
+ holder, |
+ lookup, |
+ name, |
+ optimization, |
+ miss, |
+ failure); |
} else { |
CompileRegular(masm, |
object, |
@@ -556,11 +567,12 @@ |
name, |
holder, |
miss); |
+ return true; |
} |
} |
private: |
- void CompileCacheable(MacroAssembler* masm, |
+ bool CompileCacheable(MacroAssembler* masm, |
JSObject* object, |
Register receiver, |
Register scratch1, |
@@ -570,7 +582,8 @@ |
LookupResult* lookup, |
String* name, |
const CallOptimization& optimization, |
- Label* miss_label) { |
+ Label* miss_label, |
+ Failure** failure) { |
ASSERT(optimization.is_constant_call()); |
ASSERT(!lookup->holder()->IsGlobalObject()); |
@@ -632,7 +645,11 @@ |
// Invoke function. |
if (can_do_fast_api_call) { |
- GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
+ bool success = GenerateFastApiCall(masm, optimization, |
+ arguments_.immediate(), failure); |
+ if (!success) { |
+ return false; |
+ } |
} else { |
__ InvokeFunction(optimization.constant_function(), arguments_, |
JUMP_FUNCTION); |
@@ -650,6 +667,8 @@ |
if (can_do_fast_api_call) { |
FreeSpaceForFastApiCall(masm, scratch1); |
} |
+ |
+ return true; |
} |
void CompileRegular(MacroAssembler* masm, |
@@ -1046,8 +1065,7 @@ |
__ EnterInternalFrame(); |
// Push the stack address where the list of arguments ends. |
- __ mov(scratch2, esp); |
- __ sub(Operand(scratch2), Immediate(2 * kPointerSize)); |
+ __ lea(scratch2, Operand(esp, -2 * kPointerSize)); |
__ push(scratch2); |
__ push(receiver); // receiver |
__ push(reg); // holder |
@@ -1061,12 +1079,11 @@ |
__ push(name_reg); // name |
// Save a pointer to where we pushed the arguments pointer. |
// This will be passed as the const AccessorInfo& to the C++ callback. |
- __ mov(eax, esp); |
- __ add(Operand(eax), Immediate(4 * kPointerSize)); |
+ STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5); |
+ __ lea(eax, Operand(esp, 4 * kPointerSize)); |
__ mov(ebx, esp); |
// Do call through the api. |
- ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace); |
Address getter_address = v8::ToCData<Address>(callback->getter()); |
ApiFunction fun(getter_address); |
ApiGetterEntryStub stub(callback_handle, &fun); |
@@ -2208,7 +2225,11 @@ |
} |
if (depth != kInvalidProtoDepth) { |
- GenerateFastApiCall(masm(), optimization, argc); |
+ Failure* failure; |
+ bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); |
+ if (!success) { |
+ return failure; |
+ } |
} else { |
__ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
} |
@@ -2253,16 +2274,21 @@ |
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
CallInterceptorCompiler compiler(this, arguments(), ecx); |
- compiler.Compile(masm(), |
- object, |
- holder, |
- name, |
- &lookup, |
- edx, |
- ebx, |
- edi, |
- eax, |
- &miss); |
+ Failure* failure; |
+ bool success = compiler.Compile(masm(), |
+ object, |
+ holder, |
+ name, |
+ &lookup, |
+ edx, |
+ ebx, |
+ edi, |
+ eax, |
+ &miss, |
+ &failure); |
+ if (!success) { |
+ return false; |
+ } |
// Restore receiver. |
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |