xref: /aosp_15_r20/art/runtime/mirror/string.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_MIRROR_STRING_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_MIRROR_STRING_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
22*795d594fSAndroid Build Coastguard Worker #include "class.h"
23*795d594fSAndroid Build Coastguard Worker #include "object.h"
24*795d594fSAndroid Build Coastguard Worker #include "runtime_globals.h"
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker namespace gc {
29*795d594fSAndroid Build Coastguard Worker enum AllocatorType : char;
30*795d594fSAndroid Build Coastguard Worker }  // namespace gc
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker template<class T> class Handle;
33*795d594fSAndroid Build Coastguard Worker class InternTable;
34*795d594fSAndroid Build Coastguard Worker template<class MirrorType> class ObjPtr;
35*795d594fSAndroid Build Coastguard Worker class StringBuilderAppend;
36*795d594fSAndroid Build Coastguard Worker struct StringOffsets;
37*795d594fSAndroid Build Coastguard Worker class StubTest_ReadBarrierForRoot_Test;
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker namespace mirror {
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker // String Compression
42*795d594fSAndroid Build Coastguard Worker static constexpr bool kUseStringCompression = true;
43*795d594fSAndroid Build Coastguard Worker enum class StringCompressionFlag : uint32_t {
44*795d594fSAndroid Build Coastguard Worker     kCompressed = 0u,
45*795d594fSAndroid Build Coastguard Worker     kUncompressed = 1u
46*795d594fSAndroid Build Coastguard Worker };
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker // C++ mirror of java.lang.String
49*795d594fSAndroid Build Coastguard Worker class MANAGED String final : public Object {
50*795d594fSAndroid Build Coastguard Worker  public:
51*795d594fSAndroid Build Coastguard Worker   MIRROR_CLASS("Ljava/lang/String;");
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker   // Size of java.lang.String.class.
54*795d594fSAndroid Build Coastguard Worker   static uint32_t ClassSize(PointerSize pointer_size);
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker   // Size of an instance of java.lang.String not including its value array.
InstanceSize()57*795d594fSAndroid Build Coastguard Worker   static constexpr uint32_t InstanceSize() {
58*795d594fSAndroid Build Coastguard Worker     return sizeof(String);
59*795d594fSAndroid Build Coastguard Worker   }
60*795d594fSAndroid Build Coastguard Worker 
CountOffset()61*795d594fSAndroid Build Coastguard Worker   static constexpr MemberOffset CountOffset() {
62*795d594fSAndroid Build Coastguard Worker     return OFFSET_OF_OBJECT_MEMBER(String, count_);
63*795d594fSAndroid Build Coastguard Worker   }
64*795d594fSAndroid Build Coastguard Worker 
ValueOffset()65*795d594fSAndroid Build Coastguard Worker   static constexpr MemberOffset ValueOffset() {
66*795d594fSAndroid Build Coastguard Worker     return OFFSET_OF_OBJECT_MEMBER(String, value_);
67*795d594fSAndroid Build Coastguard Worker   }
68*795d594fSAndroid Build Coastguard Worker 
GetValue()69*795d594fSAndroid Build Coastguard Worker   uint16_t* GetValue() REQUIRES_SHARED(Locks::mutator_lock_) {
70*795d594fSAndroid Build Coastguard Worker     return &value_[0];
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker 
GetValueCompressed()73*795d594fSAndroid Build Coastguard Worker   uint8_t* GetValueCompressed() REQUIRES_SHARED(Locks::mutator_lock_) {
74*795d594fSAndroid Build Coastguard Worker     return &value_compressed_[0];
75*795d594fSAndroid Build Coastguard Worker   }
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
SizeOf()78*795d594fSAndroid Build Coastguard Worker   size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_) {
79*795d594fSAndroid Build Coastguard Worker     size_t size = sizeof(String);
80*795d594fSAndroid Build Coastguard Worker     if (IsCompressed()) {
81*795d594fSAndroid Build Coastguard Worker       size += (sizeof(uint8_t) * GetLength<kVerifyFlags>());
82*795d594fSAndroid Build Coastguard Worker     } else {
83*795d594fSAndroid Build Coastguard Worker       size += (sizeof(uint16_t) * GetLength<kVerifyFlags>());
84*795d594fSAndroid Build Coastguard Worker     }
85*795d594fSAndroid Build Coastguard Worker     // String.equals() intrinsics assume zero-padding up to kObjectAlignment,
86*795d594fSAndroid Build Coastguard Worker     // so make sure the zero-padding is actually copied around if GC compaction
87*795d594fSAndroid Build Coastguard Worker     // chooses to copy only SizeOf() bytes.
88*795d594fSAndroid Build Coastguard Worker     // http://b/23528461
89*795d594fSAndroid Build Coastguard Worker     return RoundUp(size, kObjectAlignment);
90*795d594fSAndroid Build Coastguard Worker   }
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker   // Taking out the first/uppermost bit because it is not part of actual length value
93*795d594fSAndroid Build Coastguard Worker   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
GetLength()94*795d594fSAndroid Build Coastguard Worker   int32_t GetLength() REQUIRES_SHARED(Locks::mutator_lock_) {
95*795d594fSAndroid Build Coastguard Worker     return GetLengthFromCount(GetCount<kVerifyFlags>());
96*795d594fSAndroid Build Coastguard Worker   }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
GetCount()99*795d594fSAndroid Build Coastguard Worker   int32_t GetCount() REQUIRES_SHARED(Locks::mutator_lock_) {
100*795d594fSAndroid Build Coastguard Worker     return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(String, count_));
101*795d594fSAndroid Build Coastguard Worker   }
102*795d594fSAndroid Build Coastguard Worker 
SetCount(int32_t new_count)103*795d594fSAndroid Build Coastguard Worker   void SetCount(int32_t new_count) REQUIRES_SHARED(Locks::mutator_lock_) {
104*795d594fSAndroid Build Coastguard Worker     // Count is invariant so use non-transactional mode. Also disable check as we may run inside
105*795d594fSAndroid Build Coastguard Worker     // a transaction.
106*795d594fSAndroid Build Coastguard Worker     SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count);
107*795d594fSAndroid Build Coastguard Worker   }
108*795d594fSAndroid Build Coastguard Worker 
GetStoredHashCode()109*795d594fSAndroid Build Coastguard Worker   int32_t GetStoredHashCode() REQUIRES_SHARED(Locks::mutator_lock_) {
110*795d594fSAndroid Build Coastguard Worker     return GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_));
111*795d594fSAndroid Build Coastguard Worker   }
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker   int32_t GetHashCode() REQUIRES_SHARED(Locks::mutator_lock_);
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker   // Computes and returns the hash code.
116*795d594fSAndroid Build Coastguard Worker   int32_t ComputeHashCode() REQUIRES_SHARED(Locks::mutator_lock_);
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker   int32_t GetModifiedUtf8Length() REQUIRES_SHARED(Locks::mutator_lock_);
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker   uint16_t CharAt(int32_t index) REQUIRES_SHARED(Locks::mutator_lock_);
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker   // Create a new string where all occurences of `old_c` are replaced with `new_c`.
123*795d594fSAndroid Build Coastguard Worker   // String.doReplace(char, char) is called from String.replace(char, char) when there is a match.
124*795d594fSAndroid Build Coastguard Worker   static ObjPtr<String> DoReplace(Thread* self, Handle<String> src, uint16_t old_c, uint16_t new_c)
125*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker   EXPORT ObjPtr<String> Intern() REQUIRES_SHARED(Locks::mutator_lock_);
128*795d594fSAndroid Build Coastguard Worker 
129*795d594fSAndroid Build Coastguard Worker   template <bool kIsInstrumented = true, typename PreFenceVisitor>
130*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static ObjPtr<String> Alloc(Thread* self,
131*795d594fSAndroid Build Coastguard Worker                                             int32_t utf16_length_with_flag,
132*795d594fSAndroid Build Coastguard Worker                                             gc::AllocatorType allocator_type,
133*795d594fSAndroid Build Coastguard Worker                                             const PreFenceVisitor& pre_fence_visitor)
134*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
135*795d594fSAndroid Build Coastguard Worker 
136*795d594fSAndroid Build Coastguard Worker   template <bool kIsInstrumented = true>
137*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static ObjPtr<String> AllocFromByteArray(Thread* self,
138*795d594fSAndroid Build Coastguard Worker                                                          int32_t byte_length,
139*795d594fSAndroid Build Coastguard Worker                                                          Handle<ByteArray> array,
140*795d594fSAndroid Build Coastguard Worker                                                          int32_t offset,
141*795d594fSAndroid Build Coastguard Worker                                                          int32_t high_byte,
142*795d594fSAndroid Build Coastguard Worker                                                          gc::AllocatorType allocator_type)
143*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker   template <bool kIsInstrumented = true>
146*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static ObjPtr<String> AllocFromUtf16ByteArray(Thread* self,
147*795d594fSAndroid Build Coastguard Worker                                                          int32_t char_count,
148*795d594fSAndroid Build Coastguard Worker                                                          Handle<ByteArray> array,
149*795d594fSAndroid Build Coastguard Worker                                                          int32_t offset,
150*795d594fSAndroid Build Coastguard Worker                                                          gc::AllocatorType allocator_type)
151*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker   template <bool kIsInstrumented = true>
154*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static ObjPtr<String> AllocFromCharArray(Thread* self,
155*795d594fSAndroid Build Coastguard Worker                                                          int32_t count,
156*795d594fSAndroid Build Coastguard Worker                                                          Handle<CharArray> array,
157*795d594fSAndroid Build Coastguard Worker                                                          int32_t offset,
158*795d594fSAndroid Build Coastguard Worker                                                          gc::AllocatorType allocator_type)
159*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker   template <bool kIsInstrumented = true>
162*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static ObjPtr<String> AllocFromString(Thread* self,
163*795d594fSAndroid Build Coastguard Worker                                                       int32_t string_length,
164*795d594fSAndroid Build Coastguard Worker                                                       Handle<String> string,
165*795d594fSAndroid Build Coastguard Worker                                                       int32_t offset,
166*795d594fSAndroid Build Coastguard Worker                                                       gc::AllocatorType allocator_type)
167*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker   template <bool kIsInstrumented = true>
170*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static ObjPtr<String> AllocEmptyString(Thread* self,
171*795d594fSAndroid Build Coastguard Worker                                                        gc::AllocatorType allocator_type)
172*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker   static ObjPtr<String> DoConcat(Thread* self, Handle<String> h_this, Handle<String> h_arg)
175*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker   static ObjPtr<String> DoRepeat(Thread* self, Handle<String> h_this, int32_t count)
178*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
179*795d594fSAndroid Build Coastguard Worker 
180*795d594fSAndroid Build Coastguard Worker   static ObjPtr<String> AllocFromUtf16(Thread* self,
181*795d594fSAndroid Build Coastguard Worker                                        int32_t utf16_length,
182*795d594fSAndroid Build Coastguard Worker                                        const uint16_t* utf16_data_in)
183*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   EXPORT static ObjPtr<String> AllocFromModifiedUtf8(Thread* self, const char* utf)
186*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker   static ObjPtr<String> AllocFromModifiedUtf8(Thread* self,
189*795d594fSAndroid Build Coastguard Worker                                               int32_t utf16_length,
190*795d594fSAndroid Build Coastguard Worker                                               const char* utf8_data_in,
191*795d594fSAndroid Build Coastguard Worker                                               int32_t utf8_length)
192*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker   static ObjPtr<String> AllocFromModifiedUtf8(Thread* self,
195*795d594fSAndroid Build Coastguard Worker                                               int32_t utf16_length,
196*795d594fSAndroid Build Coastguard Worker                                               const char* utf8_data_in)
197*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker   bool Equals(const char* modified_utf8) REQUIRES_SHARED(Locks::mutator_lock_);
200*795d594fSAndroid Build Coastguard Worker 
Equals(ObjPtr<mirror::String> that)201*795d594fSAndroid Build Coastguard Worker   bool Equals(ObjPtr<mirror::String> that) REQUIRES_SHARED(Locks::mutator_lock_) {
202*795d594fSAndroid Build Coastguard Worker     return Equals(that.Ptr());
203*795d594fSAndroid Build Coastguard Worker   }
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker   // A version that takes a mirror::String pointer instead of ObjPtr as it's being
206*795d594fSAndroid Build Coastguard Worker   // called by the runtime app image code which can encode mirror::String at 64bit
207*795d594fSAndroid Build Coastguard Worker   // addresses (ObjPtr only works with 32bit pointers).
208*795d594fSAndroid Build Coastguard Worker   EXPORT bool Equals(mirror::String* that) REQUIRES_SHARED(Locks::mutator_lock_);
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker   // Create a modified UTF-8 encoded std::string from a java/lang/String object.
211*795d594fSAndroid Build Coastguard Worker   EXPORT std::string ToModifiedUtf8() REQUIRES_SHARED(Locks::mutator_lock_);
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker   int32_t FastIndexOf(int32_t ch, int32_t start) REQUIRES_SHARED(Locks::mutator_lock_);
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker   template <typename MemoryType>
216*795d594fSAndroid Build Coastguard Worker   int32_t FastIndexOf(MemoryType* chars, int32_t ch, int32_t start)
217*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
218*795d594fSAndroid Build Coastguard Worker 
219*795d594fSAndroid Build Coastguard Worker   int32_t LastIndexOf(int32_t ch) REQUIRES_SHARED(Locks::mutator_lock_);
220*795d594fSAndroid Build Coastguard Worker 
221*795d594fSAndroid Build Coastguard Worker   template <typename MemoryType>
222*795d594fSAndroid Build Coastguard Worker   int32_t LastIndexOf(MemoryType* chars, int32_t ch, int32_t from_index)
223*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker   int32_t CompareTo(ObjPtr<String> other) REQUIRES_SHARED(Locks::mutator_lock_);
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker   static ObjPtr<CharArray> ToCharArray(Handle<String> h_this, Thread* self)
228*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_)
229*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Roles::uninterruptible_);
230*795d594fSAndroid Build Coastguard Worker 
231*795d594fSAndroid Build Coastguard Worker   void GetChars(int32_t start, int32_t end, Handle<CharArray> array, int32_t index)
232*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker   void FillBytesLatin1(Handle<ByteArray> array, int32_t index)
235*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
236*795d594fSAndroid Build Coastguard Worker 
237*795d594fSAndroid Build Coastguard Worker   void FillBytesUTF16(Handle<ByteArray> array, int32_t index)
238*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
239*795d594fSAndroid Build Coastguard Worker 
240*795d594fSAndroid Build Coastguard Worker   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
IsCompressed()241*795d594fSAndroid Build Coastguard Worker   bool IsCompressed() REQUIRES_SHARED(Locks::mutator_lock_) {
242*795d594fSAndroid Build Coastguard Worker     return kUseStringCompression && IsCompressed(GetCount());
243*795d594fSAndroid Build Coastguard Worker   }
244*795d594fSAndroid Build Coastguard Worker 
245*795d594fSAndroid Build Coastguard Worker   bool IsValueNull() REQUIRES_SHARED(Locks::mutator_lock_);
246*795d594fSAndroid Build Coastguard Worker 
247*795d594fSAndroid Build Coastguard Worker   template<typename MemoryType>
248*795d594fSAndroid Build Coastguard Worker   static bool AllASCII(const MemoryType* chars, const int length);
249*795d594fSAndroid Build Coastguard Worker 
250*795d594fSAndroid Build Coastguard Worker   static bool DexFileStringAllASCII(const char* chars, const int length);
251*795d594fSAndroid Build Coastguard Worker 
IsCompressed(int32_t count)252*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static bool IsCompressed(int32_t count) {
253*795d594fSAndroid Build Coastguard Worker     return GetCompressionFlagFromCount(count) == StringCompressionFlag::kCompressed;
254*795d594fSAndroid Build Coastguard Worker   }
255*795d594fSAndroid Build Coastguard Worker 
GetCompressionFlagFromCount(int32_t count)256*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static StringCompressionFlag GetCompressionFlagFromCount(int32_t count) {
257*795d594fSAndroid Build Coastguard Worker     return kUseStringCompression
258*795d594fSAndroid Build Coastguard Worker         ? static_cast<StringCompressionFlag>(static_cast<uint32_t>(count) & 1u)
259*795d594fSAndroid Build Coastguard Worker         : StringCompressionFlag::kUncompressed;
260*795d594fSAndroid Build Coastguard Worker   }
261*795d594fSAndroid Build Coastguard Worker 
GetLengthFromCount(int32_t count)262*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static int32_t GetLengthFromCount(int32_t count) {
263*795d594fSAndroid Build Coastguard Worker     return kUseStringCompression ? static_cast<int32_t>(static_cast<uint32_t>(count) >> 1) : count;
264*795d594fSAndroid Build Coastguard Worker   }
265*795d594fSAndroid Build Coastguard Worker 
GetFlaggedCount(int32_t length,bool compressible)266*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE static int32_t GetFlaggedCount(int32_t length, bool compressible) {
267*795d594fSAndroid Build Coastguard Worker     return kUseStringCompression
268*795d594fSAndroid Build Coastguard Worker         ? static_cast<int32_t>((static_cast<uint32_t>(length) << 1) |
269*795d594fSAndroid Build Coastguard Worker                                (static_cast<uint32_t>(compressible
270*795d594fSAndroid Build Coastguard Worker                                                           ? StringCompressionFlag::kCompressed
271*795d594fSAndroid Build Coastguard Worker                                                           : StringCompressionFlag::kUncompressed)))
272*795d594fSAndroid Build Coastguard Worker         : length;
273*795d594fSAndroid Build Coastguard Worker   }
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   // Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
276*795d594fSAndroid Build Coastguard Worker   // "[[I" would be "int[][]", "[Ljava/lang/String;" would be
277*795d594fSAndroid Build Coastguard Worker   // "java.lang.String[]", and so forth.
278*795d594fSAndroid Build Coastguard Worker   static std::string PrettyStringDescriptor(ObjPtr<mirror::String> descriptor)
279*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
280*795d594fSAndroid Build Coastguard Worker   std::string PrettyStringDescriptor()
281*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
282*795d594fSAndroid Build Coastguard Worker 
IsASCII(uint16_t c)283*795d594fSAndroid Build Coastguard Worker   static constexpr bool IsASCII(uint16_t c) {
284*795d594fSAndroid Build Coastguard Worker     // Valid ASCII characters are in range 1..0x7f. Zero is not considered ASCII
285*795d594fSAndroid Build Coastguard Worker     // because it would complicate the detection of ASCII strings in Modified-UTF8.
286*795d594fSAndroid Build Coastguard Worker     return (c - 1u) < 0x7fu;
287*795d594fSAndroid Build Coastguard Worker   }
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker  private:
290*795d594fSAndroid Build Coastguard Worker   static bool AllASCIIExcept(const uint16_t* chars, int32_t length, uint16_t non_ascii);
291*795d594fSAndroid Build Coastguard Worker 
292*795d594fSAndroid Build Coastguard Worker   // Computes, stores, and returns the hash code.
293*795d594fSAndroid Build Coastguard Worker   EXPORT int32_t ComputeAndSetHashCode() REQUIRES_SHARED(Locks::mutator_lock_);
294*795d594fSAndroid Build Coastguard Worker 
SetHashCode(int32_t new_hash_code)295*795d594fSAndroid Build Coastguard Worker   void SetHashCode(int32_t new_hash_code) REQUIRES_SHARED(Locks::mutator_lock_) {
296*795d594fSAndroid Build Coastguard Worker     if (kIsDebugBuild) {
297*795d594fSAndroid Build Coastguard Worker       CHECK_EQ(new_hash_code, ComputeHashCode());
298*795d594fSAndroid Build Coastguard Worker       int32_t old_hash_code = GetStoredHashCode();
299*795d594fSAndroid Build Coastguard Worker       // Another thread could have raced this one and set the hash code.
300*795d594fSAndroid Build Coastguard Worker       CHECK(old_hash_code == 0 || old_hash_code == new_hash_code)
301*795d594fSAndroid Build Coastguard Worker           << "old: " << old_hash_code << " new: " << new_hash_code;
302*795d594fSAndroid Build Coastguard Worker     }
303*795d594fSAndroid Build Coastguard Worker     // Hash code is invariant so use non-transactional mode, allowing a failed transaction
304*795d594fSAndroid Build Coastguard Worker     // to set the hash code anyway. Also disable check as we may run inside a transaction.
305*795d594fSAndroid Build Coastguard Worker     SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
306*795d594fSAndroid Build Coastguard Worker         OFFSET_OF_OBJECT_MEMBER(String, hash_code_), new_hash_code);
307*795d594fSAndroid Build Coastguard Worker   }
308*795d594fSAndroid Build Coastguard Worker 
309*795d594fSAndroid Build Coastguard Worker   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
310*795d594fSAndroid Build Coastguard Worker 
311*795d594fSAndroid Build Coastguard Worker   // If string compression is enabled, count_ holds the StringCompressionFlag in the
312*795d594fSAndroid Build Coastguard Worker   // least significant bit and the length in the remaining bits, length = count_ >> 1.
313*795d594fSAndroid Build Coastguard Worker   int32_t count_;
314*795d594fSAndroid Build Coastguard Worker 
315*795d594fSAndroid Build Coastguard Worker   uint32_t hash_code_;
316*795d594fSAndroid Build Coastguard Worker 
317*795d594fSAndroid Build Coastguard Worker   // Compression of all-ASCII into 8-bit memory leads to usage one of these fields
318*795d594fSAndroid Build Coastguard Worker   union {
319*795d594fSAndroid Build Coastguard Worker     uint16_t value_[0];
320*795d594fSAndroid Build Coastguard Worker     uint8_t value_compressed_[0];
321*795d594fSAndroid Build Coastguard Worker   };
322*795d594fSAndroid Build Coastguard Worker 
323*795d594fSAndroid Build Coastguard Worker   friend class art::InternTable;  // Let `InternTable` call `SetHashCode()`.
324*795d594fSAndroid Build Coastguard Worker   friend class art::StringBuilderAppend;
325*795d594fSAndroid Build Coastguard Worker   friend struct art::StringOffsets;  // for verifying offset information
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   DISALLOW_IMPLICIT_CONSTRUCTORS(String);
328*795d594fSAndroid Build Coastguard Worker };
329*795d594fSAndroid Build Coastguard Worker 
330*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
331*795d594fSAndroid Build Coastguard Worker }  // namespace art
332*795d594fSAndroid Build Coastguard Worker 
333*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_MIRROR_STRING_H_
334