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