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 #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/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1044 __ cmpp(rax, rbx); | 1044 __ cmpp(rax, rbx); |
1045 __ j(not_equal, | 1045 __ j(not_equal, |
1046 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1046 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1047 RelocInfo::CODE_TARGET); | 1047 RelocInfo::CODE_TARGET); |
1048 | 1048 |
1049 ParameterCount expected(0); | 1049 ParameterCount expected(0); |
1050 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); | 1050 __ InvokeCode(rdx, expected, expected, JUMP_FUNCTION, NullCallWrapper()); |
1051 } | 1051 } |
1052 | 1052 |
1053 | 1053 |
1054 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1054 static void Generate_PushAppliedArguments(MacroAssembler* masm, |
1055 Register receiver, Register key, | |
1056 const int kArgumentsOffset, | |
1057 const int kIndexOffset, | |
Dmitry Lomov (no reviews)
2015/03/13 09:39:09
These are not constants anymore, name them indexOf
| |
1058 const int kLimitOffset) { | |
1059 // Copy all arguments from the array to the stack. | |
1060 Label entry, loop; | |
1061 __ movp(key, Operand(rbp, kIndexOffset)); | |
Dmitry Lomov (no reviews)
2015/03/13 09:39:09
Receiver and key must be LoadDescriptor::{Reeceive
| |
1062 __ jmp(&entry); | |
1063 __ bind(&loop); | |
1064 __ movp(receiver, Operand(rbp, kArgumentsOffset)); // load arguments | |
1065 | |
1066 // Use inline caching to speed up access to arguments. | |
1067 if (FLAG_vector_ics) { | |
1068 // TODO(mvstanton): Vector-based ics need additional infrastructure to | |
1069 // be embedded here. For now, just call the runtime. | |
1070 __ Push(receiver); | |
1071 __ Push(key); | |
1072 __ CallRuntime(Runtime::kGetProperty, 2); | |
1073 } else { | |
1074 Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code(); | |
1075 __ Call(ic, RelocInfo::CODE_TARGET); | |
1076 // It is important that we do not have a test instruction after the | |
1077 // call. A test instruction after the call is used to indicate that | |
1078 // we have generated an inline version of the keyed load. In this | |
1079 // case, we know that we are not generating a test instruction next. | |
1080 } | |
1081 | |
1082 // Push the nth argument. | |
1083 __ Push(rax); | |
1084 | |
1085 // Update the index on the stack and in register key. | |
1086 __ movp(key, Operand(rbp, kIndexOffset)); | |
1087 __ SmiAddConstant(key, key, Smi::FromInt(1)); | |
1088 __ movp(Operand(rbp, kIndexOffset), key); | |
1089 | |
1090 __ bind(&entry); | |
1091 __ cmpp(key, Operand(rbp, kLimitOffset)); | |
1092 __ j(not_equal, &loop); | |
1093 } | |
1094 | |
1095 | |
1096 // Used by FunctionApply and ReflectApply | |
1097 static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { | |
1098 const int kFormalParameters = targetIsArgument ? 3 : 2; | |
1099 const int kStackSize = kFormalParameters + 1; | |
1100 | |
1055 // Stack at entry: | 1101 // Stack at entry: |
1056 // rsp : return address | 1102 // rsp : return address |
1057 // rsp[8] : arguments | 1103 // rsp[8] : arguments |
1058 // rsp[16] : receiver ("this") | 1104 // rsp[16] : receiver ("this") |
1059 // rsp[24] : function | 1105 // rsp[24] : function |
1060 { | 1106 { |
1061 FrameScope frame_scope(masm, StackFrame::INTERNAL); | 1107 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
1062 // Stack frame: | 1108 // Stack frame: |
1063 // rbp : Old base pointer | 1109 // rbp : Old base pointer |
1064 // rbp[8] : return address | 1110 // rbp[8] : return address |
1065 // rbp[16] : function arguments | 1111 // rbp[16] : function arguments |
1066 // rbp[24] : receiver | 1112 // rbp[24] : receiver |
1067 // rbp[32] : function | 1113 // rbp[32] : function |
1068 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; | 1114 static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize; |
1069 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; | 1115 static const int kReceiverOffset = kArgumentsOffset + kPointerSize; |
1070 static const int kFunctionOffset = kReceiverOffset + kPointerSize; | 1116 static const int kFunctionOffset = kReceiverOffset + kPointerSize; |
1071 | 1117 |
1072 __ Push(Operand(rbp, kFunctionOffset)); | 1118 __ Push(Operand(rbp, kFunctionOffset)); |
1073 __ Push(Operand(rbp, kArgumentsOffset)); | 1119 __ Push(Operand(rbp, kArgumentsOffset)); |
1074 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1120 if (targetIsArgument) { |
1121 __ InvokeBuiltin(Builtins::REFLECT_APPLY_PREPARE, CALL_FUNCTION); | |
1122 } else { | |
1123 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | |
1124 } | |
1075 | 1125 |
1076 // Check the stack for overflow. We are not trying to catch | 1126 // Check the stack for overflow. We are not trying to catch |
1077 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1127 // interruptions (e.g. debug break and preemption) here, so the "real stack |
1078 // limit" is checked. | 1128 // limit" is checked. |
1079 Label okay; | 1129 Label okay; |
1080 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); | 1130 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); |
1081 __ movp(rcx, rsp); | 1131 __ movp(rcx, rsp); |
1082 // Make rcx the space we have left. The stack might already be overflowed | 1132 // Make rcx the space we have left. The stack might already be overflowed |
1083 // here which will cause rcx to become negative. | 1133 // here which will cause rcx to become negative. |
1084 __ subp(rcx, kScratchRegister); | 1134 __ subp(rcx, kScratchRegister); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1149 | 1199 |
1150 __ bind(&use_global_proxy); | 1200 __ bind(&use_global_proxy); |
1151 __ movp(rbx, | 1201 __ movp(rbx, |
1152 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 1202 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
1153 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset)); | 1203 __ movp(rbx, FieldOperand(rbx, GlobalObject::kGlobalProxyOffset)); |
1154 | 1204 |
1155 // Push the receiver. | 1205 // Push the receiver. |
1156 __ bind(&push_receiver); | 1206 __ bind(&push_receiver); |
1157 __ Push(rbx); | 1207 __ Push(rbx); |
1158 | 1208 |
1159 // Copy all arguments from the array to the stack. | |
1160 Label entry, loop; | |
1161 Register receiver = LoadDescriptor::ReceiverRegister(); | 1209 Register receiver = LoadDescriptor::ReceiverRegister(); |
1162 Register key = LoadDescriptor::NameRegister(); | 1210 Register key = LoadDescriptor::NameRegister(); |
1163 __ movp(key, Operand(rbp, kIndexOffset)); | |
1164 __ jmp(&entry); | |
1165 __ bind(&loop); | |
1166 __ movp(receiver, Operand(rbp, kArgumentsOffset)); // load arguments | |
1167 | 1211 |
1168 // Use inline caching to speed up access to arguments. | 1212 // Loop over the arguments array, pushing each value to the stack |
1169 if (FLAG_vector_ics) { | 1213 Generate_PushAppliedArguments( |
1170 // TODO(mvstanton): Vector-based ics need additional infrastructure to | 1214 masm, receiver, key, kArgumentsOffset, kIndexOffset, kLimitOffset); |
1171 // be embedded here. For now, just call the runtime. | |
1172 __ Push(receiver); | |
1173 __ Push(key); | |
1174 __ CallRuntime(Runtime::kGetProperty, 2); | |
1175 } else { | |
1176 Handle<Code> ic = CodeFactory::KeyedLoadIC(masm->isolate()).code(); | |
1177 __ Call(ic, RelocInfo::CODE_TARGET); | |
1178 // It is important that we do not have a test instruction after the | |
1179 // call. A test instruction after the call is used to indicate that | |
1180 // we have generated an inline version of the keyed load. In this | |
1181 // case, we know that we are not generating a test instruction next. | |
1182 } | |
1183 | |
1184 // Push the nth argument. | |
1185 __ Push(rax); | |
1186 | |
1187 // Update the index on the stack and in register key. | |
1188 __ movp(key, Operand(rbp, kIndexOffset)); | |
1189 __ SmiAddConstant(key, key, Smi::FromInt(1)); | |
1190 __ movp(Operand(rbp, kIndexOffset), key); | |
1191 | |
1192 __ bind(&entry); | |
1193 __ cmpp(key, Operand(rbp, kLimitOffset)); | |
1194 __ j(not_equal, &loop); | |
1195 | 1215 |
1196 // Call the function. | 1216 // Call the function. |
1197 Label call_proxy; | 1217 Label call_proxy; |
1198 ParameterCount actual(rax); | 1218 ParameterCount actual(rax); |
1199 __ SmiToInteger32(rax, key); | 1219 __ SmiToInteger32(rax, key); |
1200 __ movp(rdi, Operand(rbp, kFunctionOffset)); | 1220 __ movp(rdi, Operand(rbp, kFunctionOffset)); |
1201 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 1221 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); |
1202 __ j(not_equal, &call_proxy); | 1222 __ j(not_equal, &call_proxy); |
1203 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); | 1223 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); |
1204 | 1224 |
1205 frame_scope.GenerateLeaveFrame(); | 1225 frame_scope.GenerateLeaveFrame(); |
1206 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1226 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments |
1207 | 1227 |
1208 // Call the function proxy. | 1228 // Call the function proxy. |
1209 __ bind(&call_proxy); | 1229 __ bind(&call_proxy); |
1210 __ Push(rdi); // add function proxy as last argument | 1230 __ Push(rdi); // add function proxy as last argument |
1211 __ incp(rax); | 1231 __ incp(rax); |
1212 __ Set(rbx, 0); | 1232 __ Set(rbx, 0); |
1213 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 1233 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
1214 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1234 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1215 RelocInfo::CODE_TARGET); | 1235 RelocInfo::CODE_TARGET); |
1216 | 1236 |
1217 // Leave internal frame. | 1237 // Leave internal frame. |
1218 } | 1238 } |
1219 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1239 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments |
1220 } | 1240 } |
1221 | 1241 |
1222 | 1242 |
1243 // Used by ReflectConstruct | |
1244 static void Generate_ConstructHelper(MacroAssembler* masm) { | |
1245 const int kFormalParameters = 3; | |
1246 const int kStackSize = kFormalParameters + 1; | |
1247 | |
1248 // Stack at entry: | |
1249 // rsp : return address | |
1250 // rsp[8] : original constructor (new.target) | |
1251 // rsp[16] : arguments | |
1252 // rsp[24] : constructor | |
1253 { | |
1254 FrameScope frame_scope(masm, StackFrame::INTERNAL); | |
1255 // Stack frame: | |
1256 // rbp : Old base pointer | |
1257 // rbp[8] : return address | |
1258 // rbp[16] : function arguments | |
1259 // rbp[24] : receiver | |
1260 // rbp[32] : function | |
1261 static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize; | |
1262 static const int kArgumentsOffset = kNewTargetOffset + kPointerSize; | |
1263 static const int kFunctionOffset = kArgumentsOffset + kPointerSize; | |
1264 | |
1265 // If newTarget is not supplied, set it to constructor | |
1266 Label validate_arguments; | |
1267 __ movp(rax, Operand(rbp, kNewTargetOffset)); | |
1268 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | |
1269 __ j(not_equal, &validate_arguments, Label::kNear); | |
1270 __ movp(rax, Operand(rbp, kFunctionOffset)); | |
1271 __ movp(Operand(rbp, kNewTargetOffset), rax); | |
1272 | |
1273 // Validate arguments | |
1274 __ bind(&validate_arguments); | |
1275 __ Push(Operand(rbp, kFunctionOffset)); | |
1276 __ Push(Operand(rbp, kArgumentsOffset)); | |
1277 __ Push(Operand(rbp, kNewTargetOffset)); | |
1278 __ InvokeBuiltin(Builtins::REFLECT_CONSTRUCT_PREPARE, CALL_FUNCTION); | |
1279 | |
1280 // Check the stack for overflow. We are not trying to catch | |
Dmitry Lomov (no reviews)
2015/03/13 09:39:09
Please share the stack overflow check code between
caitp (gmail)
2015/03/13 15:10:37
I notice that the stack overflow check is running
Dmitry Lomov (no reviews)
2015/03/13 16:40:03
We can overshoot, so just make it 2 pointers alway
| |
1281 // interruptions (e.g. debug break and preemption) here, so the "real stack | |
1282 // limit" is checked. | |
1283 Label okay; | |
1284 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex); | |
1285 __ movp(rcx, rsp); | |
1286 // Make rcx the space we have left. The stack might already be overflowed | |
1287 // here which will cause rcx to become negative. | |
1288 __ subp(rcx, kScratchRegister); | |
1289 // Make rdx the space we need for the array when it is unrolled onto the | |
1290 // stack. | |
1291 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rax, kPointerSizeLog2); | |
1292 // Check if the arguments will overflow the stack. | |
1293 __ cmpp(rcx, rdx); | |
1294 __ j(greater, &okay); // Signed comparison. | |
1295 | |
1296 // Out of stack space. | |
1297 __ Push(Operand(rbp, kFunctionOffset)); | |
1298 __ Push(rax); | |
1299 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); | |
1300 __ bind(&okay); | |
1301 // End of stack check. | |
1302 | |
1303 // Push current index and limit. | |
1304 const int kLimitOffset = | |
1305 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; | |
1306 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; | |
1307 __ Push(rax); // limit | |
1308 __ Push(Immediate(0)); // index | |
1309 // Push newTarget and callee functions | |
1310 __ Push(Operand(rbp, kNewTargetOffset)); | |
1311 __ Push(Operand(rbp, kFunctionOffset)); | |
1312 | |
1313 Register receiver = LoadDescriptor::ReceiverRegister(); | |
1314 Register key = LoadDescriptor::NameRegister(); | |
1315 | |
1316 // Loop over the arguments array, pushing each value to the stack | |
1317 Generate_PushAppliedArguments( | |
1318 masm, receiver, key, kArgumentsOffset, kIndexOffset, kLimitOffset); | |
1319 | |
1320 // Use undefined feedback vector | |
1321 __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex); | |
1322 | |
1323 __ movp(rax, Operand(rbp, kLimitOffset)); | |
1324 __ SmiToInteger64(rax, rax); | |
1325 __ movp(rdi, Operand(rbp, kFunctionOffset)); | |
1326 | |
1327 // Call the function. | |
1328 CallConstructStub stub(masm->isolate(), SUPER_CONSTRUCTOR_CALL); | |
1329 __ call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | |
1330 | |
1331 __ Drop(1); | |
1332 | |
1333 // Leave internal frame. | |
1334 } | |
1335 __ ret(kStackSize * kPointerSize); // remove this, receiver, and arguments | |
1336 } | |
1337 | |
1338 | |
1339 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | |
1340 Generate_ApplyHelper(masm, false); | |
1341 } | |
1342 | |
1343 | |
1344 void Builtins::Generate_ReflectApply(MacroAssembler* masm) { | |
1345 Generate_ApplyHelper(masm, true); | |
1346 } | |
1347 | |
1348 | |
1349 void Builtins::Generate_ReflectConstruct(MacroAssembler* masm) { | |
1350 Generate_ConstructHelper(masm); | |
1351 } | |
1352 | |
1353 | |
1223 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { | 1354 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { |
1224 // ----------- S t a t e ------------- | 1355 // ----------- S t a t e ------------- |
1225 // -- rax : argc | 1356 // -- rax : argc |
1226 // -- rsp[0] : return address | 1357 // -- rsp[0] : return address |
1227 // -- rsp[8] : last argument | 1358 // -- rsp[8] : last argument |
1228 // ----------------------------------- | 1359 // ----------------------------------- |
1229 Label generic_array_code; | 1360 Label generic_array_code; |
1230 | 1361 |
1231 // Get the InternalArray function. | 1362 // Get the InternalArray function. |
1232 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi); | 1363 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi); |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1615 __ bind(&ok); | 1746 __ bind(&ok); |
1616 __ ret(0); | 1747 __ ret(0); |
1617 } | 1748 } |
1618 | 1749 |
1619 | 1750 |
1620 #undef __ | 1751 #undef __ |
1621 | 1752 |
1622 } } // namespace v8::internal | 1753 } } // namespace v8::internal |
1623 | 1754 |
1624 #endif // V8_TARGET_ARCH_X64 | 1755 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |