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

Side by Side Diff: runtime/vm/stub_code_ia32.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 | « no previous file | runtime/vm/stub_code_x64.cc » ('j') | runtime/vm/stub_code_x64.cc » ('J')
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_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after
1550 // TOS(0): return address 1550 // TOS(0): return address
1551 // Control flow: 1551 // Control flow:
1552 // - If receiver is null -> jump to IC miss. 1552 // - If receiver is null -> jump to IC miss.
1553 // - If receiver is Smi -> load Smi class. 1553 // - If receiver is Smi -> load Smi class.
1554 // - If receiver is not-Smi -> load receiver's class. 1554 // - If receiver is not-Smi -> load receiver's class.
1555 // - Check if 'num_args' (including receiver) match any IC data group. 1555 // - Check if 'num_args' (including receiver) match any IC data group.
1556 // - Match found -> jump to target. 1556 // - Match found -> jump to target.
1557 // - Match not found -> jump to IC miss. 1557 // - Match not found -> jump to IC miss.
1558 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, 1558 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
1559 intptr_t num_args) { 1559 intptr_t num_args) {
1560 const Immediate raw_null = 1560 ASSERT(num_args > 0);
1561 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1561 #if defined(DEBUG)
1562 { Label ok;
1563 // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
1564 // 'num_args_tested' is stored as an untagged int.
1565 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
1566 __ cmpl(EBX, Immediate(num_args));
1567 __ j(EQUAL, &ok, Assembler::kNearJump);
1568 __ Stop("Incorrect stub for IC data");
1569 __ Bind(&ok);
1570 }
1571 #endif // DEBUG
1562 1572
1563 __ movl(EBX, FieldAddress(ECX, ICData::function_offset())); 1573 __ movl(EBX, FieldAddress(ECX, ICData::function_offset()));
1564 Label is_hot; 1574 Label is_hot;
1565 if (FlowGraphCompiler::CanOptimize()) { 1575 if (FlowGraphCompiler::CanOptimize()) {
1566 ASSERT(FLAG_optimization_counter_threshold > 1); 1576 ASSERT(FLAG_optimization_counter_threshold > 1);
1567 // The usage_counter is always less than FLAG_optimization_counter_threshold 1577 // The usage_counter is always less than FLAG_optimization_counter_threshold
1568 // except when the function gets optimized. 1578 // except when the function gets optimized.
1569 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()), 1579 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()),
1570 Immediate(FLAG_optimization_counter_threshold - 1)); 1580 Immediate(FLAG_optimization_counter_threshold - 1));
1571 // Do not increment to equality with threshold, since a counter greater 1581 // Do not increment to equality with threshold, since a counter greater
1572 // than threshold denotes a function that was already optimized. 1582 // than threshold denotes a function that was already optimized.
1573 // The equality should be reached only at exit of the method 1583 // The equality should be reached only at exit of the method
1574 // (return instruction). 1584 // (return instruction).
1575 __ j(EQUAL, &is_hot, Assembler::kNearJump); 1585 __ j(EQUAL, &is_hot, Assembler::kNearJump);
1576 // As long as VM has no OSR do not optimize in the middle of the function 1586 // As long as VM has no OSR do not optimize in the middle of the function
1577 // but only at exit so that we have collected all type feedback before 1587 // but only at exit so that we have collected all type feedback before
1578 // optimizing. 1588 // optimizing.
1579 } 1589 }
1580 __ incl(FieldAddress(EBX, Function::usage_counter_offset())); 1590 __ incl(FieldAddress(EBX, Function::usage_counter_offset()));
1581 __ Bind(&is_hot); 1591 __ Bind(&is_hot);
1582 1592
1583 ASSERT(num_args > 0);
1584 // Get receiver (first read number of arguments from argument descriptor array
1585 // and then access the receiver from the stack).
1586 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1587 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi.
1588
1589 Label get_class_id_as_smi, ic_miss;
1590 // ECX: IC data array.
1591
1592 #if defined(DEBUG)
1593 { Label ok;
1594 // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
1595 // 'num_args_tested' is stored as an untagged int.
1596 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
1597 __ cmpl(EBX, Immediate(num_args));
1598 __ j(EQUAL, &ok, Assembler::kNearJump);
1599 __ Stop("Incorrect stub for IC data");
1600 __ Bind(&ok);
1601 }
1602 #endif // DEBUG
1603
1604 // Loop that checks if there is an IC data match. 1593 // Loop that checks if there is an IC data match.
1594 Label loop, update, test, found, get_class_id_as_smi;
1605 // ECX: IC data object (preserved). 1595 // ECX: IC data object (preserved).
1606 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); 1596 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
1607 // EBX: ic_data_array with check entries: classes and target functions. 1597 // EBX: ic_data_array with check entries: classes and target functions.
1608 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); 1598 __ leal(EBX, FieldAddress(EBX, Array::data_offset()));
1609 // EBX: points directly to the first ic data array element. 1599 // EBX: points directly to the first ic data array element.
1610 Label loop, found; 1600
1611 if (num_args == 1) { 1601 // Get the receiver's class ID (first read number of arguments from
1612 __ call(&get_class_id_as_smi); 1602 // argument descriptor array and then access the receiver from the stack).
1613 // EAX: receiver's class id Smi. 1603 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1614 __ Bind(&loop); 1604 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is smi.
1615 __ movl(EDI, Address(EBX, 0)); // Get class id (Smi) to check. 1605 __ call(&get_class_id_as_smi);
1616 __ cmpl(EAX, EDI); // Class id match? 1606 // EAX: receiver's class ID (smi).
1617 __ j(EQUAL, &found, Assembler::kNearJump); 1607 __ movl(EDI, Address(EBX, 0)); // First class id (smi) to check.
1618 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). 1608 __ jmp(&test);
1619 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1609
1620 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1610 __ Bind(&loop);
1621 } else { 1611 for (int i = 0; i < num_args; i++) {
1622 Label no_match; 1612 if (i > 0) {
1623 __ Bind(&loop); 1613 // If not the first, load the next argument's class ID.
1624 for (int i = 0; i < num_args; i++) {
1625 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 1614 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1626 __ movl(EAX, Address(ESP, EAX, TIMES_2, - i * kWordSize)); 1615 __ movl(EAX, Address(ESP, EAX, TIMES_2, - i * kWordSize));
1627 __ call(&get_class_id_as_smi); 1616 __ call(&get_class_id_as_smi);
1617 // EAX: next argument class ID (smi).
1628 __ movl(EDI, Address(EBX, i * kWordSize)); 1618 __ movl(EDI, Address(EBX, i * kWordSize));
1629 __ cmpl(EAX, EDI); // Class id match? 1619 // EDI: next class ID to check (smi).
1630 if (i < (num_args - 1)) {
1631 __ j(NOT_EQUAL, &no_match);
1632 } else {
1633 // Last check, all checks before matched.
1634 __ j(EQUAL, &found, Assembler::kNearJump);
1635 }
1636 } 1620 }
1637 __ Bind(&no_match); 1621 __ cmpl(EAX, EDI); // Class id match?
1638 // Each test entry has (1 + num_args) array elements. 1622 if (i < (num_args - 1)) {
1639 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. 1623 __ j(NOT_EQUAL, &update); // Continue.
1640 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? 1624 } else {
1641 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1625 // Last check, all checks before matched.
1626 __ j(EQUAL, &found, Assembler::kNearJump); // Break.
1627 }
1642 } 1628 }
1629 __ Bind(&update);
1630 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1631 if (num_args > 1) {
1632 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1633 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0));
1634 __ call(&get_class_id_as_smi);
1635 }
1636 // Each test entry has (1 + num_args) array elements.
1637 const intptr_t entry_size = (num_args + 1) * kWordSize;
1638 __ addl(EBX, Immediate(entry_size)); // Next entry.
1639 __ movl(EDI, Address(EBX, 0)); // Next class ID.
1643 1640
1644 __ Bind(&ic_miss); 1641 __ Bind(&test);
1645 // Compute address of arguments (first read number of arguments from argument 1642 __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done?
1646 // descriptor array and then compute address on the stack). 1643 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1644
1645 // IC miss.
1646 const Immediate raw_null =
1647 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1648 // Compute address of arguments (first read number of arguments from
1649 // argument descriptor array and then compute address on the stack).
1647 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 1650 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1648 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. 1651 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi.
1649 // Create a stub frame as we are pushing some objects on the stack before 1652 // Create a stub frame as we are pushing some objects on the stack before
1650 // calling into the runtime. 1653 // calling into the runtime.
1651 AssemblerMacros::EnterStubFrame(assembler); 1654 AssemblerMacros::EnterStubFrame(assembler);
1652 __ pushl(EDX); // Preserve arguments array. 1655 __ pushl(EDX); // Preserve arguments array.
1653 __ pushl(ECX); // Preserve IC data array 1656 __ pushl(ECX); // Preserve IC data array
1654 __ pushl(raw_null); // Setup space on stack for result (target code object). 1657 __ pushl(raw_null); // Setup space on stack for result (target code object).
1655 // Push call arguments. 1658 // Push call arguments.
1656 for (intptr_t i = 0; i < num_args; i++) { 1659 for (intptr_t i = 0; i < num_args; i++) {
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
2050 __ Drop(4); 2053 __ Drop(4);
2051 __ LeaveFrame(); 2054 __ LeaveFrame();
2052 2055
2053 __ jmp(&compute_result, Assembler::kNearJump); 2056 __ jmp(&compute_result, Assembler::kNearJump);
2054 } 2057 }
2055 2058
2056 2059
2057 } // namespace dart 2060 } // namespace dart
2058 2061
2059 #endif // defined TARGET_ARCH_IA32 2062 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/stub_code_x64.cc » ('j') | runtime/vm/stub_code_x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698