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