Chromium Code Reviews| 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)); |