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

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

Issue 10447064: In generated code for ia32 don't load object's class directly from class_ field. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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
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/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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 // Total number of args is the first Smi in args descriptor array (EDX). 288 // Total number of args is the first Smi in args descriptor array (EDX).
289 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 289 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
290 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // Get receiver. EAX is a Smi. 290 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // Get receiver. EAX is a Smi.
291 // TODO(srdjan): Remove the special casing below for null receiver, once 291 // TODO(srdjan): Remove the special casing below for null receiver, once
292 // NullClass is implemented. 292 // NullClass is implemented.
293 __ cmpl(EAX, raw_null); 293 __ cmpl(EAX, raw_null);
294 // Use Object class if receiver is null. 294 // Use Object class if receiver is null.
295 __ j(EQUAL, &null_receiver, Assembler::kNearJump); 295 __ j(EQUAL, &null_receiver, Assembler::kNearJump);
296 __ testl(EAX, Immediate(kSmiTagMask)); 296 __ testl(EAX, Immediate(kSmiTagMask));
297 __ j(ZERO, &smi_receiver, Assembler::kNearJump); 297 __ j(ZERO, &smi_receiver, Assembler::kNearJump);
298 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); 298 __ LoadClassOfObject(EAX, EAX, EDI);
299 __ jmp(&class_in_eax, Assembler::kNearJump); 299 __ jmp(&class_in_eax, Assembler::kNearJump);
300 __ Bind(&smi_receiver); 300 __ Bind(&smi_receiver);
301 // For Smis we need to get the class from the isolate. 301 // For Smis we need to get the class from the isolate.
302 // Load current Isolate pointer from Context structure into EAX. 302 // Load current Isolate pointer from Context structure into EAX.
303 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); 303 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset()));
304 __ movl(EAX, Address(EAX, Isolate::object_store_offset())); 304 __ movl(EAX, Address(EAX, Isolate::object_store_offset()));
305 __ movl(EAX, Address(EAX, ObjectStore::smi_class_offset())); 305 __ movl(EAX, Address(EAX, ObjectStore::smi_class_offset()));
306 __ jmp(&class_in_eax, Assembler::kNearJump); 306 __ jmp(&class_in_eax, Assembler::kNearJump);
307 __ Bind(&null_receiver); 307 __ Bind(&null_receiver);
308 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset())); 308 __ movl(EAX, FieldAddress(CTX, Context::isolate_offset()));
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 765
766 // Verify that EDI is a closure by checking its class. 766 // Verify that EDI is a closure by checking its class.
767 Label not_closure; 767 Label not_closure;
768 __ cmpl(EDI, raw_null); 768 __ cmpl(EDI, raw_null);
769 // Not a closure, but null object. 769 // Not a closure, but null object.
770 __ j(EQUAL, &not_closure, Assembler::kNearJump); 770 __ j(EQUAL, &not_closure, Assembler::kNearJump);
771 __ testl(EDI, Immediate(kSmiTagMask)); 771 __ testl(EDI, Immediate(kSmiTagMask));
772 __ j(ZERO, &not_closure, Assembler::kNearJump); // Not a closure, but a smi. 772 __ j(ZERO, &not_closure, Assembler::kNearJump); // Not a closure, but a smi.
773 // Verify that the class of the object is a closure class by checking that 773 // Verify that the class of the object is a closure class by checking that
774 // class.signature_function() is not null. 774 // class.signature_function() is not null.
775 __ movl(EAX, FieldAddress(EDI, Object::class_offset())); 775 __ LoadClassOfObject(EAX, EDI, ECX);
776 __ movl(EAX, FieldAddress(EAX, Class::signature_function_offset())); 776 __ movl(EAX, FieldAddress(EAX, Class::signature_function_offset()));
777 __ cmpl(EAX, raw_null); 777 __ cmpl(EAX, raw_null);
778 // Actual class is not a closure class. 778 // Actual class is not a closure class.
779 __ j(EQUAL, &not_closure, Assembler::kNearJump); 779 __ j(EQUAL, &not_closure, Assembler::kNearJump);
780 780
781 // EAX is just the signature function. Load the actual closure function. 781 // EAX is just the signature function. Load the actual closure function.
782 __ movl(ECX, FieldAddress(EDI, Closure::function_offset())); 782 __ movl(ECX, FieldAddress(EDI, Closure::function_offset()));
783 783
784 // Load closure context in CTX; note that CTX has already been preserved. 784 // Load closure context in CTX; note that CTX has already been preserved.
785 __ movl(CTX, FieldAddress(EDI, Closure::context_offset())); 785 __ movl(CTX, FieldAddress(EDI, Closure::context_offset()));
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 __ Bind(&not_yet_hot); 1569 __ Bind(&not_yet_hot);
1570 } 1570 }
1571 1571
1572 ASSERT(num_args > 0); 1572 ASSERT(num_args > 0);
1573 // Get receiver (first read number of arguments from argument descriptor array 1573 // Get receiver (first read number of arguments from argument descriptor array
1574 // and then access the receiver from the stack). 1574 // and then access the receiver from the stack).
1575 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 1575 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1576 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. 1576 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi.
1577 1577
1578 Label get_class, ic_miss; 1578 Label get_class, ic_miss;
1579 __ call(&get_class);
1580 // EAX: receiver's class
1581 // ECX: IC data array. 1579 // ECX: IC data array.
1582 1580
1583 #if defined(DEBUG) 1581 #if defined(DEBUG)
1584 { Label ok; 1582 { Label ok;
1585 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. 1583 // Check that the IC data array has NumberOfArgumentsChecked() == num_args.
1586 // 'num_args_tested' is stored as an untagged int. 1584 // 'num_args_tested' is stored as an untagged int.
1587 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); 1585 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset()));
1588 __ cmpl(EBX, Immediate(num_args)); 1586 __ cmpl(EBX, Immediate(num_args));
1589 __ j(EQUAL, &ok, Assembler::kNearJump); 1587 __ j(EQUAL, &ok, Assembler::kNearJump);
1590 __ Stop("Incorrect stub for IC data"); 1588 __ Stop("Incorrect stub for IC data");
1591 __ Bind(&ok); 1589 __ Bind(&ok);
1592 } 1590 }
1593 #endif // DEBUG 1591 #endif // DEBUG
1594 1592
1595 // Loop that checks if there is an IC data match. 1593 // Loop that checks if there is an IC data match.
1596 // EAX: receiver's class. 1594 // EAX: receiver's class.
Ivan Posva 2012/05/30 05:48:09 This comment is out of date.
1597 // ECX: IC data object (preserved). 1595 // ECX: IC data object (preserved).
1598 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); 1596 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
1599 // EBX: ic_data_array with check entries: classes and target functions. 1597 // EBX: ic_data_array with check entries: classes and target functions.
1600 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); 1598 __ leal(EBX, FieldAddress(EBX, Array::data_offset()));
1601 // EBX: points directly to the first ic data array element. 1599 // EBX: points directly to the first ic data array element.
1602 Label loop, found; 1600 Label loop, found;
1603 if (num_args == 1) { 1601 if (num_args == 1) {
1602 __ call(&get_class);
1603 // EAX: receiver's class
1604 __ Bind(&loop); 1604 __ Bind(&loop);
1605 __ movl(EDI, Address(EBX, 0)); // Get class to check. 1605 __ movl(EDI, Address(EBX, 0)); // Get class to check.
1606 __ cmpl(EAX, EDI); // Match? 1606 __ cmpl(EAX, EDI); // Match?
1607 __ j(EQUAL, &found, Assembler::kNearJump); 1607 __ j(EQUAL, &found, Assembler::kNearJump);
1608 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). 1608 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target).
1609 __ cmpl(EDI, raw_null); // Done? 1609 __ cmpl(EDI, raw_null); // Done?
1610 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1610 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1611 } else if (num_args == 2) { 1611 } else if (num_args == 2) {
1612 // EDI: class to check. 1612 // EDI: class to check.
1613 Label no_match; 1613 Label no_match;
1614 __ Bind(&loop); 1614 __ Bind(&loop);
1615 // Get class from IC data to check. 1615 // Get class from IC data to check.
1616 __ movl(EDI, Address(EBX, 0));
1617 // Get receiver using argument descriptor in EDX. 1616 // Get receiver using argument descriptor in EDX.
1618 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 1617 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1619 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. 1618 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi.
1620 __ call(&get_class); 1619 __ call(&get_class);
1620 // TODO(vegorov): switch IC data to store class index insted of class.
Ivan Posva 2012/05/30 05:48:09 instead In general I think resolving this TODO is
1621 __ movl(EDI, Address(EBX, 0));
1621 __ cmpl(EAX, EDI); // Match? 1622 __ cmpl(EAX, EDI); // Match?
1622 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); 1623 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump);
1623 // Check second class/argument. 1624 // Check second class/argument.
1624 // Get class from IC data to check. 1625 // Get class from IC data to check.
1625 __ movl(EDI, Address(EBX, kWordSize));
1626 // Get next argument. 1626 // Get next argument.
1627 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 1627 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
1628 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); 1628 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize));
1629 // EAX (argument count) is Smi. 1629 // EAX (argument count) is Smi.
1630 __ call(&get_class); 1630 __ call(&get_class);
1631 __ movl(EDI, Address(EBX, kWordSize));
1631 __ cmpl(EAX, EDI); // Match? 1632 __ cmpl(EAX, EDI); // Match?
1632 __ j(EQUAL, &found, Assembler::kNearJump); 1633 __ j(EQUAL, &found, Assembler::kNearJump);
1633 __ Bind(&no_match); 1634 __ Bind(&no_match);
1634 // Each test entry has (1 + num_args) array elements. 1635 // Each test entry has (1 + num_args) array elements.
1635 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. 1636 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element.
1636 __ cmpl(EDI, raw_null); // Done? 1637 __ cmpl(EDI, raw_null); // Done?
1637 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); 1638 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1638 } 1639 }
1639 1640
1640 __ Bind(&ic_miss); 1641 __ Bind(&ic_miss);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1689 Label not_smi; 1690 Label not_smi;
1690 // Test if Smi -> load Smi class for comparison. 1691 // Test if Smi -> load Smi class for comparison.
1691 __ testl(EAX, Immediate(kSmiTagMask)); 1692 __ testl(EAX, Immediate(kSmiTagMask));
1692 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump); 1693 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
1693 const Class& smi_class = 1694 const Class& smi_class =
1694 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); 1695 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class());
1695 __ LoadObject(EAX, smi_class); 1696 __ LoadObject(EAX, smi_class);
1696 __ ret(); 1697 __ ret();
1697 1698
1698 __ Bind(&not_smi); 1699 __ Bind(&not_smi);
1699 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); 1700 __ LoadClassOfObject(EAX, EAX, EDI);
1700 __ ret(); 1701 __ ret();
1701 } 1702 }
1702 1703
1703 1704
1704 // Use inline cache data array to invoke the target or continue in inline 1705 // Use inline cache data array to invoke the target or continue in inline
1705 // cache miss handler. Stub for 1-argument check (receiver class). 1706 // cache miss handler. Stub for 1-argument check (receiver class).
1706 // ECX: Inline cache data array 1707 // ECX: Inline cache data array
1707 // EDX: Arguments array 1708 // EDX: Arguments array
1708 // TOS(0): return address 1709 // TOS(0): return address
1709 // Inline cache data array structure: 1710 // Inline cache data array structure:
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 // TOS + 3: SubtypeTestCache. 1796 // TOS + 3: SubtypeTestCache.
1796 // Result in ECX: null -> not found, otherwise result (true or false). 1797 // Result in ECX: null -> not found, otherwise result (true or false).
1797 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1798 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1798 ASSERT((1 <= n) && (n <= 3)); 1799 ASSERT((1 <= n) && (n <= 3));
1799 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; 1800 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize;
1800 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; 1801 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize;
1801 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; 1802 const intptr_t kCacheOffsetInBytes = 3 * kWordSize;
1802 const Immediate raw_null = 1803 const Immediate raw_null =
1803 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1804 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1804 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes)); 1805 __ movl(EAX, Address(ESP, kInstanceOffsetInBytes));
1805 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1806 __ LoadClassOfObject(ECX, EAX, EBX);
1806 // EAX: instance, ECX: instance-class. 1807 // EAX: instance, ECX: instance-class.
1807 // Get instance type arguments 1808 // Get instance type arguments
1808 if (n > 1) { 1809 if (n > 1) {
1809 // Compute instance type arguments into EBX. 1810 // Compute instance type arguments into EBX.
1810 Label has_no_type_arguments; 1811 Label has_no_type_arguments;
1811 __ movl(EBX, raw_null); 1812 __ movl(EBX, raw_null);
1812 __ movl(EDI, FieldAddress(ECX, 1813 __ movl(EDI, FieldAddress(ECX,
1813 Class::type_arguments_instance_field_offset_offset())); 1814 Class::type_arguments_instance_field_offset_offset()));
1814 __ cmpl(EDI, Immediate(Class::kNoTypeArguments)); 1815 __ cmpl(EDI, Immediate(Class::kNoTypeArguments));
1815 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); 1816 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1891 // TOS + 2: instance. 1892 // TOS + 2: instance.
1892 // TOS + 3: cache array. 1893 // TOS + 3: cache array.
1893 // Result in ECX: null -> not found, otherwise result (true or false). 1894 // Result in ECX: null -> not found, otherwise result (true or false).
1894 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { 1895 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) {
1895 GenerateSubtypeNTestCacheStub(assembler, 3); 1896 GenerateSubtypeNTestCacheStub(assembler, 3);
1896 } 1897 }
1897 1898
1898 } // namespace dart 1899 } // namespace dart
1899 1900
1900 #endif // defined TARGET_ARCH_IA32 1901 #endif // defined TARGET_ARCH_IA32
OLDNEW
« runtime/vm/code_generator_ia32.cc ('K') | « runtime/vm/opt_code_generator_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698