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