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