| OLD | NEW |
| 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" | |
| 11 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
| 12 #include "vm/pages.h" | 11 #include "vm/pages.h" |
| 13 #include "vm/resolver.h" | 12 #include "vm/resolver.h" |
| 14 #include "vm/scavenger.h" | 13 #include "vm/scavenger.h" |
| 15 #include "vm/stub_code.h" | 14 #include "vm/stub_code.h" |
| 16 | 15 |
| 17 | 16 |
| 18 #define __ assembler-> | 17 #define __ assembler-> |
| 19 | 18 |
| 20 namespace dart { | 19 namespace dart { |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 // Iterate and search for identical name. | 356 // Iterate and search for identical name. |
| 358 __ leal(EBX, FieldAddress(EAX, Array::data_offset())); | 357 __ leal(EBX, FieldAddress(EAX, Array::data_offset())); |
| 359 | 358 |
| 360 // EBX is pointing into content of functions_map_ array. | 359 // EBX is pointing into content of functions_map_ array. |
| 361 __ Bind(&loop); | 360 __ Bind(&loop); |
| 362 __ movl(EDI, Address(EBX, FunctionsCache::kFunctionName * kWordSize)); | 361 __ movl(EDI, Address(EBX, FunctionsCache::kFunctionName * kWordSize)); |
| 363 | 362 |
| 364 __ cmpl(EDI, raw_null); | 363 __ cmpl(EDI, raw_null); |
| 365 __ j(EQUAL, ¬_found, Assembler::kNearJump); | 364 __ j(EQUAL, ¬_found, Assembler::kNearJump); |
| 366 | 365 |
| 367 ASSERT(ICData::kNameIndex == 0); | 366 __ cmpl(EDI, FieldAddress(ECX, ICData::target_name_offset())); |
| 368 __ cmpl(EDI, FieldAddress(ECX, Array::data_offset())); | |
| 369 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 367 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 370 | 368 |
| 371 // Name found, check total argument count and named argument count. | 369 // Name found, check total argument count and named argument count. |
| 372 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 370 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 373 // EAX is total argument count as Smi. | 371 // EAX is total argument count as Smi. |
| 374 __ movl(EDI, Address(EBX, FunctionsCache::kArgCount * kWordSize)); | 372 __ movl(EDI, Address(EBX, FunctionsCache::kArgCount * kWordSize)); |
| 375 __ cmpl(EAX, EDI); // Compare total argument counts. | 373 __ cmpl(EAX, EDI); // Compare total argument counts. |
| 376 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); | 374 __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump); |
| 377 __ subl(EAX, FieldAddress(EDX, Array::data_offset() + kWordSize)); | 375 __ subl(EAX, FieldAddress(EDX, Array::data_offset() + kWordSize)); |
| 378 // EAX is named argument count as Smi. | 376 // EAX is named argument count as Smi. |
| (...skipping 1150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1529 __ popl(EAX); // Get result into EAX. | 1527 __ popl(EAX); // Get result into EAX. |
| 1530 | 1528 |
| 1531 // Remove the stub frame as we are about to return. | 1529 // Remove the stub frame as we are about to return. |
| 1532 __ LeaveFrame(); | 1530 __ LeaveFrame(); |
| 1533 __ ret(); | 1531 __ ret(); |
| 1534 } | 1532 } |
| 1535 | 1533 |
| 1536 | 1534 |
| 1537 | 1535 |
| 1538 // Generate inline cache check for 'num_args'. | 1536 // Generate inline cache check for 'num_args'. |
| 1539 // ECX: Inline cache data array. | 1537 // ECX: Inline cache data object. |
| 1540 // EDX: Arguments array. | 1538 // EDX: Arguments array. |
| 1541 // TOS(0): return address | 1539 // TOS(0): return address |
| 1542 // Control flow: | 1540 // Control flow: |
| 1543 // - If receiver is null -> jump to IC miss. | 1541 // - If receiver is null -> jump to IC miss. |
| 1544 // - If receiver is Smi -> load Smi class. | 1542 // - If receiver is Smi -> load Smi class. |
| 1545 // - If receiver is not-Smi -> load receiver's class. | 1543 // - If receiver is not-Smi -> load receiver's class. |
| 1546 // - Check if 'num_args' (including receiver) match any IC data group. | 1544 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1547 // - Match found -> jump to target. | 1545 // - Match found -> jump to target. |
| 1548 // - Match not found -> jump to IC miss. | 1546 // - Match not found -> jump to IC miss. |
| 1549 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1547 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1550 intptr_t num_args) { | 1548 intptr_t num_args) { |
| 1551 ASSERT(num_args > 0); | 1549 ASSERT(num_args > 0); |
| 1552 // Get receiver. | 1550 // Get receiver. |
| 1553 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1551 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1554 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1552 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. |
| 1555 | 1553 |
| 1556 Label get_class, ic_miss; | 1554 Label get_class, ic_miss; |
| 1557 __ call(&get_class); | 1555 __ call(&get_class); |
| 1558 // EAX: receiver's class | 1556 // EAX: receiver's class |
| 1559 // ECX: IC data array. | 1557 // ECX: IC data array. |
| 1560 | 1558 |
| 1561 #if defined(DEBUG) | 1559 #if defined(DEBUG) |
| 1562 { Label ok; | 1560 { Label ok; |
| 1563 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1561 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1564 __ movl(EBX, FieldAddress(ECX, | 1562 // 'num_args_tested' is stored as an untagged int. |
| 1565 Array::data_offset() + ICData::kNumArgsCheckedIndex * kWordSize)); | 1563 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1566 const Immediate value = | 1564 __ cmpl(EBX, Immediate(num_args)); |
| 1567 Immediate(reinterpret_cast<int32_t>(Smi::New(num_args))); | |
| 1568 __ cmpl(EBX, value); | |
| 1569 __ j(EQUAL, &ok, Assembler::kNearJump); | 1565 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1570 __ Stop("Incorrect stub for IC data"); | 1566 __ Stop("Incorrect stub for IC data"); |
| 1571 __ Bind(&ok); | 1567 __ Bind(&ok); |
| 1572 } | 1568 } |
| 1573 #endif // DEBUG | 1569 #endif // DEBUG |
| 1574 | 1570 |
| 1575 // Loop that checks if there is an IC data match. | 1571 // Loop that checks if there is an IC data match. |
| 1576 // EAX: receiver's class. | 1572 // EAX: receiver's class. |
| 1577 // ECX: IC data array (preserved). | 1573 // ECX: IC data object (preserved). |
| 1578 __ leal(EBX, FieldAddress(ECX, | 1574 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1579 Array::data_offset() + ICData::kChecksStartIndex * kWordSize)); | 1575 // EBX: ic_data_array with check entries: classes and target functions. |
| 1580 // EBX: pointing to a class to check against (into IC data array). | 1576 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1577 // EBX: points directly to the first ic data array element. |
| 1581 const Immediate raw_null = | 1578 const Immediate raw_null = |
| 1582 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1579 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1583 Label loop, found; | 1580 Label loop, found; |
| 1584 if (num_args == 1) { | 1581 if (num_args == 1) { |
| 1585 __ Bind(&loop); | 1582 __ Bind(&loop); |
| 1586 __ movl(EDI, Address(EBX, 0)); // Get class to check. | 1583 __ movl(EDI, Address(EBX, 0)); // Get class to check. |
| 1587 __ cmpl(EAX, EDI); // Match? | 1584 __ cmpl(EAX, EDI); // Match? |
| 1588 __ j(EQUAL, &found, Assembler::kNearJump); | 1585 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1589 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1586 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1590 __ cmpl(EDI, raw_null); // Done? | 1587 __ cmpl(EDI, raw_null); // Done? |
| 1591 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1588 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1592 } else if (num_args == 2) { | 1589 } else if (num_args == 2) { |
| 1590 // EDI: class to check. |
| 1593 Label no_match; | 1591 Label no_match; |
| 1594 __ Bind(&loop); | 1592 __ Bind(&loop); |
| 1595 __ movl(EDI, Address(EBX, 0)); // Get class from IC data to check. | 1593 // Get class from IC data to check. |
| 1596 // Get receiver. | 1594 __ movl(EDI, Address(EBX, 0)); |
| 1595 // Get receiver using argument descriptor in EDX. |
| 1597 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1596 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1598 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1597 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. |
| 1599 __ call(&get_class); | 1598 __ call(&get_class); |
| 1600 __ cmpl(EAX, EDI); // Match? | 1599 __ cmpl(EAX, EDI); // Match? |
| 1601 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1600 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 1602 // Check second. | 1601 // Check second class/argument. |
| 1603 __ movl(EDI, Address(EBX, kWordSize)); // Get class from IC data to check. | 1602 // Get class from IC data to check. |
| 1603 __ movl(EDI, Address(EBX, kWordSize)); |
| 1604 // Get next argument. | 1604 // Get next argument. |
| 1605 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1605 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1606 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); // EAX is Smi. | 1606 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); |
| 1607 // EAX (argument count) is Smi. |
| 1607 __ call(&get_class); | 1608 __ call(&get_class); |
| 1608 __ cmpl(EAX, EDI); // Match? | 1609 __ cmpl(EAX, EDI); // Match? |
| 1609 __ j(EQUAL, &found, Assembler::kNearJump); | 1610 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1610 __ Bind(&no_match); | 1611 __ Bind(&no_match); |
| 1612 // Each test entry has (1 + num_args) array elements. |
| 1611 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1613 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1612 __ cmpl(EDI, raw_null); // Done? | 1614 __ cmpl(EDI, raw_null); // Done? |
| 1613 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1615 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1614 } | 1616 } |
| 1615 | 1617 |
| 1616 __ Bind(&ic_miss); | 1618 __ Bind(&ic_miss); |
| 1617 // Get receiver, again. | 1619 // Get receiver, again. |
| 1618 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1620 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1619 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. | 1621 __ leal(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX is Smi. |
| 1620 __ EnterFrame(0); | 1622 __ EnterFrame(0); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1727 __ popl(EDX); | 1729 __ popl(EDX); |
| 1728 __ popl(ECX); | 1730 __ popl(ECX); |
| 1729 __ LeaveFrame(); | 1731 __ LeaveFrame(); |
| 1730 // Now call the dynamic function. | 1732 // Now call the dynamic function. |
| 1731 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1733 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
| 1732 } | 1734 } |
| 1733 | 1735 |
| 1734 } // namespace dart | 1736 } // namespace dart |
| 1735 | 1737 |
| 1736 #endif // defined TARGET_ARCH_IA32 | 1738 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |