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

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

Issue 11272028: Simplify the implementation and generated code for the IC stubs. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/stub_code_ia32.cc ('k') | no next file » | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/assembler_macros.h" 9 #include "vm/assembler_macros.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 1519 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 // TOS(0): return address 1530 // TOS(0): return address
1531 // Control flow: 1531 // Control flow:
1532 // - If receiver is null -> jump to IC miss. 1532 // - If receiver is null -> jump to IC miss.
1533 // - If receiver is Smi -> load Smi class. 1533 // - If receiver is Smi -> load Smi class.
1534 // - If receiver is not-Smi -> load receiver's class. 1534 // - If receiver is not-Smi -> load receiver's class.
1535 // - Check if 'num_args' (including receiver) match any IC data group. 1535 // - Check if 'num_args' (including receiver) match any IC data group.
1536 // - Match found -> jump to target. 1536 // - Match found -> jump to target.
1537 // - Match not found -> jump to IC miss. 1537 // - Match not found -> jump to IC miss.
1538 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, 1538 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
1539 intptr_t num_args) { 1539 intptr_t num_args) {
1540 ASSERT(num_args > 0);
1541 #if defined(DEBUG)
1542 { Label ok;
1543 // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
1544 // 'num_args_tested' is stored as an untagged int.
1545 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset()));
1546 __ cmpq(RCX, Immediate(num_args));
1547 __ j(EQUAL, &ok, Assembler::kNearJump);
1548 __ Stop("Incorrect stub for IC data");
1549 __ Bind(&ok);
1550 }
1551 #endif // DEBUG
1552
1540 __ movq(RCX, FieldAddress(RBX, ICData::function_offset())); 1553 __ movq(RCX, FieldAddress(RBX, ICData::function_offset()));
1541 Label is_hot; 1554 Label is_hot;
1542 if (FlowGraphCompiler::CanOptimize()) { 1555 if (FlowGraphCompiler::CanOptimize()) {
1543 ASSERT(FLAG_optimization_counter_threshold > 1); 1556 ASSERT(FLAG_optimization_counter_threshold > 1);
1544 // The usage_counter is always less than FLAG_optimization_counter_threshold 1557 // The usage_counter is always less than FLAG_optimization_counter_threshold
1545 // except when the function gets optimized. 1558 // except when the function gets optimized.
1546 __ cmpq(FieldAddress(RCX, Function::usage_counter_offset()), 1559 __ cmpq(FieldAddress(RCX, Function::usage_counter_offset()),
1547 Immediate(FLAG_optimization_counter_threshold - 1)); 1560 Immediate(FLAG_optimization_counter_threshold - 1));
1548 // Do not increment to equality with threshold, since a counter greater 1561 // Do not increment to equality with threshold, since a counter greater
1549 // than threshold denotes a function that was already optimized. 1562 // than threshold denotes a function that was already optimized.
1550 // The equality should be reached only at exit of the method 1563 // The equality should be reached only at exit of the method
1551 // (return instruction). 1564 // (return instruction).
1552 __ j(EQUAL, &is_hot, Assembler::kNearJump); 1565 __ j(EQUAL, &is_hot, Assembler::kNearJump);
1553 // As long as VM has no OSR do not optimize in the middle of the function 1566 // As long as VM has no OSR do not optimize in the middle of the function
1554 // but only at exit so that we have collected all type feedback before 1567 // but only at exit so that we have collected all type feedback before
1555 // optimizing. 1568 // optimizing.
1556 } 1569 }
1557 __ incq(FieldAddress(RCX, Function::usage_counter_offset())); 1570 __ incq(FieldAddress(RCX, Function::usage_counter_offset()));
1558 __ Bind(&is_hot); 1571 __ Bind(&is_hot);
1559 1572
1560 ASSERT(num_args > 0);
1561 // Get receiver (first read number of arguments from argument descriptor array
1562 // and then access the receiver from the stack).
1563 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
1564 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1565
1566 Label get_class_id_as_smi, ic_miss;
1567 // RBX: IC data array.
1568
1569 #if defined(DEBUG)
1570 { Label ok;
1571 // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
1572 // 'num_args_tested' is stored as an untagged int.
1573 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset()));
1574 __ cmpq(RCX, Immediate(num_args));
1575 __ j(EQUAL, &ok, Assembler::kNearJump);
1576 __ Stop("Incorrect stub for IC data");
1577 __ Bind(&ok);
1578 }
1579 #endif // DEBUG
1580
1581 // Loop that checks if there is an IC data match. 1573 // Loop that checks if there is an IC data match.
1574 Label loop, update, test, found, get_class_id_as_smi;
1582 // RBX: IC data object (preserved). 1575 // RBX: IC data object (preserved).
1583 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); 1576 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
1584 // R12: ic_data_array with check entries: classes and target functions. 1577 // R12: ic_data_array with check entries: classes and target functions.
1585 __ leaq(R12, FieldAddress(R12, Array::data_offset())); 1578 __ leaq(R12, FieldAddress(R12, Array::data_offset()));
1586 // R12: points directly to the first ic data array element. 1579 // R12: points directly to the first ic data array element.
1587 const Immediate raw_null = 1580
1588 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1581 // Get the receiver's class ID (first read number of arguments from
1589 Label loop, found; 1582 // argument descriptor array and then access the receiver from the stack).
1590 if (num_args == 1) { 1583 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
1591 __ call(&get_class_id_as_smi); 1584 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1592 // RAX: receiver's class id as Smi. 1585 __ call(&get_class_id_as_smi);
1593 __ Bind(&loop); 1586 // RAX: receiver's class ID as smi.
1594 __ movq(R13, Address(R12, 0)); // Get class if (Smi) to check. 1587 __ movq(R13, Address(R12, 0)); // First class ID (Smi) to check.
1595 __ cmpq(RAX, R13); // Match? 1588 __ jmp(&test);
1596 __ j(EQUAL, &found, Assembler::kNearJump); 1589
1597 __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target). 1590 __ Bind(&loop);
1598 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1591 for (int i = 0; i < num_args; i++) {
1599 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1592 if (i > 0) {
1600 } else { 1593 // If not the first, load the next argument's class ID.
1601 Label no_match;
1602 __ Bind(&loop);
1603 for (int i = 0; i < num_args; i++) {
1604 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1594 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
1605 __ movq(RAX, Address(RSP, RAX, TIMES_4, - i * kWordSize)); 1595 __ movq(RAX, Address(RSP, RAX, TIMES_4, - i * kWordSize));
1606 __ call(&get_class_id_as_smi); 1596 __ call(&get_class_id_as_smi);
1597 // RAX: next argument class ID (smi).
1607 __ movq(R13, Address(R12, i * kWordSize)); 1598 __ movq(R13, Address(R12, i * kWordSize));
1608 __ cmpq(RAX, R13); // Class id match? 1599 // R13: next class ID to check (smi).
1609 if (i < (num_args - 1)) {
1610 __ j(NOT_EQUAL, &no_match);
1611 } else {
1612 // Last check, all checks before matched.
1613 __ j(EQUAL, &found);
1614 }
1615 } 1600 }
1616 __ Bind(&no_match); 1601 __ cmpq(RAX, R13); // Class id match?
1617 // Each test entry has (1 + num_args) array elements. 1602 if (i < (num_args - 1)) {
1618 __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element. 1603 __ j(NOT_EQUAL, &update); // Continue.
1619 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1604 } else {
1620 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1605 // Last check, all checks before matched.
1606 __ j(EQUAL, &found); // Break.
1607 }
1621 } 1608 }
1609 __ Bind(&update);
1610 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1611 if (num_args > 1) {
1612 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
Florian Schneider 2012/10/25 12:41:31 Could you keep FieldAddress(R10, Array::data_offse
1613 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0));
1614 __ call(&get_class_id_as_smi);
1615 }
1616 // Each test entry has (1 + num_args) array elements.
1617 const intptr_t entry_size = (num_args + 1) * kWordSize;
1618 __ addq(R12, Immediate(entry_size)); // Next entry.
1619 __ movq(R13, Address(R12, 0)); // Next class ID.
1622 1620
1623 __ Bind(&ic_miss); 1621 __ Bind(&test);
1624 // Compute address of arguments (first read number of arguments from argument 1622 __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1625 // descriptor array and then compute address on the stack). 1623 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1624
1625 // IC miss.
1626 const Immediate raw_null =
1627 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1628 // Compute address of arguments (first read number of arguments from
1629 // argument descriptor array and then compute address on the stack).
1626 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1630 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
1627 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. 1631 __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
1628 AssemblerMacros::EnterStubFrame(assembler); 1632 AssemblerMacros::EnterStubFrame(assembler);
1629 __ pushq(R10); // Preserve arguments array. 1633 __ pushq(R10); // Preserve arguments array.
1630 __ pushq(RBX); // Preserve IC data array 1634 __ pushq(RBX); // Preserve IC data array
1631 __ pushq(raw_null); // Setup space on stack for result (target code object). 1635 __ pushq(raw_null); // Setup space on stack for result (target code object).
1632 // Push call arguments. 1636 // Push call arguments.
1633 for (intptr_t i = 0; i < num_args; i++) { 1637 for (intptr_t i = 0; i < num_args; i++) {
1634 __ movq(R10, Address(RAX, -kWordSize * i)); 1638 __ movq(R10, Address(RAX, -kWordSize * i));
1635 __ pushq(R10); 1639 __ pushq(R10);
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
2013 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry); 2017 __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry);
2014 __ Drop(4); 2018 __ Drop(4);
2015 __ LeaveFrame(); 2019 __ LeaveFrame();
2016 2020
2017 __ jmp(&compute_result, Assembler::kNearJump); 2021 __ jmp(&compute_result, Assembler::kNearJump);
2018 } 2022 }
2019 2023
2020 } // namespace dart 2024 } // namespace dart
2021 2025
2022 #endif // defined TARGET_ARCH_X64 2026 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698