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

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

Issue 2737303003: Allow dispatch to use a range of Class-ids in tests (Closed)
Patch Set: 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) 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" // Needed here to get TARGET_ARCH_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
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 1229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1240 const Array& arguments_descriptor = 1240 const Array& arguments_descriptor =
1241 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); 1241 Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
1242 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1242 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1243 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle( 1243 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
1244 zone(), 1244 zone(),
1245 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); 1245 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
1246 1246
1247 __ Comment("MegamorphicCall"); 1247 __ Comment("MegamorphicCall");
1248 // Load receiver into R0. 1248 // Load receiver into R0.
1249 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize); 1249 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
1250 Label done;
1251 if (ShouldInlineSmiStringHashCode(ic_data)) {
1252 Label megamorphic_call;
1253 __ Comment("Inlined get:hashCode for Smi and OneByteString");
1254 __ tst(R0, Operand(kSmiTagMask));
1255 __ b(&done, EQ); // Is Smi (result is receiver).
1256
1257 // Use R9 (cache for megamorphic call) as scratch.
1258 __ CompareClassId(R0, kOneByteStringCid, R9);
1259 __ b(&megamorphic_call, NE);
1260
1261 __ mov(R9, Operand(R0)); // Preserve receiver in R9.
1262 __ ldr(R0, FieldAddress(R0, String::hash_offset()));
1263 ASSERT(Smi::New(0) == 0);
1264 __ cmp(R0, Operand(0));
1265
1266 __ b(&done, NE); // Return if already computed.
1267 __ mov(R0, Operand(R9)); // Restore receiver in R0.
1268
1269 __ Bind(&megamorphic_call);
1270 __ Comment("Slow case: megamorphic call");
1271 }
1272 __ LoadObject(R9, cache); 1250 __ LoadObject(R9, cache);
1273 __ ldr(LR, Address(THR, Thread::megamorphic_call_checked_entry_offset())); 1251 __ ldr(LR, Address(THR, Thread::megamorphic_call_checked_entry_offset()));
1274 __ blx(LR); 1252 __ blx(LR);
1275 1253
1276 __ Bind(&done);
1277 RecordSafepoint(locs, slow_path_argument_count); 1254 RecordSafepoint(locs, slow_path_argument_count);
1278 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1255 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1279 if (FLAG_precompiled_mode) { 1256 if (FLAG_precompiled_mode) {
1280 // Megamorphic calls may occur in slow path stubs. 1257 // Megamorphic calls may occur in slow path stubs.
1281 // If valid use try_index argument. 1258 // If valid use try_index argument.
1282 if (try_index == CatchClauseNode::kInvalidTryIndex) { 1259 if (try_index == CatchClauseNode::kInvalidTryIndex) {
1283 try_index = CurrentTryIndex(); 1260 try_index = CurrentTryIndex();
1284 } 1261 }
1285 AddDescriptor(RawPcDescriptors::kOther, assembler()->CodeSize(), 1262 AddDescriptor(RawPcDescriptors::kOther, assembler()->CodeSize(),
1286 Thread::kNoDeoptId, token_pos, try_index); 1263 Thread::kNoDeoptId, token_pos, try_index);
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 1496
1520 1497
1521 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1498 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
1522 intptr_t argument_count, 1499 intptr_t argument_count,
1523 const Array& argument_names, 1500 const Array& argument_names,
1524 Label* failed, 1501 Label* failed,
1525 Label* match_found, 1502 Label* match_found,
1526 intptr_t deopt_id, 1503 intptr_t deopt_id,
1527 TokenPosition token_index, 1504 TokenPosition token_index,
1528 LocationSummary* locs, 1505 LocationSummary* locs,
1529 bool complete) { 1506 bool complete,
1507 intptr_t total_ic_calls) {
1530 ASSERT(is_optimizing()); 1508 ASSERT(is_optimizing());
1531 __ Comment("EmitTestAndCall"); 1509 __ Comment("EmitTestAndCall");
1532 const Array& arguments_descriptor = Array::ZoneHandle( 1510 const Array& arguments_descriptor = Array::ZoneHandle(
1533 zone(), ArgumentsDescriptor::New(argument_count, argument_names)); 1511 zone(), ArgumentsDescriptor::New(argument_count, argument_names));
1534 1512
1535 // Load receiver into R0. 1513 // Load receiver into R0.
1536 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize); 1514 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize);
1537 __ LoadObject(R4, arguments_descriptor); 1515 __ LoadObject(R4, arguments_descriptor);
1538 1516
1539 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; 1517 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
(...skipping 25 matching lines...) Expand all
1565 // Receiver is Smi, but Smi is not a valid class therefore fail. 1543 // Receiver is Smi, but Smi is not a valid class therefore fail.
1566 // (Smi class must be first in the list). 1544 // (Smi class must be first in the list).
1567 if (!complete) { 1545 if (!complete) {
1568 __ tst(R0, Operand(kSmiTagMask)); 1546 __ tst(R0, Operand(kSmiTagMask));
1569 __ b(failed, EQ); 1547 __ b(failed, EQ);
1570 } 1548 }
1571 } 1549 }
1572 __ Bind(&after_smi_test); 1550 __ Bind(&after_smi_test);
1573 1551
1574 ASSERT(!ic_data.IsNull() && (num_checks > 0)); 1552 ASSERT(!ic_data.IsNull() && (num_checks > 0));
1575 GrowableArray<CidTarget> sorted(num_checks); 1553 GrowableArray<CidRangeTarget> sorted(num_checks);
1576 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); 1554 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
1577 1555
1556 const intptr_t sorted_len = sorted.length();
1557 // If sorted_len is 0 then only a Smi check was needed; the Smi check above
1558 // will fail if there was only one check and receiver is not Smi.
1559 if (sorted_len == 0) return;
1560
1578 // Value is not Smi, 1561 // Value is not Smi,
1579 const intptr_t kSortedLen = sorted.length(); 1562 __ LoadClassId(R2, R0);
1580 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
1581 // will fail if there was only one check and receiver is not Smi.
1582 if (kSortedLen == 0) return;
1583 1563
1584 __ LoadClassId(R2, R0); 1564 bool add_megamorphic_call = false;
1585 for (intptr_t i = 0; i < kSortedLen; i++) { 1565 int bias = GetGoodBias(sorted, 256);
1586 const bool kIsLastCheck = (i == (kSortedLen - 1)); 1566 if (bias != 0) __ AddImmediate(R2, R2, -bias);
1587 ASSERT(sorted[i].cid != kSmiCid); 1567
1568 for (intptr_t i = 0; i < sorted_len; i++) {
1569 const bool is_last_check = (i == (sorted_len - 1));
1570 int cid_start = sorted[i].cid_start;
1571 int cid_end = sorted[i].cid_end;
1572 int count = sorted[i].count;
1573 if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
Vyacheslav Egorov (Google) 2017/03/10 10:31:30 Magic constants! This is a suspect optimization b
erikcorry 2017/03/10 13:30:01 Previous behaviour: * If there are only a few cid
1574 // This case is hit too rarely to be worth writing class-id checks inline
1575 // for.
1576 add_megamorphic_call = true;
1577 break;
1578 }
1579 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
1588 Label next_test; 1580 Label next_test;
1589 if (!complete) { 1581 if (!complete || !is_last_check) {
1590 __ CompareImmediate(R2, sorted[i].cid); 1582 Label* next_label = is_last_check ? failed : &next_test;
1591 if (kIsLastCheck) { 1583 if (cid_start == cid_end) {
1592 __ b(failed, NE); 1584 __ CompareImmediate(R2, cid_start - bias);
1585 __ b(next_label, NE);
1593 } else { 1586 } else {
1594 __ b(&next_test, NE); 1587 __ AddImmediate(R2, R2, bias - cid_start);
1595 } 1588 bias = cid_start;
1596 } else { 1589 __ CompareImmediate(R2, cid_end - cid_start);
1597 if (!kIsLastCheck) { 1590 __ b(next_label, HI); // Unsigned higher.
1598 __ CompareImmediate(R2, sorted[i].cid);
1599 __ b(&next_test, NE);
1600 } 1591 }
1601 } 1592 }
1602 // Do not use the code from the function, but let the code be patched so 1593 // Do not use the code from the function, but let the code be patched so
1603 // that we can record the outgoing edges to other code. 1594 // that we can record the outgoing edges to other code.
1604 const Function& function = *sorted[i].target; 1595 const Function& function = *sorted[i].target;
1605 GenerateStaticDartCall(deopt_id, token_index, 1596 GenerateStaticDartCall(deopt_id, token_index,
1606 *StubCode::CallStaticFunction_entry(), 1597 *StubCode::CallStaticFunction_entry(),
1607 RawPcDescriptors::kOther, locs, function); 1598 RawPcDescriptors::kOther, locs, function);
1608 __ Drop(argument_count); 1599 __ Drop(argument_count);
1609 if (!kIsLastCheck) { 1600 if (!is_last_check) {
1610 __ b(match_found); 1601 __ b(match_found);
1611 } 1602 }
1612 __ Bind(&next_test); 1603 __ Bind(&next_test);
1613 } 1604 }
1605 if (add_megamorphic_call) {
1606 int try_index = CatchClauseNode::kInvalidTryIndex;
1607 EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id, token_index,
1608 locs, try_index, argument_count);
1609 }
1614 } 1610 }
1615 1611
1616 1612
1617 #undef __ 1613 #undef __
1618 #define __ compiler_->assembler()-> 1614 #define __ compiler_->assembler()->
1619 1615
1620 1616
1621 void ParallelMoveResolver::EmitMove(int index) { 1617 void ParallelMoveResolver::EmitMove(int index) {
1622 MoveOperands* move = moves_[index]; 1618 MoveOperands* move = moves_[index];
1623 const Location source = move->src(); 1619 const Location source = move->src();
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1906 DRegister dreg = EvenDRegisterOf(reg); 1902 DRegister dreg = EvenDRegisterOf(reg);
1907 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); 1903 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex));
1908 } 1904 }
1909 1905
1910 1906
1911 #undef __ 1907 #undef __
1912 1908
1913 } // namespace dart 1909 } // namespace dart
1914 1910
1915 #endif // defined TARGET_ARCH_ARM 1911 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698