Index: src/arm/stub-cache-arm.cc |
=================================================================== |
--- src/arm/stub-cache-arm.cc (revision 6551) |
+++ src/arm/stub-cache-arm.cc (working copy) |
@@ -575,72 +575,94 @@ |
__ 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 |
+ // (refer to 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; |
+ __ EnterExitFrame(false, kApiStackSpace); |
+ |
+ // r0 = v8::Arguments& |
+ // Arguments is after the return address. |
+ __ add(r0, sp, Operand(1 * kPointerSize)); |
+ // v8::Arguments::implicit_args = data |
+ __ str(r2, MemOperand(r0, 0 * kPointerSize)); |
+ // v8::Arguments::values = last argument |
+ __ add(ip, r2, Operand(argc * kPointerSize)); |
+ __ str(ip, MemOperand(r0, 1 * kPointerSize)); |
+ // v8::Arguments::length_ = argc |
+ __ mov(ip, Operand(argc)); |
+ __ str(ip, MemOperand(r0, 2 * kPointerSize)); |
+ // v8::Arguments::is_construct_call = 0 |
+ __ mov(ip, Operand(0)); |
+ __ str(ip, MemOperand(r0, 3 * kPointerSize)); |
+ |
+ // 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, argc + kFastApiCallArguments + 1); |
+ if (result->IsFailure()) { |
+ return result; |
+ } |
+ return Heap::undefined_value(); |
} |
- |
class CallInterceptorCompiler BASE_EMBEDDED { |
public: |
CallInterceptorCompiler(StubCompiler* stub_compiler, |
@@ -650,16 +672,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()); |
@@ -669,17 +691,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, |
@@ -690,21 +712,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()); |
@@ -768,7 +791,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); |
@@ -786,6 +812,8 @@ |
if (can_do_fast_api_call) { |
FreeSpaceForFastApiCall(masm); |
} |
+ |
+ return Heap::undefined_value(); |
} |
void CompileRegular(MacroAssembler* masm, |
@@ -2368,7 +2396,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); |
} |
@@ -2412,16 +2441,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); |