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

Side by Side Diff: vm/stub_code_ia32.cc

Issue 8827015: Implement two-argument check inline cache. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: '' Created 9 years 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 | « vm/stub_code_arm.cc ('k') | vm/stub_code_x64.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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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/code_generator.h" 8 #include "vm/code_generator.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/ic_data.h" 10 #include "vm/ic_data.h"
(...skipping 1446 matching lines...) Expand 10 before | Expand all | Expand 10 after
1457 __ popl(EAX); 1457 __ popl(EAX);
1458 __ popl(EAX); 1458 __ popl(EAX);
1459 __ popl(EAX); // Get result into EAX. 1459 __ popl(EAX); // Get result into EAX.
1460 1460
1461 // Remove the stub frame as we are about to return. 1461 // Remove the stub frame as we are about to return.
1462 __ LeaveFrame(); 1462 __ LeaveFrame();
1463 __ ret(); 1463 __ ret();
1464 } 1464 }
1465 1465
1466 1466
1467 // Use inline cache data array to invoke the target or continue in inline 1467
1468 // cache miss handler. Stub for 1-argument check (receiver class). 1468 // Generate inline cache check for 'num_args'.
1469 // ECX: Inline cache data array 1469 // ECX: Inline cache data array.
1470 // EDX: Arguments array 1470 // EDX: Arguments array.
1471 // TOS(0): return address 1471 // TOS(0): return address
1472 void StubCode::GenerateInlineCacheStub(Assembler* assembler) { 1472 // Control flow:
1473 Label ic_miss, is_smi, test_class; 1473 // - If receiver is null -> jump to IC miss.
1474 // - If receiver is Smi -> load Smi class.
1475 // - If receiver is not-Smi -> load receiver's class.
1476 // - Check if 'num_args' (including receiver) match any IC data group.
1477 // - Match found -> jump to target.
1478 // - Match not found -> jump to IC miss.
1479 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler,
1480 intptr_t num_args) {
1481 ASSERT(num_args > 0);
1474 // Get receiver. 1482 // Get receiver.
1475 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 1483 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1476 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); 1484 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0));
1477 1485
1478 __ CompareObject(EAX, Instance::ZoneHandle(Instance::null())); 1486 Label get_class, ic_miss;
1479 __ j(EQUAL, &ic_miss, Assembler::kNearJump); // Null receiver -> IC miss. 1487 __ call(&get_class);
1480
1481 // Test if Smi -> load Smi class for comparison.
1482 __ testl(EAX, Immediate(kSmiTagMask));
1483 __ j(ZERO, &is_smi, Assembler::kNearJump);
1484 __ movl(EAX, FieldAddress(EAX, Object::class_offset()));
1485 __ jmp(&test_class);
1486 __ Bind(&is_smi);
1487 const Class& smi_class =
1488 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class());
1489 __ LoadObject(EAX, smi_class);
1490
1491 __ Bind(&test_class);
1492 // EAX: receiver's class 1488 // EAX: receiver's class
1493 // ECX: IC data array. 1489 // ECX: IC data array.
1494 1490
1495 #if defined(DEBUG) 1491 #if defined(DEBUG)
1496 { Label ok; 1492 { Label ok;
1497 // Check that the IC data array has NumberOfArgumentsChecked() == 1. 1493 // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
1498 __ movl(EBX, FieldAddress(ECX, 1494 __ movl(EBX, FieldAddress(ECX,
1499 Array::data_offset() + ICData::kNumArgsCheckedIndex * kWordSize)); 1495 Array::data_offset() + ICData::kNumArgsCheckedIndex * kWordSize));
1500 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1))); 1496 const Immediate value =
1497 Immediate(reinterpret_cast<int32_t>(Smi::New(num_args)));
1501 __ cmpl(EBX, value); 1498 __ cmpl(EBX, value);
1502 __ j(EQUAL, &ok, Assembler::kNearJump); 1499 __ j(EQUAL, &ok, Assembler::kNearJump);
1503 __ Stop("Incorrect stub for IC data"); 1500 __ Stop("Incorrect stub for IC data");
1504 __ Bind(&ok); 1501 __ Bind(&ok);
1505 } 1502 }
1506 #endif // DEBUG 1503 #endif // DEBUG
1507 1504
1505 // Loop that checks if there is an IC data match.
1506 // EAX: receiver's class.
1507 // ECX: IC data array (preserved).
1508 __ leal(EBX, FieldAddress(ECX,
1509 Array::data_offset() + ICData::kChecksStartIndex * kWordSize));
1510 // EBX: pointing to a class to check against (into IC data array).
1508 const Immediate raw_null = 1511 const Immediate raw_null =
1509 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1512 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1510 __ leal(EBX, FieldAddress(ECX, 1513 Label loop, found;
1511 Array::data_offset() + ICData::kChecksStartIndex * kWordSize)); 1514 if (num_args == 1) {
1512 Label loop, found, call_target_function; 1515 __ Bind(&loop);
1513 __ Bind(&loop); 1516 __ movl(EDI, Address(EBX, 0)); // Get class to check.
1514 __ movl(EDI, Address(EBX, 0)); // Get class to check. 1517 __ cmpl(EAX, EDI); // Match?
1515 __ cmpl(EAX, EDI); // Match? 1518 __ j(EQUAL, &found, Assembler::kNearJump);
1516 __ j(EQUAL, &found, Assembler::kNearJump); 1519 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target).
1517 __ addl(EBX, Immediate(kWordSize * 2)); // next element (class + target). 1520 __ cmpl(EDI, raw_null); // Done?
1518 __ cmpl(EDI, raw_null); // Done? 1521 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1519 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1522 } else if (num_args == 2) {
1523 Label no_match;
1524 __ Bind(&loop);
1525 __ movl(EDI, Address(EBX, 0)); // Get class from IC data to check.
1526 // Get receiver.
1527 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1528 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0));
1529 __ call(&get_class);
1530 __ cmpl(EAX, EDI); // Match?
1531 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump);
1532 // Check second.
1533 __ movl(EDI, Address(EBX, kWordSize)); // Get class from IC data to check.
1534 // Get next argument.
1535 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1536 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize));
1537 __ call(&get_class);
1538 __ cmpl(EAX, EDI); // Match?
1539 __ j(EQUAL, &found, Assembler::kNearJump);
1540 __ Bind(&no_match);
1541 __ addl(EBX, Immediate(kWordSize * 1 + (num_args))); // Next element.
1542 __ cmpl(EDI, raw_null); // Done?
1543 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1544 }
1520 1545
1521 __ Bind(&ic_miss); 1546 __ Bind(&ic_miss);
1522 1547 // Get receiver, again.
1523 // Get receiver.
1524 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 1548 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1525 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); 1549 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0));
1526 __ EnterFrame(0); 1550 __ EnterFrame(0);
1527 // Setup space for return value on stack by pushing smi 0. 1551 // Setup space for return value on stack by pushing smi 0.
1528 __ pushl(EDX); // Preserve arguments array. 1552 __ pushl(EDX); // Preserve arguments array.
1529 __ pushl(ECX); // Preserve IC data array 1553 __ pushl(ECX); // Preserve IC data array
1530 __ pushl(Immediate(0)); 1554 __ pushl(Immediate(0)); // Space for result (target code object).
1531 __ pushl(EAX); // Push receiver. 1555 __ movl(EDX, FieldAddress(EDX, Array::data_offset()));
1532 __ CallRuntimeFromStub(kInlineCacheMissHandlerRuntimeEntry); 1556 // Push call arguments.
1533 __ popl(EAX); // Remove receiver pushed earlier. 1557 for (intptr_t i = 0; i < num_args; i++) {
1534 __ popl(EAX); // Pop returned code object into EAX. 1558 __ movl(EDX, Address(EAX, -kWordSize * i));
1559 __ pushl(EDX);
1560 }
1561 if (num_args == 1) {
1562 __ CallRuntimeFromStub(kInlineCacheMissHandlerOneArgRuntimeEntry);
1563 } else if (num_args == 2) {
1564 __ CallRuntimeFromStub(kInlineCacheMissHandlerTwoArgsRuntimeEntry);
1565 } else {
1566 UNIMPLEMENTED();
1567 }
1568 // Remove call arguments pushed earlier.
1569 for (intptr_t i = 0; i < num_args; i++) {
1570 __ popl(EAX);
1571 }
1572 __ popl(EAX); // Pop returned code object into EAX (null if not found).
1535 __ popl(ECX); // Restore IC data array. 1573 __ popl(ECX); // Restore IC data array.
1536 __ popl(EDX); // Restore arguments array. 1574 __ popl(EDX); // Restore arguments array.
1537 __ LeaveFrame(); 1575 __ LeaveFrame();
1576 Label call_target_function;
1538 __ cmpl(EAX, raw_null); 1577 __ cmpl(EAX, raw_null);
1539 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump); 1578 __ j(NOT_EQUAL, &call_target_function, Assembler::kNearJump);
1540 // NoSuchMethod or closure. 1579 // NoSuchMethod or closure.
1541 __ jmp(&StubCode::MegamorphicLookupLabel()); 1580 __ jmp(&StubCode::MegamorphicLookupLabel());
1542 1581
1543 __ Bind(&found); 1582 __ Bind(&found);
1544 __ movl(EAX, Address(EBX, kWordSize)); // Target function. 1583 // EBX: Pointer to an IC data check group (classes + target)
1584 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function.
1545 1585
1546 __ Bind(&call_target_function); 1586 __ Bind(&call_target_function);
1547 // EAX: Target function. 1587 // EAX: Target function.
1548 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); 1588 __ movl(EAX, FieldAddress(EAX, Function::code_offset()));
1549 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); 1589 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset()));
1550 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); 1590 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
1551 __ jmp(EAX); 1591 __ jmp(EAX);
1592
1593 __ Bind(&get_class);
1594 Label not_smi;
1595 // Test if Smi -> load Smi class for comparison.
1596 __ testl(EAX, Immediate(kSmiTagMask));
1597 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
1598 const Class& smi_class =
1599 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class());
1600 __ LoadObject(EAX, smi_class);
1601 __ ret();
1602
1603 __ Bind(&not_smi);
1604 __ movl(EAX, FieldAddress(EAX, Object::class_offset()));
1605 __ ret();
1552 } 1606 }
1553 1607
1554 1608
1609 // Use inline cache data array to invoke the target or continue in inline
1610 // cache miss handler. Stub for 1-argument check (receiver class).
1611 // ECX: Inline cache data array
1612 // EDX: Arguments array
1613 // TOS(0): return address
1614 // Inline cache data array structure:
1615 // 0: function-name
1616 // 1: N, number of arguments checked.
1617 // 2 .. (length - 1): group of checks, each check containing:
1618 // - N classes.
1619 // - 1 target function.
1620 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1621 return GenerateNArgsCheckInlineCacheStub(assembler, 1);
1622 }
1623
1624
1625 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1626 return GenerateNArgsCheckInlineCacheStub(assembler, 2);
1627 }
1628
1555 // ECX: Function object. 1629 // ECX: Function object.
1556 // EDX: Arguments array. 1630 // EDX: Arguments array.
1557 // TOS(0): return address (Dart code). 1631 // TOS(0): return address (Dart code).
1558 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { 1632 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
1559 __ EnterFrame(0); 1633 __ EnterFrame(0);
1560 __ pushl(EDX); 1634 __ pushl(EDX);
1561 __ pushl(ECX); 1635 __ pushl(ECX);
1562 __ CallRuntimeFromStub(kBreakpointStaticHandlerRuntimeEntry); 1636 __ CallRuntimeFromStub(kBreakpointStaticHandlerRuntimeEntry);
1563 __ popl(ECX); 1637 __ popl(ECX);
1564 __ popl(EDX); 1638 __ popl(EDX);
(...skipping 13 matching lines...) Expand all
1578 // TOS(0): return address (Dart code). 1652 // TOS(0): return address (Dart code).
1579 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { 1653 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
1580 __ EnterFrame(0); 1654 __ EnterFrame(0);
1581 __ pushl(ECX); 1655 __ pushl(ECX);
1582 __ pushl(EDX); 1656 __ pushl(EDX);
1583 __ CallRuntimeFromStub(kBreakpointDynamicHandlerRuntimeEntry); 1657 __ CallRuntimeFromStub(kBreakpointDynamicHandlerRuntimeEntry);
1584 __ popl(EDX); 1658 __ popl(EDX);
1585 __ popl(ECX); 1659 __ popl(ECX);
1586 __ LeaveFrame(); 1660 __ LeaveFrame();
1587 // Now call the dynamic function. 1661 // Now call the dynamic function.
1588 __ jmp(&StubCode::InlineCacheLabel()); 1662 __ jmp(&StubCode::OneArgCheckInlineCacheLabel());
1589 } 1663 }
1590 1664
1591 } // namespace dart 1665 } // namespace dart
1592 1666
1593 #endif // defined TARGET_ARCH_IA32 1667 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « vm/stub_code_arm.cc ('k') | vm/stub_code_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698