Chromium Code Reviews| Index: src/arm/macro-assembler-arm.cc |
| =================================================================== |
| --- src/arm/macro-assembler-arm.cc (revision 6213) |
| +++ src/arm/macro-assembler-arm.cc (working copy) |
| @@ -1397,6 +1397,133 @@ |
| } |
| +MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub, Condition cond) { |
| + ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs |
| + Object* result; |
| + { MaybeObject* maybe_result = stub->TryGetCode(); |
| + if (!maybe_result->ToObject(&result)) return maybe_result; |
| + } |
| + Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond); |
| + return result; |
| +} |
| + |
| + |
| +void MacroAssembler::PrepareCallApiFunction(int arg_stack_space, |
| + int unwind_space, |
| + Register scratch) { |
| + mov(scratch, Operand(unwind_space)); |
|
antonm
2011/01/11 14:11:33
it looks like a lot of code below is shared with M
Zaheer
2011/01/11 15:44:35
The behavior is different from EnterExitFrame
- v8
antonm
2011/01/11 19:27:40
Zaheer,
I am not sure it's something which cannot
Zaheer
2011/01/12 13:20:03
split the code as EnterApiExitFramePrologue/Epilog
|
| + add(ip, sp, Operand(scratch, LSL, kPointerSizeLog2)); |
|
SeRya
2011/01/11 16:34:50
add(ip, sp, Operand(unwind_space * kPointerSize));
Zaheer
2011/01/12 13:20:03
Done
|
| + |
| + stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); |
| + mov(fp, Operand(sp)); |
| + |
| + mov(ip, Operand(CodeObject())); |
| + push(ip); |
| + push(ip); // Exit Frame pc patched before call |
| + |
| + // create space for the args |
| + sub(sp, sp, Operand(arg_stack_space * kPointerSize)); |
| + |
| + int frame_alignment = ActivationFrameAlignment(); |
| + int frame_alignment_mask = frame_alignment - 1; |
| + if (frame_alignment > kPointerSize) { |
| + mov(scratch, Operand(0)); |
| + tst(sp, Operand(frame_alignment_mask)); |
| + push(scratch, nz); |
|
SeRya
2011/01/11 16:34:50
ASSERT(frame_alignment == 2 * kPointerSize);
Zaheer
2011/01/12 13:20:03
Done
|
| + } |
| + |
| + mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
|
SeRya
2011/01/11 16:34:50
ia32 code allocates C arguments below c_entry_fp_a
Zaheer
2011/01/12 13:20:03
i do allocate the args on top of the exit frame si
|
| + str(fp, MemOperand(ip)); |
| + mov(ip, Operand(ExternalReference(Top::k_context_address))); |
| + str(cp, MemOperand(ip)); |
| +} |
| + |
| + |
| +MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn( |
| + ApiFunction* function) { |
| + ExternalReference next_address = |
| + ExternalReference::handle_scope_next_address(); |
| + ExternalReference limit_address = |
| + ExternalReference::handle_scope_limit_address(); |
| + ExternalReference level_address = |
| + ExternalReference::handle_scope_level_address(); |
| + |
| + // Allocate HandleScope in callee-save registers. |
| + mov(ip, Operand(next_address)); |
|
SeRya
2011/01/11 16:34:50
x64 implementation use offsets to eliminate 2 of 3
Zaheer
2011/01/12 13:20:03
Done! but i could remove only the mov not ldr inst
|
| + ldr(r4, MemOperand(ip)); |
| + mov(ip, Operand(limit_address)); |
| + ldr(r5, MemOperand(ip)); |
| + mov(ip, Operand(level_address)); |
| + ldr(r6, MemOperand(ip)); |
| + add(r6, r6, Operand(1)); |
| + str(r6, MemOperand(ip)); |
| + |
| + // patch the exit frame pc and Call the api function! |
|
antonm
2011/01/11 14:11:33
nit: [P]atch and [c]all.
antonm
2011/01/11 14:11:33
once again, can we factor out frame handling?
Zaheer
2011/01/11 15:44:35
Done
Zaheer
2011/01/11 15:44:35
same issues as mentioned before for refactoring
|
| + add(ip, pc, Operand(8)); |
| + str(ip, MemOperand(fp, -2 * kPointerSize)); |
|
antonm
2011/01/11 14:11:33
do not we have a named constant for -2?
Zaheer
2011/01/11 15:44:35
check ExitFrame::FillState(..) it seems to be hard
|
| + Call(function->address(), RelocInfo::RUNTIME_ENTRY); |
| + |
| + Label empty_handle; |
| + Label prologue; |
| + Label promote_scheduled_exception; |
| + Label delete_allocated_handles; |
| + Label leave_exit_frame; |
| + |
| + // Check if the result handle holds 0. |
| + cmp(r0, Operand(0)); |
| + b(eq, &empty_handle); |
| + // It was non-zero. Dereference to get the result value. |
| + ldr(r0, MemOperand(r0)); |
|
SeRya
2011/01/11 16:34:50
LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
Zaheer
2011/01/12 13:20:03
Done! Thanks for the pointer, it simplifies the co
|
| + bind(&prologue); |
| + // No more valid handles (the result handle was the last one). Restore |
| + // previous handle scope. |
| + mov(ip, Operand(next_address)); |
| + str(r4, MemOperand(ip)); |
| + mov(ip, Operand(level_address)); |
| + ldr(r6, MemOperand(ip)); |
| + sub(r6, r6, Operand(1)); |
| + str(r6, MemOperand(ip)); |
| + mov(ip, Operand(limit_address)); |
| + ldr(ip, MemOperand(ip)); |
| + cmp(r5, ip); |
| + b(ne, &delete_allocated_handles); |
| + |
| + // Check if the function scheduled an exception. |
| + bind(&leave_exit_frame); |
| + mov(ip, Operand(ExternalReference::the_hole_value_location())); |
| + ldr(r4, MemOperand(ip)); |
|
antonm
2011/01/11 14:11:33
Shouldn't it be LoadRoot(r4, Heap::kTheHoleValueRo
Zaheer
2011/01/11 15:44:35
Done
|
| + mov(ip, Operand(ExternalReference(Top::k_pending_exception_address))); |
| + ldr(r5, MemOperand(ip)); |
| + cmp(r4, r5); |
| + b(ne, &promote_scheduled_exception); |
| + LeaveExitFrame(0); |
|
antonm
2011/01/11 14:11:33
LeaveExitFrame apparently takes bool, not int
Zaheer
2011/01/11 15:44:35
done
|
| + |
| + bind(&promote_scheduled_exception); |
| + MaybeObject* result = TryTailCallExternalReference( |
| + ExternalReference(Runtime::kPromoteScheduledException), 0, 1); |
| + if (result->IsFailure()) { |
| + return result; |
| + } |
| + |
| + bind(&empty_handle); |
| + // It was zero; the result is undefined. |
| + LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| + b(&prologue); |
| + |
| + // HandleScope limit has changed. Delete allocated extensions. |
| + bind(&delete_allocated_handles); |
| + mov(ip, Operand(limit_address)); |
| + str(r5, MemOperand(ip)); |
| + mov(r4, r0); |
| + PrepareCallCFunction(0, r5); |
| + CallCFunction(ExternalReference::delete_handle_scope_extensions(), 0); |
| + mov(r0, r4); |
| + jmp(&leave_exit_frame); |
| + |
| + return result; |
| +} |
| + |
| + |
| void MacroAssembler::IllegalOperation(int num_arguments) { |
| if (num_arguments > 0) { |
| add(sp, sp, Operand(num_arguments * kPointerSize)); |
| @@ -1649,6 +1776,15 @@ |
| JumpToExternalReference(ext); |
| } |
| +MaybeObject* MacroAssembler::TryTailCallExternalReference( |
| + const ExternalReference& ext, int num_arguments, int result_size) { |
| + // TODO(1236192): Most runtime routines don't need the number of |
| + // arguments passed in because it is constant. At some point we |
| + // should remove this need and make the runtime routine entry code |
| + // smarter. |
| + mov(r0, Operand(num_arguments)); |
| + return TryJumpToExternalReference(ext); |
| +} |
| void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
| int num_arguments, |
| @@ -1667,6 +1803,16 @@ |
| Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| } |
| +MaybeObject* MacroAssembler::TryJumpToExternalReference( |
| + const ExternalReference& builtin) { |
| +#if defined(__thumb__) |
| + // Thumb mode builtin. |
| + ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); |
| +#endif |
| + mov(r1, Operand(builtin)); |
| + CEntryStub stub(1); |
| + return TryTailCallStub(&stub); |
| +} |
| void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| InvokeJSFlags flags) { |