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

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

Issue 2737303003: Allow dispatch to use a range of Class-ids in tests (Closed)
Patch Set: Feedback from Slava Created 3 years, 9 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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" // Needed here to get TARGET_ARCH_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
(...skipping 1218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 const Array& arguments_descriptor = 1229 const Array& arguments_descriptor =
1230 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); 1230 Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
1231 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1231 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1232 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle( 1232 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
1233 zone(), 1233 zone(),
1234 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); 1234 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
1235 1235
1236 __ Comment("MegamorphicCall"); 1236 __ Comment("MegamorphicCall");
1237 // Load receiver into R0. 1237 // Load receiver into R0.
1238 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); 1238 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
1239 Label done;
1240 if (ShouldInlineSmiStringHashCode(ic_data)) {
1241 Label megamorphic_call;
1242 __ Comment("Inlined get:hashCode for Smi and OneByteString");
1243 __ tsti(R0, Immediate(kSmiTagMask));
1244 __ b(&done, EQ); // Is Smi (result is receiver).
1245
1246 __ CompareClassId(R0, kOneByteStringCid);
1247 __ b(&megamorphic_call, NE);
1248
1249 // Use R5 (cache for megamorphic call) as scratch.
1250 __ mov(R5, R0); // Preserve receiver in R5, result in R0.
1251 __ ldr(R0, FieldAddress(R0, String::hash_offset()));
1252 __ CompareRegisters(R0, ZR);
1253 __ b(&done, NE);
1254 __ mov(R0, R5); // Restore receiver in R0,
1255
1256 __ Bind(&megamorphic_call);
1257 __ Comment("Slow case: megamorphic call");
1258 }
1259 1239
1260 __ LoadObject(R5, cache); 1240 __ LoadObject(R5, cache);
1261 __ ldr(LR, Address(THR, Thread::megamorphic_call_checked_entry_offset())); 1241 __ ldr(LR, Address(THR, Thread::megamorphic_call_checked_entry_offset()));
1262 __ blr(LR); 1242 __ blr(LR);
1263 1243
1264 __ Bind(&done);
1265 RecordSafepoint(locs, slow_path_argument_count); 1244 RecordSafepoint(locs, slow_path_argument_count);
1266 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1245 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1267 if (FLAG_precompiled_mode) { 1246 if (FLAG_precompiled_mode) {
1268 // Megamorphic calls may occur in slow path stubs. 1247 // Megamorphic calls may occur in slow path stubs.
1269 // If valid use try_index argument. 1248 // If valid use try_index argument.
1270 if (try_index == CatchClauseNode::kInvalidTryIndex) { 1249 if (try_index == CatchClauseNode::kInvalidTryIndex) {
1271 try_index = CurrentTryIndex(); 1250 try_index = CurrentTryIndex();
1272 } 1251 }
1273 AddDescriptor(RawPcDescriptors::kOther, assembler()->CodeSize(), 1252 AddDescriptor(RawPcDescriptors::kOther, assembler()->CodeSize(),
1274 Thread::kNoDeoptId, token_pos, try_index); 1253 Thread::kNoDeoptId, token_pos, try_index);
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 1460
1482 1461
1483 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1462 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
1484 intptr_t argument_count, 1463 intptr_t argument_count,
1485 const Array& argument_names, 1464 const Array& argument_names,
1486 Label* failed, 1465 Label* failed,
1487 Label* match_found, 1466 Label* match_found,
1488 intptr_t deopt_id, 1467 intptr_t deopt_id,
1489 TokenPosition token_index, 1468 TokenPosition token_index,
1490 LocationSummary* locs, 1469 LocationSummary* locs,
1491 bool complete) { 1470 bool complete,
1471 intptr_t total_ic_calls) {
1492 ASSERT(is_optimizing()); 1472 ASSERT(is_optimizing());
1493
1494 __ Comment("EmitTestAndCall"); 1473 __ Comment("EmitTestAndCall");
1495 const Array& arguments_descriptor = Array::ZoneHandle( 1474 const Array& arguments_descriptor = Array::ZoneHandle(
1496 zone(), ArgumentsDescriptor::New(argument_count, argument_names)); 1475 zone(), ArgumentsDescriptor::New(argument_count, argument_names));
1497 1476
1498 // Load receiver into R0. 1477 // Load receiver into R0.
1499 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); 1478 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
1500 __ LoadObject(R4, arguments_descriptor); 1479 __ LoadObject(R4, arguments_descriptor);
1501 1480
1502 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; 1481 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
1503 const intptr_t num_checks = ic_data.NumberOfChecks(); 1482 const intptr_t num_checks = ic_data.NumberOfChecks();
(...skipping 24 matching lines...) Expand all
1528 // Receiver is Smi, but Smi is not a valid class therefore fail. 1507 // Receiver is Smi, but Smi is not a valid class therefore fail.
1529 // (Smi class must be first in the list). 1508 // (Smi class must be first in the list).
1530 if (!complete) { 1509 if (!complete) {
1531 __ tsti(R0, Immediate(kSmiTagMask)); 1510 __ tsti(R0, Immediate(kSmiTagMask));
1532 __ b(failed, EQ); 1511 __ b(failed, EQ);
1533 } 1512 }
1534 } 1513 }
1535 __ Bind(&after_smi_test); 1514 __ Bind(&after_smi_test);
1536 1515
1537 ASSERT(!ic_data.IsNull() && (num_checks > 0)); 1516 ASSERT(!ic_data.IsNull() && (num_checks > 0));
1538 GrowableArray<CidTarget> sorted(num_checks); 1517 GrowableArray<CidRangeTarget> sorted(num_checks);
1539 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); 1518 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
1540 1519
1520 const intptr_t sorted_len = sorted.length();
1521 // If sorted_len is 0 then only a Smi check was needed; the Smi check above
1522 // will fail if there was only one check and receiver is not Smi.
1523 if (sorted_len == 0) return;
1524
1541 // Value is not Smi, 1525 // Value is not Smi,
1542 const intptr_t kSortedLen = sorted.length(); 1526 __ LoadClassId(R2, R0);
1543 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
1544 // will fail if there was only one check and receiver is not Smi.
1545 if (kSortedLen == 0) return;
1546 1527
1547 __ LoadClassId(R2, R0); 1528 bool add_megamorphic_call = false;
1548 for (intptr_t i = 0; i < kSortedLen; i++) { 1529 const int kMaxImmediateInInstruction = 256;
1549 const bool kIsLastCheck = (i == (kSortedLen - 1)); 1530 int bias =
1550 ASSERT(sorted[i].cid != kSmiCid); 1531 ComputeGoodBiasForCidComparison(sorted, kMaxImmediateInInstruction);
1532 if (bias != 0) __ AddImmediate(R2, R2, -bias);
1533
1534 for (intptr_t i = 0; i < sorted_len; i++) {
1535 const bool is_last_check = (i == (sorted_len - 1));
1536 int cid_start = sorted[i].cid_start;
1537 int cid_end = sorted[i].cid_end;
1538 int count = sorted[i].count;
1539 if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
1540 // This case is hit too rarely to be worth writing class-id checks inline
1541 // for.
1542 add_megamorphic_call = true;
1543 break;
1544 }
1545 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
1551 Label next_test; 1546 Label next_test;
1552 if (!complete) { 1547 if (!complete || !is_last_check) {
1553 __ CompareImmediate(R2, sorted[i].cid); 1548 Label* next_label = is_last_check ? failed : &next_test;
1554 if (kIsLastCheck) { 1549 if (cid_start == cid_end) {
1555 __ b(failed, NE); 1550 __ CompareImmediate(R2, cid_start - bias);
1551 __ b(next_label, NE);
1556 } else { 1552 } else {
1557 __ b(&next_test, NE); 1553 __ AddImmediate(R2, R2, bias - cid_start);
1558 } 1554 bias = cid_start;
1559 } else { 1555 __ CompareImmediate(R2, cid_end - cid_start);
1560 if (!kIsLastCheck) { 1556 __ b(next_label, HI); // Unsigned higher.
1561 __ CompareImmediate(R2, sorted[i].cid);
1562 __ b(&next_test, NE);
1563 } 1557 }
1564 } 1558 }
1565 // Do not use the code from the function, but let the code be patched so 1559 // Do not use the code from the function, but let the code be patched so
1566 // that we can record the outgoing edges to other code. 1560 // that we can record the outgoing edges to other code.
1567 const Function& function = *sorted[i].target; 1561 const Function& function = *sorted[i].target;
1568 GenerateStaticDartCall(deopt_id, token_index, 1562 GenerateStaticDartCall(deopt_id, token_index,
1569 *StubCode::CallStaticFunction_entry(), 1563 *StubCode::CallStaticFunction_entry(),
1570 RawPcDescriptors::kOther, locs, function); 1564 RawPcDescriptors::kOther, locs, function);
1571 __ Drop(argument_count); 1565 __ Drop(argument_count);
1572 if (!kIsLastCheck) { 1566 if (!is_last_check) {
1573 __ b(match_found); 1567 __ b(match_found);
1574 } 1568 }
1575 __ Bind(&next_test); 1569 __ Bind(&next_test);
1576 } 1570 }
1571 if (add_megamorphic_call) {
1572 int try_index = CatchClauseNode::kInvalidTryIndex;
1573 EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id, token_index,
1574 locs, try_index, argument_count);
1575 }
1577 } 1576 }
1578 1577
1579 1578
1580 #undef __ 1579 #undef __
1581 #define __ compiler_->assembler()-> 1580 #define __ compiler_->assembler()->
1582 1581
1583 1582
1584 void ParallelMoveResolver::EmitMove(int index) { 1583 void ParallelMoveResolver::EmitMove(int index) {
1585 MoveOperands* move = moves_[index]; 1584 MoveOperands* move = moves_[index];
1586 const Location source = move->src(); 1585 const Location source = move->src();
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
1849 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 1848 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
1850 __ PopDouble(reg); 1849 __ PopDouble(reg);
1851 } 1850 }
1852 1851
1853 1852
1854 #undef __ 1853 #undef __
1855 1854
1856 } // namespace dart 1855 } // namespace dart
1857 1856
1858 #endif // defined TARGET_ARCH_ARM64 1857 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698