Index: src/x64/macro-assembler-x64.cc |
=================================================================== |
--- src/x64/macro-assembler-x64.cc (revision 5685) |
+++ src/x64/macro-assembler-x64.cc (working copy) |
@@ -469,76 +469,89 @@ |
} |
-void MacroAssembler::PushHandleScope(Register scratch) { |
- ExternalReference extensions_address = |
- ExternalReference::handle_scope_extensions_address(); |
- const int kExtensionsOffset = 0; |
- const int kNextOffset = Offset( |
- ExternalReference::handle_scope_next_address(), |
- extensions_address); |
- const int kLimitOffset = Offset( |
- ExternalReference::handle_scope_limit_address(), |
- extensions_address); |
- |
- // Push the number of extensions, smi-tagged so the gc will ignore it. |
- movq(kScratchRegister, extensions_address); |
- movq(scratch, Operand(kScratchRegister, kExtensionsOffset)); |
- movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); |
- Integer32ToSmi(scratch, scratch); |
- push(scratch); |
- // Push next and limit pointers which will be wordsize aligned and |
- // hence automatically smi tagged. |
- push(Operand(kScratchRegister, kNextOffset)); |
- push(Operand(kScratchRegister, kLimitOffset)); |
+void MacroAssembler::PrepareCallApiFunction(int stack_space) { |
+ EnterApiExitFrame(stack_space, 0); |
} |
-Object* MacroAssembler::PopHandleScopeHelper(Register saved, |
- Register scratch, |
- bool gc_allowed) { |
- ExternalReference extensions_address = |
- ExternalReference::handle_scope_extensions_address(); |
- const int kExtensionsOffset = 0; |
- const int kNextOffset = Offset( |
- ExternalReference::handle_scope_next_address(), |
- extensions_address); |
+void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) { |
+ Label empty_result; |
+ Label prologue; |
+ Label promote_scheduled_exception; |
+ Label delete_allocated_handles; |
+ Label leave_exit_frame; |
+ Label write_back; |
+ |
+ ExternalReference next_address = |
+ ExternalReference::handle_scope_next_address(); |
+ const int kNextOffset = 0; |
const int kLimitOffset = Offset( |
ExternalReference::handle_scope_limit_address(), |
- extensions_address); |
+ next_address); |
+ const int kLevelOffset = Offset( |
+ ExternalReference::handle_scope_level_address(), |
+ next_address); |
+ ExternalReference scheduled_exception_address = |
+ ExternalReference::scheduled_exception_address(); |
- Object* result = NULL; |
- Label write_back; |
- movq(kScratchRegister, extensions_address); |
- cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0)); |
- j(equal, &write_back); |
- push(saved); |
- if (gc_allowed) { |
- CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); |
- } else { |
- result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); |
- if (result->IsFailure()) return result; |
- } |
- pop(saved); |
- movq(kScratchRegister, extensions_address); |
+ // Allocate HandleScope in callee-save registers. |
+ Register prev_next_address_reg = r14; |
+ Register prev_limit_reg = rbx; |
+ Register base_reg = kSmiConstantRegister; |
+ movq(base_reg, next_address); |
+ movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); |
+ movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
+ addl(Operand(base_reg, kLevelOffset), Immediate(1)); |
+ // Call the api function! |
+ movq(rax, |
+ reinterpret_cast<int64_t>(function->address()), |
+ RelocInfo::RUNTIME_ENTRY); |
+ call(rax); |
- bind(&write_back); |
- pop(Operand(kScratchRegister, kLimitOffset)); |
- pop(Operand(kScratchRegister, kNextOffset)); |
- pop(scratch); |
- SmiToInteger32(scratch, scratch); |
- movq(Operand(kScratchRegister, kExtensionsOffset), scratch); |
+#ifdef _WIN64 |
+ // rax keeps a pointer to v8::Handle, unpack it. |
+ movq(rax, Operand(rax, 0)); |
+#endif |
+ // Check if the result handle holds 0. |
+ testq(rax, rax); |
+ j(zero, &empty_result); |
+ // It was non-zero. Dereference to get the result value. |
+ movq(rax, Operand(rax, 0)); |
+ bind(&prologue); |
- return result; |
-} |
+ // No more valid handles (the result handle was the last one). Restore |
+ // previous handle scope. |
+ subl(Operand(base_reg, kLevelOffset), Immediate(1)); |
+ movq(Operand(base_reg, kNextOffset), prev_next_address_reg); |
+ cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset)); |
+ j(not_equal, &delete_allocated_handles); |
+ bind(&leave_exit_frame); |
+ InitializeSmiConstantRegister(); |
+ // Check if the function scheduled an exception. |
+ movq(rsi, scheduled_exception_address); |
+ Cmp(Operand(rsi, 0), Factory::the_hole_value()); |
+ j(not_equal, &promote_scheduled_exception); |
-void MacroAssembler::PopHandleScope(Register saved, Register scratch) { |
- PopHandleScopeHelper(saved, scratch, true); |
-} |
+ LeaveExitFrame(); |
+ ret(0); |
+ bind(&promote_scheduled_exception); |
+ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
-Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { |
- return PopHandleScopeHelper(saved, scratch, false); |
+ bind(&empty_result); |
+ // It was zero; the result is undefined. |
+ Move(rax, Factory::undefined_value()); |
+ jmp(&prologue); |
+ |
+ // HandleScope limit has changed. Delete allocated extensions. |
+ bind(&delete_allocated_handles); |
+ movq(Operand(base_reg, kLimitOffset), prev_limit_reg); |
+ movq(prev_limit_reg, rax); |
+ movq(rax, ExternalReference::delete_handle_scope_extensions()); |
+ call(rax); |
+ movq(rax, prev_limit_reg); |
+ jmp(&leave_exit_frame); |
} |