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

Side by Side Diff: runtime/vm/intrinsifier_arm64.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_arm.cc ('k') | runtime/vm/intrinsifier_ia32.cc » ('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) 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);
1826 __ CompareRegisters(R0, ZR); 1827 __ adds(R0, R0, Operand(R0)); // Smi tag the hash code, setting Z flag.
1827 __ b(&fall_through, EQ); 1828 __ b(&fall_through, EQ);
1828 __ ret(); 1829 __ ret();
1829 // Hash not yet computed. 1830 // Hash not yet computed.
1830 __ Bind(&fall_through); 1831 __ Bind(&fall_through);
1831 } 1832 }
1832 1833
1833 1834
1834 void GenerateSubstringMatchesSpecialization(Assembler* assembler, 1835 void GenerateSubstringMatchesSpecialization(Assembler* assembler,
1835 intptr_t receiver_cid, 1836 intptr_t receiver_cid,
1836 intptr_t other_cid, 1837 intptr_t other_cid,
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1988 __ LoadObject(R0, Bool::True()); 1989 __ LoadObject(R0, Bool::True());
1989 __ LoadObject(TMP, Bool::False()); 1990 __ LoadObject(TMP, Bool::False());
1990 __ csel(R0, TMP, R0, NE); 1991 __ csel(R0, TMP, R0, NE);
1991 __ ret(); 1992 __ ret();
1992 } 1993 }
1993 1994
1994 1995
1995 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { 1996 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
1996 Label compute_hash; 1997 Label compute_hash;
1997 __ ldr(R1, Address(SP, 0 * kWordSize)); // OneByteString object. 1998 __ ldr(R1, Address(SP, 0 * kWordSize)); // OneByteString object.
1998 __ ldr(R0, FieldAddress(R1, String::hash_offset())); 1999 __ ldr(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord);
1999 __ CompareRegisters(R0, ZR); 2000 __ adds(R0, R0, Operand(R0)); // Smi tag the hash code, setting Z flag.
2000 __ b(&compute_hash, EQ); 2001 __ b(&compute_hash, EQ);
2001 __ ret(); // Return if already computed. 2002 __ ret(); // Return if already computed.
2002 2003
2003 __ Bind(&compute_hash); 2004 __ Bind(&compute_hash);
2004 __ ldr(R2, FieldAddress(R1, String::length_offset())); 2005 __ ldr(R2, FieldAddress(R1, String::length_offset()));
2005 __ SmiUntag(R2); 2006 __ SmiUntag(R2);
2006 2007
2007 Label done; 2008 Label done;
2008 // If the string is empty, set the hash to 1, and return. 2009 // If the string is empty, set the hash to 1, and return.
2009 __ CompareRegisters(R2, ZR); 2010 __ CompareRegisters(R2, ZR);
(...skipping 29 matching lines...) Expand all
2039 // hash_ += hash_ << 15; 2040 // hash_ += hash_ << 15;
2040 __ addw(R0, R0, Operand(R0, LSL, 3)); 2041 __ addw(R0, R0, Operand(R0, LSL, 3));
2041 __ eorw(R0, R0, Operand(R0, LSR, 11)); 2042 __ eorw(R0, R0, Operand(R0, LSR, 11));
2042 __ addw(R0, R0, Operand(R0, LSL, 15)); 2043 __ addw(R0, R0, Operand(R0, LSL, 15));
2043 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1); 2044 // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
2044 __ AndImmediate(R0, R0, (static_cast<intptr_t>(1) << String::kHashBits) - 1); 2045 __ AndImmediate(R0, R0, (static_cast<intptr_t>(1) << String::kHashBits) - 1);
2045 __ CompareRegisters(R0, ZR); 2046 __ CompareRegisters(R0, ZR);
2046 // return hash_ == 0 ? 1 : hash_; 2047 // return hash_ == 0 ? 1 : hash_;
2047 __ Bind(&done); 2048 __ Bind(&done);
2048 __ csinc(R0, R0, ZR, NE); // R0 <- (R0 != 0) ? R0 : (ZR + 1). 2049 __ csinc(R0, R0, ZR, NE); // R0 <- (R0 != 0) ? R0 : (ZR + 1).
2050 __ str(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord);
2049 __ SmiTag(R0); 2051 __ SmiTag(R0);
2050 __ str(R0, FieldAddress(R1, String::hash_offset()));
2051 __ ret(); 2052 __ ret();
2052 } 2053 }
2053 2054
2054 2055
2055 // Allocates one-byte string of length 'end - start'. The content is not 2056 // Allocates one-byte string of length 'end - start'. The content is not
2056 // initialized. 2057 // initialized.
2057 // 'length-reg' (R2) contains tagged length. 2058 // 'length-reg' (R2) contains tagged length.
2058 // Returns new string as tagged pointer in R0. 2059 // Returns new string as tagged pointer in R0.
2059 static void TryAllocateOnebyteString(Assembler* assembler, 2060 static void TryAllocateOnebyteString(Assembler* assembler,
2060 Label* ok, 2061 Label* ok,
2061 Label* failure) { 2062 Label* failure) {
2062 const Register length_reg = R2; 2063 const Register length_reg = R2;
2063 Label fail; 2064 Label fail;
2064 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, R0, failure)); 2065 NOT_IN_PRODUCT(__ MaybeTraceAllocation(kOneByteStringCid, R0, failure));
2065 __ mov(R6, length_reg); // Save the length register. 2066 __ mov(R6, length_reg); // Save the length register.
2066 // TODO(koda): Protect against negative length and overflow here. 2067 // TODO(koda): Protect against negative length and overflow here.
2067 __ SmiUntag(length_reg); 2068 __ adds(length_reg, ZR, Operand(length_reg, ASR, kSmiTagSize)); // Smi untag.
2068 const intptr_t fixed_size = sizeof(RawString) + kObjectAlignment - 1; 2069 // If the length is 0 then we have to make the allocated size a bit bigger,
2069 __ AddImmediate(length_reg, fixed_size); 2070 // otherwise the string takes up less space than an ExternalOneByteString,
2071 // and cannot be externalized. TODO(erikcorry): We should probably just
2072 // return a static zero length string here instead.
2073 // length <- (length != 0) ? length : (ZR + 1).
2074 __ csinc(length_reg, length_reg, ZR, NE);
2075 const intptr_t fixed_size_plus_alignment_padding =
2076 sizeof(RawString) + kObjectAlignment - 1;
2077 __ AddImmediate(length_reg, fixed_size_plus_alignment_padding);
2070 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1))); 2078 __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1)));
2071 2079
2072 const intptr_t cid = kOneByteStringCid; 2080 const intptr_t cid = kOneByteStringCid;
2073 Heap::Space space = Heap::kNew; 2081 Heap::Space space = Heap::kNew;
2074 __ ldr(R3, Address(THR, Thread::heap_offset())); 2082 __ ldr(R3, Address(THR, Thread::heap_offset()));
2075 __ ldr(R0, Address(R3, Heap::TopOffset(space))); 2083 __ ldr(R0, Address(R3, Heap::TopOffset(space)));
2076 2084
2077 // length_reg: allocation size. 2085 // length_reg: allocation size.
2078 __ adds(R1, R0, Operand(length_reg)); 2086 __ adds(R1, R0, Operand(length_reg));
2079 __ b(&fail, CS); // Fail on unsigned overflow. 2087 __ b(&fail, CS); // Fail on unsigned overflow.
(...skipping 19 matching lines...) Expand all
2099 // R2: allocation size. 2107 // R2: allocation size.
2100 { 2108 {
2101 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2; 2109 const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
2102 2110
2103 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag); 2111 __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
2104 __ LslImmediate(R2, R2, shift); 2112 __ LslImmediate(R2, R2, shift);
2105 __ csel(R2, R2, ZR, LS); 2113 __ csel(R2, R2, ZR, LS);
2106 2114
2107 // Get the class index and insert it into the tags. 2115 // Get the class index and insert it into the tags.
2108 // R2: size and bit tags. 2116 // R2: size and bit tags.
2117 // This also clears the hash, which is in the high word of the tags.
2109 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid)); 2118 __ LoadImmediate(TMP, RawObject::ClassIdTag::encode(cid));
2110 __ orr(R2, R2, Operand(TMP)); 2119 __ orr(R2, R2, Operand(TMP));
2111 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags. 2120 __ str(R2, FieldAddress(R0, String::tags_offset())); // Store tags.
2112 } 2121 }
2113 2122
2114 // Set the length field using the saved length (R6). 2123 // Set the length field using the saved length (R6).
2115 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::length_offset()), 2124 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::length_offset()),
2116 R6); 2125 R6);
2117 // Clear hash.
2118 __ mov(TMP, ZR);
2119 __ str(TMP, FieldAddress(R0, String::hash_offset()));
2120 __ b(ok); 2126 __ b(ok);
2121 2127
2122 __ Bind(&fail); 2128 __ Bind(&fail);
2123 __ b(failure); 2129 __ b(failure);
2124 } 2130 }
2125 2131
2126 2132
2127 // Arg0: OneByteString (receiver). 2133 // Arg0: OneByteString (receiver).
2128 // Arg1: Start index as Smi. 2134 // Arg1: Start index as Smi.
2129 // Arg2: End index as Smi. 2135 // Arg2: End index as Smi.
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
2377 2383
2378 void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler) { 2384 void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler) {
2379 __ ldr(R0, Address(THR, Thread::async_stack_trace_offset())); 2385 __ ldr(R0, Address(THR, Thread::async_stack_trace_offset()));
2380 __ LoadObject(R0, Object::null_object()); 2386 __ LoadObject(R0, Object::null_object());
2381 __ ret(); 2387 __ ret();
2382 } 2388 }
2383 2389
2384 } // namespace dart 2390 } // namespace dart
2385 2391
2386 #endif // defined TARGET_ARCH_ARM64 2392 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698