Index: src/x64/macro-assembler-x64.cc |
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc |
index 2c946f56b9fc4c13c15e7d16ea59c76aeabf67f1..293d8a5633f6ed33e40a47dc864cc305cf1654c1 100644 |
--- a/src/x64/macro-assembler-x64.cc |
+++ b/src/x64/macro-assembler-x64.cc |
@@ -315,11 +315,12 @@ void MacroAssembler::CallStub(CodeStub* stub) { |
} |
-Object* MacroAssembler::TryCallStub(CodeStub* stub) { |
+MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) { |
ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. |
- Object* result = stub->TryGetCode(); |
+ MaybeObject* result = stub->TryGetCode(); |
if (!result->IsFailure()) { |
- call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); |
+ call(Handle<Code>(Code::cast(result->ToObjectUnchecked())), |
+ RelocInfo::CODE_TARGET); |
} |
return result; |
} |
@@ -331,11 +332,12 @@ void MacroAssembler::TailCallStub(CodeStub* stub) { |
} |
-Object* MacroAssembler::TryTailCallStub(CodeStub* stub) { |
+MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) { |
ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. |
- Object* result = stub->TryGetCode(); |
+ MaybeObject* result = stub->TryGetCode(); |
if (!result->IsFailure()) { |
- jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); |
+ jmp(Handle<Code>(Code::cast(result->ToObjectUnchecked())), |
+ RelocInfo::CODE_TARGET); |
} |
return result; |
} |
@@ -379,8 +381,8 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { |
} |
-Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, |
- int num_arguments) { |
+MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, |
+ int num_arguments) { |
return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); |
} |
@@ -405,8 +407,8 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { |
} |
-Object* MacroAssembler::TryCallRuntime(Runtime::Function* f, |
- int num_arguments) { |
+MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f, |
+ int num_arguments) { |
if (f->nargs >= 0 && f->nargs != num_arguments) { |
IllegalOperation(num_arguments); |
// Since we did not call the stub, there was no allocation failure. |
@@ -469,76 +471,89 @@ static int Offset(ExternalReference ref0, ExternalReference ref1) { |
} |
-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); |
- const int kLimitOffset = Offset( |
- ExternalReference::handle_scope_limit_address(), |
- extensions_address); |
- |
- Object* result = NULL; |
+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; |
- 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); |
- |
- bind(&write_back); |
- pop(Operand(kScratchRegister, kLimitOffset)); |
- pop(Operand(kScratchRegister, kNextOffset)); |
- pop(scratch); |
- SmiToInteger32(scratch, scratch); |
- movq(Operand(kScratchRegister, kExtensionsOffset), scratch); |
- return result; |
-} |
+ ExternalReference next_address = |
+ ExternalReference::handle_scope_next_address(); |
+ const int kNextOffset = 0; |
+ const int kLimitOffset = Offset( |
+ ExternalReference::handle_scope_limit_address(), |
+ next_address); |
+ const int kLevelOffset = Offset( |
+ ExternalReference::handle_scope_level_address(), |
+ next_address); |
+ ExternalReference scheduled_exception_address = |
+ ExternalReference::scheduled_exception_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); |
+#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); |
+ |
+ // 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); |
+ |
+ LeaveExitFrame(); |
+ ret(0); |
-void MacroAssembler::PopHandleScope(Register saved, Register scratch) { |
- PopHandleScopeHelper(saved, scratch, true); |
-} |
+ bind(&promote_scheduled_exception); |
+ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
+ bind(&empty_result); |
+ // It was zero; the result is undefined. |
+ Move(rax, Factory::undefined_value()); |
+ jmp(&prologue); |
-Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { |
- return PopHandleScopeHelper(saved, scratch, false); |
+ // 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); |
} |
@@ -1891,6 +1906,20 @@ void MacroAssembler::AllocateInNewSpace(int object_size, |
Register scratch, |
Label* gc_required, |
AllocationFlags flags) { |
+ if (!FLAG_inline_new) { |
+ if (FLAG_debug_code) { |
+ // Trash the registers to simulate an allocation failure. |
+ movl(result, Immediate(0x7091)); |
+ if (result_end.is_valid()) { |
+ movl(result_end, Immediate(0x7191)); |
+ } |
+ if (scratch.is_valid()) { |
+ movl(scratch, Immediate(0x7291)); |
+ } |
+ } |
+ jmp(gc_required); |
+ return; |
+ } |
ASSERT(!result.is(result_end)); |
// Load address of new object into result. |
@@ -1935,6 +1964,19 @@ void MacroAssembler::AllocateInNewSpace(int header_size, |
Register scratch, |
Label* gc_required, |
AllocationFlags flags) { |
+ if (!FLAG_inline_new) { |
+ if (FLAG_debug_code) { |
+ // Trash the registers to simulate an allocation failure. |
+ movl(result, Immediate(0x7091)); |
+ movl(result_end, Immediate(0x7191)); |
+ if (scratch.is_valid()) { |
+ movl(scratch, Immediate(0x7291)); |
+ } |
+ // Register element_count is not modified by the function. |
+ } |
+ jmp(gc_required); |
+ return; |
+ } |
ASSERT(!result.is(result_end)); |
// Load address of new object into result. |
@@ -1964,6 +2006,21 @@ void MacroAssembler::AllocateInNewSpace(Register object_size, |
Register scratch, |
Label* gc_required, |
AllocationFlags flags) { |
+ if (!FLAG_inline_new) { |
+ if (FLAG_debug_code) { |
+ // Trash the registers to simulate an allocation failure. |
+ movl(result, Immediate(0x7091)); |
+ movl(result_end, Immediate(0x7191)); |
+ if (scratch.is_valid()) { |
+ movl(scratch, Immediate(0x7291)); |
+ } |
+ // object_size is left unchanged by this function. |
+ } |
+ jmp(gc_required); |
+ return; |
+ } |
+ ASSERT(!result.is(result_end)); |
+ |
// Load address of new object into result. |
LoadAllocationTopHelper(result, result_end, scratch, flags); |