Chromium Code Reviews| Index: src/arm/stub-cache-arm.cc |
| =================================================================== |
| --- src/arm/stub-cache-arm.cc (revision 6213) |
| +++ src/arm/stub-cache-arm.cc (working copy) |
| @@ -571,72 +571,91 @@ |
| __ CallStub(&stub); |
| } |
| +static const int kFastApiCallArguments = 3; |
| // Reserves space for the extra arguments to FastHandleApiCall in the |
| // caller's frame. |
| // |
| -// These arguments are set by CheckPrototypes and GenerateFastApiCall. |
| +// These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
| static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
| Register scratch) { |
| __ mov(scratch, Operand(Smi::FromInt(0))); |
| - __ push(scratch); |
| - __ push(scratch); |
| - __ push(scratch); |
| - __ push(scratch); |
| + for (int i = 0; i < kFastApiCallArguments; i++) { |
| + __ push(scratch); |
| + } |
| } |
| // Undoes the effects of ReserveSpaceForFastApiCall. |
| static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
| - __ Drop(4); |
| + __ Drop(kFastApiCallArguments); |
| } |
| -// Generates call to FastHandleApiCall builtin. |
| -static void GenerateFastApiCall(MacroAssembler* masm, |
| - const CallOptimization& optimization, |
| - int argc) { |
| +static MaybeObject* GenerateFastApiDirectCall(MacroAssembler* masm, |
| + const CallOptimization& optimization, |
| + int argc) { |
| + // ----------- S t a t e ------------- |
| + // -- sp[0] : holder (set by CheckPrototypes) |
| + // -- sp[4] : callee js function |
| + // -- sp[8] : call data |
| + // -- sp[12] : last js argument |
| + // -- ... |
| + // -- sp[(argc + 3) * 4] : first js argument |
| + // -- sp[(argc + 4) * 4] : receiver |
| + // ----------------------------------- |
| // Get the function and setup the context. |
| JSFunction* function = optimization.constant_function(); |
| __ mov(r5, Operand(Handle<JSFunction>(function))); |
| __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); |
| // Pass the additional arguments FastHandleApiCall expects. |
| - bool info_loaded = false; |
| - Object* callback = optimization.api_call_info()->callback(); |
| - if (Heap::InNewSpace(callback)) { |
| - info_loaded = true; |
| - __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| - __ ldr(r7, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset)); |
| - } else { |
| - __ Move(r7, Handle<Object>(callback)); |
| - } |
| 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) { |
| - __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); |
| - } |
| + __ Move(r0, api_call_info_handle); |
| __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); |
| } else { |
| __ Move(r6, Handle<Object>(call_data)); |
| } |
| + // Store js function and call data. |
| + __ stm(ib, sp, r5.bit() | r6.bit()); |
| - __ add(sp, sp, Operand(1 * kPointerSize)); |
| - __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit()); |
| - __ sub(sp, sp, Operand(1 * kPointerSize)); |
| + // r2 points to call data as expected by Arguments class (refer layout above). |
|
antonm
2011/01/26 11:36:38
nit: refer <to> layout above?
Zaheer
2011/02/02 10:05:59
Done.
|
| + __ add(r2, sp, Operand(2 * kPointerSize)); |
| - // Set the number of arguments. |
| - __ mov(r0, Operand(argc + 4)); |
| + Object* callback = optimization.api_call_info()->callback(); |
| + Address api_function_address = v8::ToCData<Address>(callback); |
| + ApiFunction fun(api_function_address); |
| - // 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); |
| + const int kApiStackSpace = 4; |
| + __ PrepareCallApiFunction(kApiStackSpace, |
| + argc + kFastApiCallArguments + 1); |
| + // v8::Arguments::implicit_args = data |
| + __ str(r2, MemOperand(sp)); |
| + // v8::Arguments::values = last argument |
| + __ add(ip, r2, Operand(argc * kPointerSize)); |
| + __ str(ip, MemOperand(sp, 1 * kPointerSize)); |
| + // v8::Arguments::length_ = argc |
| + __ mov(ip, Operand(argc)); |
| + __ str(ip, MemOperand(sp, 2 * kPointerSize)); |
| + // v8::Arguments::is_construct_call = 0 |
| + __ mov(ip, Operand(0)); |
| + __ str(ip, MemOperand(sp, 3 * kPointerSize)); |
| + // r0 = v8::Arguments& |
| + __ mov(r0, sp); |
| + |
| + // 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->TryCallApiFunctionAndReturn(&fun); |
| + if (result->IsFailure()) { |
| + return result; |
| + } |
| + return Heap::undefined_value(); |
| } |
| - |
| class CallInterceptorCompiler BASE_EMBEDDED { |
| public: |
| CallInterceptorCompiler(StubCompiler* stub_compiler, |
| @@ -646,16 +665,16 @@ |
| arguments_(arguments), |
| name_(name) {} |
| - void Compile(MacroAssembler* masm, |
| - JSObject* object, |
| - JSObject* holder, |
| - String* name, |
| - LookupResult* lookup, |
| - Register receiver, |
| - Register scratch1, |
| - Register scratch2, |
| - Register scratch3, |
| - Label* miss) { |
| + MaybeObject* Compile(MacroAssembler* masm, |
| + JSObject* object, |
| + JSObject* holder, |
| + String* name, |
| + LookupResult* lookup, |
| + Register receiver, |
| + Register scratch1, |
| + Register scratch2, |
| + Register scratch3, |
| + Label* miss) { |
| ASSERT(holder->HasNamedInterceptor()); |
| ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| @@ -665,17 +684,17 @@ |
| 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); |
| } else { |
| CompileRegular(masm, |
| object, |
| @@ -686,21 +705,22 @@ |
| name, |
| holder, |
| miss); |
| + return Heap::undefined_value(); |
| } |
| } |
| private: |
| - void CompileCacheable(MacroAssembler* masm, |
| - JSObject* object, |
| - Register receiver, |
| - Register scratch1, |
| - Register scratch2, |
| - Register scratch3, |
| - JSObject* interceptor_holder, |
| - LookupResult* lookup, |
| - String* name, |
| - const CallOptimization& optimization, |
| - Label* miss_label) { |
| + MaybeObject* CompileCacheable(MacroAssembler* masm, |
| + JSObject* object, |
| + Register receiver, |
| + Register scratch1, |
| + Register scratch2, |
| + Register scratch3, |
| + JSObject* interceptor_holder, |
| + LookupResult* lookup, |
| + String* name, |
| + const CallOptimization& optimization, |
| + Label* miss_label) { |
| ASSERT(optimization.is_constant_call()); |
| ASSERT(!lookup->holder()->IsGlobalObject()); |
| @@ -764,7 +784,10 @@ |
| // Invoke function. |
| if (can_do_fast_api_call) { |
| - GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| + MaybeObject* result = GenerateFastApiDirectCall(masm, |
| + optimization, |
| + arguments_.immediate()); |
| + if (result->IsFailure()) return result; |
| } else { |
| __ InvokeFunction(optimization.constant_function(), arguments_, |
| JUMP_FUNCTION); |
| @@ -782,6 +805,8 @@ |
| if (can_do_fast_api_call) { |
| FreeSpaceForFastApiCall(masm); |
| } |
| + |
| + return Heap::undefined_value(); |
| } |
| void CompileRegular(MacroAssembler* masm, |
| @@ -2238,7 +2263,8 @@ |
| } |
| if (depth != kInvalidProtoDepth) { |
| - GenerateFastApiCall(masm(), optimization, argc); |
| + MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); |
| + if (result->IsFailure()) return result; |
| } else { |
| __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| } |
| @@ -2282,16 +2308,19 @@ |
| __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| CallInterceptorCompiler compiler(this, arguments(), r2); |
| - compiler.Compile(masm(), |
| - object, |
| - holder, |
| - name, |
| - &lookup, |
| - r1, |
| - r3, |
| - r4, |
| - r0, |
| - &miss); |
| + MaybeObject* result = compiler.Compile(masm(), |
| + object, |
| + holder, |
| + name, |
| + &lookup, |
| + r1, |
| + r3, |
| + r4, |
| + r0, |
| + &miss); |
| + if (result->IsFailure()) { |
| + return result; |
| + } |
| // Move returned value, the function to call, to r1. |
| __ mov(r1, r0); |