Chromium Code Reviews| 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. Map may be trashed. | |
| 5029 static void SignatureCheck(MacroAssembler* masm, Register map, Register holder, | |
| 5030 Register signature, Register scratch, | |
| 5031 Label* illegal_receiver) { | |
| 5032 // Loop over hidden prototype chain. | |
| 5033 Label prototype_chain_loop, prototype_chain_loop_next, legal_receiver; | |
| 5034 __ bind(&prototype_chain_loop); | |
| 5035 | |
| 5036 // Verify signature for current map. | |
| 5037 Register type = scratch; | |
| 5038 // Requires a constructor of type jsfunction. | |
| 5039 __ movp(type, FieldOperand(map, Map::kConstructorOffset)); | |
| 5040 __ CmpObjectType(type, JS_FUNCTION_TYPE, kScratchRegister); | |
| 5041 __ j(not_equal, &prototype_chain_loop_next, Label::kNear); | |
|
jochen (gone - plz use gerrit)
2015/01/21 12:01:39
I wonder whether we can here already jump to illeg
| |
| 5042 // Load shared function data. | |
| 5043 __ movp(type, FieldOperand(type, JSFunction::kSharedFunctionInfoOffset)); | |
| 5044 __ movp(type, FieldOperand(type, SharedFunctionInfo::kFunctionDataOffset)); | |
| 5045 | |
| 5046 { | |
| 5047 // Loop over function template info chain, hunting for signature. | |
| 5048 Label function_template_loop; | |
| 5049 __ bind(&function_template_loop); | |
| 5050 // Requires a data of type FunctionTemplateInfo. | |
| 5051 __ CmpObjectType(type, FUNCTION_TEMPLATE_INFO_TYPE, kScratchRegister); | |
| 5052 __ j(not_equal, &prototype_chain_loop_next, Label::kNear); | |
| 5053 __ cmpp(signature, type); | |
| 5054 __ j(equal, &legal_receiver, Label::kNear); | |
| 5055 // Incorrect signature, load parent and loop. | |
| 5056 __ movp(type, | |
| 5057 FieldOperand(type, FunctionTemplateInfo::kParentTemplateOffset)); | |
| 5058 __ jmp(&function_template_loop, Label::kNear); | |
| 5059 } | |
| 5060 | |
| 5061 __ bind(&prototype_chain_loop_next); | |
| 5062 __ movp(holder, FieldOperand(map, Map::kPrototypeOffset)); | |
| 5063 | |
| 5064 // End of prototype chain walk. | |
| 5065 __ CompareRoot(holder, Heap::kNullValueRootIndex); | |
| 5066 __ j(equal, illegal_receiver); | |
| 5067 | |
| 5068 __ movp(map, FieldOperand(holder, HeapObject::kMapOffset)); | |
| 5069 // End of prototype chain walk. | |
| 5070 __ testb(FieldOperand(map, Map::kBitFieldOffset), | |
| 5071 Immediate(1 << Map::kIsHiddenPrototype)); | |
| 5072 __ j(zero, illegal_receiver); | |
| 5073 | |
| 5074 // TODO(dcarney): this check is probably unnecessary. | |
| 5075 // Requires a js object map. | |
| 5076 __ CmpInstanceType(map, FIRST_JS_OBJECT_TYPE); | |
| 5077 __ j(below, &prototype_chain_loop_next, Label::kNear); | |
| 5078 | |
| 5079 // Jump up to start of signature check loop for this map. | |
| 5080 __ jmp(&prototype_chain_loop, Label::kNear); | |
| 5081 | |
| 5082 // Successful exit. | |
| 5083 __ bind(&legal_receiver); | |
| 5084 } | |
| 5085 | |
| 5086 | |
| 5087 void JSApiFunctionStub::Generate(MacroAssembler* masm) { | |
| 5088 // ----------- S t a t e ------------- | |
| 5089 // -- rax : number of arguments excluding receiver | |
| 5090 // -- rdi : callee | |
| 5091 // -- rsi : context | |
| 5092 // -- rsp[0] : return address | |
| 5093 // -- rsp[8] : last argument | |
| 5094 // -- ... | |
| 5095 // -- rsp[8 * argc] : first argument (argc == rax) | |
| 5096 // -- rsp[8 * (argc + 1)] : receiver | |
| 5097 // ----------------------------------- | |
| 5098 | |
| 5099 StackArgumentsAccessor args(rsp, rax); | |
| 5100 __ movp(rcx, args.GetReceiverOperand()); | |
| 5101 | |
| 5102 // Update receiver if this is a contextual call. | |
| 5103 Label set_global_proxy, receiver_correct; | |
| 5104 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); | |
| 5105 __ j(equal, &set_global_proxy); | |
| 5106 __ bind(&receiver_correct); | |
| 5107 | |
| 5108 // Load FunctionTemplateInfo. | |
| 5109 __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
| 5110 __ movp(rbx, FieldOperand(rbx, SharedFunctionInfo::kFunctionDataOffset)); | |
| 5111 | |
| 5112 // TODO(dcarney): CHECK that !has_call_code implies !has_signature. | |
| 5113 Label illegal_receiver; | |
| 5114 if (has_signature()) { | |
| 5115 // Typecheck. Update receiver with api holder. | |
| 5116 __ movp(r8, FieldOperand(rbx, FunctionTemplateInfo::kSignatureOffset)); | |
| 5117 __ movp(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); | |
| 5118 SignatureCheck(masm, rdx, rcx, r8, r9, &illegal_receiver); | |
| 5119 } | |
| 5120 | |
| 5121 if (!has_call_code()) { | |
| 5122 // Return receiver for non c call. Pop arguments and receiver. | |
| 5123 __ leap(rbx, Operand(rax, times_pointer_size, 1 * kPointerSize)); | |
| 5124 __ movp(rax, args.GetReceiverOperand()); | |
| 5125 __ PopReturnAddressTo(rcx); | |
| 5126 __ addp(rsp, rbx); | |
| 5127 __ jmp(rcx); | |
| 5128 } else { | |
| 5129 // c call. | |
| 5130 __ movp(rbx, FieldOperand(rbx, FunctionTemplateInfo::kCallCodeOffset)); | |
| 5131 // Put call_data and function address in place. | |
| 5132 __ movp(rdx, FieldOperand(rbx, CallHandlerInfo::kCallbackOffset)); | |
| 5133 __ movp(rdx, FieldOperand(rdx, Foreign::kForeignAddressOffset)); | |
| 5134 __ movp(rbx, FieldOperand(rbx, CallHandlerInfo::kDataOffset)); | |
| 5135 // Jump to stub. | |
| 5136 // TODO(dcarney): fix abi for CallApiFunctionStub. | |
| 5137 __ xchgp(rax, rdi); // Put callee in place. Put n_args in place. | |
| 5138 CallApiFunctionStub stub(masm->isolate(), call_data_undefined()); | |
| 5139 __ TailCallStub(&stub); | |
| 5140 } | |
| 5141 | |
| 5142 // Deferred code: Replace receiver on stack with global proxy for contextual | |
| 5143 // calls. | |
| 5144 __ bind(&set_global_proxy); | |
| 5145 __ movp(rcx, GlobalObjectOperand()); | |
| 5146 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset)); | |
| 5147 __ movp(args.GetReceiverOperand(), rcx); | |
| 5148 __ jmp(&receiver_correct); | |
| 5149 | |
| 5150 if (!illegal_receiver.is_unused()) { | |
| 5151 // Deferred code: Receiver does not match signature. Throw exception. | |
| 5152 __ bind(&illegal_receiver); | |
| 5153 | |
| 5154 // Pop return address, arguments and receiver. | |
| 5155 __ PopReturnAddressTo(rbx); | |
| 5156 __ leap(rax, Operand(rax, times_pointer_size, 1 * kPointerSize)); | |
| 5157 __ addp(rsp, rax); | |
| 5158 __ PushReturnAddressFrom(rbx); | |
| 5159 | |
| 5160 FrameScope frame(masm, StackFrame::INTERNAL); | |
| 5161 __ Push(rdi); | |
| 5162 __ TailCallRuntime(Runtime::kThrowIllegalInvocation, 1, 1); | |
| 5163 } | |
| 5164 } | |
| 5165 | |
| 5028 #undef __ | 5166 #undef __ |
| 5029 | 5167 |
| 5030 } } // namespace v8::internal | 5168 } } // namespace v8::internal |
| 5031 | 5169 |
| 5032 #endif // V8_TARGET_ARCH_X64 | 5170 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |