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

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

Issue 2647913002: Optimizations to IC stub for unoptimized code performance on x64. (Closed)
Patch Set: Feedback from Regis Created 3 years, 11 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/object.cc ('k') | runtime/vm/stub_code_arm64.cc » ('j') | 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_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1332 __ CompareImmediate(R1, imm_smi_cid); 1332 __ CompareImmediate(R1, imm_smi_cid);
1333 __ b(&error, NE); 1333 __ b(&error, NE);
1334 __ ldr(R1, Address(R8, kWordSize)); 1334 __ ldr(R1, Address(R8, kWordSize));
1335 __ CompareImmediate(R1, imm_smi_cid); 1335 __ CompareImmediate(R1, imm_smi_cid);
1336 __ b(&ok, EQ); 1336 __ b(&ok, EQ);
1337 __ Bind(&error); 1337 __ Bind(&error);
1338 __ Stop("Incorrect IC data"); 1338 __ Stop("Incorrect IC data");
1339 __ Bind(&ok); 1339 __ Bind(&ok);
1340 #endif 1340 #endif
1341 if (FLAG_optimization_counter_threshold >= 0) { 1341 if (FLAG_optimization_counter_threshold >= 0) {
1342 // Update counter. 1342 // Update counter, ignore overflow.
1343 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1343 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1344 __ LoadFromOffset(kWord, R1, R8, count_offset); 1344 __ LoadFromOffset(kWord, R1, R8, count_offset);
1345 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1345 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1346 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow.
1347 __ StoreIntoSmiField(Address(R8, count_offset), R1); 1346 __ StoreIntoSmiField(Address(R8, count_offset), R1);
1348 } 1347 }
1349 __ Ret(); 1348 __ Ret();
1350 } 1349 }
1351 1350
1352 1351
1353 // Generate inline cache check for 'num_args'. 1352 // Generate inline cache check for 'num_args'.
1354 // LR: return address. 1353 // LR: return address.
1355 // R9: inline cache data object. 1354 // R9: inline cache data object.
1356 // Control flow: 1355 // Control flow:
1357 // - If receiver is null -> jump to IC miss. 1356 // - If receiver is null -> jump to IC miss.
1358 // - If receiver is Smi -> load Smi class. 1357 // - If receiver is Smi -> load Smi class.
1359 // - If receiver is not-Smi -> load receiver's class. 1358 // - If receiver is not-Smi -> load receiver's class.
1360 // - Check if 'num_args' (including receiver) match any IC data group. 1359 // - Check if 'num_args' (including receiver) match any IC data group.
1361 // - Match found -> jump to target. 1360 // - Match found -> jump to target.
1362 // - Match not found -> jump to IC miss. 1361 // - Match not found -> jump to IC miss.
1363 void StubCode::GenerateNArgsCheckInlineCacheStub( 1362 void StubCode::GenerateNArgsCheckInlineCacheStub(
1364 Assembler* assembler, 1363 Assembler* assembler,
1365 intptr_t num_args, 1364 intptr_t num_args,
1366 const RuntimeEntry& handle_ic_miss, 1365 const RuntimeEntry& handle_ic_miss,
1367 Token::Kind kind, 1366 Token::Kind kind,
1368 bool optimized) { 1367 bool optimized) {
1369 __ CheckCodePointer(); 1368 __ CheckCodePointer();
1370 ASSERT(num_args > 0); 1369 ASSERT(num_args == 1 || num_args == 2);
1371 #if defined(DEBUG) 1370 #if defined(DEBUG)
1372 { 1371 {
1373 Label ok; 1372 Label ok;
1374 // Check that the IC data array has NumArgsTested() == num_args. 1373 // Check that the IC data array has NumArgsTested() == num_args.
1375 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1374 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1376 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset())); 1375 __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset()));
1377 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1376 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1378 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask())); 1377 __ and_(R8, R8, Operand(ICData::NumArgsTestedMask()));
1379 __ CompareImmediate(R8, num_args); 1378 __ CompareImmediate(R8, num_args);
1380 __ b(&ok, EQ); 1379 __ b(&ok, EQ);
(...skipping 15 matching lines...) Expand all
1396 Label not_smi_or_overflow; 1395 Label not_smi_or_overflow;
1397 if (kind != Token::kILLEGAL) { 1396 if (kind != Token::kILLEGAL) {
1398 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow); 1397 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
1399 } 1398 }
1400 __ Bind(&not_smi_or_overflow); 1399 __ Bind(&not_smi_or_overflow);
1401 1400
1402 __ Comment("Extract ICData initial values and receiver cid"); 1401 __ Comment("Extract ICData initial values and receiver cid");
1403 // Load arguments descriptor into R4. 1402 // Load arguments descriptor into R4.
1404 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); 1403 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
1405 // Loop that checks if there is an IC data match. 1404 // Loop that checks if there is an IC data match.
1406 Label loop, update, test, found; 1405 Label loop, found, miss;
1407 // R9: IC data object (preserved). 1406 // R9: IC data object (preserved).
1408 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); 1407 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
1409 // R8: ic_data_array with check entries: classes and target functions. 1408 // R8: ic_data_array with check entries: classes and target functions.
1410 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); 1409 const int kIcDataOffset = Array::data_offset() - kHeapObjectTag;
1411 // R8: points directly to the first ic data array element. 1410 // R8: points at the IC data array.
1412 1411
1413 // Get the receiver's class ID (first read number of arguments from 1412 // Get the receiver's class ID (first read number of arguments from
1414 // arguments descriptor array and then access the receiver from the stack). 1413 // arguments descriptor array and then access the receiver from the stack).
1415 __ ldr(NOTFP, FieldAddress(R4, ArgumentsDescriptor::count_offset())); 1414 __ ldr(NOTFP, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
1416 __ sub(NOTFP, NOTFP, Operand(Smi::RawValue(1))); 1415 __ sub(NOTFP, NOTFP, Operand(Smi::RawValue(1)));
1417 __ ldr(R0, Address(SP, NOTFP, LSL, 1)); // NOTFP (argument_count - 1) is smi.
1418 __ LoadTaggedClassIdMayBeSmi(R0, R0);
1419 // NOTFP: argument_count - 1 (smi). 1416 // NOTFP: argument_count - 1 (smi).
1420 // R0: receiver's class ID (smi).
1421 __ ldr(R1, Address(R8, 0)); // First class id (smi) to check.
1422 __ b(&test);
1423 1417
1424 __ Comment("ICData loop"); 1418 __ Comment("ICData loop");
1419
1420 __ ldr(R0, Address(SP, NOTFP, LSL, 1)); // NOTFP (argument_count - 1) is Smi.
1421 __ LoadTaggedClassIdMayBeSmi(R0, R0);
1422 if (num_args == 2) {
1423 __ sub(R1, NOTFP, Operand(Smi::RawValue(1)));
1424 __ ldr(R1, Address(SP, R1, LSL, 1)); // R1 (argument_count - 2) is Smi.
1425 __ LoadTaggedClassIdMayBeSmi(R1, R1);
1426 }
1427
1428 // We unroll the generic one that is generated once more than the others.
1429 bool optimize = kind == Token::kILLEGAL;
1430
1425 __ Bind(&loop); 1431 __ Bind(&loop);
1426 for (int i = 0; i < num_args; i++) { 1432 for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
1427 if (i > 0) { 1433 Label update;
1428 // If not the first, load the next argument's class ID. 1434
1429 __ AddImmediate(R0, NOTFP, Smi::RawValue(-i)); 1435 __ ldr(R2, Address(R8, kIcDataOffset));
1430 __ ldr(R0, Address(SP, R0, LSL, 1)); 1436 __ cmp(R0, Operand(R2)); // Class id match?
1431 __ LoadTaggedClassIdMayBeSmi(R0, R0); 1437 if (num_args == 2) {
1432 // R0: next argument class ID (smi). 1438 __ b(&update, NE); // Continue.
1433 __ LoadFromOffset(kWord, R1, R8, i * kWordSize); 1439 __ ldr(R2, Address(R8, kIcDataOffset + kWordSize));
1434 // R1: next class ID to check (smi). 1440 __ cmp(R1, Operand(R2)); // Class id match?
1435 } 1441 }
1436 __ cmp(R0, Operand(R1)); // Class id match? 1442 __ b(&found, EQ); // Break.
1437 if (i < (num_args - 1)) { 1443
1438 __ b(&update, NE); // Continue. 1444 __ Bind(&update);
1445
1446 const intptr_t entry_size =
1447 ICData::TestEntryLengthFor(num_args) * kWordSize;
1448 __ AddImmediate(R8, entry_size); // Next entry.
1449
1450 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); // Done?
1451 if (unroll == 0) {
1452 __ b(&loop, NE);
1439 } else { 1453 } else {
1440 // Last check, all checks before matched. 1454 __ b(&miss, EQ);
1441 __ b(&found, EQ); // Break.
1442 } 1455 }
1443 } 1456 }
1444 __ Bind(&update);
1445 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1446 if (num_args > 1) {
1447 __ ldr(R0, Address(SP, NOTFP, LSL, 1));
1448 __ LoadTaggedClassIdMayBeSmi(R0, R0);
1449 }
1450 1457
1451 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1458 __ Bind(&miss);
1452 __ AddImmediate(R8, entry_size); // Next entry.
1453 __ ldr(R1, Address(R8, 0)); // Next class ID.
1454
1455 __ Bind(&test);
1456 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done?
1457 __ b(&loop, NE);
1458
1459 __ Comment("IC miss"); 1459 __ Comment("IC miss");
1460 // Compute address of arguments. 1460 // Compute address of arguments.
1461 // NOTFP: argument_count - 1 (smi). 1461 // NOTFP: argument_count - 1 (smi).
1462 __ add(NOTFP, SP, Operand(NOTFP, LSL, 1)); // NOTFP is Smi. 1462 __ add(NOTFP, SP, Operand(NOTFP, LSL, 1)); // NOTFP is Smi.
1463 // NOTFP: address of receiver. 1463 // NOTFP: address of receiver.
1464 // Create a stub frame as we are pushing some objects on the stack before 1464 // Create a stub frame as we are pushing some objects on the stack before
1465 // calling into the runtime. 1465 // calling into the runtime.
1466 __ EnterStubFrame(); 1466 __ EnterStubFrame();
1467 __ LoadImmediate(R0, 0); 1467 __ LoadImmediate(R0, 0);
1468 // Preserve IC data object and arguments descriptor array and 1468 // Preserve IC data object and arguments descriptor array and
(...skipping 18 matching lines...) Expand all
1487 if (!FLAG_lazy_dispatchers) { 1487 if (!FLAG_lazy_dispatchers) {
1488 GenerateDispatcherCode(assembler, &call_target_function); 1488 GenerateDispatcherCode(assembler, &call_target_function);
1489 } else { 1489 } else {
1490 __ b(&call_target_function); 1490 __ b(&call_target_function);
1491 } 1491 }
1492 1492
1493 __ Bind(&found); 1493 __ Bind(&found);
1494 // R8: pointer to an IC data check group. 1494 // R8: pointer to an IC data check group.
1495 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1495 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1496 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1496 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1497 __ LoadFromOffset(kWord, R0, R8, target_offset); 1497 __ LoadFromOffset(kWord, R0, R8, kIcDataOffset + target_offset);
1498 1498
1499 if (FLAG_optimization_counter_threshold >= 0) { 1499 if (FLAG_optimization_counter_threshold >= 0) {
1500 __ Comment("Update caller's counter"); 1500 __ Comment("Update caller's counter");
1501 __ LoadFromOffset(kWord, R1, R8, count_offset); 1501 __ LoadFromOffset(kWord, R1, R8, kIcDataOffset + count_offset);
1502 // Ignore overflow.
1502 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1503 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1503 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow. 1504 __ StoreIntoSmiField(Address(R8, kIcDataOffset + count_offset), R1);
1504 __ StoreIntoSmiField(Address(R8, count_offset), R1);
1505 } 1505 }
1506 1506
1507 __ Comment("Call target"); 1507 __ Comment("Call target");
1508 __ Bind(&call_target_function); 1508 __ Bind(&call_target_function);
1509 // R0: target function. 1509 // R0: target function.
1510 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); 1510 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset()));
1511 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); 1511 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
1512 __ bx(R2); 1512 __ bx(R2);
1513 1513
1514 if (FLAG_support_debugger && !optimized) { 1514 if (FLAG_support_debugger && !optimized) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1620 1620
1621 // R9: IC data object (preserved). 1621 // R9: IC data object (preserved).
1622 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); 1622 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
1623 // R8: ic_data_array with entries: target functions and count. 1623 // R8: ic_data_array with entries: target functions and count.
1624 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); 1624 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag);
1625 // R8: points directly to the first ic data array element. 1625 // R8: points directly to the first ic data array element.
1626 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; 1626 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
1627 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; 1627 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
1628 1628
1629 if (FLAG_optimization_counter_threshold >= 0) { 1629 if (FLAG_optimization_counter_threshold >= 0) {
1630 // Increment count for this call. 1630 // Increment count for this call, ignore overflow.
1631 __ LoadFromOffset(kWord, R1, R8, count_offset); 1631 __ LoadFromOffset(kWord, R1, R8, count_offset);
1632 __ adds(R1, R1, Operand(Smi::RawValue(1))); 1632 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1633 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue), VS); // Overflow.
1634 __ StoreIntoSmiField(Address(R8, count_offset), R1); 1633 __ StoreIntoSmiField(Address(R8, count_offset), R1);
1635 } 1634 }
1636 1635
1637 // Load arguments descriptor into R4. 1636 // Load arguments descriptor into R4.
1638 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); 1637 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
1639 1638
1640 // Get function and call it, if possible. 1639 // Get function and call it, if possible.
1641 __ LoadFromOffset(kWord, R0, R8, target_offset); 1640 __ LoadFromOffset(kWord, R0, R8, target_offset);
1642 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); 1641 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
1643 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); 1642 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset()));
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after
2281 } 2280 }
2282 2281
2283 2282
2284 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2283 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2285 __ bkpt(0); 2284 __ bkpt(0);
2286 } 2285 }
2287 2286
2288 } // namespace dart 2287 } // namespace dart
2289 2288
2290 #endif // defined TARGET_ARCH_ARM 2289 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/object.cc ('k') | runtime/vm/stub_code_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698