Chromium Code Reviews| 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 |