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

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

Issue 2893553002: More compact string representation on 64 bit. (Closed)
Patch Set: 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 __ tsti(R2, Immediate(kSmiTagMask)); \ 189 __ tsti(R2, Immediate(kSmiTagMask)); \
190 __ b(&fall_through, NE); \ 190 __ b(&fall_through, NE); \
191 __ CompareRegisters(R2, ZR); \ 191 __ CompareRegisters(R2, ZR); \
192 __ b(&fall_through, LT); \ 192 __ b(&fall_through, LT); \
193 __ SmiUntag(R2); \ 193 __ SmiUntag(R2); \
194 /* Check for maximum allowed length. */ \ 194 /* Check for maximum allowed length. */ \
195 /* R2: untagged array length. */ \ 195 /* R2: untagged array length. */ \
196 __ CompareImmediate(R2, max_len); \ 196 __ CompareImmediate(R2, max_len); \
197 __ b(&fall_through, GT); \ 197 __ b(&fall_through, GT); \
198 __ LslImmediate(R2, R2, scale_shift); \ 198 __ LslImmediate(R2, R2, scale_shift); \
199 const intptr_t fixed_size = sizeof(Raw##type_name) + kObjectAlignment - 1; \ 199 const intptr_t fixed_size_plus_alignment_padding = \
200 __ AddImmediate(R2, fixed_size); \ 200 sizeof(Raw##type_name) + kObjectAlignment - 1; \
201 __ AddImmediate(R2, fixed_size_plus_alignment_padding); \
201 __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); \ 202 __ andi(R2, R2, Immediate(~(kObjectAlignment - 1))); \
202 Heap::Space space = Heap::kNew; \ 203 Heap::Space space = Heap::kNew; \
203 __ ldr(R3, Address(THR, Thread::heap_offset())); \ 204 __ ldr(R3, Address(THR, Thread::heap_offset())); \
204 __ ldr(R0, Address(R3, Heap::TopOffset(space))); \ 205 __ ldr(R0, Address(R3, Heap::TopOffset(space))); \
205 \ 206 \
206 /* R2: allocation size. */ \ 207 /* R2: allocation size. */ \
207 __ adds(R1, R0, Operand(R2)); \ 208 __ adds(R1, R0, Operand(R2)); \
208 __ b(&fall_through, CS); /* Fail on unsigned overflow. */ \ 209 __ b(&fall_through, CS); /* Fail on unsigned overflow. */ \
209 \ 210 \
210 /* Check if the allocation fits into the remaining space. */ \ 211 /* Check if the allocation fits into the remaining space. */ \
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after
1815 __ LoadObject(R0, Bool::False()); 1816 __ LoadObject(R0, Bool::False());
1816 __ ret(); 1817 __ ret();
1817 1818
1818 __ Bind(&fall_through); 1819 __ Bind(&fall_through);
1819 } 1820 }
1820 1821
1821 1822
1822 void Intrinsifier::String_getHashCode(Assembler* assembler) { 1823 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1823 Label fall_through; 1824 Label fall_through;
1824 __ ldr(R0, Address(SP, 0 * kWordSize)); 1825 __ ldr(R0, Address(SP, 0 * kWordSize));
1825 __ ldr(R0, FieldAddress(R0, String::hash_offset())); 1826 __ ldr(R0, FieldAddress(R0, String::hash_offset()), kUnsignedWord);
1827 __ SmiTag(R0);
Vyacheslav Egorov (Google) 2017/05/18 06:14:42 if you use something that sets flags for tagging y
erikcorry 2017/05/18 14:28:38 Done.
1826 __ CompareRegisters(R0, ZR); 1828 __ CompareRegisters(R0, ZR);
1827 __ b(&fall_through, EQ); 1829 __ b(&fall_through, EQ);
1828 __ ret(); 1830 __ ret();
1829 // Hash not yet computed. 1831 // Hash not yet computed.
1830 __ Bind(&fall_through); 1832 __ Bind(&fall_through);
1831 } 1833 }
1832 1834
1833 1835
1834 void GenerateSubstringMatchesSpecialization(Assembler* assembler, 1836 void GenerateSubstringMatchesSpecialization(Assembler* assembler,
1835 intptr_t receiver_cid, 1837 intptr_t receiver_cid,
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
1988 __ LoadObject(R0, Bool::True()); 1990 __ LoadObject(R0, Bool::True());
1989 __ LoadObject(TMP, Bool::False()); 1991 __ LoadObject(TMP, Bool::False());
1990 __ csel(R0, TMP, R0, NE); 1992 __ csel(R0, TMP, R0, NE);
1991 __ ret(); 1993 __ ret();
1992 } 1994 }
1993 1995
1994 1996
1995 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { 1997 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
1996 Label compute_hash; 1998 Label compute_hash;
1997 __ ldr(R1, Address(SP, 0 * kWordSize)); // OneByteString object. 1999 __ ldr(R1, Address(SP, 0 * kWordSize)); // OneByteString object.
1998 __ ldr(R0, FieldAddress(R1, String::hash_offset())); 2000 __ ldr(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord);
2001 __ SmiTag(R0);
1999 __ CompareRegisters(R0, ZR); 2002 __ CompareRegisters(R0, ZR);
2000 __ b(&compute_hash, EQ); 2003 __ b(&compute_hash, EQ);
2001 __ ret(); // Return if already computed. 2004 __ ret(); // Return if already computed.
2002 2005
2003 __ Bind(&compute_hash); 2006 __ Bind(&compute_hash);
2004 __ ldr(R2, FieldAddress(R1, String::length_offset())); 2007 __ ldr(R2, FieldAddress(R1, String::length_offset()));
2005 __ SmiUntag(R2); 2008 __ SmiUntag(R2);
2006 2009
2007 Label done; 2010 Label done;
2008 // If the string is empty, set the hash to 1, and return. 2011 // If the string is empty, set the hash to 1, and return.
(...skipping 30 matching lines...) Expand all
2039 // hash_ += hash_ << 15; 2042 // hash_ += hash_ << 15;
2040 __ addw(R0, R0, Operand(R0, LSL, 3)); 2043 __ addw(R0, R0, Operand(R0, LSL, 3));
2041 __ eorw(R0, R0, Operand(R0, LSR, 11)); 2044 __ eorw(R0, R0, Operand(R0, LSR, 11));
2042 __ addw(R0, R0, Operand(R0, LSL, 15)); 2045 __ addw(R0, R0, Operand(R0, LSL, 15));
2043 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); 2046 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
2044 __ AndImmediate(R0, R0, (static_cast<intptr_t>(1) << String::kHashBits) - 1); 2047 __ AndImmediate(R0, R0, (static_cast<intptr_t>(1) << String::kHashBits) - 1);
2045 __ CompareRegisters(R0, ZR); 2048 __ CompareRegisters(R0, ZR);
2046 // return hash_ == 0 ? 1 : hash_; 2049 // return hash_ == 0 ? 1 : hash_;
2047 __ Bind(&done); 2050 __ Bind(&done);
2048 __ csinc(R0, R0, ZR, NE); // R0 <- (R0 != 0) ? R0 : (ZR + 1). 2051 __ csinc(R0, R0, ZR, NE); // R0 <- (R0 != 0) ? R0 : (ZR + 1).
2052 __ str(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord);
2049 __ SmiTag(R0); 2053 __ SmiTag(R0);
2050 __ str(R0, FieldAddress(R1, String::hash_offset()));
2051 __ ret(); 2054 __ ret();
2052 } 2055 }
2053 2056
2054 2057
2055 // Allocates one-byte string of length 'end - start'. The content is not 2058 // Allocates one-byte string of length 'end - start'. The content is not
2056 // initialized. 2059 // initialized.
2057 // 'length-reg' (R2) contains tagged length. 2060 // 'length-reg' (R2) contains tagged length.
2058 // Returns new string as tagged pointer in R0. 2061 // Returns new string as tagged pointer in R0.
2059 static void TryAllocateOnebyteString(Assembler* assembler, 2062 static void TryAllocateOnebyteString(Assembler* assembler,
2060 Label* ok, 2063 Label* ok,
2061 Label* failure) { 2064 Label* failure) {
2062 const Register length_reg = R2; 2065 const Register length_reg = R2;
2063 Label fail; 2066 Label fail, not_zero_length;
2064 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, R0, failure)); 2067 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, R0, failure));
2065 __ mov(R6, length_reg); // Save the length register. 2068 __ mov(R6, length_reg); // Save the length register.
2066 // TODO(koda): Protect against negative length and overflow here. 2069 // TODO(koda): Protect against negative length and overflow here.
2067 __ SmiUntag(length_reg); 2070 __ adds(length_reg, ZR, Operand(length_reg, ASR, kSmiTagSize)); // Smi untag.
2068 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; 2071 // If the length is 0 then we have to make the allocated size a bit bigger,
2069 __ AddImmediate(length_reg, fixed_size); 2072 // otherwise the string takes up less space than an ExternalOneByteString,
2073 // and cannot be externalized. TODO(erikcorry): We should probably just
2074 // return a static zero length string here instead.
2075 __ b(&not_zero_length, NE);
2076 __ AddImmediate(length_reg, 1);
Vyacheslav Egorov (Google) 2017/05/18 06:14:42 maybe conditional add() here instead of branching?
erikcorry 2017/05/18 14:28:38 Done.
2077 __ Bind(&not_zero_length);
2078 const intptr_t fixed_size_plus_alignment_padding =
2079 sizeof(RawString) + kObjectAlignment - 1;
2080 __ AddImmediate(length_reg, fixed_size_plus_alignment_padding);
2070 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1))); 2081 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1)));
2071 2082
2072 const intptr_t cid = kOneByteStringCid; 2083 const intptr_t cid = kOneByteStringCid;
2073 Heap::Space space = Heap::kNew; 2084 Heap::Space space = Heap::kNew;
2074 __ ldr(R3, Address(THR, Thread::heap_offset())); 2085 __ ldr(R3, Address(THR, Thread::heap_offset()));
2075 __ ldr(R0, Address(R3, Heap::TopOffset(space))); 2086 __ ldr(R0, Address(R3, Heap::TopOffset(space)));
2076 2087
2077 // length_reg: allocation size. 2088 // length_reg: allocation size.
2078 __ adds(R1, R0, Operand(length_reg)); 2089 __ adds(R1, R0, Operand(length_reg));
2079 __ b(&fail, CS); // Fail on unsigned overflow. 2090 __ b(&fail, CS); // Fail on unsigned overflow.
(...skipping 19 matching lines...) Expand all
2099 // R2: allocation size. 2110 // R2: allocation size.
2100 { 2111 {
2101 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 2112 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
2102 2113
2103 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); 2114 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
2104 __ LslImmediate(R2, R2, shift); 2115 __ LslImmediate(R2, R2, shift);
2105 __ csel(R2, R2, ZR, LS); 2116 __ csel(R2, R2, ZR, LS);
2106 2117
2107 // Get the class index and insert it into the tags. 2118 // Get the class index and insert it into the tags.
2108 // R2: size and bit tags. 2119 // R2: size and bit tags.
2120 // This also clears the hash, which is in the high word of the tags.
2109 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); 2121 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
2110 __ orr(R2, R2, Operand(TMP)); 2122 __ orr(R2, R2, Operand(TMP));
2111 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags. 2123 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags.
2112 } 2124 }
2113 2125
2114 // Set the length field using the saved length (R6). 2126 // Set the length field using the saved length (R6).
2115 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::length_offset()), 2127 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::length_offset()),
2116 R6); 2128 R6);
2117 // Clear hash.
2118 __ mov(TMP, ZR);
2119 __ str(TMP, FieldAddress(R0, String::hash_offset()));
2120 __ b(ok); 2129 __ b(ok);
2121 2130
2122 __ Bind(&fail); 2131 __ Bind(&fail);
2123 __ b(failure); 2132 __ b(failure);
2124 } 2133 }
2125 2134
2126 2135
2127 // Arg0: OneByteString (receiver). 2136 // Arg0: OneByteString (receiver).
2128 // Arg1: Start index as Smi. 2137 // Arg1: Start index as Smi.
2129 // Arg2: End index as Smi. 2138 // Arg2: End index as Smi.
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 2386
2378 void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler) { 2387 void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler) {
2379 __ ldr(R0, Address(THR, Thread::async_stack_trace_offset())); 2388 __ ldr(R0, Address(THR, Thread::async_stack_trace_offset()));
2380 __ LoadObject(R0, Object::null_object()); 2389 __ LoadObject(R0, Object::null_object());
2381 __ ret(); 2390 __ ret();
2382 } 2391 }
2383 2392
2384 } // namespace dart 2393 } // namespace dart
2385 2394
2386 #endif // defined TARGET_ARCH_ARM64 2395 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698