Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Unified Diff: src/x64/code-stubs-x64.cc

Issue 847913005: move HandleApiCall builtin to assembly (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: cleanup Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime/runtime-api.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/code-stubs-x64.cc
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index f7bd9b6a31005bfe6f879eab5a928ffaa6ede4bd..5025b644a943e2872ed0e438e6bda22e8e7bd419 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -5025,6 +5025,170 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
}
+// Updates holder to the correct api holder. info is preserved.
+static void SignatureCheck(MacroAssembler* masm, Register holder, Register info,
+ Register scratch_0, Register scratch_1,
+ Register scratch_2, Label* illegal_receiver) {
+ Register signature = scratch_0;
+ Register map = scratch_1;
+ __ movp(signature,
+ FieldOperand(info, FunctionTemplateInfo::kSignatureOffset));
+ __ movp(map, FieldOperand(holder, HeapObject::kMapOffset));
+
+ // Loop over hidden prototype chain.
+ Label prototype_chain_loop, prototype_chain_loop_next, legal_receiver;
+ __ bind(&prototype_chain_loop);
+
+ // Verify signature for current map.
+ Register cons = scratch_2;
+ // Requires a constructor of type jsfunction.
+ __ movp(cons, FieldOperand(map, Map::kConstructorOffset));
+ __ CompareRoot(cons, Heap::kNullValueRootIndex);
+ __ j(equal, &prototype_chain_loop_next, Label::kNear);
+#ifdef DEBUG
+ {
+ Label expected;
+ // constructors should be null or js functions.
+ __ CmpObjectType(cons, JS_FUNCTION_TYPE, kScratchRegister);
+ __ j(equal, &expected);
+ __ int3(); // Can't call abort without a frame.
+ __ bind(&expected);
+ }
+#endif
+ // Load shared function data for checked object.
+ Register type = cons;
+ __ movp(type, FieldOperand(cons, JSFunction::kSharedFunctionInfoOffset));
+ __ movp(type, FieldOperand(type, SharedFunctionInfo::kFunctionDataOffset));
+
+ {
+ // Loop over function template info chain, hunting for signature.
+ Label function_template_loop;
+ __ bind(&function_template_loop);
+ __ cmpp(signature, type);
+ __ j(equal, &legal_receiver, Label::kNear);
+ // Requires a data of type FunctionTemplateInfo.
+ Condition is_smi = masm->CheckSmi(type);
+ __ j(is_smi, &prototype_chain_loop_next, Label::kNear);
+ __ CmpObjectType(type, FUNCTION_TEMPLATE_INFO_TYPE, kScratchRegister);
+ __ j(not_equal, &prototype_chain_loop_next, Label::kNear);
+ // Load parent and loop.
+ __ movp(type,
+ FieldOperand(type, FunctionTemplateInfo::kParentTemplateOffset));
+ __ jmp(&function_template_loop, Label::kNear);
+ }
+
+ __ bind(&prototype_chain_loop_next);
+
+ // Load next holder.
+ __ movp(holder, FieldOperand(map, Map::kPrototypeOffset));
+
+ // End of prototype chain walk.
+ __ CompareRoot(holder, Heap::kNullValueRootIndex);
+ __ j(equal, illegal_receiver);
+
+ // Load next map.
+ __ movp(map, FieldOperand(holder, HeapObject::kMapOffset));
+
+ // End of prototype chain walk.
+ __ testb(FieldOperand(map, Map::kBitFieldOffset),
+ Immediate(1 << Map::kIsHiddenPrototype));
+ __ j(zero, illegal_receiver);
+
+#ifdef DEBUG
+ {
+ Label expected;
+ // Hidden prototypes should already be js objects.
+ __ CmpInstanceType(map, FIRST_JS_OBJECT_TYPE);
+ __ j(above_equal, &expected, Label::kNear);
+ __ int3(); // Can't call abort without a frame.
+ __ bind(&expected);
+ }
+#endif
+
+ // Jump up to start of signature check loop for this map.
+ __ jmp(&prototype_chain_loop, Label::kNear);
+
+ // Successful exit.
+ __ bind(&legal_receiver);
+}
+
+
+void JSApiFunctionStub::Generate(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : number of arguments excluding receiver
+ // -- rdi : callee
+ // -- rsi : context
+ // -- rsp[0] : return address
+ // -- rsp[8] : last argument
+ // -- ...
+ // -- rsp[8 * argc] : first argument (argc == rax)
+ // -- rsp[8 * (argc + 1)] : receiver
+ // -----------------------------------
+
+ StackArgumentsAccessor args(rsp, rax);
+ __ movp(rcx, args.GetReceiverOperand());
+
+ // Update receiver if this is a contextual call.
+ Label set_global_proxy, receiver_correct;
+ __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
+ __ j(equal, &set_global_proxy);
+ __ bind(&receiver_correct);
+
+ // Load FunctionTemplateInfo.
+ __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+ __ movp(rbx, FieldOperand(rbx, SharedFunctionInfo::kFunctionDataOffset));
+
+ Label illegal_receiver;
+ if (has_signature()) {
+ // Typecheck. Update receiver with api holder.
+ SignatureCheck(masm, rcx, rbx, rdx, r8, r9, &illegal_receiver);
+ }
+
+ if (!has_call_code()) {
+ // Return receiver for non c call. Pop arguments and receiver.
+ __ leap(rbx, Operand(rax, times_pointer_size, 1 * kPointerSize));
+ __ movp(rax, args.GetReceiverOperand());
+ __ PopReturnAddressTo(rcx);
+ __ addp(rsp, rbx);
+ __ jmp(rcx);
+ } else {
+ // c call.
+ __ movp(rbx, FieldOperand(rbx, FunctionTemplateInfo::kCallCodeOffset));
+ // Put call_data and function address in place.
+ __ movp(rdx, FieldOperand(rbx, CallHandlerInfo::kCallbackOffset));
+ __ movp(rdx, FieldOperand(rdx, Foreign::kForeignAddressOffset));
+ __ movp(rbx, FieldOperand(rbx, CallHandlerInfo::kDataOffset));
+ // Jump to stub.
+ // TODO(dcarney): fix abi for CallApiFunctionStub.
+ __ xchgp(rax, rdi); // Put callee in place. Put n_args in place.
+ CallApiFunctionStub stub(masm->isolate(), call_data_undefined());
+ __ TailCallStub(&stub);
+ }
+
+ // Deferred code: Replace receiver on stack with global proxy for contextual
+ // calls.
+ __ bind(&set_global_proxy);
+ __ movp(rcx, GlobalObjectOperand());
+ __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset));
+ __ movp(args.GetReceiverOperand(), rcx);
+ __ jmp(&receiver_correct);
+
+ if (!illegal_receiver.is_unused()) {
+ // Deferred code: Receiver does not match signature. Throw exception.
+ __ bind(&illegal_receiver);
+
+ // Pop return address, arguments and receiver.
+ __ PopReturnAddressTo(rbx);
+ __ leap(rax, Operand(rax, times_pointer_size, 1 * kPointerSize));
+ __ addp(rsp, rax);
+ __ PushReturnAddressFrom(rbx);
+
+ FrameScope frame(masm, StackFrame::INTERNAL);
+ __ Push(rdi);
+ __ TailCallRuntime(Runtime::kThrowIllegalInvocation, 1, 1);
+ }
+}
+
#undef __
} } // namespace v8::internal
« no previous file with comments | « src/runtime/runtime-api.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698