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

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

Issue 10458031: In generated code for x64 don't load object's class directly from class_ field. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: CoreClass in flow_graph_compiler_x64.cc should return RawClass* Created 8 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 | Annotate | Revision Log
« runtime/vm/stub_code_ia32.cc ('K') | « 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/code_generator.h" 10 #include "vm/code_generator.h"
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 // Total number of args is the first Smi in args descriptor array (R10). 287 // Total number of args is the first Smi in args descriptor array (R10).
288 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 288 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
289 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // Get receiver. RAX is a Smi. 289 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // Get receiver. RAX is a Smi.
290 // TODO(srdjan): Remove the special casing below for null receiver, once 290 // TODO(srdjan): Remove the special casing below for null receiver, once
291 // NullClass is implemented. 291 // NullClass is implemented.
292 __ cmpq(RAX, raw_null); 292 __ cmpq(RAX, raw_null);
293 // Use Object class if receiver is null. 293 // Use Object class if receiver is null.
294 __ j(EQUAL, &null_receiver, Assembler::kNearJump); 294 __ j(EQUAL, &null_receiver, Assembler::kNearJump);
295 __ testq(RAX, Immediate(kSmiTagMask)); 295 __ testq(RAX, Immediate(kSmiTagMask));
296 __ j(ZERO, &smi_receiver, Assembler::kNearJump); 296 __ j(ZERO, &smi_receiver, Assembler::kNearJump);
297 __ movq(RAX, FieldAddress(RAX, Object::class_offset())); 297 __ LoadClassOfObject(RAX, RAX);
298 __ jmp(&class_in_rax, Assembler::kNearJump); 298 __ jmp(&class_in_rax, Assembler::kNearJump);
299 __ Bind(&smi_receiver); 299 __ Bind(&smi_receiver);
300 // For Smis we need to get the class from the isolate. 300 // For Smis we need to get the class from the isolate.
301 // Load current Isolate pointer from Context structure into RAX. 301 // Load current Isolate pointer from Context structure into RAX.
302 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); 302 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset()));
303 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); 303 __ movq(RAX, Address(RAX, Isolate::object_store_offset()));
304 __ movq(RAX, Address(RAX, ObjectStore::smi_class_offset())); 304 __ movq(RAX, Address(RAX, ObjectStore::smi_class_offset()));
305 __ jmp(&class_in_rax, Assembler::kNearJump); 305 __ jmp(&class_in_rax, Assembler::kNearJump);
306 __ Bind(&null_receiver); 306 __ Bind(&null_receiver);
307 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); 307 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset()));
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 742
743 // Total number of args is the first Smi in args descriptor array (R10). 743 // Total number of args is the first Smi in args descriptor array (R10).
744 __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args. 744 __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args.
745 // Load closure object in R13. 745 // Load closure object in R13.
746 __ movq(R13, Address(RSP, RAX, TIMES_4, kWordSize)); // RAX is a Smi. 746 __ movq(R13, Address(RSP, RAX, TIMES_4, kWordSize)); // RAX is a Smi.
747 747
748 // Verify that R13 is a closure by checking its class. 748 // Verify that R13 is a closure by checking its class.
749 Label not_closure; 749 Label not_closure;
750 __ cmpq(R13, raw_null); 750 __ cmpq(R13, raw_null);
751 // Not a closure, but null object. 751 // Not a closure, but null object.
752 __ j(EQUAL, &not_closure, Assembler::kNearJump); 752 __ j(EQUAL, &not_closure);
753 __ testq(R13, Immediate(kSmiTagMask)); 753 __ testq(R13, Immediate(kSmiTagMask));
754 __ j(ZERO, &not_closure, Assembler::kNearJump); // Not a closure, but a smi. 754 __ j(ZERO, &not_closure); // Not a closure, but a smi.
755 // Verify that the class of the object is a closure class by checking that 755 // Verify that the class of the object is a closure class by checking that
756 // class.signature_function() is not null. 756 // class.signature_function() is not null.
757 __ movq(RAX, FieldAddress(R13, Object::class_offset())); 757 __ LoadClassOfObject(RAX, R13);
758 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); 758 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset()));
759 __ cmpq(RAX, raw_null); 759 __ cmpq(RAX, raw_null);
760 // Actual class is not a closure class. 760 // Actual class is not a closure class.
761 __ j(EQUAL, &not_closure, Assembler::kNearJump); 761 __ j(EQUAL, &not_closure, Assembler::kNearJump);
762 762
763 // RAX is just the signature function. Load the actual closure function. 763 // RAX is just the signature function. Load the actual closure function.
764 __ movq(RBX, FieldAddress(R13, Closure::function_offset())); 764 __ movq(RBX, FieldAddress(R13, Closure::function_offset()));
765 765
766 // Load closure context in CTX; note that CTX has already been preserved. 766 // Load closure context in CTX; note that CTX has already been preserved.
767 __ movq(CTX, FieldAddress(R13, Closure::context_offset())); 767 __ movq(CTX, FieldAddress(R13, Closure::context_offset()));
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
1547 __ LeaveFrame(); 1547 __ LeaveFrame();
1548 __ Bind(&not_yet_hot); 1548 __ Bind(&not_yet_hot);
1549 } 1549 }
1550 ASSERT(num_args > 0); 1550 ASSERT(num_args > 0);
1551 // Get receiver (first read number of arguments from argument descriptor array 1551 // Get receiver (first read number of arguments from argument descriptor array
1552 // and then access the receiver from the stack). 1552 // and then access the receiver from the stack).
1553 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1553 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
1554 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi. 1554 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX (argument count) is Smi.
1555 1555
1556 Label get_class, ic_miss; 1556 Label get_class, ic_miss;
1557 __ call(&get_class);
1558 // RAX: receiver's class
1559 // RBX: IC data array. 1557 // RBX: 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 // 'num_args_tested' is stored as an untagged int. 1562 // 'num_args_tested' is stored as an untagged int.
1565 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); 1563 __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset()));
1566 __ cmpq(RCX, Immediate(num_args)); 1564 __ cmpq(RCX, Immediate(num_args));
1567 __ j(EQUAL, &ok, Assembler::kNearJump); 1565 __ j(EQUAL, &ok, Assembler::kNearJump);
1568 __ Stop("Incorrect stub for IC data"); 1566 __ Stop("Incorrect stub for IC data");
1569 __ Bind(&ok); 1567 __ Bind(&ok);
1570 } 1568 }
1571 #endif // DEBUG 1569 #endif // DEBUG
1572 1570
1573 // Loop that checks if there is an IC data match. 1571 // Loop that checks if there is an IC data match.
1574 // RAX: receiver's class.
1575 // RBX: IC data object (preserved). 1572 // RBX: IC data object (preserved).
1576 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); 1573 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
1577 // R12: ic_data_array with check entries: classes and target functions. 1574 // R12: ic_data_array with check entries: classes and target functions.
1578 __ leaq(R12, FieldAddress(R12, Array::data_offset())); 1575 __ leaq(R12, FieldAddress(R12, Array::data_offset()));
1579 // R12: points directly to the first ic data array element. 1576 // R12: points directly to the first ic data array element.
1580 const Immediate raw_null = 1577 const Immediate raw_null =
1581 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1578 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1582 Label loop, found; 1579 Label loop, found;
1583 if (num_args == 1) { 1580 if (num_args == 1) {
1581 __ call(&get_class);
1582 // RAX: receiver's class.
1584 __ Bind(&loop); 1583 __ Bind(&loop);
1585 __ movq(R13, Address(R12, 0)); // Get class to check. 1584 __ movq(R13, Address(R12, 0)); // Get class to check.
1586 __ cmpq(RAX, R13); // Match? 1585 __ cmpq(RAX, R13); // Match?
1587 __ j(EQUAL, &found, Assembler::kNearJump); 1586 __ j(EQUAL, &found, Assembler::kNearJump);
1588 __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target). 1587 __ addq(R12, Immediate(kWordSize * 2)); // Next element (class + target).
1589 __ cmpq(R13, raw_null); // Done? 1588 __ cmpq(R13, raw_null); // Done?
1590 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1589 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1591 } else if (num_args == 2) { 1590 } else if (num_args == 2) {
1592 Label no_match; 1591 Label no_match;
1593 __ Bind(&loop); 1592 __ Bind(&loop);
1594 __ movq(R13, Address(R12, 0)); // Get class from IC data to check.
1595 // Get receiver. 1593 // Get receiver.
1596 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1594 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
1597 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi. 1595 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // RAX is Smi.
1598 __ call(&get_class); 1596 __ call(&get_class);
1597 // TODO(vegorov): switch IC data to store class index instead of class.
1598 __ movq(R13, Address(R12, 0)); // Get class from IC data to check.
1599 __ cmpq(RAX, R13); // Match? 1599 __ cmpq(RAX, R13); // Match?
1600 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); 1600 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump);
1601 // Check second. 1601 // Check second.
1602 __ movq(R13, Address(R12, kWordSize)); // Get class from IC data to check.
1603 // Get next argument. 1602 // Get next argument.
1604 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 1603 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
1605 __ movq(RAX, Address(RSP, RAX, TIMES_4, -kWordSize)); // RAX is Smi. 1604 __ movq(RAX, Address(RSP, RAX, TIMES_4, -kWordSize)); // RAX is Smi.
1606 __ call(&get_class); 1605 __ call(&get_class);
1606 __ movq(R13, Address(R12, kWordSize)); // Get class from IC data to check.
1607 __ cmpq(RAX, R13); // Match? 1607 __ cmpq(RAX, R13); // Match?
1608 __ j(EQUAL, &found); 1608 __ j(EQUAL, &found);
1609 __ Bind(&no_match); 1609 __ Bind(&no_match);
1610 __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element. 1610 __ addq(R12, Immediate(kWordSize * (1 + num_args))); // Next element.
1611 __ cmpq(R13, raw_null); // Done? 1611 __ cmpq(R13, raw_null); // Done?
1612 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1612 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1613 } 1613 }
1614 1614
1615 __ Bind(&ic_miss); 1615 __ Bind(&ic_miss);
1616 // Compute address of arguments (first read number of arguments from argument 1616 // Compute address of arguments (first read number of arguments from argument
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 Label not_smi; 1662 Label not_smi;
1663 // Test if Smi -> load Smi class for comparison. 1663 // Test if Smi -> load Smi class for comparison.
1664 __ testq(RAX, Immediate(kSmiTagMask)); 1664 __ testq(RAX, Immediate(kSmiTagMask));
1665 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump); 1665 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
1666 const Class& smi_class = 1666 const Class& smi_class =
1667 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); 1667 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class());
1668 __ LoadObject(RAX, smi_class); 1668 __ LoadObject(RAX, smi_class);
1669 __ ret(); 1669 __ ret();
1670 1670
1671 __ Bind(&not_smi); 1671 __ Bind(&not_smi);
1672 __ movq(RAX, FieldAddress(RAX, Object::class_offset())); 1672 __ LoadClassOfObject(RAX, RAX);
1673 __ ret(); 1673 __ ret();
1674 } 1674 }
1675 1675
1676 1676
1677 // Use inline cache data array to invoke the target or continue in inline 1677 // Use inline cache data array to invoke the target or continue in inline
1678 // cache miss handler. Stub for 1-argument check (receiver class). 1678 // cache miss handler. Stub for 1-argument check (receiver class).
1679 // RCX: Inline cache data array 1679 // RCX: Inline cache data array
1680 // RDX: Arguments array 1680 // RDX: Arguments array
1681 // TOS(0): return address 1681 // TOS(0): return address
1682 // Inline cache data array structure: 1682 // Inline cache data array structure:
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1760 // TOS + 3: SubtypeTestCache. 1760 // TOS + 3: SubtypeTestCache.
1761 // Result in RCX: null -> not found, otherwise result (true or false). 1761 // Result in RCX: null -> not found, otherwise result (true or false).
1762 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1762 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1763 ASSERT((1 <= n) && (n <= 3)); 1763 ASSERT((1 <= n) && (n <= 3));
1764 const Immediate raw_null = 1764 const Immediate raw_null =
1765 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1765 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1766 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; 1766 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize;
1767 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; 1767 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize;
1768 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; 1768 const intptr_t kCacheOffsetInBytes = 3 * kWordSize;
1769 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); 1769 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes));
1770 __ movq(R10, FieldAddress(RAX, Object::class_offset())); 1770 __ LoadClassOfObject(R10, RAX);
1771 // RAX: instance, R10: instance class. 1771 // RAX: instance, R10: instance class.
1772 if (n > 1) { 1772 if (n > 1) {
1773 // Compute instance type arguments into R13. 1773 // Compute instance type arguments into R13.
1774 Label has_no_type_arguments; 1774 Label has_no_type_arguments;
1775 __ movq(R13, raw_null); 1775 __ movq(R13, raw_null);
1776 __ movq(RDI, FieldAddress(R10, 1776 __ movq(RDI, FieldAddress(R10,
1777 Class::type_arguments_instance_field_offset_offset())); 1777 Class::type_arguments_instance_field_offset_offset()));
1778 __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); 1778 __ cmpq(RDI, Immediate(Class::kNoTypeArguments));
1779 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); 1779 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
1780 __ movq(R13, FieldAddress(RAX, RDI, TIMES_1, 0)); 1780 __ movq(R13, FieldAddress(RAX, RDI, TIMES_1, 0));
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 // TOS + 2: instance. 1855 // TOS + 2: instance.
1856 // TOS + 3: cache array. 1856 // TOS + 3: cache array.
1857 // Result in RCX: null -> not found, otherwise result (true or false). 1857 // Result in RCX: null -> not found, otherwise result (true or false).
1858 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { 1858 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) {
1859 GenerateSubtypeNTestCacheStub(assembler, 3); 1859 GenerateSubtypeNTestCacheStub(assembler, 3);
1860 } 1860 }
1861 1861
1862 } // namespace dart 1862 } // namespace dart
1863 1863
1864 #endif // defined TARGET_ARCH_X64 1864 #endif // defined TARGET_ARCH_X64
OLDNEW
« runtime/vm/stub_code_ia32.cc ('K') | « runtime/vm/stub_code_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698