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

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

Issue 1184093004: Faster checks in polymorphic instance calls if Smi-s are involved (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: m Created 5 years, 6 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 1491 matching lines...) Expand 10 before | Expand all | Expand 10 after
1502 if (tmp.IsRegister() && 1502 if (tmp.IsRegister() &&
1503 !locs->live_registers()->ContainsRegister(tmp.reg())) { 1503 !locs->live_registers()->ContainsRegister(tmp.reg())) {
1504 __ movl(tmp.reg(), Immediate(0xf7)); 1504 __ movl(tmp.reg(), Immediate(0xf7));
1505 } 1505 }
1506 } 1506 }
1507 } 1507 }
1508 #endif 1508 #endif
1509 1509
1510 1510
1511 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1511 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
1512 Register class_id_reg,
1513 intptr_t argument_count, 1512 intptr_t argument_count,
1514 const Array& argument_names, 1513 const Array& argument_names,
1515 Label* deopt, 1514 Label* failed,
1515 Label* match_found,
1516 intptr_t deopt_id, 1516 intptr_t deopt_id,
1517 intptr_t token_index, 1517 intptr_t token_index,
1518 LocationSummary* locs) { 1518 LocationSummary* locs) {
1519 ASSERT(is_optimizing()); 1519 ASSERT(is_optimizing());
1520 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfUsedChecks() > 0)); 1520 __ Comment("EmitTestAndCall");
1521 Label match_found;
1522 const intptr_t len = ic_data.NumberOfChecks();
1523 GrowableArray<CidTarget> sorted(len);
1524 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ false);
1525 ASSERT(class_id_reg != EDX);
1526 ASSERT(len > 0); // Why bother otherwise.
1527 const Array& arguments_descriptor = 1521 const Array& arguments_descriptor =
1528 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, 1522 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
1529 argument_names)); 1523 argument_names));
1530 StubCode* stub_code = isolate()->stub_code(); 1524 StubCode* stub_code = isolate()->stub_code();
1525 // Load receiver into EAX.
1526 __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
1527 __ LoadObject(EDX, arguments_descriptor);
1531 1528
1532 __ LoadObject(EDX, arguments_descriptor); 1529 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
1533 for (intptr_t i = 0; i < len; i++) { 1530 const intptr_t kNumChecks = ic_data.NumberOfChecks();
1534 const bool is_last_check = (i == (len - 1)); 1531
1535 Label next_test; 1532 ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
1536 assembler()->cmpl(class_id_reg, Immediate(sorted[i].cid)); 1533
1537 if (is_last_check) { 1534 Label after_smi_test;
1538 assembler()->j(NOT_EQUAL, deopt); 1535 __ testl(EAX, Immediate(kSmiTagMask));
1536 if (kFirstCheckIsSmi) {
1537 // Jump if receiver is not Smi.
1538 if (kNumChecks == 1) {
1539 __ j(NOT_ZERO, failed);
1539 } else { 1540 } else {
1540 assembler()->j(NOT_EQUAL, &next_test); 1541 __ j(NOT_ZERO, &after_smi_test);
1541 } 1542 }
1542 // Do not use the code from the function, but let the code be patched so 1543 // Do not use the code from the function, but let the code be patched so
1543 // that we can record the outgoing edges to other code. 1544 // that we can record the outgoing edges to other code.
1545 GenerateDartCall(deopt_id,
1546 token_index,
1547 &stub_code->CallStaticFunctionLabel(),
1548 RawPcDescriptors::kOther,
1549 locs);
1550 const Function& function = Function::Handle(ic_data.GetTargetAt(0));
1551 AddStaticCallTarget(function);
1552 __ Drop(argument_count);
1553 if (kNumChecks > 1) {
1554 __ jmp(match_found);
1555 }
1556 } else {
1557 // Receiver is Smi, but Smi is not a valid class therefore fail.
1558 // (Smi class must be first in the list).
1559 __ j(ZERO, failed);
1560 }
1561 __ Bind(&after_smi_test);
1562
1563 ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
1564 GrowableArray<CidTarget> sorted(kNumChecks);
1565 SortICDataByCount(ic_data, &sorted, /* drop_smi = */ true);
1566
1567 // Value is not Smi,
1568 // LoadValueCid(this, EDI, EAX, failed);
1569 const intptr_t kSortedLen = sorted.length();
1570 // If kSortedLen is 0 then only a Smi check was needed; the Smi check above
1571 // will fail if there was only one check and receiver is not Smi.
1572 if (kSortedLen == 0) return;
1573
1574 __ LoadClassId(EDI, EAX);
1575 for (intptr_t i = 0; i < kSortedLen; i++) {
1576 const bool kIsLastCheck = (i == (kSortedLen - 1));
1577 ASSERT(sorted[i].cid != kSmiCid);
1578 Label next_test;
1579 __ cmpl(EDI, Immediate(sorted[i].cid));
1580 if (kIsLastCheck) {
1581 __ j(NOT_EQUAL, failed);
1582 } else {
1583 __ j(NOT_EQUAL, &next_test);
1584 }
1585 // Do not use the code from the function, but let the code be patched so
1586 // that we can record the outgoing edges to other code.
1544 GenerateDartCall(deopt_id, 1587 GenerateDartCall(deopt_id,
1545 token_index, 1588 token_index,
1546 &stub_code->CallStaticFunctionLabel(), 1589 &stub_code->CallStaticFunctionLabel(),
1547 RawPcDescriptors::kOther, 1590 RawPcDescriptors::kOther,
1548 locs); 1591 locs);
1549 const Function& function = *sorted[i].target; 1592 const Function& function = *sorted[i].target;
1550 AddStaticCallTarget(function); 1593 AddStaticCallTarget(function);
1551 __ Drop(argument_count); 1594 __ Drop(argument_count);
1552 if (!is_last_check) { 1595 if (!kIsLastCheck) {
1553 assembler()->jmp(&match_found); 1596 __ jmp(match_found);
1554 } 1597 }
1555 assembler()->Bind(&next_test); 1598 __ Bind(&next_test);
1556 } 1599 }
1557 assembler()->Bind(&match_found);
1558 } 1600 }
1559 1601
1560 1602
1561 #undef __ 1603 #undef __
1562 #define __ compiler_->assembler()-> 1604 #define __ compiler_->assembler()->
1563 1605
1564 1606
1565 void ParallelMoveResolver::EmitMove(int index) { 1607 void ParallelMoveResolver::EmitMove(int index) {
1566 MoveOperands* move = moves_[index]; 1608 MoveOperands* move = moves_[index];
1567 const Location source = move->src(); 1609 const Location source = move->src();
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
1818 __ movups(reg, Address(ESP, 0)); 1860 __ movups(reg, Address(ESP, 0));
1819 __ addl(ESP, Immediate(kFpuRegisterSize)); 1861 __ addl(ESP, Immediate(kFpuRegisterSize));
1820 } 1862 }
1821 1863
1822 1864
1823 #undef __ 1865 #undef __
1824 1866
1825 } // namespace dart 1867 } // namespace dart
1826 1868
1827 #endif // defined TARGET_ARCH_IA32 1869 #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