| Index: src/x64/stub-cache-x64.cc
|
| diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
|
| index 2a918f16879ad41cd56189dae1219e7be1c5c4d1..e67000a133a083579227ce1e86bbbdcdfbc5c185 100644
|
| --- a/src/x64/stub-cache-x64.cc
|
| +++ b/src/x64/stub-cache-x64.cc
|
| @@ -2211,23 +2211,80 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
|
|
|
| // Check that the maps haven't changed.
|
| Register reg =
|
| - CheckPrototypes(object, receiver, holder,
|
| - scratch1, scratch2, scratch3, name, miss);
|
| + CheckPrototypes(object, receiver, holder, scratch1,
|
| + scratch2, scratch3, name, miss);
|
|
|
| - // Push the arguments on the JS stack of the caller.
|
| - __ pop(scratch2); // remove return address
|
| + Handle<AccessorInfo> callback_handle(callback);
|
| +
|
| + __ EnterInternalFrame();
|
| + __ PushHandleScope(scratch2);
|
| + // Push the stack address where the list of arguments ends.
|
| + __ movq(scratch2, rsp);
|
| + __ subq(scratch2, Immediate(2 * kPointerSize));
|
| + __ push(scratch2);
|
| __ push(receiver); // receiver
|
| __ push(reg); // holder
|
| - __ Move(reg, Handle<AccessorInfo>(callback)); // callback data
|
| - __ push(reg);
|
| - __ push(FieldOperand(reg, AccessorInfo::kDataOffset));
|
| + if (Heap::InNewSpace(callback_handle->data())) {
|
| + __ Move(scratch2, callback_handle);
|
| + __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset)); // data
|
| + } else {
|
| + __ Push(Handle<Object>(callback_handle->data()));
|
| + }
|
| __ push(name_reg); // name
|
| - __ push(scratch2); // restore return address
|
| + // Save a pointer to where we pushed the arguments pointer.
|
| + // This will be passed as the const AccessorInfo& to the C++ callback.
|
| +
|
| +#ifdef _WIN64
|
| + // Win64 uses first register--rcx--for returned value.
|
| + Register accessor_info_arg = r8;
|
| + Register name_arg = rdx;
|
| +#else
|
| + Register accessor_info_arg = rdx; // temporary, copied to rsi by the stub.
|
| + Register name_arg = rdi;
|
| +#endif
|
|
|
| - // Do tail-call to the runtime system.
|
| - ExternalReference load_callback_property =
|
| - ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
|
| - __ TailCallExternalReference(load_callback_property, 5, 1);
|
| + __ movq(accessor_info_arg, rsp);
|
| + __ addq(accessor_info_arg, Immediate(4 * kPointerSize));
|
| + __ movq(name_arg, rsp);
|
| +
|
| + // Do call through the api.
|
| + ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace);
|
| + Address getter_address = v8::ToCData<Address>(callback->getter());
|
| + ApiFunction fun(getter_address);
|
| + ApiGetterEntryStub stub(callback_handle, &fun);
|
| +#ifdef _WIN64
|
| + // We need to prepare a slot for result handle on stack and put
|
| + // a pointer to it into 1st arg register.
|
| + __ push(Immediate(0));
|
| + __ movq(rcx, rsp);
|
| +#endif
|
| + // 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.
|
| + Object* result = masm()->TryCallStub(&stub);
|
| + if (result->IsFailure()) {
|
| + *failure = Failure::cast(result);
|
| + return false;
|
| + }
|
| +#ifdef _WIN64
|
| + // Discard allocated slot.
|
| + __ addq(rsp, Immediate(kPointerSize));
|
| +#endif
|
| +
|
| + // We need to avoid using rax since that now holds the result.
|
| + Register tmp = scratch2.is(rax) ? reg : scratch2;
|
| + // Emitting PopHandleScope may try to allocate. Do not allow the
|
| + // assembler to perform a garbage collection but instead return a
|
| + // failure object.
|
| + result = masm()->TryPopHandleScope(rax, tmp);
|
| + if (result->IsFailure()) {
|
| + *failure = Failure::cast(result);
|
| + return false;
|
| + }
|
| + __ LeaveInternalFrame();
|
| +
|
| + __ ret(0);
|
|
|
| return true;
|
| }
|
|
|