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,6 +571,7 @@ |
| __ CallStub(&stub); |
| } |
| +static const int kFastApiCallArguments = 3; |
| // Reserves space for the extra arguments to FastHandleApiCall in the |
| // caller's frame. |
| @@ -579,64 +580,85 @@ |
| 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 bool GenerateFastApiDirectCall(MacroAssembler* masm, |
|
Erik Corry
2011/01/24 21:45:16
Instead of returning a bool and using a Failure**
Zaheer
2011/01/25 07:39:52
Actually i followed the IA32 return structure. Mod
|
| + const CallOptimization& optimization, |
| + int argc, |
| + Failure** failure) { |
| + // ----------- 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). |
| + __ 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()) { |
| + *failure = Failure::cast(result); |
| + return false; |
| + } |
| + return true; |
| } |
| - |
| class CallInterceptorCompiler BASE_EMBEDDED { |
| public: |
| CallInterceptorCompiler(StubCompiler* stub_compiler, |
| @@ -646,7 +668,7 @@ |
| arguments_(arguments), |
| name_(name) {} |
| - void Compile(MacroAssembler* masm, |
| + bool Compile(MacroAssembler* masm, |
| JSObject* object, |
| JSObject* holder, |
| String* name, |
| @@ -655,7 +677,8 @@ |
| Register scratch1, |
| Register scratch2, |
| Register scratch3, |
| - Label* miss) { |
| + Label* miss, |
| + Failure **failure) { |
| ASSERT(holder->HasNamedInterceptor()); |
| ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| @@ -665,7 +688,7 @@ |
| CallOptimization optimization(lookup); |
| if (optimization.is_constant_call()) { |
| - CompileCacheable(masm, |
| + return CompileCacheable(masm, |
| object, |
| receiver, |
| scratch1, |
| @@ -675,7 +698,8 @@ |
| lookup, |
| name, |
| optimization, |
| - miss); |
| + miss, |
| + failure); |
| } else { |
| CompileRegular(masm, |
| object, |
| @@ -686,11 +710,12 @@ |
| name, |
| holder, |
| miss); |
| + return true; |
| } |
| } |
| private: |
| - void CompileCacheable(MacroAssembler* masm, |
| + bool CompileCacheable(MacroAssembler* masm, |
| JSObject* object, |
| Register receiver, |
| Register scratch1, |
| @@ -700,7 +725,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()); |
| @@ -764,7 +790,13 @@ |
| // Invoke function. |
| if (can_do_fast_api_call) { |
| - GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
| + bool success = GenerateFastApiDirectCall(masm, |
| + optimization, |
| + arguments_.immediate(), |
| + failure); |
| + if (!success) { |
| + return false; |
| + } |
| } else { |
| __ InvokeFunction(optimization.constant_function(), arguments_, |
| JUMP_FUNCTION); |
| @@ -782,6 +814,8 @@ |
| if (can_do_fast_api_call) { |
| FreeSpaceForFastApiCall(masm); |
| } |
| + |
| + return true; |
| } |
| void CompileRegular(MacroAssembler* masm, |
| @@ -2238,7 +2272,14 @@ |
| } |
| if (depth != kInvalidProtoDepth) { |
| - GenerateFastApiCall(masm(), optimization, argc); |
| + Failure* failure; |
| + bool success = GenerateFastApiDirectCall(masm(), |
| + optimization, |
| + argc, |
| + &failure); |
| + if (!success) { |
| + return failure; |
| + } |
| } else { |
| __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| } |
| @@ -2282,7 +2323,8 @@ |
| __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| CallInterceptorCompiler compiler(this, arguments(), r2); |
| - compiler.Compile(masm(), |
| + Failure *failure; |
| + bool success = compiler.Compile(masm(), |
| object, |
| holder, |
| name, |
| @@ -2291,7 +2333,11 @@ |
| r3, |
| r4, |
| r0, |
| - &miss); |
| + &miss, |
| + &failure); |
| + if (!success) { |
| + return false; |
| + } |
| // Move returned value, the function to call, to r1. |
| __ mov(r1, r0); |