 Chromium Code Reviews
 Chromium Code Reviews Issue 6170001:
  Direct call api functions (arm implementation)  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
    
  
    Issue 6170001:
  Direct call api functions (arm implementation)  (Closed) 
  Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/| 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,84 @@ | 
| 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, | 
| + 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)); | 
| } | 
| + __ stm(ib, sp, r5.bit() | r6.bit()); | 
| 
antonm
2011/01/21 17:56:36
Please, add a comment
 
Zaheer
2011/01/24 09:43:31
Done.
 | 
| - __ add(sp, sp, Operand(1 * kPointerSize)); | 
| - __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit()); | 
| - __ sub(sp, sp, Operand(1 * kPointerSize)); | 
| + // r2 points to calldata as expected by Arguments class (refer layout above) | 
| 
antonm
2011/01/21 17:56:36
nit: either call_data or call data, please
 
Zaheer
2011/01/24 09:43:31
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()) { | 
| + *failure = Failure::cast(result); | 
| + return false; | 
| + } | 
| + return true; | 
| } | 
| - | 
| class CallInterceptorCompiler BASE_EMBEDDED { | 
| public: | 
| CallInterceptorCompiler(StubCompiler* stub_compiler, | 
| @@ -646,7 +667,7 @@ | 
| arguments_(arguments), | 
| name_(name) {} | 
| - void Compile(MacroAssembler* masm, | 
| + bool Compile(MacroAssembler* masm, | 
| JSObject* object, | 
| JSObject* holder, | 
| String* name, | 
| @@ -655,7 +676,8 @@ | 
| Register scratch1, | 
| Register scratch2, | 
| Register scratch3, | 
| - Label* miss) { | 
| + Label* miss, | 
| + Failure **failure) { | 
| ASSERT(holder->HasNamedInterceptor()); | 
| ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 
| @@ -665,7 +687,7 @@ | 
| CallOptimization optimization(lookup); | 
| if (optimization.is_constant_call()) { | 
| - CompileCacheable(masm, | 
| + return CompileCacheable(masm, | 
| object, | 
| receiver, | 
| scratch1, | 
| @@ -675,7 +697,8 @@ | 
| lookup, | 
| name, | 
| optimization, | 
| - miss); | 
| + miss, | 
| + failure); | 
| } else { | 
| CompileRegular(masm, | 
| object, | 
| @@ -686,11 +709,12 @@ | 
| name, | 
| holder, | 
| miss); | 
| + return true; | 
| } | 
| } | 
| private: | 
| - void CompileCacheable(MacroAssembler* masm, | 
| + bool CompileCacheable(MacroAssembler* masm, | 
| JSObject* object, | 
| Register receiver, | 
| Register scratch1, | 
| @@ -700,7 +724,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 +789,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 +813,8 @@ | 
| if (can_do_fast_api_call) { | 
| FreeSpaceForFastApiCall(masm); | 
| } | 
| + | 
| + return true; | 
| } | 
| void CompileRegular(MacroAssembler* masm, | 
| @@ -2238,7 +2271,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 +2322,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 +2332,11 @@ | 
| r3, | 
| r4, | 
| r0, | 
| - &miss); | 
| + &miss, | 
| + &failure); | 
| + if (!success) { | 
| + return false; | 
| + } | 
| // Move returned value, the function to call, to r1. | 
| __ mov(r1, r0); |