| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 1037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address. | 1048 __ DropUnderReturnAddress(1, rbx); // Drop one slot under return address. |
| 1049 __ decp(rax); // One fewer argument (first argument is new receiver). | 1049 __ decp(rax); // One fewer argument (first argument is new receiver). |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 // 4. Call the callable. | 1052 // 4. Call the callable. |
| 1053 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1053 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1054 } | 1054 } |
| 1055 | 1055 |
| 1056 | 1056 |
| 1057 static void Generate_PushAppliedArguments(MacroAssembler* masm, | 1057 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
| 1058 const int vectorOffset, |
| 1058 const int argumentsOffset, | 1059 const int argumentsOffset, |
| 1059 const int indexOffset, | 1060 const int indexOffset, |
| 1060 const int limitOffset) { | 1061 const int limitOffset) { |
| 1061 Register receiver = LoadDescriptor::ReceiverRegister(); | 1062 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 1062 Register key = LoadDescriptor::NameRegister(); | 1063 Register key = LoadDescriptor::NameRegister(); |
| 1063 Register slot = LoadDescriptor::SlotRegister(); | 1064 Register slot = LoadDescriptor::SlotRegister(); |
| 1064 Register vector = LoadWithVectorDescriptor::VectorRegister(); | 1065 Register vector = LoadWithVectorDescriptor::VectorRegister(); |
| 1065 | 1066 |
| 1066 // Copy all arguments from the array to the stack. | 1067 // Copy all arguments from the array to the stack. |
| 1067 Label entry, loop; | 1068 Label entry, loop; |
| 1068 __ movp(key, Operand(rbp, indexOffset)); | 1069 __ movp(key, Operand(rbp, indexOffset)); |
| 1069 __ jmp(&entry); | 1070 __ jmp(&entry); |
| 1070 __ bind(&loop); | 1071 __ bind(&loop); |
| 1071 __ movp(receiver, Operand(rbp, argumentsOffset)); // load arguments | 1072 __ movp(receiver, Operand(rbp, argumentsOffset)); // load arguments |
| 1072 | 1073 |
| 1073 // Use inline caching to speed up access to arguments. | 1074 // Use inline caching to speed up access to arguments. |
| 1074 Code::Kind kinds[] = {Code::KEYED_LOAD_IC}; | 1075 int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex(); |
| 1075 FeedbackVectorSpec spec(0, 1, kinds); | 1076 __ Move(slot, Smi::FromInt(slot_index)); |
| 1076 Handle<TypeFeedbackVector> feedback_vector = | 1077 __ movp(vector, Operand(rbp, vectorOffset)); |
| 1077 masm->isolate()->factory()->NewTypeFeedbackVector(&spec); | |
| 1078 int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0)); | |
| 1079 __ Move(slot, Smi::FromInt(index)); | |
| 1080 __ Move(vector, feedback_vector); | |
| 1081 Handle<Code> ic = | 1078 Handle<Code> ic = |
| 1082 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); | 1079 KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode(); |
| 1083 __ Call(ic, RelocInfo::CODE_TARGET); | 1080 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1084 // It is important that we do not have a test instruction after the | 1081 // It is important that we do not have a test instruction after the |
| 1085 // call. A test instruction after the call is used to indicate that | 1082 // call. A test instruction after the call is used to indicate that |
| 1086 // we have generated an inline version of the keyed load. In this | 1083 // we have generated an inline version of the keyed load. In this |
| 1087 // case, we know that we are not generating a test instruction next. | 1084 // case, we know that we are not generating a test instruction next. |
| 1088 | 1085 |
| 1089 // Push the nth argument. | 1086 // Push the nth argument. |
| 1090 __ Push(rax); | 1087 __ Push(rax); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1117 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1114 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
| 1118 // Stack frame: | 1115 // Stack frame: |
| 1119 // rbp : Old base pointer | 1116 // rbp : Old base pointer |
| 1120 // rbp[8] : return address | 1117 // rbp[8] : return address |
| 1121 // rbp[16] : function arguments | 1118 // rbp[16] : function arguments |
| 1122 // rbp[24] : receiver | 1119 // rbp[24] : receiver |
| 1123 // rbp[32] : function | 1120 // rbp[32] : function |
| 1124 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | 1121 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
| 1125 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; | 1122 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
| 1126 static const int kFunctionOffset = kReceiverOffset + kPointerSize; | 1123 static const int kFunctionOffset = kReceiverOffset + kPointerSize; |
| 1124 static const int kVectorOffset = |
| 1125 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; |
| 1126 |
| 1127 // Push the vector. |
| 1128 __ movp(rdi, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 1129 __ movp(rdi, FieldOperand(rdi, SharedFunctionInfo::kFeedbackVectorOffset)); |
| 1130 __ Push(rdi); |
| 1127 | 1131 |
| 1128 __ Push(Operand(rbp, kFunctionOffset)); | 1132 __ Push(Operand(rbp, kFunctionOffset)); |
| 1129 __ Push(Operand(rbp, kArgumentsOffset)); | 1133 __ Push(Operand(rbp, kArgumentsOffset)); |
| 1130 if (targetIsArgument) { | 1134 if (targetIsArgument) { |
| 1131 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, | 1135 __ InvokeBuiltin(Context::REFLECT_APPLY_PREPARE_BUILTIN_INDEX, |
| 1132 CALL_FUNCTION); | 1136 CALL_FUNCTION); |
| 1133 } else { | 1137 } else { |
| 1134 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); | 1138 __ InvokeBuiltin(Context::APPLY_PREPARE_BUILTIN_INDEX, CALL_FUNCTION); |
| 1135 } | 1139 } |
| 1136 | 1140 |
| 1137 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); | 1141 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); |
| 1138 | 1142 |
| 1139 // Push current index and limit, and receiver. | 1143 // Push current index and limit, and receiver. |
| 1140 const int kLimitOffset = | 1144 const int kLimitOffset = kVectorOffset - 1 * kPointerSize; |
| 1141 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | |
| 1142 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 1145 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
| 1143 __ Push(rax); // limit | 1146 __ Push(rax); // limit |
| 1144 __ Push(Immediate(0)); // index | 1147 __ Push(Immediate(0)); // index |
| 1145 __ Push(Operand(rbp, kReceiverOffset)); // receiver | 1148 __ Push(Operand(rbp, kReceiverOffset)); // receiver |
| 1146 | 1149 |
| 1147 // Loop over the arguments array, pushing each value to the stack | 1150 // Loop over the arguments array, pushing each value to the stack |
| 1148 Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset, | 1151 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, |
| 1149 kLimitOffset); | 1152 kIndexOffset, kLimitOffset); |
| 1150 | 1153 |
| 1151 // Call the callable. | 1154 // Call the callable. |
| 1152 // TODO(bmeurer): This should be a tail call according to ES6. | 1155 // TODO(bmeurer): This should be a tail call according to ES6. |
| 1153 __ movp(rdi, Operand(rbp, kFunctionOffset)); | 1156 __ movp(rdi, Operand(rbp, kFunctionOffset)); |
| 1154 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | 1157 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1155 | 1158 |
| 1156 // Leave internal frame. | 1159 // Leave internal frame. |
| 1157 } | 1160 } |
| 1158 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments | 1161 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments |
| 1159 } | 1162 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1174 // Stack frame: | 1177 // Stack frame: |
| 1175 // rbp : Old base pointer | 1178 // rbp : Old base pointer |
| 1176 // rbp[8] : return address | 1179 // rbp[8] : return address |
| 1177 // rbp[16] : original constructor (new.target) | 1180 // rbp[16] : original constructor (new.target) |
| 1178 // rbp[24] : arguments | 1181 // rbp[24] : arguments |
| 1179 // rbp[32] : constructor | 1182 // rbp[32] : constructor |
| 1180 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; | 1183 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; |
| 1181 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize; | 1184 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize; |
| 1182 static const int kFunctionOffset = kArgumentsOffset + kPointerSize; | 1185 static const int kFunctionOffset = kArgumentsOffset + kPointerSize; |
| 1183 | 1186 |
| 1187 static const int kVectorOffset = |
| 1188 InternalFrameConstants::kCodeOffset - 1 * kPointerSize; |
| 1189 |
| 1190 // Push the vector. |
| 1191 __ movp(rdi, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 1192 __ movp(rdi, FieldOperand(rdi, SharedFunctionInfo::kFeedbackVectorOffset)); |
| 1193 __ Push(rdi); |
| 1194 |
| 1184 // If newTarget is not supplied, set it to constructor | 1195 // If newTarget is not supplied, set it to constructor |
| 1185 Label validate_arguments; | 1196 Label validate_arguments; |
| 1186 __ movp(rax, Operand(rbp, kNewTargetOffset)); | 1197 __ movp(rax, Operand(rbp, kNewTargetOffset)); |
| 1187 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 1198 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 1188 __ j(not_equal, &validate_arguments, Label::kNear); | 1199 __ j(not_equal, &validate_arguments, Label::kNear); |
| 1189 __ movp(rax, Operand(rbp, kFunctionOffset)); | 1200 __ movp(rax, Operand(rbp, kFunctionOffset)); |
| 1190 __ movp(Operand(rbp, kNewTargetOffset), rax); | 1201 __ movp(Operand(rbp, kNewTargetOffset), rax); |
| 1191 | 1202 |
| 1192 // Validate arguments | 1203 // Validate arguments |
| 1193 __ bind(&validate_arguments); | 1204 __ bind(&validate_arguments); |
| 1194 __ Push(Operand(rbp, kFunctionOffset)); | 1205 __ Push(Operand(rbp, kFunctionOffset)); |
| 1195 __ Push(Operand(rbp, kArgumentsOffset)); | 1206 __ Push(Operand(rbp, kArgumentsOffset)); |
| 1196 __ Push(Operand(rbp, kNewTargetOffset)); | 1207 __ Push(Operand(rbp, kNewTargetOffset)); |
| 1197 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, | 1208 __ InvokeBuiltin(Context::REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, |
| 1198 CALL_FUNCTION); | 1209 CALL_FUNCTION); |
| 1199 | 1210 |
| 1200 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); | 1211 Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged); |
| 1201 | 1212 |
| 1202 // Push current index and limit. | 1213 // Push current index and limit. |
| 1203 const int kLimitOffset = | 1214 const int kLimitOffset = kVectorOffset - 1 * kPointerSize; |
| 1204 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | |
| 1205 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | 1215 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; |
| 1206 __ Push(rax); // limit | 1216 __ Push(rax); // limit |
| 1207 __ Push(Immediate(0)); // index | 1217 __ Push(Immediate(0)); // index |
| 1208 // Push the constructor function as callee. | 1218 // Push the constructor function as callee. |
| 1209 __ Push(Operand(rbp, kFunctionOffset)); | 1219 __ Push(Operand(rbp, kFunctionOffset)); |
| 1210 | 1220 |
| 1211 // Loop over the arguments array, pushing each value to the stack | 1221 // Loop over the arguments array, pushing each value to the stack |
| 1212 Generate_PushAppliedArguments( | 1222 Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset, |
| 1213 masm, kArgumentsOffset, kIndexOffset, kLimitOffset); | 1223 kIndexOffset, kLimitOffset); |
| 1214 | 1224 |
| 1215 // Use undefined feedback vector | 1225 // Use undefined feedback vector |
| 1216 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); | 1226 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); |
| 1217 __ movp(rdi, Operand(rbp, kFunctionOffset)); | 1227 __ movp(rdi, Operand(rbp, kFunctionOffset)); |
| 1218 __ movp(rcx, Operand(rbp, kNewTargetOffset)); | 1228 __ movp(rcx, Operand(rbp, kNewTargetOffset)); |
| 1219 | 1229 |
| 1220 // Call the function. | 1230 // Call the function. |
| 1221 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); | 1231 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); |
| 1222 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 1232 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 1223 | 1233 |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1809 __ ret(0); | 1819 __ ret(0); |
| 1810 } | 1820 } |
| 1811 | 1821 |
| 1812 | 1822 |
| 1813 #undef __ | 1823 #undef __ |
| 1814 | 1824 |
| 1815 } // namespace internal | 1825 } // namespace internal |
| 1816 } // namespace v8 | 1826 } // namespace v8 |
| 1817 | 1827 |
| 1818 #endif // V8_TARGET_ARCH_X64 | 1828 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |