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

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: 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) 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 const int kMaxImmediateInInstruction = 256;
1586 const bool kIsLastCheck = (i == (kSortedLen - 1)); 1566 int bias =
1587 ASSERT(sorted[i].cid != kSmiCid); 1567 ComputeGoodBiasForCidComparison(sorted, kMaxImmediateInInstruction);
1568 if (bias != 0) __ AddImmediate(R2, R2, -bias);
1569
1570 for (intptr_t i = 0; i < sorted_len; i++) {
1571 const bool is_last_check = (i == (sorted_len - 1));
1572 int cid_start = sorted[i].cid_start;
1573 int cid_end = sorted[i].cid_end;
1574 int count = sorted[i].count;
1575 if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
1576 // This case is hit too rarely to be worth writing class-id checks inline
1577 // for.
1578 add_megamorphic_call = true;
1579 break;
1580 }
1581 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
1588 Label next_test; 1582 Label next_test;
1589 if (!complete) { 1583 if (!complete || !is_last_check) {
1590 __ CompareImmediate(R2, sorted[i].cid); 1584 Label* next_label = is_last_check ? failed : &next_test;
1591 if (kIsLastCheck) { 1585 if (cid_start == cid_end) {
1592 __ b(failed, NE); 1586 __ CompareImmediate(R2, cid_start - bias);
1587 __ b(next_label, NE);
1593 } else { 1588 } else {
1594 __ b(&next_test, NE); 1589 __ AddImmediate(R2, R2, bias - cid_start);
1595 } 1590 bias = cid_start;
1596 } else { 1591 __ CompareImmediate(R2, cid_end - cid_start);
1597 if (!kIsLastCheck) { 1592 __ b(next_label, HI); // Unsigned higher.
1598 __ CompareImmediate(R2, sorted[i].cid);
1599 __ b(&next_test, NE);
1600 } 1593 }
1601 } 1594 }
1602 // Do not use the code from the function, but let the code be patched so 1595 // 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. 1596 // that we can record the outgoing edges to other code.
1604 const Function& function = *sorted[i].target; 1597 const Function& function = *sorted[i].target;
1605 GenerateStaticDartCall(deopt_id, token_index, 1598 GenerateStaticDartCall(deopt_id, token_index,
1606 *StubCode::CallStaticFunction_entry(), 1599 *StubCode::CallStaticFunction_entry(),
1607 RawPcDescriptors::kOther, locs, function); 1600 RawPcDescriptors::kOther, locs, function);
1608 __ Drop(argument_count); 1601 __ Drop(argument_count);
1609 if (!kIsLastCheck) { 1602 if (!is_last_check) {
1610 __ b(match_found); 1603 __ b(match_found);
1611 } 1604 }
1612 __ Bind(&next_test); 1605 __ Bind(&next_test);
1613 } 1606 }
1607 if (add_megamorphic_call) {
1608 int try_index = CatchClauseNode::kInvalidTryIndex;
1609 EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id, token_index,
1610 locs, try_index, argument_count);
1611 }
1614 } 1612 }
1615 1613
1616 1614
1617 #undef __ 1615 #undef __
1618 #define __ compiler_->assembler()-> 1616 #define __ compiler_->assembler()->
1619 1617
1620 1618
1621 void ParallelMoveResolver::EmitMove(int index) { 1619 void ParallelMoveResolver::EmitMove(int index) {
1622 MoveOperands* move = moves_[index]; 1620 MoveOperands* move = moves_[index];
1623 const Location source = move->src(); 1621 const Location source = move->src();
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1906 DRegister dreg = EvenDRegisterOf(reg); 1904 DRegister dreg = EvenDRegisterOf(reg);
1907 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); 1905 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex));
1908 } 1906 }
1909 1907
1910 1908
1911 #undef __ 1909 #undef __
1912 1910
1913 } // namespace dart 1911 } // namespace dart
1914 1912
1915 #endif // defined TARGET_ARCH_ARM 1913 #endif // defined TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698