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,11 @@ |
__ CallStub(&stub); |
} |
+#ifdef USE_SIMULATOR |
+static const int kFastApiCallArguments = 4; |
+#else |
+static const int kFastApiCallArguments = 3; |
+#endif |
// Reserves space for the extra arguments to FastHandleApiCall in the |
// caller's frame. |
@@ -579,16 +584,15 @@ |
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); |
} |
@@ -636,7 +640,75 @@ |
RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
} |
+#ifndef USE_SIMULATOR |
+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. |
+ Object* call_data = optimization.api_call_info()->data(); |
+ Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); |
+ if (Heap::InNewSpace(call_data)) { |
+ __ 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()); |
+ |
+ // r2 points to calldata as expected by Arguments class (refer layout above) |
+ __ add(r2, sp, Operand(2 * kPointerSize)); |
+ |
+ Object* callback = optimization.api_call_info()->callback(); |
+ Address api_function_address = v8::ToCData<Address>(callback); |
+ ApiFunction fun(api_function_address); |
+ |
+ 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; |
+} |
+#endif |
+ |
+ |
class CallInterceptorCompiler BASE_EMBEDDED { |
public: |
CallInterceptorCompiler(StubCompiler* stub_compiler, |
@@ -646,7 +718,7 @@ |
arguments_(arguments), |
name_(name) {} |
- void Compile(MacroAssembler* masm, |
+ bool Compile(MacroAssembler* masm, |
JSObject* object, |
JSObject* holder, |
String* name, |
@@ -655,7 +727,8 @@ |
Register scratch1, |
Register scratch2, |
Register scratch3, |
- Label* miss) { |
+ Label* miss, |
+ Failure **failure) { |
ASSERT(holder->HasNamedInterceptor()); |
ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
@@ -665,7 +738,7 @@ |
CallOptimization optimization(lookup); |
if (optimization.is_constant_call()) { |
- CompileCacheable(masm, |
+ return CompileCacheable(masm, |
object, |
receiver, |
scratch1, |
@@ -675,7 +748,8 @@ |
lookup, |
name, |
optimization, |
- miss); |
+ miss, |
+ failure); |
} else { |
CompileRegular(masm, |
object, |
@@ -686,11 +760,12 @@ |
name, |
holder, |
miss); |
+ return true; |
} |
} |
private: |
- void CompileCacheable(MacroAssembler* masm, |
+ bool CompileCacheable(MacroAssembler* masm, |
JSObject* object, |
Register receiver, |
Register scratch1, |
@@ -700,7 +775,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 +840,17 @@ |
// Invoke function. |
if (can_do_fast_api_call) { |
+#ifdef USE_SIMULATOR |
GenerateFastApiCall(masm, optimization, arguments_.immediate()); |
+#else |
+ bool success = GenerateFastApiDirectCall(masm, |
+ optimization, |
+ arguments_.immediate(), |
+ failure); |
+ if (!success) { |
+ return false; |
+ } |
+#endif |
} else { |
__ InvokeFunction(optimization.constant_function(), arguments_, |
JUMP_FUNCTION); |
@@ -782,6 +868,8 @@ |
if (can_do_fast_api_call) { |
FreeSpaceForFastApiCall(masm); |
} |
+ |
+ return true; |
} |
void CompileRegular(MacroAssembler* masm, |
@@ -2238,7 +2326,18 @@ |
} |
if (depth != kInvalidProtoDepth) { |
+#ifdef USE_SIMULATOR |
GenerateFastApiCall(masm(), optimization, argc); |
+#else |
+ Failure* failure; |
+ bool success = GenerateFastApiDirectCall(masm(), |
+ optimization, |
+ argc, |
+ &failure); |
+ if (!success) { |
+ return failure; |
+ } |
+#endif |
} else { |
__ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
} |
@@ -2282,7 +2381,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 +2391,11 @@ |
r3, |
r4, |
r0, |
- &miss); |
+ &miss, |
+ &failure); |
+ if (!success) { |
+ return false; |
+ } |
// Move returned value, the function to call, to r1. |
__ mov(r1, r0); |