OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
9 | 9 |
10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 /* RDI: untagged array length. */ \ | 163 /* RDI: untagged array length. */ \ |
164 __ cmpq(RDI, Immediate(max_len)); \ | 164 __ cmpq(RDI, Immediate(max_len)); \ |
165 __ j(GREATER, &fall_through); \ | 165 __ j(GREATER, &fall_through); \ |
166 /* Special case for scaling by 16. */ \ | 166 /* Special case for scaling by 16. */ \ |
167 if (scale_factor == TIMES_16) { \ | 167 if (scale_factor == TIMES_16) { \ |
168 /* double length of array. */ \ | 168 /* double length of array. */ \ |
169 __ addq(RDI, RDI); \ | 169 __ addq(RDI, RDI); \ |
170 /* only scale by 8. */ \ | 170 /* only scale by 8. */ \ |
171 scale_factor = TIMES_8; \ | 171 scale_factor = TIMES_8; \ |
172 } \ | 172 } \ |
173 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ | 173 const intptr_t fixed_size_plus_alignment_padding = \ |
174 __ leaq(RDI, Address(RDI, scale_factor, fixed_size)); \ | 174 sizeof(Raw##type_name) + kObjectAlignment - 1; \ |
| 175 __ leaq(RDI, Address(RDI, scale_factor, fixed_size_plus_alignment_padding)); \ |
175 __ andq(RDI, Immediate(-kObjectAlignment)); \ | 176 __ andq(RDI, Immediate(-kObjectAlignment)); \ |
176 Heap::Space space = Heap::kNew; \ | 177 Heap::Space space = Heap::kNew; \ |
177 __ movq(R13, Address(THR, Thread::heap_offset())); \ | 178 __ movq(R13, Address(THR, Thread::heap_offset())); \ |
178 __ movq(RAX, Address(R13, Heap::TopOffset(space))); \ | 179 __ movq(RAX, Address(R13, Heap::TopOffset(space))); \ |
179 __ movq(RCX, RAX); \ | 180 __ movq(RCX, RAX); \ |
180 \ | 181 \ |
181 /* RDI: allocation size. */ \ | 182 /* RDI: allocation size. */ \ |
182 __ addq(RCX, RDI); \ | 183 __ addq(RCX, RDI); \ |
183 __ j(CARRY, &fall_through); \ | 184 __ j(CARRY, &fall_through); \ |
184 \ | 185 \ |
(...skipping 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1735 __ LoadObject(RAX, Bool::False()); | 1736 __ LoadObject(RAX, Bool::False()); |
1736 __ ret(); | 1737 __ ret(); |
1737 | 1738 |
1738 __ Bind(&fall_through); | 1739 __ Bind(&fall_through); |
1739 } | 1740 } |
1740 | 1741 |
1741 | 1742 |
1742 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1743 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
1743 Label fall_through; | 1744 Label fall_through; |
1744 __ movq(RAX, Address(RSP, +1 * kWordSize)); // String object. | 1745 __ movq(RAX, Address(RSP, +1 * kWordSize)); // String object. |
1745 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); | 1746 __ movl(RAX, FieldAddress(RAX, String::hash_offset())); |
1746 __ cmpq(RAX, Immediate(0)); | 1747 ASSERT(kSmiTag == 0); |
1747 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1748 ASSERT(kSmiTagShift == 1); |
| 1749 __ addq(RAX, RAX); // Smi tag RAX, setting Z flag. |
| 1750 __ j(ZERO, &fall_through, Assembler::kNearJump); |
1748 __ ret(); | 1751 __ ret(); |
1749 __ Bind(&fall_through); | 1752 __ Bind(&fall_through); |
1750 // Hash not yet computed. | 1753 // Hash not yet computed. |
1751 } | 1754 } |
1752 | 1755 |
1753 | 1756 |
1754 void GenerateSubstringMatchesSpecialization(Assembler* assembler, | 1757 void GenerateSubstringMatchesSpecialization(Assembler* assembler, |
1755 intptr_t receiver_cid, | 1758 intptr_t receiver_cid, |
1756 intptr_t other_cid, | 1759 intptr_t other_cid, |
1757 Label* return_true, | 1760 Label* return_true, |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1904 __ ret(); | 1907 __ ret(); |
1905 __ Bind(&is_true); | 1908 __ Bind(&is_true); |
1906 __ LoadObject(RAX, Bool::True()); | 1909 __ LoadObject(RAX, Bool::True()); |
1907 __ ret(); | 1910 __ ret(); |
1908 } | 1911 } |
1909 | 1912 |
1910 | 1913 |
1911 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { | 1914 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { |
1912 Label compute_hash; | 1915 Label compute_hash; |
1913 __ movq(RBX, Address(RSP, +1 * kWordSize)); // OneByteString object. | 1916 __ movq(RBX, Address(RSP, +1 * kWordSize)); // OneByteString object. |
1914 __ movq(RAX, FieldAddress(RBX, String::hash_offset())); | 1917 __ movl(RAX, FieldAddress(RBX, String::hash_offset())); |
1915 __ cmpq(RAX, Immediate(0)); | 1918 __ cmpq(RAX, Immediate(0)); |
1916 __ j(EQUAL, &compute_hash, Assembler::kNearJump); | 1919 __ j(EQUAL, &compute_hash, Assembler::kNearJump); |
| 1920 __ SmiTag(RAX); |
1917 __ ret(); | 1921 __ ret(); |
1918 | 1922 |
1919 __ Bind(&compute_hash); | 1923 __ Bind(&compute_hash); |
1920 // Hash not yet computed, use algorithm of class StringHasher. | 1924 // Hash not yet computed, use algorithm of class StringHasher. |
1921 __ movq(RCX, FieldAddress(RBX, String::length_offset())); | 1925 __ movq(RCX, FieldAddress(RBX, String::length_offset())); |
1922 __ SmiUntag(RCX); | 1926 __ SmiUntag(RCX); |
1923 __ xorq(RAX, RAX); | 1927 __ xorq(RAX, RAX); |
1924 __ xorq(RDI, RDI); | 1928 __ xorq(RDI, RDI); |
1925 // RBX: Instance of OneByteString. | 1929 // RBX: Instance of OneByteString. |
1926 // RCX: String length, untagged integer. | 1930 // RCX: String length, untagged integer. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1964 __ addl(RAX, RDX); | 1968 __ addl(RAX, RDX); |
1965 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); | 1969 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); |
1966 __ andl(RAX, | 1970 __ andl(RAX, |
1967 Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1))); | 1971 Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1))); |
1968 | 1972 |
1969 // return hash_ == 0 ? 1 : hash_; | 1973 // return hash_ == 0 ? 1 : hash_; |
1970 __ cmpq(RAX, Immediate(0)); | 1974 __ cmpq(RAX, Immediate(0)); |
1971 __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump); | 1975 __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump); |
1972 __ incq(RAX); | 1976 __ incq(RAX); |
1973 __ Bind(&set_hash_code); | 1977 __ Bind(&set_hash_code); |
| 1978 __ movl(FieldAddress(RBX, String::hash_offset()), RAX); |
1974 __ SmiTag(RAX); | 1979 __ SmiTag(RAX); |
1975 __ StoreIntoSmiField(FieldAddress(RBX, String::hash_offset()), RAX); | |
1976 __ ret(); | 1980 __ ret(); |
1977 } | 1981 } |
1978 | 1982 |
1979 | 1983 |
1980 // Allocates one-byte string of length 'end - start'. The content is not | 1984 // Allocates one-byte string of length 'end - start'. The content is not |
1981 // initialized. 'length-reg' contains tagged length. | 1985 // initialized. 'length-reg' contains tagged length. |
1982 // Returns new string as tagged pointer in RAX. | 1986 // Returns new string as tagged pointer in RAX. |
1983 static void TryAllocateOnebyteString(Assembler* assembler, | 1987 static void TryAllocateOnebyteString(Assembler* assembler, |
1984 Label* ok, | 1988 Label* ok, |
1985 Label* failure, | 1989 Label* failure, |
1986 Register length_reg) { | 1990 Register length_reg) { |
1987 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, failure, false)); | 1991 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, failure, false)); |
1988 if (length_reg != RDI) { | 1992 if (length_reg != RDI) { |
1989 __ movq(RDI, length_reg); | 1993 __ movq(RDI, length_reg); |
1990 } | 1994 } |
1991 Label pop_and_fail; | 1995 Label pop_and_fail, not_zero_length; |
1992 __ pushq(RDI); // Preserve length. | 1996 __ pushq(RDI); // Preserve length. |
1993 __ SmiUntag(RDI); | 1997 __ sarq(RDI, Immediate(kSmiTagShift)); // Untag length. |
1994 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; | 1998 // If the length is 0 then we have to make the allocated size a bit bigger, |
1995 __ leaq(RDI, Address(RDI, TIMES_1, fixed_size)); // RDI is a Smi. | 1999 // otherwise the string takes up less space than an ExternalOneByteString, |
| 2000 // and cannot be externalized. TODO(erikcorry): We should probably just |
| 2001 // return a static zero length string here instead. |
| 2002 __ j(NOT_ZERO, ¬_zero_length); |
| 2003 __ addq(RDI, Immediate(1)); |
| 2004 __ Bind(¬_zero_length); |
| 2005 const intptr_t fixed_size_plus_alignment_padding = |
| 2006 sizeof(RawString) + kObjectAlignment - 1; |
| 2007 __ addq(RDI, Immediate(fixed_size_plus_alignment_padding)); |
1996 __ andq(RDI, Immediate(-kObjectAlignment)); | 2008 __ andq(RDI, Immediate(-kObjectAlignment)); |
1997 | 2009 |
1998 const intptr_t cid = kOneByteStringCid; | 2010 const intptr_t cid = kOneByteStringCid; |
1999 Heap::Space space = Heap::kNew; | 2011 Heap::Space space = Heap::kNew; |
2000 __ movq(R13, Address(THR, Thread::heap_offset())); | 2012 __ movq(R13, Address(THR, Thread::heap_offset())); |
2001 __ movq(RAX, Address(R13, Heap::TopOffset(space))); | 2013 __ movq(RAX, Address(R13, Heap::TopOffset(space))); |
2002 | 2014 |
2003 // RDI: allocation size. | 2015 // RDI: allocation size. |
2004 __ movq(RCX, RAX); | 2016 __ movq(RCX, RAX); |
2005 __ addq(RCX, RDI); | 2017 __ addq(RCX, RDI); |
(...skipping 21 matching lines...) Expand all Loading... |
2027 __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 2039 __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
2028 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 2040 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
2029 __ shlq(RDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); | 2041 __ shlq(RDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); |
2030 __ jmp(&done, Assembler::kNearJump); | 2042 __ jmp(&done, Assembler::kNearJump); |
2031 | 2043 |
2032 __ Bind(&size_tag_overflow); | 2044 __ Bind(&size_tag_overflow); |
2033 __ xorq(RDI, RDI); | 2045 __ xorq(RDI, RDI); |
2034 __ Bind(&done); | 2046 __ Bind(&done); |
2035 | 2047 |
2036 // Get the class index and insert it into the tags. | 2048 // Get the class index and insert it into the tags. |
| 2049 // This also clears the hash, which is in the high bits of the tags. |
2037 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cid))); | 2050 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cid))); |
2038 __ movq(FieldAddress(RAX, String::tags_offset()), RDI); // Tags. | 2051 __ movq(FieldAddress(RAX, String::tags_offset()), RDI); // Tags. |
2039 } | 2052 } |
2040 | 2053 |
2041 // Set the length field. | 2054 // Set the length field. |
2042 __ popq(RDI); | 2055 __ popq(RDI); |
2043 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, String::length_offset()), | 2056 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, String::length_offset()), |
2044 RDI); | 2057 RDI); |
2045 // Clear hash. | |
2046 __ ZeroInitSmiField(FieldAddress(RAX, String::hash_offset())); | |
2047 __ jmp(ok, Assembler::kNearJump); | 2058 __ jmp(ok, Assembler::kNearJump); |
2048 | 2059 |
2049 __ Bind(&pop_and_fail); | 2060 __ Bind(&pop_and_fail); |
2050 __ popq(RDI); | 2061 __ popq(RDI); |
2051 __ jmp(failure); | 2062 __ jmp(failure); |
2052 } | 2063 } |
2053 | 2064 |
2054 | 2065 |
2055 // Arg0: OneByteString (receiver). | 2066 // Arg0: OneByteString (receiver). |
2056 // Arg1: Start index as Smi. | 2067 // Arg1: Start index as Smi. |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2291 __ movq(Address(THR, Thread::async_stack_trace_offset()), RAX); | 2302 __ movq(Address(THR, Thread::async_stack_trace_offset()), RAX); |
2292 __ LoadObject(RAX, Object::null_object()); | 2303 __ LoadObject(RAX, Object::null_object()); |
2293 __ ret(); | 2304 __ ret(); |
2294 } | 2305 } |
2295 | 2306 |
2296 #undef __ | 2307 #undef __ |
2297 | 2308 |
2298 } // namespace dart | 2309 } // namespace dart |
2299 | 2310 |
2300 #endif // defined TARGET_ARCH_X64 | 2311 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |