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