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

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

Issue 2893553002: More compact string representation on 64 bit. (Closed)
Patch Set: Slava feedback Created 3 years, 7 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
« no previous file with comments | « runtime/vm/intrinsifier_mips.cc ('k') | runtime/vm/object.h » ('j') | 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) 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
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
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
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
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, &not_zero_length);
2003 __ addq(RDI, Immediate(1));
2004 __ Bind(&not_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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_mips.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698