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

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

Issue 2842753002: Reland "Use off-heap data for type feedback in PolymorphicInstanceCallInstr" (Closed)
Patch Set: Fix AOT case Created 3 years, 8 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
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm64.cc ('k') | runtime/vm/flow_graph_compiler_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 if (is_optimizing()) { 1124 if (is_optimizing()) {
1125 AddDeoptIndexAtCall(deopt_id_after); 1125 AddDeoptIndexAtCall(deopt_id_after);
1126 } else { 1126 } else {
1127 // Add deoptimization continuation point after the call and before the 1127 // Add deoptimization continuation point after the call and before the
1128 // arguments are removed. 1128 // arguments are removed.
1129 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); 1129 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
1130 } 1130 }
1131 } 1131 }
1132 1132
1133 1133
1134 void FlowGraphCompiler::GenerateStaticDartCall(intptr_t deopt_id,
1135 TokenPosition token_pos,
1136 const StubEntry& stub_entry,
1137 RawPcDescriptors::Kind kind,
1138 LocationSummary* locs,
1139 const Function& target) {
1140 GenerateDartCall(deopt_id, token_pos, stub_entry, kind, locs);
1141 AddStaticCallTarget(target);
1142 }
1143
1144
1134 void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos, 1145 void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos,
1135 intptr_t deopt_id, 1146 intptr_t deopt_id,
1136 const RuntimeEntry& entry, 1147 const RuntimeEntry& entry,
1137 intptr_t argument_count, 1148 intptr_t argument_count,
1138 LocationSummary* locs) { 1149 LocationSummary* locs) {
1139 __ CallRuntime(entry, argument_count); 1150 __ CallRuntime(entry, argument_count);
1140 EmitCallsiteMetaData(token_pos, deopt_id, RawPcDescriptors::kOther, locs); 1151 EmitCallsiteMetaData(token_pos, deopt_id, RawPcDescriptors::kOther, locs);
1141 if (deopt_id != Thread::kNoDeoptId) { 1152 if (deopt_id != Thread::kNoDeoptId) {
1142 // Marks either the continuation point in unoptimized code or the 1153 // Marks either the continuation point in unoptimized code or the
1143 // deoptimization point in optimized code, after call. 1154 // deoptimization point in optimized code, after call.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 LocationSummary* locs) { 1220 LocationSummary* locs) {
1210 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); 1221 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0);
1211 __ LoadObject(ECX, ic_data); 1222 __ LoadObject(ECX, ic_data);
1212 GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall, 1223 GenerateDartCall(deopt_id, token_pos, stub_entry, RawPcDescriptors::kIcCall,
1213 locs); 1224 locs);
1214 __ Drop(argument_count); 1225 __ Drop(argument_count);
1215 } 1226 }
1216 1227
1217 1228
1218 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1229 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
1219 const ICData& ic_data, 1230 const String& name,
1231 const Array& arguments_descriptor,
1220 intptr_t argument_count, 1232 intptr_t argument_count,
1221 intptr_t deopt_id, 1233 intptr_t deopt_id,
1222 TokenPosition token_pos, 1234 TokenPosition token_pos,
1223 LocationSummary* locs, 1235 LocationSummary* locs,
1224 intptr_t try_index, 1236 intptr_t try_index,
1225 intptr_t slow_path_argument_count) { 1237 intptr_t slow_path_argument_count) {
1226 const String& name = String::Handle(zone(), ic_data.target_name());
1227 const Array& arguments_descriptor =
1228 Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
1229 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1238 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1230 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle( 1239 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
1231 zone(), 1240 zone(),
1232 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); 1241 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor));
1233 1242
1234 __ Comment("MegamorphicCall"); 1243 __ Comment("MegamorphicCall");
1235 // Load receiver into EBX. 1244 // Load receiver into EBX.
1236 __ movl(EBX, Address(ESP, (argument_count - 1) * kWordSize)); 1245 __ movl(EBX, Address(ESP, (argument_count - 1) * kWordSize));
1237 __ LoadObject(ECX, cache); 1246 __ LoadObject(ECX, cache);
1238 __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset())); 1247 __ call(Address(THR, Thread::megamorphic_call_checked_entry_offset()));
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 // TODO(zerny): clobber non-live temporary FPU registers. 1427 // TODO(zerny): clobber non-live temporary FPU registers.
1419 if (tmp.IsRegister() && 1428 if (tmp.IsRegister() &&
1420 !locs->live_registers()->ContainsRegister(tmp.reg())) { 1429 !locs->live_registers()->ContainsRegister(tmp.reg())) {
1421 __ movl(tmp.reg(), Immediate(0xf7)); 1430 __ movl(tmp.reg(), Immediate(0xf7));
1422 } 1431 }
1423 } 1432 }
1424 } 1433 }
1425 #endif 1434 #endif
1426 1435
1427 1436
1428 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1437 void FlowGraphCompiler::EmitTestAndCallLoadReceiver(
1429 intptr_t argument_count, 1438 intptr_t argument_count,
1430 const Array& argument_names, 1439 const Array& arguments_descriptor) {
1431 Label* failed,
1432 Label* match_found,
1433 intptr_t deopt_id,
1434 TokenPosition token_index,
1435 LocationSummary* locs,
1436 bool complete,
1437 intptr_t total_ic_calls) {
1438 ASSERT(is_optimizing());
1439 ASSERT(!complete);
1440 __ Comment("EmitTestAndCall"); 1440 __ Comment("EmitTestAndCall");
1441 const Array& arguments_descriptor = Array::ZoneHandle(
1442 zone(), ArgumentsDescriptor::New(argument_count, argument_names));
1443 // Load receiver into EAX. 1441 // Load receiver into EAX.
1444 __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize)); 1442 __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
1445 __ LoadObject(EDX, arguments_descriptor); 1443 __ LoadObject(EDX, arguments_descriptor);
1446
1447 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
1448 const intptr_t num_checks = ic_data.NumberOfChecks();
1449
1450 ASSERT(!ic_data.IsNull() && (num_checks > 0));
1451
1452 Label after_smi_test;
1453 __ testl(EAX, Immediate(kSmiTagMask));
1454 if (kFirstCheckIsSmi) {
1455 // Jump if receiver is not Smi.
1456 if (num_checks == 1) {
1457 __ j(NOT_ZERO, failed);
1458 } else {
1459 __ j(NOT_ZERO, &after_smi_test);
1460 }
1461 // Do not use the code from the function, but let the code be patched so
1462 // that we can record the outgoing edges to other code.
1463 GenerateDartCall(deopt_id, token_index,
1464 *StubCode::CallStaticFunction_entry(),
1465 RawPcDescriptors::kOther, locs);
1466 const Function& function =
1467 Function::ZoneHandle(zone(), ic_data.GetTargetAt(0));
1468 AddStaticCallTarget(function);
1469 __ Drop(argument_count);
1470 if (num_checks > 1) {
1471 __ jmp(match_found);
1472 }
1473 } else {
1474 // Receiver is Smi, but Smi is not a valid class therefore fail.
1475 // (Smi class must be first in the list).
1476 __ j(ZERO, failed);
1477 }
1478 __ Bind(&after_smi_test);
1479
1480 ASSERT(!ic_data.IsNull() && (num_checks > 0));
1481 GrowableArray<CidRangeTarget> sorted(num_checks);
1482 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
1483
1484 const intptr_t sorted_len = sorted.length();
1485 // If sorted_len is 0 then only a Smi check was needed; the Smi check above
1486 // will fail if there was only one check and receiver is not Smi.
1487 if (sorted_len == 0) return;
1488
1489 // Value is not Smi,
1490 __ LoadClassId(EDI, EAX);
1491
1492 bool add_megamorphic_call = false;
1493 const int kMaxImmediateInInstruction = 127;
1494 int bias =
1495 ComputeGoodBiasForCidComparison(sorted, kMaxImmediateInInstruction);
1496 if (bias != 0) __ addl(EDI, Immediate(-bias));
1497
1498 for (intptr_t i = 0; i < sorted_len; i++) {
1499 const bool is_last_check = (i == (sorted_len - 1));
1500 int cid_start = sorted[i].cid_start;
1501 int cid_end = sorted[i].cid_end;
1502 int count = sorted[i].count;
1503 if (!is_last_check && !complete && count < (total_ic_calls >> 5)) {
1504 // This case is hit too rarely to be worth writing class-id checks inline
1505 // for.
1506 add_megamorphic_call = true;
1507 break;
1508 }
1509 ASSERT(cid_start > kSmiCid || cid_end < kSmiCid);
1510 Label next_test;
1511 if (!complete || !is_last_check) {
1512 Label* next_label = is_last_check ? failed : &next_test;
1513 if (cid_start == cid_end) {
1514 __ cmpl(EDI, Immediate(cid_start - bias));
1515 __ j(NOT_EQUAL, next_label);
1516 } else {
1517 __ addl(EDI, Immediate(bias - cid_start));
1518 bias = cid_start;
1519 __ cmpl(EDI, Immediate(cid_end - cid_start));
1520 __ j(ABOVE, next_label); // Unsigned higher.
1521 }
1522 }
1523 // Do not use the code from the function, but let the code be patched so
1524 // that we can record the outgoing edges to other code.
1525 const Function& function = *sorted[i].target;
1526 GenerateDartCall(deopt_id, token_index,
1527 *StubCode::CallStaticFunction_entry(),
1528 RawPcDescriptors::kOther, locs);
1529 AddStaticCallTarget(function);
1530 __ Drop(argument_count);
1531 if (!is_last_check) {
1532 __ jmp(match_found);
1533 }
1534 __ Bind(&next_test);
1535 }
1536 if (add_megamorphic_call) {
1537 int try_index = CatchClauseNode::kInvalidTryIndex;
1538 EmitMegamorphicInstanceCall(ic_data, argument_count, deopt_id, token_index,
1539 locs, try_index, argument_count);
1540 }
1541 } 1444 }
1542 1445
1543 1446
1447 void FlowGraphCompiler::EmitTestAndCallSmiBranch(Label* label, bool if_smi) {
1448 __ testl(EAX, Immediate(kSmiTagMask));
1449 // Jump if receiver is (not) Smi.
1450 __ j(if_smi ? ZERO : NOT_ZERO, label);
1451 }
1452
1453
1454 void FlowGraphCompiler::EmitTestAndCallLoadCid() {
1455 __ LoadClassId(EDI, EAX);
1456 }
1457
1458
1459 int FlowGraphCompiler::EmitTestAndCallCheckCid(Label* next_label,
1460 const CidRangeTarget& target,
1461 int bias) {
1462 intptr_t cid_start = target.cid_start;
1463 intptr_t cid_end = target.cid_end;
1464 if (cid_start == cid_end) {
1465 __ cmpl(EDI, Immediate(cid_start - bias));
1466 __ j(NOT_EQUAL, next_label);
1467 } else {
1468 __ addl(EDI, Immediate(bias - cid_start));
1469 bias = cid_start;
1470 __ cmpl(EDI, Immediate(cid_end - cid_start));
1471 __ j(ABOVE, next_label); // Unsigned higher.
1472 }
1473 return bias;
1474 }
1475
1476
1544 #undef __ 1477 #undef __
1545 #define __ compiler_->assembler()-> 1478 #define __ compiler_->assembler()->
1546 1479
1547 1480
1548 void ParallelMoveResolver::EmitMove(int index) { 1481 void ParallelMoveResolver::EmitMove(int index) {
1549 MoveOperands* move = moves_[index]; 1482 MoveOperands* move = moves_[index];
1550 const Location source = move->src(); 1483 const Location source = move->src();
1551 const Location destination = move->dest(); 1484 const Location destination = move->dest();
1552 1485
1553 if (source.IsRegister()) { 1486 if (source.IsRegister()) {
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
1800 __ movups(reg, Address(ESP, 0)); 1733 __ movups(reg, Address(ESP, 0));
1801 __ addl(ESP, Immediate(kFpuRegisterSize)); 1734 __ addl(ESP, Immediate(kFpuRegisterSize));
1802 } 1735 }
1803 1736
1804 1737
1805 #undef __ 1738 #undef __
1806 1739
1807 } // namespace dart 1740 } // namespace dart
1808 1741
1809 #endif // defined TARGET_ARCH_IA32 1742 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm64.cc ('k') | runtime/vm/flow_graph_compiler_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698