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); |