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

Side by Side Diff: runtime/vm/flow_graph_compiler_x64.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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1243 const String& name = String::Handle(zone(), ic_data.target_name()); 1243 const String& name = String::Handle(zone(), ic_data.target_name());
1244 const Array& arguments_descriptor = 1244 const Array& arguments_descriptor =
1245 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); 1245 Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
1246 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1246 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1247 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle( 1247 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
1248 zone(), 1248 zone(),
1249 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); 1249 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
1250 __ Comment("MegamorphicCall"); 1250 __ Comment("MegamorphicCall");
1251 // Load receiver into RDI. 1251 // Load receiver into RDI.
1252 __ movq(RDI, Address(RSP, (argument_count - 1) * kWordSize)); 1252 __ movq(RDI, Address(RSP, (argument_count - 1) * kWordSize));
1253 Label done;
1254 if (ShouldInlineSmiStringHashCode(ic_data)) {
1255 Label megamorphic_call;
1256 __ Comment("Inlined get:hashCode for Smi and OneByteString");
1257 __ movq(RAX, RDI); // Move Smi hashcode to RAX.
1258 __ testq(RDI, Immediate(kSmiTagMask));
1259 __ j(ZERO, &done, Assembler::kNearJump); // It is Smi, we are done.
1260
1261 __ CompareClassId(RDI, kOneByteStringCid);
1262 __ j(NOT_EQUAL, &megamorphic_call, Assembler::kNearJump);
1263 __ movq(RAX, FieldAddress(RDI, String::hash_offset()));
1264 __ cmpq(RAX, Immediate(0));
1265 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
1266
1267 __ Bind(&megamorphic_call);
1268 __ Comment("Slow case: megamorphic call");
1269 }
1270 __ LoadObject(RBX, cache); 1253 __ LoadObject(RBX, cache);
1271 __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset())); 1254 __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset()));
1272 1255
1273 __ Bind(&done);
1274 RecordSafepoint(locs, slow_path_argument_count); 1256 RecordSafepoint(locs, slow_path_argument_count);
1275 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1257 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1276 if (FLAG_precompiled_mode) { 1258 if (FLAG_precompiled_mode) {
1277 // Megamorphic calls may occur in slow path stubs. 1259 // Megamorphic calls may occur in slow path stubs.
1278 // If valid use try_index argument. 1260 // If valid use try_index argument.
1279 if (try_index == CatchClauseNode::kInvalidTryIndex) { 1261 if (try_index == CatchClauseNode::kInvalidTryIndex) {
1280 try_index = CurrentTryIndex(); 1262 try_index = CurrentTryIndex();
1281 } 1263 }
1282 AddDescriptor(RawPcDescriptors::kOther, assembler()->CodeSize(), 1264 AddDescriptor(RawPcDescriptors::kOther, assembler()->CodeSize(),
1283 Thread::kNoDeoptId, token_pos, try_index); 1265 Thread::kNoDeoptId, token_pos, try_index);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 1429
1448 1430
1449 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1431 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
1450 intptr_t argument_count, 1432 intptr_t argument_count,
1451 const Array& argument_names, 1433 const Array& argument_names,
1452 Label* failed, 1434 Label* failed,
1453 Label* match_found, 1435 Label* match_found,
1454 intptr_t deopt_id, 1436 intptr_t deopt_id,
1455 TokenPosition token_index, 1437 TokenPosition token_index,
1456 LocationSummary* locs, 1438 LocationSummary* locs,
1457 bool complete) { 1439 bool complete,
1440 intptr_t total_ic_calls) {
1458 ASSERT(is_optimizing()); 1441 ASSERT(is_optimizing());
1459 1442
1460 __ Comment("EmitTestAndCall"); 1443 __ Comment("EmitTestAndCall");
1461 const Array& arguments_descriptor = Array::ZoneHandle( 1444 const Array& arguments_descriptor = Array::ZoneHandle(
1462 zone(), ArgumentsDescriptor::New(argument_count, argument_names)); 1445 zone(), ArgumentsDescriptor::New(argument_count, argument_names));
1463 // Load receiver into RAX. 1446 // Load receiver into RAX.
1464 __ movq(RAX, Address(RSP, (argument_count - 1) * kWordSize)); 1447 __ movq(RAX, Address(RSP, (argument_count - 1) * kWordSize));
1465 __ LoadObject(R10, arguments_descriptor); 1448 __ LoadObject(R10, arguments_descriptor);
1466 1449
1467 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; 1450 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
(...skipping 25 matching lines...) Expand all
1493 // Receiver is Smi, but Smi is not a valid class therefore fail. 1476 // Receiver is Smi, but Smi is not a valid class therefore fail.
1494 // (Smi class must be first in the list). 1477 // (Smi class must be first in the list).
1495 if (!complete) { 1478 if (!complete) {
1496 __ testq(RAX, Immediate(kSmiTagMask)); 1479 __ testq(RAX, Immediate(kSmiTagMask));
1497 __ j(ZERO, failed); 1480 __ j(ZERO, failed);
1498 } 1481 }
1499 } 1482 }
1500 __ Bind(&after_smi_test); 1483 __ Bind(&after_smi_test);
1501 1484
1502 ASSERT(!ic_data.IsNull() && (num_checks > 0)); 1485 ASSERT(!ic_data.IsNull() && (num_checks > 0));
1503 GrowableArray<CidTarget> sorted(num_checks); 1486 GrowableArray<CidRangeTarget> sorted(num_checks);
1504 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); 1487 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
1505 1488
1506 const intptr_t kSortedLen = sorted.length(); 1489 const intptr_t sorted_len = sorted.length();
1507 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above 1490 // If sorted_len is 0 then only a Smi check was needed; the Smi check above
1508 // will fail if there was only one check and receiver is not Smi. 1491 // will fail if there was only one check and receiver is not Smi.
1509 if (kSortedLen == 0) return; 1492 if (sorted_len == 0) return;
1510 1493
1511 // Value is not Smi, 1494 // Value is not Smi,
1512 __ LoadClassId(RDI, RAX); 1495 __ LoadClassId(RDI, RAX);
1513 for (intptr_t i = 0; i < kSortedLen; i++) { 1496
1514 const bool kIsLastCheck = (i == (kSortedLen - 1)); 1497 bool add_megamorphic_call = false;
1515 ASSERT(sorted[i].cid != kSmiCid); 1498 int bias = GetGoodBias(sorted, 127);
Vyacheslav Egorov (Google) 2017/03/10 10:31:30 magic constant?
erikcorry 2017/03/10 13:30:01 I gave it a name, kMaxImmediateInInstruction. It'
1499 if (bias != 0) __ addl(RDI, Immediate(-bias));
1500
1501 for (intptr_t i = 0; i < sorted_len; i++) {
1502 const bool is_last_check = (i == (sorted_len - 1));
1503 int cid_start = sorted[i].cid_start;
1504 int cid_end = sorted[i].cid_end;
1505 int count = sorted[i].count;
1506 if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
1507 // This case is hit too rarely to be worth writing class-id checks inline
1508 // for.
1509 add_megamorphic_call = true;
1510 break;
1511 }
1512 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
1516 Label next_test; 1513 Label next_test;
1517 if (!complete) { 1514 if (!complete || !is_last_check) {
1518 __ cmpl(RDI, Immediate(sorted[i].cid)); 1515 Label* next_label = is_last_check ? failed : &next_test;
1519 if (kIsLastCheck) { 1516 bool near = is_last_check ? Assembler::kFarJump : Assembler::kNearJump;
1520 __ j(NOT_EQUAL, failed); 1517 if (cid_start == cid_end) {
1518 __ cmpl(RDI, Immediate(cid_start - bias));
1519 __ j(NOT_EQUAL, next_label, near);
1521 } else { 1520 } else {
1522 __ j(NOT_EQUAL, &next_test); 1521 __ addl(RDI, Immediate(bias - cid_start));
1523 } 1522 bias = cid_start;
1524 } else { 1523 __ cmpl(RDI, Immediate(cid_end - cid_start));
1525 if (!kIsLastCheck) { 1524 __ j(ABOVE, next_label, near); // Unsigned higher.
1526 __ cmpl(RDI, Immediate(sorted[i].cid));
1527 __ j(NOT_EQUAL, &next_test);
1528 } 1525 }
1529 } 1526 }
1530 // Do not use the code from the function, but let the code be patched so 1527 // Do not use the code from the function, but let the code be patched so
1531 // that we can record the outgoing edges to other code. 1528 // that we can record the outgoing edges to other code.
1532 const Function& function = *sorted[i].target; 1529 const Function& function = *sorted[i].target;
1533 GenerateStaticDartCall(deopt_id, token_index, 1530 GenerateStaticDartCall(deopt_id, token_index,
1534 *StubCode::CallStaticFunction_entry(), 1531 *StubCode::CallStaticFunction_entry(),
1535 RawPcDescriptors::kOther, locs, function); 1532 RawPcDescriptors::kOther, locs, function);
1536 __ Drop(argument_count, RCX); 1533 __ Drop(argument_count, RCX);
1537 if (!kIsLastCheck) { 1534 if (!is_last_check) {
1538 __ jmp(match_found); 1535 __ jmp(match_found);
1539 } 1536 }
1540 __ Bind(&next_test); 1537 __ Bind(&next_test);
1541 } 1538 }
1539 if (add_megamorphic_call) {
1540 int try_index = CatchClauseNode::kInvalidTryIndex;
1541 EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id, token_index,
1542 locs, try_index, argument_count);
1543 }
1542 } 1544 }
1543 1545
1544 1546
1545 #undef __ 1547 #undef __
1546 #define __ compiler_->assembler()-> 1548 #define __ compiler_->assembler()->
1547 1549
1548 1550
1549 void ParallelMoveResolver::EmitMove(int index) { 1551 void ParallelMoveResolver::EmitMove(int index) {
1550 MoveOperands* move = moves_[index]; 1552 MoveOperands* move = moves_[index];
1551 const Location source = move->src(); 1553 const Location source = move->src();
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1772 __ movups(reg, Address(RSP, 0)); 1774 __ movups(reg, Address(RSP, 0));
1773 __ AddImmediate(RSP, Immediate(kFpuRegisterSize)); 1775 __ AddImmediate(RSP, Immediate(kFpuRegisterSize));
1774 } 1776 }
1775 1777
1776 1778
1777 #undef __ 1779 #undef __
1778 1780
1779 } // namespace dart 1781 } // namespace dart
1780 1782
1781 #endif // defined TARGET_ARCH_X64 1783 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698