| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 Smi::FromInt(PropertyDetails::TypeField::mask())); | 373 Smi::FromInt(PropertyDetails::TypeField::mask())); |
| 374 __ j(not_zero, miss); | 374 __ j(not_zero, miss); |
| 375 | 375 |
| 376 // Get the value at the masked, scaled index. | 376 // Get the value at the masked, scaled index. |
| 377 const int kValueOffset = | 377 const int kValueOffset = |
| 378 NumberDictionary::kElementsStartOffset + kPointerSize; | 378 NumberDictionary::kElementsStartOffset + kPointerSize; |
| 379 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 379 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
| 380 } | 380 } |
| 381 | 381 |
| 382 | 382 |
| 383 // One byte opcode for test rax,0xXXXXXXXX. | 383 // The offset from the inlined patch site to the start of the inlined |
| 384 static const byte kTestEaxByte = 0xA9; | 384 // load instruction. |
| 385 const int LoadIC::kOffsetToLoadInstruction = 20; |
| 385 | 386 |
| 386 | 387 |
| 387 static bool PatchInlinedMapCheck(Address address, Object* map) { | 388 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 388 if (V8::UseCrankshaft()) return false; | 389 // ----------- S t a t e ------------- |
| 390 // -- rax : receiver |
| 391 // -- rcx : name |
| 392 // -- rsp[0] : return address |
| 393 // ----------------------------------- |
| 394 Label miss; |
| 389 | 395 |
| 390 // Arguments are address of start of call sequence that called | 396 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); |
| 391 // the IC, | 397 __ bind(&miss); |
| 392 Address test_instruction_address = | 398 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 393 address + Assembler::kCallTargetAddressOffset; | |
| 394 // The keyed load has a fast inlined case if the IC call instruction | |
| 395 // is immediately followed by a test instruction. | |
| 396 if (*test_instruction_address != kTestEaxByte) return false; | |
| 397 | |
| 398 // Fetch the offset from the test instruction to the map compare | |
| 399 // instructions (starting with the 64-bit immediate mov of the map | |
| 400 // address). This offset is stored in the last 4 bytes of the 5 | |
| 401 // byte test instruction. | |
| 402 Address delta_address = test_instruction_address + 1; | |
| 403 int delta = *reinterpret_cast<int*>(delta_address); | |
| 404 // Compute the map address. The map address is in the last 8 bytes | |
| 405 // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2 | |
| 406 // to the offset to get the map address. | |
| 407 Address map_address = test_instruction_address + delta + 2; | |
| 408 // Patch the map check. | |
| 409 *(reinterpret_cast<Object**>(map_address)) = map; | |
| 410 return true; | |
| 411 } | 399 } |
| 412 | 400 |
| 413 | 401 |
| 414 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { | 402 void LoadIC::GenerateStringLength(MacroAssembler* masm) { |
| 415 return PatchInlinedMapCheck(address, map); | 403 // ----------- S t a t e ------------- |
| 404 // -- rax : receiver |
| 405 // -- rcx : name |
| 406 // -- rsp[0] : return address |
| 407 // ----------------------------------- |
| 408 Label miss; |
| 409 |
| 410 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); |
| 411 __ bind(&miss); |
| 412 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 416 } | 413 } |
| 417 | 414 |
| 418 | 415 |
| 419 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { | 416 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { |
| 420 return PatchInlinedMapCheck(address, map); | 417 // ----------- S t a t e ------------- |
| 418 // -- rax : receiver |
| 419 // -- rcx : name |
| 420 // -- rsp[0] : return address |
| 421 // ----------------------------------- |
| 422 Label miss; |
| 423 |
| 424 StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss); |
| 425 __ bind(&miss); |
| 426 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
| 421 } | 427 } |
| 422 | 428 |
| 423 | 429 |
| 424 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | |
| 425 // ----------- S t a t e ------------- | |
| 426 // -- rax : key | |
| 427 // -- rdx : receiver | |
| 428 // -- rsp[0] : return address | |
| 429 // ----------------------------------- | |
| 430 | |
| 431 __ IncrementCounter(&Counters::keyed_load_miss, 1); | |
| 432 | |
| 433 __ pop(rbx); | |
| 434 __ push(rdx); // receiver | |
| 435 __ push(rax); // name | |
| 436 __ push(rbx); // return address | |
| 437 | |
| 438 // Perform tail call to the entry. | |
| 439 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); | |
| 440 __ TailCallExternalReference(ref, 2, 1); | |
| 441 } | |
| 442 | |
| 443 | |
| 444 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | |
| 445 // ----------- S t a t e ------------- | |
| 446 // -- rax : key | |
| 447 // -- rdx : receiver | |
| 448 // -- rsp[0] : return address | |
| 449 // ----------------------------------- | |
| 450 | |
| 451 __ pop(rbx); | |
| 452 __ push(rdx); // receiver | |
| 453 __ push(rax); // name | |
| 454 __ push(rbx); // return address | |
| 455 | |
| 456 // Perform tail call to the entry. | |
| 457 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | |
| 458 } | |
| 459 | |
| 460 | |
| 461 // Checks the receiver for special cases (value type, slow case bits). | 430 // Checks the receiver for special cases (value type, slow case bits). |
| 462 // Falls through for regular JS object. | 431 // Falls through for regular JS object. |
| 463 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, | 432 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
| 464 Register receiver, | 433 Register receiver, |
| 465 Register map, | 434 Register map, |
| 466 int interceptor_bit, | 435 int interceptor_bit, |
| 467 Label* slow) { | 436 Label* slow) { |
| 468 // Register use: | 437 // Register use: |
| 469 // receiver - holds the receiver and is unchanged. | 438 // receiver - holds the receiver and is unchanged. |
| 470 // Scratch registers: | 439 // Scratch registers: |
| (...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 | 887 |
| 919 // Perform tail call to the entry. | 888 // Perform tail call to the entry. |
| 920 __ TailCallExternalReference(ExternalReference( | 889 __ TailCallExternalReference(ExternalReference( |
| 921 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); | 890 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); |
| 922 | 891 |
| 923 __ bind(&slow); | 892 __ bind(&slow); |
| 924 GenerateMiss(masm); | 893 GenerateMiss(masm); |
| 925 } | 894 } |
| 926 | 895 |
| 927 | 896 |
| 928 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | |
| 929 // ----------- S t a t e ------------- | |
| 930 // -- rax : value | |
| 931 // -- rcx : key | |
| 932 // -- rdx : receiver | |
| 933 // -- rsp[0] : return address | |
| 934 // ----------------------------------- | |
| 935 | |
| 936 __ pop(rbx); | |
| 937 __ push(rdx); // receiver | |
| 938 __ push(rcx); // key | |
| 939 __ push(rax); // value | |
| 940 __ push(rbx); // return address | |
| 941 | |
| 942 // Do tail-call to runtime routine. | |
| 943 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | |
| 944 __ TailCallExternalReference(ref, 3, 1); | |
| 945 } | |
| 946 | |
| 947 | |
| 948 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | |
| 949 // ----------- S t a t e ------------- | |
| 950 // -- rax : value | |
| 951 // -- rcx : key | |
| 952 // -- rdx : receiver | |
| 953 // -- rsp[0] : return address | |
| 954 // ----------------------------------- | |
| 955 | |
| 956 __ pop(rbx); | |
| 957 __ push(rdx); // receiver | |
| 958 __ push(rcx); // key | |
| 959 __ push(rax); // value | |
| 960 __ push(rbx); // return address | |
| 961 | |
| 962 // Do tail-call to runtime routine. | |
| 963 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | |
| 964 } | |
| 965 | |
| 966 | |
| 967 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 897 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
| 968 // ----------- S t a t e ------------- | 898 // ----------- S t a t e ------------- |
| 969 // -- rax : value | 899 // -- rax : value |
| 970 // -- rcx : key | 900 // -- rcx : key |
| 971 // -- rdx : receiver | 901 // -- rdx : receiver |
| 972 // -- rsp[0] : return address | 902 // -- rsp[0] : return address |
| 973 // ----------------------------------- | 903 // ----------------------------------- |
| 974 Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array; | 904 Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array; |
| 975 | 905 |
| 976 // Check that the object isn't a smi. | 906 // Check that the object isn't a smi. |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 } | 1163 } |
| 1234 __ ret(0); | 1164 __ ret(0); |
| 1235 } | 1165 } |
| 1236 | 1166 |
| 1237 // Slow case: call runtime. | 1167 // Slow case: call runtime. |
| 1238 __ bind(&slow); | 1168 __ bind(&slow); |
| 1239 GenerateRuntimeSetProperty(masm); | 1169 GenerateRuntimeSetProperty(masm); |
| 1240 } | 1170 } |
| 1241 | 1171 |
| 1242 | 1172 |
| 1243 // Defined in ic.cc. | |
| 1244 Object* CallIC_Miss(Arguments args); | |
| 1245 | |
| 1246 | |
| 1247 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { | |
| 1248 // ----------- S t a t e ------------- | |
| 1249 // rcx : function name | |
| 1250 // rsp[0] : return address | |
| 1251 // rsp[8] : argument argc | |
| 1252 // rsp[16] : argument argc - 1 | |
| 1253 // ... | |
| 1254 // rsp[argc * 8] : argument 1 | |
| 1255 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
| 1256 // ----------------------------------- | |
| 1257 | |
| 1258 if (id == IC::kCallIC_Miss) { | |
| 1259 __ IncrementCounter(&Counters::call_miss, 1); | |
| 1260 } else { | |
| 1261 __ IncrementCounter(&Counters::keyed_call_miss, 1); | |
| 1262 } | |
| 1263 | |
| 1264 // Get the receiver of the function from the stack; 1 ~ return address. | |
| 1265 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | |
| 1266 | |
| 1267 // Enter an internal frame. | |
| 1268 __ EnterInternalFrame(); | |
| 1269 | |
| 1270 // Push the receiver and the name of the function. | |
| 1271 __ push(rdx); | |
| 1272 __ push(rcx); | |
| 1273 | |
| 1274 // Call the entry. | |
| 1275 CEntryStub stub(1); | |
| 1276 __ movq(rax, Immediate(2)); | |
| 1277 __ movq(rbx, ExternalReference(IC_Utility(id))); | |
| 1278 __ CallStub(&stub); | |
| 1279 | |
| 1280 // Move result to rdi and exit the internal frame. | |
| 1281 __ movq(rdi, rax); | |
| 1282 __ LeaveInternalFrame(); | |
| 1283 | |
| 1284 // Check if the receiver is a global object of some sort. | |
| 1285 // This can happen only for regular CallIC but not KeyedCallIC. | |
| 1286 if (id == IC::kCallIC_Miss) { | |
| 1287 Label invoke, global; | |
| 1288 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver | |
| 1289 __ JumpIfSmi(rdx, &invoke); | |
| 1290 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); | |
| 1291 __ j(equal, &global); | |
| 1292 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); | |
| 1293 __ j(not_equal, &invoke); | |
| 1294 | |
| 1295 // Patch the receiver on the stack. | |
| 1296 __ bind(&global); | |
| 1297 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 1298 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | |
| 1299 __ bind(&invoke); | |
| 1300 } | |
| 1301 | |
| 1302 // Invoke the function. | |
| 1303 ParameterCount actual(argc); | |
| 1304 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); | |
| 1305 } | |
| 1306 | |
| 1307 | |
| 1308 // The generated code does not accept smi keys. | 1173 // The generated code does not accept smi keys. |
| 1309 // The generated code falls through if both probes miss. | 1174 // The generated code falls through if both probes miss. |
| 1310 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 1175 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
| 1311 int argc, | 1176 int argc, |
| 1312 Code::Kind kind) { | 1177 Code::Kind kind) { |
| 1313 // ----------- S t a t e ------------- | 1178 // ----------- S t a t e ------------- |
| 1314 // rcx : function name | 1179 // rcx : function name |
| 1315 // rdx : receiver | 1180 // rdx : receiver |
| 1316 // ----------------------------------- | 1181 // ----------------------------------- |
| 1317 Label number, non_number, non_string, boolean, probe, miss; | 1182 Label number, non_number, non_string, boolean, probe, miss; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 // rax: elements | 1271 // rax: elements |
| 1407 // Search the dictionary placing the result in rdi. | 1272 // Search the dictionary placing the result in rdi. |
| 1408 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); | 1273 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); |
| 1409 | 1274 |
| 1410 GenerateFunctionTailCall(masm, argc, &miss); | 1275 GenerateFunctionTailCall(masm, argc, &miss); |
| 1411 | 1276 |
| 1412 __ bind(&miss); | 1277 __ bind(&miss); |
| 1413 } | 1278 } |
| 1414 | 1279 |
| 1415 | 1280 |
| 1416 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1281 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { |
| 1417 // ----------- S t a t e ------------- | 1282 // ----------- S t a t e ------------- |
| 1418 // rcx : function name | 1283 // rcx : function name |
| 1419 // rsp[0] : return address | 1284 // rsp[0] : return address |
| 1420 // rsp[8] : argument argc | 1285 // rsp[8] : argument argc |
| 1421 // rsp[16] : argument argc - 1 | 1286 // rsp[16] : argument argc - 1 |
| 1422 // ... | 1287 // ... |
| 1423 // rsp[argc * 8] : argument 1 | 1288 // rsp[argc * 8] : argument 1 |
| 1424 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1289 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1425 // ----------------------------------- | 1290 // ----------------------------------- |
| 1426 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); | 1291 |
| 1292 if (id == IC::kCallIC_Miss) { |
| 1293 __ IncrementCounter(&Counters::call_miss, 1); |
| 1294 } else { |
| 1295 __ IncrementCounter(&Counters::keyed_call_miss, 1); |
| 1296 } |
| 1297 |
| 1298 // Get the receiver of the function from the stack; 1 ~ return address. |
| 1299 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1300 |
| 1301 // Enter an internal frame. |
| 1302 __ EnterInternalFrame(); |
| 1303 |
| 1304 // Push the receiver and the name of the function. |
| 1305 __ push(rdx); |
| 1306 __ push(rcx); |
| 1307 |
| 1308 // Call the entry. |
| 1309 CEntryStub stub(1); |
| 1310 __ movq(rax, Immediate(2)); |
| 1311 __ movq(rbx, ExternalReference(IC_Utility(id))); |
| 1312 __ CallStub(&stub); |
| 1313 |
| 1314 // Move result to rdi and exit the internal frame. |
| 1315 __ movq(rdi, rax); |
| 1316 __ LeaveInternalFrame(); |
| 1317 |
| 1318 // Check if the receiver is a global object of some sort. |
| 1319 // This can happen only for regular CallIC but not KeyedCallIC. |
| 1320 if (id == IC::kCallIC_Miss) { |
| 1321 Label invoke, global; |
| 1322 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver |
| 1323 __ JumpIfSmi(rdx, &invoke); |
| 1324 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); |
| 1325 __ j(equal, &global); |
| 1326 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); |
| 1327 __ j(not_equal, &invoke); |
| 1328 |
| 1329 // Patch the receiver on the stack. |
| 1330 __ bind(&global); |
| 1331 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1332 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1333 __ bind(&invoke); |
| 1334 } |
| 1335 |
| 1336 // Invoke the function. |
| 1337 ParameterCount actual(argc); |
| 1338 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); |
| 1427 } | 1339 } |
| 1428 | 1340 |
| 1429 | 1341 |
| 1430 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1342 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 1431 // ----------- S t a t e ------------- | 1343 // ----------- S t a t e ------------- |
| 1432 // rcx : function name | 1344 // rcx : function name |
| 1433 // rsp[0] : return address | 1345 // rsp[0] : return address |
| 1434 // rsp[8] : argument argc | 1346 // rsp[8] : argument argc |
| 1435 // rsp[16] : argument argc - 1 | 1347 // rsp[16] : argument argc - 1 |
| 1436 // ... | 1348 // ... |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1454 // ... | 1366 // ... |
| 1455 // rsp[argc * 8] : argument 1 | 1367 // rsp[argc * 8] : argument 1 |
| 1456 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1368 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1457 // ----------------------------------- | 1369 // ----------------------------------- |
| 1458 | 1370 |
| 1459 GenerateCallNormal(masm, argc); | 1371 GenerateCallNormal(masm, argc); |
| 1460 GenerateMiss(masm, argc); | 1372 GenerateMiss(masm, argc); |
| 1461 } | 1373 } |
| 1462 | 1374 |
| 1463 | 1375 |
| 1464 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1376 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1465 // ----------- S t a t e ------------- | 1377 // ----------- S t a t e ------------- |
| 1466 // rcx : function name | 1378 // rcx : function name |
| 1467 // rsp[0] : return address | 1379 // rsp[0] : return address |
| 1468 // rsp[8] : argument argc | 1380 // rsp[8] : argument argc |
| 1469 // rsp[16] : argument argc - 1 | 1381 // rsp[16] : argument argc - 1 |
| 1470 // ... | 1382 // ... |
| 1471 // rsp[argc * 8] : argument 1 | 1383 // rsp[argc * 8] : argument 1 |
| 1472 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1384 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1473 // ----------------------------------- | 1385 // ----------------------------------- |
| 1474 | 1386 |
| 1475 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); | 1387 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); |
| 1476 } | 1388 } |
| 1477 | 1389 |
| 1478 | 1390 |
| 1479 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1391 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 1480 // ----------- S t a t e ------------- | 1392 // ----------- S t a t e ------------- |
| 1481 // rcx : function name | 1393 // rcx : function name |
| 1482 // rsp[0] : return address | 1394 // rsp[0] : return address |
| 1483 // rsp[8] : argument argc | 1395 // rsp[8] : argument argc |
| 1484 // rsp[16] : argument argc - 1 | 1396 // rsp[16] : argument argc - 1 |
| 1485 // ... | 1397 // ... |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1591 // ... | 1503 // ... |
| 1592 // rsp[argc * 8] : argument 1 | 1504 // rsp[argc * 8] : argument 1 |
| 1593 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1505 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1594 // ----------------------------------- | 1506 // ----------------------------------- |
| 1595 | 1507 |
| 1596 GenerateCallNormal(masm, argc); | 1508 GenerateCallNormal(masm, argc); |
| 1597 GenerateMiss(masm, argc); | 1509 GenerateMiss(masm, argc); |
| 1598 } | 1510 } |
| 1599 | 1511 |
| 1600 | 1512 |
| 1601 // The offset from the inlined patch site to the start of the inlined | 1513 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1602 // load instruction. | |
| 1603 const int LoadIC::kOffsetToLoadInstruction = 20; | |
| 1604 | |
| 1605 | |
| 1606 void LoadIC::GenerateMiss(MacroAssembler* masm) { | |
| 1607 // ----------- S t a t e ------------- | 1514 // ----------- S t a t e ------------- |
| 1608 // -- rax : receiver | 1515 // rcx : function name |
| 1609 // -- rcx : name | 1516 // rsp[0] : return address |
| 1610 // -- rsp[0] : return address | 1517 // rsp[8] : argument argc |
| 1518 // rsp[16] : argument argc - 1 |
| 1519 // ... |
| 1520 // rsp[argc * 8] : argument 1 |
| 1521 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1611 // ----------------------------------- | 1522 // ----------------------------------- |
| 1612 | 1523 |
| 1613 __ IncrementCounter(&Counters::load_miss, 1); | 1524 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); |
| 1614 | |
| 1615 __ pop(rbx); | |
| 1616 __ push(rax); // receiver | |
| 1617 __ push(rcx); // name | |
| 1618 __ push(rbx); // return address | |
| 1619 | |
| 1620 // Perform tail call to the entry. | |
| 1621 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); | |
| 1622 __ TailCallExternalReference(ref, 2, 1); | |
| 1623 } | |
| 1624 | |
| 1625 | |
| 1626 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | |
| 1627 // ----------- S t a t e ------------- | |
| 1628 // -- rax : receiver | |
| 1629 // -- rcx : name | |
| 1630 // -- rsp[0] : return address | |
| 1631 // ----------------------------------- | |
| 1632 Label miss; | |
| 1633 | |
| 1634 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); | |
| 1635 __ bind(&miss); | |
| 1636 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | |
| 1637 } | |
| 1638 | |
| 1639 | |
| 1640 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { | |
| 1641 // ----------- S t a t e ------------- | |
| 1642 // -- rax : receiver | |
| 1643 // -- rcx : name | |
| 1644 // -- rsp[0] : return address | |
| 1645 // ----------------------------------- | |
| 1646 Label miss; | |
| 1647 | |
| 1648 StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss); | |
| 1649 __ bind(&miss); | |
| 1650 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | |
| 1651 } | 1525 } |
| 1652 | 1526 |
| 1653 | 1527 |
| 1654 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 1528 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1655 // ----------- S t a t e ------------- | 1529 // ----------- S t a t e ------------- |
| 1656 // -- rax : receiver | 1530 // -- rax : receiver |
| 1657 // -- rcx : name | 1531 // -- rcx : name |
| 1658 // -- rsp[0] : return address | 1532 // -- rsp[0] : return address |
| 1659 // ----------------------------------- | 1533 // ----------------------------------- |
| 1660 | 1534 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1683 // Search the dictionary placing the result in rax. | 1557 // Search the dictionary placing the result in rax. |
| 1684 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); | 1558 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); |
| 1685 __ ret(0); | 1559 __ ret(0); |
| 1686 | 1560 |
| 1687 // Cache miss: Jump to runtime. | 1561 // Cache miss: Jump to runtime. |
| 1688 __ bind(&miss); | 1562 __ bind(&miss); |
| 1689 GenerateMiss(masm); | 1563 GenerateMiss(masm); |
| 1690 } | 1564 } |
| 1691 | 1565 |
| 1692 | 1566 |
| 1693 void LoadIC::GenerateStringLength(MacroAssembler* masm) { | 1567 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1694 // ----------- S t a t e ------------- | 1568 // ----------- S t a t e ------------- |
| 1695 // -- rax : receiver | 1569 // -- rax : receiver |
| 1696 // -- rcx : name | 1570 // -- rcx : name |
| 1697 // -- rsp[0] : return address | 1571 // -- rsp[0] : return address |
| 1698 // ----------------------------------- | 1572 // ----------------------------------- |
| 1699 Label miss; | |
| 1700 | 1573 |
| 1701 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); | 1574 __ IncrementCounter(&Counters::load_miss, 1); |
| 1702 __ bind(&miss); | 1575 |
| 1703 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 1576 __ pop(rbx); |
| 1577 __ push(rax); // receiver |
| 1578 __ push(rcx); // name |
| 1579 __ push(rbx); // return address |
| 1580 |
| 1581 // Perform tail call to the entry. |
| 1582 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); |
| 1583 __ TailCallExternalReference(ref, 2, 1); |
| 1704 } | 1584 } |
| 1705 | 1585 |
| 1706 | 1586 |
| 1707 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | 1587 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| 1708 if (V8::UseCrankshaft()) return false; | 1588 if (V8::UseCrankshaft()) return false; |
| 1709 | 1589 |
| 1710 // The address of the instruction following the call. | 1590 // The address of the instruction following the call. |
| 1711 Address test_instruction_address = | 1591 Address test_instruction_address = |
| 1712 address + Assembler::kCallTargetAddressOffset; | 1592 address + Assembler::kCallTargetAddressOffset; |
| 1713 // If the instruction following the call is not a test rax, nothing | 1593 // If the instruction following the call is not a test rax, nothing |
| 1714 // was inlined. | 1594 // was inlined. |
| 1715 if (*test_instruction_address != kTestEaxByte) return false; | 1595 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1716 | 1596 |
| 1717 Address delta_address = test_instruction_address + 1; | 1597 Address delta_address = test_instruction_address + 1; |
| 1718 // The delta to the start of the map check instruction. | 1598 // The delta to the start of the map check instruction. |
| 1719 int delta = *reinterpret_cast<int*>(delta_address); | 1599 int delta = *reinterpret_cast<int*>(delta_address); |
| 1720 | 1600 |
| 1721 // The map address is the last 8 bytes of the 10-byte | 1601 // The map address is the last 8 bytes of the 10-byte |
| 1722 // immediate move instruction, so we add 2 to get the | 1602 // immediate move instruction, so we add 2 to get the |
| 1723 // offset to the last 8 bytes. | 1603 // offset to the last 8 bytes. |
| 1724 Address map_address = test_instruction_address + delta + 2; | 1604 Address map_address = test_instruction_address + delta + 2; |
| 1725 *(reinterpret_cast<Object**>(map_address)) = map; | 1605 *(reinterpret_cast<Object**>(map_address)) = map; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1736 | 1616 |
| 1737 bool LoadIC::PatchInlinedContextualLoad(Address address, | 1617 bool LoadIC::PatchInlinedContextualLoad(Address address, |
| 1738 Object* map, | 1618 Object* map, |
| 1739 Object* cell, | 1619 Object* cell, |
| 1740 bool is_dont_delete) { | 1620 bool is_dont_delete) { |
| 1741 // TODO(<bug#>): implement this. | 1621 // TODO(<bug#>): implement this. |
| 1742 return false; | 1622 return false; |
| 1743 } | 1623 } |
| 1744 | 1624 |
| 1745 | 1625 |
| 1746 // The offset from the inlined patch site to the start of the inlined | |
| 1747 // store instruction. | |
| 1748 const int StoreIC::kOffsetToStoreInstruction = 20; | |
| 1749 | |
| 1750 | |
| 1751 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { | 1626 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { |
| 1752 if (V8::UseCrankshaft()) return false; | 1627 if (V8::UseCrankshaft()) return false; |
| 1753 | 1628 |
| 1754 // The address of the instruction following the call. | 1629 // The address of the instruction following the call. |
| 1755 Address test_instruction_address = | 1630 Address test_instruction_address = |
| 1756 address + Assembler::kCallTargetAddressOffset; | 1631 address + Assembler::kCallTargetAddressOffset; |
| 1757 | 1632 |
| 1758 // If the instruction following the call is not a test rax, nothing | 1633 // If the instruction following the call is not a test rax, nothing |
| 1759 // was inlined. | 1634 // was inlined. |
| 1760 if (*test_instruction_address != kTestEaxByte) return false; | 1635 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1761 | 1636 |
| 1762 // Extract the encoded deltas from the test rax instruction. | 1637 // Extract the encoded deltas from the test rax instruction. |
| 1763 Address encoded_offsets_address = test_instruction_address + 1; | 1638 Address encoded_offsets_address = test_instruction_address + 1; |
| 1764 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); | 1639 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); |
| 1765 int delta_to_map_check = -(encoded_offsets & 0xFFFF); | 1640 int delta_to_map_check = -(encoded_offsets & 0xFFFF); |
| 1766 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER | 1641 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER |
| 1767 int delta_to_record_write = encoded_offsets >> 16; | 1642 int delta_to_record_write = encoded_offsets >> 16; |
| 1768 #endif | 1643 #endif |
| 1769 | 1644 |
| 1770 // Patch the map to check. The map address is the last 8 bytes of | 1645 // Patch the map to check. The map address is the last 8 bytes of |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1793 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || | 1668 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || |
| 1794 *reinterpret_cast<int*>(offset_address) == -1 || | 1669 *reinterpret_cast<int*>(offset_address) == -1 || |
| 1795 (offset == 0 && map == Heap::null_value())); | 1670 (offset == 0 && map == Heap::null_value())); |
| 1796 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | 1671 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1797 #endif | 1672 #endif |
| 1798 | 1673 |
| 1799 return true; | 1674 return true; |
| 1800 } | 1675 } |
| 1801 | 1676 |
| 1802 | 1677 |
| 1803 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1678 static bool PatchInlinedMapCheck(Address address, Object* map) { |
| 1679 if (V8::UseCrankshaft()) return false; |
| 1680 |
| 1681 // Arguments are address of start of call sequence that called |
| 1682 // the IC, |
| 1683 Address test_instruction_address = |
| 1684 address + Assembler::kCallTargetAddressOffset; |
| 1685 // The keyed load has a fast inlined case if the IC call instruction |
| 1686 // is immediately followed by a test instruction. |
| 1687 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1688 |
| 1689 // Fetch the offset from the test instruction to the map compare |
| 1690 // instructions (starting with the 64-bit immediate mov of the map |
| 1691 // address). This offset is stored in the last 4 bytes of the 5 |
| 1692 // byte test instruction. |
| 1693 Address delta_address = test_instruction_address + 1; |
| 1694 int delta = *reinterpret_cast<int*>(delta_address); |
| 1695 // Compute the map address. The map address is in the last 8 bytes |
| 1696 // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2 |
| 1697 // to the offset to get the map address. |
| 1698 Address map_address = test_instruction_address + delta + 2; |
| 1699 // Patch the map check. |
| 1700 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1701 return true; |
| 1702 } |
| 1703 |
| 1704 |
| 1705 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { |
| 1706 return PatchInlinedMapCheck(address, map); |
| 1707 } |
| 1708 |
| 1709 |
| 1710 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { |
| 1711 return PatchInlinedMapCheck(address, map); |
| 1712 } |
| 1713 |
| 1714 |
| 1715 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1804 // ----------- S t a t e ------------- | 1716 // ----------- S t a t e ------------- |
| 1805 // -- rax : value | 1717 // -- rax : key |
| 1806 // -- rcx : name | |
| 1807 // -- rdx : receiver | 1718 // -- rdx : receiver |
| 1808 // -- rsp[0] : return address | 1719 // -- rsp[0] : return address |
| 1720 // ----------------------------------- |
| 1721 |
| 1722 __ IncrementCounter(&Counters::keyed_load_miss, 1); |
| 1723 |
| 1724 __ pop(rbx); |
| 1725 __ push(rdx); // receiver |
| 1726 __ push(rax); // name |
| 1727 __ push(rbx); // return address |
| 1728 |
| 1729 // Perform tail call to the entry. |
| 1730 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); |
| 1731 __ TailCallExternalReference(ref, 2, 1); |
| 1732 } |
| 1733 |
| 1734 |
| 1735 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1736 // ----------- S t a t e ------------- |
| 1737 // -- rax : key |
| 1738 // -- rdx : receiver |
| 1739 // -- rsp[0] : return address |
| 1809 // ----------------------------------- | 1740 // ----------------------------------- |
| 1810 | 1741 |
| 1811 __ pop(rbx); | 1742 __ pop(rbx); |
| 1812 __ push(rdx); // receiver | 1743 __ push(rdx); // receiver |
| 1813 __ push(rcx); // name | 1744 __ push(rax); // name |
| 1814 __ push(rax); // value | |
| 1815 __ push(rbx); // return address | 1745 __ push(rbx); // return address |
| 1816 | 1746 |
| 1817 // Perform tail call to the entry. | 1747 // Perform tail call to the entry. |
| 1818 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); | 1748 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 1819 __ TailCallExternalReference(ref, 3, 1); | |
| 1820 } | 1749 } |
| 1821 | 1750 |
| 1822 | 1751 |
| 1823 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1752 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1824 // ----------- S t a t e ------------- | 1753 // ----------- S t a t e ------------- |
| 1825 // -- rax : value | 1754 // -- rax : value |
| 1826 // -- rcx : name | 1755 // -- rcx : name |
| 1827 // -- rdx : receiver | 1756 // -- rdx : receiver |
| 1828 // -- rsp[0] : return address | 1757 // -- rsp[0] : return address |
| 1829 // ----------------------------------- | 1758 // ----------------------------------- |
| 1830 | 1759 |
| 1831 // Get the receiver from the stack and probe the stub cache. | 1760 // Get the receiver from the stack and probe the stub cache. |
| 1832 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 1761 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
| 1833 NOT_IN_LOOP, | 1762 NOT_IN_LOOP, |
| 1834 MONOMORPHIC); | 1763 MONOMORPHIC); |
| 1835 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); | 1764 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); |
| 1836 | 1765 |
| 1837 // Cache miss: Jump to runtime. | 1766 // Cache miss: Jump to runtime. |
| 1838 GenerateMiss(masm); | 1767 GenerateMiss(masm); |
| 1839 } | 1768 } |
| 1840 | 1769 |
| 1841 | 1770 |
| 1771 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1772 // ----------- S t a t e ------------- |
| 1773 // -- rax : value |
| 1774 // -- rcx : name |
| 1775 // -- rdx : receiver |
| 1776 // -- rsp[0] : return address |
| 1777 // ----------------------------------- |
| 1778 |
| 1779 __ pop(rbx); |
| 1780 __ push(rdx); // receiver |
| 1781 __ push(rcx); // name |
| 1782 __ push(rax); // value |
| 1783 __ push(rbx); // return address |
| 1784 |
| 1785 // Perform tail call to the entry. |
| 1786 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); |
| 1787 __ TailCallExternalReference(ref, 3, 1); |
| 1788 } |
| 1789 |
| 1790 |
| 1791 // The offset from the inlined patch site to the start of the inlined |
| 1792 // store instruction. |
| 1793 const int StoreIC::kOffsetToStoreInstruction = 20; |
| 1794 |
| 1795 |
| 1842 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { | 1796 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
| 1843 // ----------- S t a t e ------------- | 1797 // ----------- S t a t e ------------- |
| 1844 // -- rax : value | 1798 // -- rax : value |
| 1845 // -- rcx : name | 1799 // -- rcx : name |
| 1846 // -- rdx : receiver | 1800 // -- rdx : receiver |
| 1847 // -- rsp[0] : return address | 1801 // -- rsp[0] : return address |
| 1848 // ----------------------------------- | 1802 // ----------------------------------- |
| 1849 // | 1803 // |
| 1850 // This accepts as a receiver anything JSObject::SetElementsLength accepts | 1804 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
| 1851 // (currently anything except for external and pixel arrays which means | 1805 // (currently anything except for external and pixel arrays which means |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1924 __ push(rdx); | 1878 __ push(rdx); |
| 1925 __ push(rcx); | 1879 __ push(rcx); |
| 1926 __ push(rax); | 1880 __ push(rax); |
| 1927 __ push(rbx); | 1881 __ push(rbx); |
| 1928 | 1882 |
| 1929 // Do tail-call to runtime routine. | 1883 // Do tail-call to runtime routine. |
| 1930 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1884 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
| 1931 } | 1885 } |
| 1932 | 1886 |
| 1933 | 1887 |
| 1888 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 1889 // ----------- S t a t e ------------- |
| 1890 // -- rax : value |
| 1891 // -- rcx : key |
| 1892 // -- rdx : receiver |
| 1893 // -- rsp[0] : return address |
| 1894 // ----------------------------------- |
| 1895 |
| 1896 __ pop(rbx); |
| 1897 __ push(rdx); // receiver |
| 1898 __ push(rcx); // key |
| 1899 __ push(rax); // value |
| 1900 __ push(rbx); // return address |
| 1901 |
| 1902 // Do tail-call to runtime routine. |
| 1903 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
| 1904 } |
| 1905 |
| 1906 |
| 1907 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1908 // ----------- S t a t e ------------- |
| 1909 // -- rax : value |
| 1910 // -- rcx : key |
| 1911 // -- rdx : receiver |
| 1912 // -- rsp[0] : return address |
| 1913 // ----------------------------------- |
| 1914 |
| 1915 __ pop(rbx); |
| 1916 __ push(rdx); // receiver |
| 1917 __ push(rcx); // key |
| 1918 __ push(rax); // value |
| 1919 __ push(rbx); // return address |
| 1920 |
| 1921 // Do tail-call to runtime routine. |
| 1922 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
| 1923 __ TailCallExternalReference(ref, 3, 1); |
| 1924 } |
| 1925 |
| 1926 |
| 1934 #undef __ | 1927 #undef __ |
| 1935 | 1928 |
| 1936 | 1929 |
| 1937 Condition CompareIC::ComputeCondition(Token::Value op) { | 1930 Condition CompareIC::ComputeCondition(Token::Value op) { |
| 1938 switch (op) { | 1931 switch (op) { |
| 1939 case Token::EQ_STRICT: | 1932 case Token::EQ_STRICT: |
| 1940 case Token::EQ: | 1933 case Token::EQ: |
| 1941 return equal; | 1934 return equal; |
| 1942 case Token::LT: | 1935 case Token::LT: |
| 1943 return less; | 1936 return less; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1977 GetStateName(state), | 1970 GetStateName(state), |
| 1978 Token::Name(op_)); | 1971 Token::Name(op_)); |
| 1979 } | 1972 } |
| 1980 #endif | 1973 #endif |
| 1981 } | 1974 } |
| 1982 | 1975 |
| 1983 void PatchInlinedSmiCode(Address address) { | 1976 void PatchInlinedSmiCode(Address address) { |
| 1984 UNIMPLEMENTED(); | 1977 UNIMPLEMENTED(); |
| 1985 } | 1978 } |
| 1986 | 1979 |
| 1980 |
| 1987 } } // namespace v8::internal | 1981 } } // namespace v8::internal |
| 1988 | 1982 |
| 1989 #endif // V8_TARGET_ARCH_X64 | 1983 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |