| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 5007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5018 // The name handler is counted as an argument. | 5018 // The name handler is counted as an argument. |
| 5019 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); | 5019 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); |
| 5020 Operand return_value_operand = args.GetArgumentOperand( | 5020 Operand return_value_operand = args.GetArgumentOperand( |
| 5021 PropertyCallbackArguments::kArgsLength - 1 - | 5021 PropertyCallbackArguments::kArgsLength - 1 - |
| 5022 PropertyCallbackArguments::kReturnValueOffset); | 5022 PropertyCallbackArguments::kReturnValueOffset); |
| 5023 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, getter_arg, | 5023 CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, getter_arg, |
| 5024 kStackSpace, nullptr, return_value_operand, NULL); | 5024 kStackSpace, nullptr, return_value_operand, NULL); |
| 5025 } | 5025 } |
| 5026 | 5026 |
| 5027 | 5027 |
| 5028 // Updates holder to the correct api holder. info is preserved. |
| 5029 static void SignatureCheck(MacroAssembler* masm, Register holder, Register info, |
| 5030 Register scratch_0, Register scratch_1, |
| 5031 Register scratch_2, Label* illegal_receiver) { |
| 5032 Register signature = scratch_0; |
| 5033 Register map = scratch_1; |
| 5034 __ movp(signature, |
| 5035 FieldOperand(info, FunctionTemplateInfo::kSignatureOffset)); |
| 5036 __ movp(map, FieldOperand(holder, HeapObject::kMapOffset)); |
| 5037 |
| 5038 // Loop over hidden prototype chain. |
| 5039 Label prototype_chain_loop, prototype_chain_loop_next, legal_receiver; |
| 5040 __ bind(&prototype_chain_loop); |
| 5041 |
| 5042 // Verify signature for current map. |
| 5043 Register cons = scratch_2; |
| 5044 // Requires a constructor of type jsfunction. |
| 5045 __ movp(cons, FieldOperand(map, Map::kConstructorOffset)); |
| 5046 __ CompareRoot(cons, Heap::kNullValueRootIndex); |
| 5047 __ j(equal, &prototype_chain_loop_next, Label::kNear); |
| 5048 #ifdef DEBUG |
| 5049 { |
| 5050 Label expected; |
| 5051 // constructors should be null or js functions. |
| 5052 __ CmpObjectType(cons, JS_FUNCTION_TYPE, kScratchRegister); |
| 5053 __ j(equal, &expected); |
| 5054 __ int3(); // Can't call abort without a frame. |
| 5055 __ bind(&expected); |
| 5056 } |
| 5057 #endif |
| 5058 // Load shared function data for checked object. |
| 5059 Register type = cons; |
| 5060 __ movp(type, FieldOperand(cons, JSFunction::kSharedFunctionInfoOffset)); |
| 5061 __ movp(type, FieldOperand(type, SharedFunctionInfo::kFunctionDataOffset)); |
| 5062 |
| 5063 { |
| 5064 // Loop over function template info chain, hunting for signature. |
| 5065 Label function_template_loop; |
| 5066 __ bind(&function_template_loop); |
| 5067 __ cmpp(signature, type); |
| 5068 __ j(equal, &legal_receiver, Label::kNear); |
| 5069 // Requires a data of type FunctionTemplateInfo. |
| 5070 Condition is_smi = masm->CheckSmi(type); |
| 5071 __ j(is_smi, &prototype_chain_loop_next, Label::kNear); |
| 5072 __ CmpObjectType(type, FUNCTION_TEMPLATE_INFO_TYPE, kScratchRegister); |
| 5073 __ j(not_equal, &prototype_chain_loop_next, Label::kNear); |
| 5074 // Load parent and loop. |
| 5075 __ movp(type, |
| 5076 FieldOperand(type, FunctionTemplateInfo::kParentTemplateOffset)); |
| 5077 __ jmp(&function_template_loop, Label::kNear); |
| 5078 } |
| 5079 |
| 5080 __ bind(&prototype_chain_loop_next); |
| 5081 |
| 5082 // Load next holder. |
| 5083 __ movp(holder, FieldOperand(map, Map::kPrototypeOffset)); |
| 5084 |
| 5085 // End of prototype chain walk. |
| 5086 __ CompareRoot(holder, Heap::kNullValueRootIndex); |
| 5087 __ j(equal, illegal_receiver); |
| 5088 |
| 5089 // Load next map. |
| 5090 __ movp(map, FieldOperand(holder, HeapObject::kMapOffset)); |
| 5091 |
| 5092 // End of prototype chain walk. |
| 5093 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
| 5094 Immediate(1 << Map::kIsHiddenPrototype)); |
| 5095 __ j(zero, illegal_receiver); |
| 5096 |
| 5097 #ifdef DEBUG |
| 5098 { |
| 5099 Label expected; |
| 5100 // Hidden prototypes should already be js objects. |
| 5101 __ CmpInstanceType(map, FIRST_JS_OBJECT_TYPE); |
| 5102 __ j(above_equal, &expected, Label::kNear); |
| 5103 __ int3(); // Can't call abort without a frame. |
| 5104 __ bind(&expected); |
| 5105 } |
| 5106 #endif |
| 5107 |
| 5108 // Jump up to start of signature check loop for this map. |
| 5109 __ jmp(&prototype_chain_loop, Label::kNear); |
| 5110 |
| 5111 // Successful exit. |
| 5112 __ bind(&legal_receiver); |
| 5113 } |
| 5114 |
| 5115 |
| 5116 void JSApiFunctionStub::Generate(MacroAssembler* masm) { |
| 5117 // ----------- S t a t e ------------- |
| 5118 // -- rax : number of arguments excluding receiver |
| 5119 // -- rdi : callee |
| 5120 // -- rsi : context |
| 5121 // -- rsp[0] : return address |
| 5122 // -- rsp[8] : last argument |
| 5123 // -- ... |
| 5124 // -- rsp[8 * argc] : first argument (argc == rax) |
| 5125 // -- rsp[8 * (argc + 1)] : receiver |
| 5126 // ----------------------------------- |
| 5127 |
| 5128 StackArgumentsAccessor args(rsp, rax); |
| 5129 __ movp(rcx, args.GetReceiverOperand()); |
| 5130 |
| 5131 // Update receiver if this is a contextual call. |
| 5132 Label set_global_proxy, receiver_correct; |
| 5133 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); |
| 5134 __ j(equal, &set_global_proxy); |
| 5135 __ bind(&receiver_correct); |
| 5136 |
| 5137 // Load FunctionTemplateInfo. |
| 5138 __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 5139 __ movp(rbx, FieldOperand(rbx, SharedFunctionInfo::kFunctionDataOffset)); |
| 5140 |
| 5141 Label illegal_receiver; |
| 5142 if (has_signature()) { |
| 5143 // Typecheck. Update receiver with api holder. |
| 5144 SignatureCheck(masm, rcx, rbx, rdx, r8, r9, &illegal_receiver); |
| 5145 } |
| 5146 |
| 5147 if (!has_call_code()) { |
| 5148 // Return receiver for non c call. Pop arguments and receiver. |
| 5149 __ leap(rbx, Operand(rax, times_pointer_size, 1 * kPointerSize)); |
| 5150 __ movp(rax, args.GetReceiverOperand()); |
| 5151 __ PopReturnAddressTo(rcx); |
| 5152 __ addp(rsp, rbx); |
| 5153 __ jmp(rcx); |
| 5154 } else { |
| 5155 // c call. |
| 5156 __ movp(rbx, FieldOperand(rbx, FunctionTemplateInfo::kCallCodeOffset)); |
| 5157 // Put call_data and function address in place. |
| 5158 __ movp(rdx, FieldOperand(rbx, CallHandlerInfo::kCallbackOffset)); |
| 5159 __ movp(rdx, FieldOperand(rdx, Foreign::kForeignAddressOffset)); |
| 5160 __ movp(rbx, FieldOperand(rbx, CallHandlerInfo::kDataOffset)); |
| 5161 // Jump to stub. |
| 5162 // TODO(dcarney): fix abi for CallApiFunctionStub. |
| 5163 __ xchgp(rax, rdi); // Put callee in place. Put n_args in place. |
| 5164 CallApiFunctionStub stub(masm->isolate(), call_data_undefined()); |
| 5165 __ TailCallStub(&stub); |
| 5166 } |
| 5167 |
| 5168 // Deferred code: Replace receiver on stack with global proxy for contextual |
| 5169 // calls. |
| 5170 __ bind(&set_global_proxy); |
| 5171 __ movp(rcx, GlobalObjectOperand()); |
| 5172 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset)); |
| 5173 __ movp(args.GetReceiverOperand(), rcx); |
| 5174 __ jmp(&receiver_correct); |
| 5175 |
| 5176 if (!illegal_receiver.is_unused()) { |
| 5177 // Deferred code: Receiver does not match signature. Throw exception. |
| 5178 __ bind(&illegal_receiver); |
| 5179 |
| 5180 // Pop return address, arguments and receiver. |
| 5181 __ PopReturnAddressTo(rbx); |
| 5182 __ leap(rax, Operand(rax, times_pointer_size, 1 * kPointerSize)); |
| 5183 __ addp(rsp, rax); |
| 5184 __ PushReturnAddressFrom(rbx); |
| 5185 |
| 5186 FrameScope frame(masm, StackFrame::INTERNAL); |
| 5187 __ Push(rdi); |
| 5188 __ TailCallRuntime(Runtime::kThrowIllegalInvocation, 1, 1); |
| 5189 } |
| 5190 } |
| 5191 |
| 5028 #undef __ | 5192 #undef __ |
| 5029 | 5193 |
| 5030 } } // namespace v8::internal | 5194 } } // namespace v8::internal |
| 5031 | 5195 |
| 5032 #endif // V8_TARGET_ARCH_X64 | 5196 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |