Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(806)

Side by Side Diff: runtime/vm/stub_code_x64.cc

Issue 2658603002: Revert "Optimizations to IC stub for unoptimized code performance on x64." (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/stub_code_mips.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 1290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1301 __ j(NOT_EQUAL, &error, Assembler::kNearJump); 1301 __ j(NOT_EQUAL, &error, Assembler::kNearJump);
1302 __ cmpq(Address(R13, 1 * kWordSize), imm_smi_cid); 1302 __ cmpq(Address(R13, 1 * kWordSize), imm_smi_cid);
1303 __ j(EQUAL, &ok, Assembler::kNearJump); 1303 __ j(EQUAL, &ok, Assembler::kNearJump);
1304 __ Bind(&error); 1304 __ Bind(&error);
1305 __ Stop("Incorrect IC data"); 1305 __ Stop("Incorrect IC data");
1306 __ Bind(&ok); 1306 __ Bind(&ok);
1307 #endif 1307 #endif
1308 1308
1309 if (FLAG_optimization_counter_threshold >= 0) { 1309 if (FLAG_optimization_counter_threshold >= 0) {
1310 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1310 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1311 // Update counter, ignore overflow. 1311 // Update counter.
1312 __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1))); 1312 __ movq(R8, Address(R13, count_offset));
1313 __ addq(R8, Immediate(Smi::RawValue(1)));
1314 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue)));
1315 __ cmovnoq(R9, R8);
1316 __ StoreIntoSmiField(Address(R13, count_offset), R9);
1313 } 1317 }
1314 1318
1315 __ ret(); 1319 __ ret();
1316 } 1320 }
1317 1321
1318 1322
1319 // Generate inline cache check for 'num_args'. 1323 // Generate inline cache check for 'num_args'.
1320 // RBX: Inline cache data object. 1324 // RBX: Inline cache data object.
1321 // TOS(0): return address 1325 // TOS(0): return address
1322 // Control flow: 1326 // Control flow:
1323 // - If receiver is null -> jump to IC miss. 1327 // - If receiver is null -> jump to IC miss.
1324 // - If receiver is Smi -> load Smi class. 1328 // - If receiver is Smi -> load Smi class.
1325 // - If receiver is not-Smi -> load receiver's class. 1329 // - If receiver is not-Smi -> load receiver's class.
1326 // - Check if 'num_args' (including receiver) match any IC data group. 1330 // - Check if 'num_args' (including receiver) match any IC data group.
1327 // - Match found -> jump to target. 1331 // - Match found -> jump to target.
1328 // - Match not found -> jump to IC miss. 1332 // - Match not found -> jump to IC miss.
1329 void StubCode::GenerateNArgsCheckInlineCacheStub( 1333 void StubCode::GenerateNArgsCheckInlineCacheStub(
1330 Assembler* assembler, 1334 Assembler* assembler,
1331 intptr_t num_args, 1335 intptr_t num_args,
1332 const RuntimeEntry& handle_ic_miss, 1336 const RuntimeEntry& handle_ic_miss,
1333 Token::Kind kind, 1337 Token::Kind kind,
1334 bool optimized) { 1338 bool optimized) {
1335 ASSERT(num_args == 1 || num_args == 2); 1339 ASSERT(num_args > 0);
1336 #if defined(DEBUG) 1340 #if defined(DEBUG)
1337 { 1341 {
1338 Label ok; 1342 Label ok;
1339 // Check that the IC data array has NumArgsTested() == num_args. 1343 // Check that the IC data array has NumArgsTested() == num_args.
1340 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1344 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1341 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset())); 1345 __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset()));
1342 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1346 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1343 __ andq(RCX, Immediate(ICData::NumArgsTestedMask())); 1347 __ andq(RCX, Immediate(ICData::NumArgsTestedMask()));
1344 __ cmpq(RCX, Immediate(num_args)); 1348 __ cmpq(RCX, Immediate(num_args));
1345 __ j(EQUAL, &ok, Assembler::kNearJump); 1349 __ j(EQUAL, &ok, Assembler::kNearJump);
(...skipping 14 matching lines...) Expand all
1360 Label not_smi_or_overflow; 1364 Label not_smi_or_overflow;
1361 if (kind != Token::kILLEGAL) { 1365 if (kind != Token::kILLEGAL) {
1362 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow); 1366 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
1363 } 1367 }
1364 __ Bind(&not_smi_or_overflow); 1368 __ Bind(&not_smi_or_overflow);
1365 1369
1366 __ Comment("Extract ICData initial values and receiver cid"); 1370 __ Comment("Extract ICData initial values and receiver cid");
1367 // Load arguments descriptor into R10. 1371 // Load arguments descriptor into R10.
1368 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); 1372 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
1369 // Loop that checks if there is an IC data match. 1373 // Loop that checks if there is an IC data match.
1370 Label loop, found, miss; 1374 Label loop, update, test, found;
1371 // RBX: IC data object (preserved). 1375 // RBX: IC data object (preserved).
1372 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); 1376 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
1373 // R13: ic_data_array with check entries: classes and target functions. 1377 // R13: ic_data_array with check entries: classes and target functions.
1374 __ leaq(R13, FieldAddress(R13, Array::data_offset())); 1378 __ leaq(R13, FieldAddress(R13, Array::data_offset()));
1375 // R13: points directly to the first ic data array element. 1379 // R13: points directly to the first ic data array element.
1376 1380
1377 // Get argument descriptor into RCX. 1381 // Get the receiver's class ID (first read number of arguments from
1378 __ movq(RCX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1382 // arguments descriptor array and then access the receiver from the stack).
1379 // Load first argument into R9. 1383 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1380 __ movq(R9, Address(RSP, RCX, TIMES_4, 0)); 1384 __ movq(R9, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1381 __ LoadTaggedClassIdMayBeSmi(RAX, R9); 1385 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1382 // RAX: first argument class ID as Smi. 1386 // RAX: receiver's class ID as smi.
1383 if (num_args == 2) { 1387 __ movq(R9, Address(R13, 0)); // First class ID (Smi) to check.
1384 // Load second argument into R9. 1388 __ jmp(&test);
1385 __ movq(R9, Address(RSP, RCX, TIMES_4, -kWordSize)); 1389
1386 __ LoadTaggedClassIdMayBeSmi(RCX, R9); 1390 __ Comment("ICData loop");
1387 // RCX: second argument class ID (smi). 1391 __ Bind(&loop);
1392 for (int i = 0; i < num_args; i++) {
1393 if (i > 0) {
1394 // If not the first, load the next argument's class ID.
1395 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1396 __ movq(R9, Address(RSP, RAX, TIMES_4, -i * kWordSize));
1397 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1398 // RAX: next argument class ID (smi).
1399 __ movq(R9, Address(R13, i * kWordSize));
1400 // R9: next class ID to check (smi).
1401 }
1402 __ cmpq(RAX, R9); // Class id match?
1403 if (i < (num_args - 1)) {
1404 __ j(NOT_EQUAL, &update); // Continue.
1405 } else {
1406 // Last check, all checks before matched.
1407 __ j(EQUAL, &found); // Break.
1408 }
1409 }
1410 __ Bind(&update);
1411 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1412 if (num_args > 1) {
1413 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1414 __ movq(R9, Address(RSP, RAX, TIMES_4, 0));
1415 __ LoadTaggedClassIdMayBeSmi(RAX, R9);
1388 } 1416 }
1389 1417
1390 __ Comment("ICData loop"); 1418 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1419 __ addq(R13, Immediate(entry_size)); // Next entry.
1420 __ movq(R9, Address(R13, 0)); // Next class ID.
1391 1421
1392 // We unroll the generic one that is generated once more than the others. 1422 __ Bind(&test);
1393 bool optimize = kind == Token::kILLEGAL; 1423 __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1394 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1424 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1395 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1396 1425
1397 __ Bind(&loop);
1398 for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
1399 Label update;
1400 __ movq(R9, Address(R13, 0));
1401 __ cmpq(RAX, R9); // Class id match?
1402 if (num_args == 2) {
1403 __ j(NOT_EQUAL, &update); // Continue.
1404 __ movq(R9, Address(R13, kWordSize));
1405 // R9: next class ID to check (smi).
1406 __ cmpq(RCX, R9); // Class id match?
1407 }
1408 __ j(EQUAL, &found); // Break.
1409
1410 __ Bind(&update);
1411
1412 const intptr_t entry_size =
1413 ICData::TestEntryLengthFor(num_args) * kWordSize;
1414 __ addq(R13, Immediate(entry_size)); // Next entry.
1415
1416 __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1417 if (unroll == 0) {
1418 __ j(NOT_EQUAL, &loop);
1419 } else {
1420 __ j(EQUAL, &miss);
1421 }
1422 }
1423
1424 __ Bind(&miss);
1425 __ Comment("IC miss"); 1426 __ Comment("IC miss");
1426 // Compute address of arguments (first read number of arguments from 1427 // Compute address of arguments (first read number of arguments from
1427 // arguments descriptor array and then compute address on the stack). 1428 // arguments descriptor array and then compute address on the stack).
1428 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1429 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1429 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. 1430 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
1430 __ EnterStubFrame(); 1431 __ EnterStubFrame();
1431 __ pushq(R10); // Preserve arguments descriptor array. 1432 __ pushq(R10); // Preserve arguments descriptor array.
1432 __ pushq(RBX); // Preserve IC data object. 1433 __ pushq(RBX); // Preserve IC data object.
1433 __ pushq(Immediate(0)); // Result slot. 1434 __ pushq(Immediate(0)); // Result slot.
1434 // Push call arguments. 1435 // Push call arguments.
(...skipping 14 matching lines...) Expand all
1449 __ LeaveStubFrame(); 1450 __ LeaveStubFrame();
1450 Label call_target_function; 1451 Label call_target_function;
1451 if (!FLAG_lazy_dispatchers) { 1452 if (!FLAG_lazy_dispatchers) {
1452 GenerateDispatcherCode(assembler, &call_target_function); 1453 GenerateDispatcherCode(assembler, &call_target_function);
1453 } else { 1454 } else {
1454 __ jmp(&call_target_function); 1455 __ jmp(&call_target_function);
1455 } 1456 }
1456 1457
1457 __ Bind(&found); 1458 __ Bind(&found);
1458 // R13: Pointer to an IC data check group. 1459 // R13: Pointer to an IC data check group.
1460 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1461 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1459 __ movq(RAX, Address(R13, target_offset)); 1462 __ movq(RAX, Address(R13, target_offset));
1460 1463
1461 if (FLAG_optimization_counter_threshold >= 0) { 1464 if (FLAG_optimization_counter_threshold >= 0) {
1465 // Update counter.
1462 __ Comment("Update caller's counter"); 1466 __ Comment("Update caller's counter");
1463 // Ignore overflow. 1467 __ movq(R8, Address(R13, count_offset));
1464 __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1))); 1468 __ addq(R8, Immediate(Smi::RawValue(1)));
1469 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue)));
1470 __ cmovnoq(R9, R8);
1471 __ StoreIntoSmiField(Address(R13, count_offset), R9);
1465 } 1472 }
1466 1473
1467 __ Comment("Call target"); 1474 __ Comment("Call target");
1468 __ Bind(&call_target_function); 1475 __ Bind(&call_target_function);
1469 // RAX: Target function. 1476 // RAX: Target function.
1477 Label is_compiled;
1470 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); 1478 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1471 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); 1479 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
1472 __ jmp(RCX); 1480 __ jmp(RCX);
1473 1481
1474 if (FLAG_support_debugger && !optimized) { 1482 if (FLAG_support_debugger && !optimized) {
1475 __ Bind(&stepping); 1483 __ Bind(&stepping);
1476 __ EnterStubFrame(); 1484 __ EnterStubFrame();
1477 __ pushq(RBX); 1485 __ pushq(RBX);
1478 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); 1486 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
1479 __ popq(RBX); 1487 __ popq(RBX);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1596 1604
1597 // RBX: IC data object (preserved). 1605 // RBX: IC data object (preserved).
1598 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); 1606 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
1599 // R12: ic_data_array with entries: target functions and count. 1607 // R12: ic_data_array with entries: target functions and count.
1600 __ leaq(R12, FieldAddress(R12, Array::data_offset())); 1608 __ leaq(R12, FieldAddress(R12, Array::data_offset()));
1601 // R12: points directly to the first ic data array element. 1609 // R12: points directly to the first ic data array element.
1602 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; 1610 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
1603 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; 1611 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
1604 1612
1605 if (FLAG_optimization_counter_threshold >= 0) { 1613 if (FLAG_optimization_counter_threshold >= 0) {
1606 // Increment count for this call, ignore overflow. 1614 // Increment count for this call.
1607 __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); 1615 __ movq(R8, Address(R12, count_offset));
1616 __ addq(R8, Immediate(Smi::RawValue(1)));
1617 __ movq(R13, Immediate(Smi::RawValue(Smi::kMaxValue)));
1618 __ cmovnoq(R13, R8);
1619 __ StoreIntoSmiField(Address(R12, count_offset), R13);
1608 } 1620 }
1609 1621
1610 // Load arguments descriptor into R10. 1622 // Load arguments descriptor into R10.
1611 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); 1623 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
1612 1624
1613 // Get function and call it, if possible. 1625 // Get function and call it, if possible.
1614 __ movq(RAX, Address(R12, target_offset)); 1626 __ movq(RAX, Address(R12, target_offset));
1615 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); 1627 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
1616 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); 1628 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
1617 __ jmp(RCX); 1629 __ jmp(RCX);
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after
2264 } 2276 }
2265 2277
2266 2278
2267 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2279 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2268 __ int3(); 2280 __ int3();
2269 } 2281 }
2270 2282
2271 } // namespace dart 2283 } // namespace dart
2272 2284
2273 #endif // defined TARGET_ARCH_X64 2285 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698