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

Side by Side Diff: runtime/vm/flow_graph_compiler_ia32.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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1207 const Array& arguments_descriptor = 1207 const Array& arguments_descriptor =
1208 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); 1208 Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
1209 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1209 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1210 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle( 1210 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
1211 zone(), 1211 zone(),
1212 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); 1212 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
1213 1213
1214 __ Comment("MegamorphicCall"); 1214 __ Comment("MegamorphicCall");
1215 // Load receiver into EBX. 1215 // Load receiver into EBX.
1216 __ movl(EBX, Address(ESP, (argument_count - 1) * kWordSize)); 1216 __ movl(EBX, Address(ESP, (argument_count - 1) * kWordSize));
1217 Label done;
1218 if (ShouldInlineSmiStringHashCode(ic_data)) {
1219 Label megamorphic_call;
1220 __ Comment("Inlined get:hashCode for Smi and OneByteString");
1221 __ movl(EAX, EBX); // Move Smi hashcode to EAX.
1222 __ testl(EBX, Immediate(kSmiTagMask));
1223 __ j(ZERO, &done, Assembler::kNearJump); // It is Smi, we are done.
1224
1225 __ CompareClassId(EBX, kOneByteStringCid, EAX);
1226 __ j(NOT_EQUAL, &megamorphic_call, Assembler::kNearJump);
1227 __ movl(EAX, FieldAddress(EBX, String::hash_offset()));
1228 __ cmpl(EAX, Immediate(0));
1229 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
1230
1231 __ Bind(&megamorphic_call);
1232 __ Comment("Slow case: megamorphic call");
1233 }
1234 __ LoadObject(ECX, cache); 1217 __ LoadObject(ECX, cache);
1235 __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset())); 1218 __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset()));
1236 __ call(EBX); 1219 __ call(EBX);
1237 1220
1238 __ Bind(&done);
1239 AddCurrentDescriptor(RawPcDescriptors::kOther, Thread::kNoDeoptId, token_pos); 1221 AddCurrentDescriptor(RawPcDescriptors::kOther, Thread::kNoDeoptId, token_pos);
1240 RecordSafepoint(locs, slow_path_argument_count); 1222 RecordSafepoint(locs, slow_path_argument_count);
1241 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); 1223 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id);
1242 // Precompilation not implemented on ia32 platform. 1224 // Precompilation not implemented on ia32 platform.
1243 ASSERT(!FLAG_precompiled_mode); 1225 ASSERT(!FLAG_precompiled_mode);
1244 if (is_optimizing()) { 1226 if (is_optimizing()) {
1245 AddDeoptIndexAtCall(deopt_id_after); 1227 AddDeoptIndexAtCall(deopt_id_after);
1246 } else { 1228 } else {
1247 // Add deoptimization continuation point after the call and before the 1229 // Add deoptimization continuation point after the call and before the
1248 // arguments are removed. 1230 // arguments are removed.
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 1405
1424 1406
1425 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1407 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
1426 intptr_t argument_count, 1408 intptr_t argument_count,
1427 const Array& argument_names, 1409 const Array& argument_names,
1428 Label* failed, 1410 Label* failed,
1429 Label* match_found, 1411 Label* match_found,
1430 intptr_t deopt_id, 1412 intptr_t deopt_id,
1431 TokenPosition token_index, 1413 TokenPosition token_index,
1432 LocationSummary* locs, 1414 LocationSummary* locs,
1433 bool complete) { 1415 bool complete,
1416 intptr_t total_ic_calls) {
1434 ASSERT(is_optimizing()); 1417 ASSERT(is_optimizing());
1435 ASSERT(!complete); 1418 ASSERT(!complete);
1436 __ Comment("EmitTestAndCall"); 1419 __ Comment("EmitTestAndCall");
1437 const Array& arguments_descriptor = Array::ZoneHandle( 1420 const Array& arguments_descriptor = Array::ZoneHandle(
1438 zone(), ArgumentsDescriptor::New(argument_count, argument_names)); 1421 zone(), ArgumentsDescriptor::New(argument_count, argument_names));
1439 // Load receiver into EAX. 1422 // Load receiver into EAX.
1440 __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize)); 1423 __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
1441 __ LoadObject(EDX, arguments_descriptor); 1424 __ LoadObject(EDX, arguments_descriptor);
1442 1425
1443 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; 1426 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
(...skipping 23 matching lines...) Expand all
1467 __ jmp(match_found); 1450 __ jmp(match_found);
1468 } 1451 }
1469 } else { 1452 } else {
1470 // Receiver is Smi, but Smi is not a valid class therefore fail. 1453 // Receiver is Smi, but Smi is not a valid class therefore fail.
1471 // (Smi class must be first in the list). 1454 // (Smi class must be first in the list).
1472 __ j(ZERO, failed); 1455 __ j(ZERO, failed);
1473 } 1456 }
1474 __ Bind(&after_smi_test); 1457 __ Bind(&after_smi_test);
1475 1458
1476 ASSERT(!ic_data.IsNull() && (num_checks > 0)); 1459 ASSERT(!ic_data.IsNull() && (num_checks > 0));
1477 GrowableArray<CidTarget> sorted(num_checks); 1460 GrowableArray<CidRangeTarget> sorted(num_checks);
1478 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true); 1461 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
1479 1462
1463 const intptr_t sorted_len = sorted.length();
1464 // If sorted_len is 0 then only a Smi check was needed; the Smi check above
1465 // will fail if there was only one check and receiver is not Smi.
1466 if (sorted_len == 0) return;
1467
1480 // Value is not Smi, 1468 // Value is not Smi,
1481 // LoadValueCid(this, EDI, EAX, failed); 1469 __ LoadClassId(EDI, EAX);
1482 const intptr_t kSortedLen = sorted.length();
1483 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
1484 // will fail if there was only one check and receiver is not Smi.
1485 if (kSortedLen == 0) return;
1486 1470
1487 __ LoadClassId(EDI, EAX); 1471 bool add_megamorphic_call = false;
1488 for (intptr_t i = 0; i < kSortedLen; i++) { 1472 const int kMaxImmediateInInstruction = 127;
1489 const bool kIsLastCheck = (i == (kSortedLen - 1)); 1473 int bias =
1490 ASSERT(sorted[i].cid != kSmiCid); 1474 ComputeGoodBiasForCidComparison(sorted, kMaxImmediateInInstruction);
1475 if (bias != 0) __ addl(EDI, Immediate(-bias));
1476
1477 for (intptr_t i = 0; i < sorted_len; i++) {
1478 const bool is_last_check = (i == (sorted_len - 1));
1479 int cid_start = sorted[i].cid_start;
1480 int cid_end = sorted[i].cid_end;
1481 int count = sorted[i].count;
1482 if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
1483 // This case is hit too rarely to be worth writing class-id checks inline
1484 // for.
1485 add_megamorphic_call = true;
1486 break;
1487 }
1488 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
1491 Label next_test; 1489 Label next_test;
1492 __ cmpl(EDI, Immediate(sorted[i].cid)); 1490 if (!complete || !is_last_check) {
1493 if (kIsLastCheck) { 1491 Label* next_label = is_last_check ? failed : &next_test;
1494 __ j(NOT_EQUAL, failed); 1492 if (cid_start == cid_end) {
1495 } else { 1493 __ cmpl(EDI, Immediate(cid_start - bias));
1496 __ j(NOT_EQUAL, &next_test); 1494 __ j(NOT_EQUAL, next_label);
1495 } else {
1496 __ addl(EDI, Immediate(bias - cid_start));
1497 bias = cid_start;
1498 __ cmpl(EDI, Immediate(cid_end - cid_start));
1499 __ j(ABOVE, next_label); // Unsigned higher.
1500 }
1497 } 1501 }
1498 // Do not use the code from the function, but let the code be patched so 1502 // Do not use the code from the function, but let the code be patched so
1499 // that we can record the outgoing edges to other code. 1503 // that we can record the outgoing edges to other code.
1504 const Function& function = *sorted[i].target;
1500 GenerateDartCall(deopt_id, token_index, 1505 GenerateDartCall(deopt_id, token_index,
1501 *StubCode::CallStaticFunction_entry(), 1506 *StubCode::CallStaticFunction_entry(),
1502 RawPcDescriptors::kOther, locs); 1507 RawPcDescriptors::kOther, locs);
1503 const Function& function = *sorted[i].target;
1504 AddStaticCallTarget(function); 1508 AddStaticCallTarget(function);
1505 __ Drop(argument_count); 1509 __ Drop(argument_count);
1506 if (!kIsLastCheck) { 1510 if (!is_last_check) {
1507 __ jmp(match_found); 1511 __ jmp(match_found);
1508 } 1512 }
1509 __ Bind(&next_test); 1513 __ Bind(&next_test);
1510 } 1514 }
1515 if (add_megamorphic_call) {
1516 int try_index = CatchClauseNode::kInvalidTryIndex;
1517 EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id, token_index,
1518 locs, try_index, argument_count);
1519 }
1511 } 1520 }
1512 1521
1513 1522
1514 #undef __ 1523 #undef __
1515 #define __ compiler_->assembler()-> 1524 #define __ compiler_->assembler()->
1516 1525
1517 1526
1518 void ParallelMoveResolver::EmitMove(int index) { 1527 void ParallelMoveResolver::EmitMove(int index) {
1519 MoveOperands* move = moves_[index]; 1528 MoveOperands* move = moves_[index];
1520 const Location source = move->src(); 1529 const Location source = move->src();
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
1770 __ movups(reg, Address(ESP, 0)); 1779 __ movups(reg, Address(ESP, 0));
1771 __ addl(ESP, Immediate(kFpuRegisterSize)); 1780 __ addl(ESP, Immediate(kFpuRegisterSize));
1772 } 1781 }
1773 1782
1774 1783
1775 #undef __ 1784 #undef __
1776 1785
1777 } // namespace dart 1786 } // namespace dart
1778 1787
1779 #endif // defined TARGET_ARCH_IA32 1788 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698