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 "gc/allocator_type.h"
21 #include "gc_root.h"
22 #include "object.h"
23 
24 namespace art {
25 
26 template<class T> class Handle;
27 struct StringOffsets;
28 class StringPiece;
29 class StubTest_ReadBarrierForRoot_Test;
30 
31 namespace mirror {
32 
33 // String Compression
34 static constexpr bool kUseStringCompression = true;
35 enum class StringCompressionFlag : uint32_t {
36     kCompressed = 0u,
37     kUncompressed = 1u
38 };
39 
40 // C++ mirror of java.lang.String
41 class MANAGED String FINAL : public Object {
42  public:
43   // Size of java.lang.String.class.
44   static uint32_t ClassSize(PointerSize pointer_size);
45 
46   // Size of an instance of java.lang.String not including its value array.
InstanceSize()47   static constexpr uint32_t InstanceSize() {
48     return sizeof(String);
49   }
50 
CountOffset()51   static MemberOffset CountOffset() {
52     return OFFSET_OF_OBJECT_MEMBER(String, count_);
53   }
54 
ValueOffset()55   static MemberOffset ValueOffset() {
56     return OFFSET_OF_OBJECT_MEMBER(String, value_);
57   }
58 
GetValue()59   uint16_t* GetValue() REQUIRES_SHARED(Locks::mutator_lock_) {
60     return &value_[0];
61   }
62 
GetValueCompressed()63   uint8_t* GetValueCompressed() REQUIRES_SHARED(Locks::mutator_lock_) {
64     return &value_compressed_[0];
65   }
66 
67   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
68   size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_);
69 
70   // Taking out the first/uppermost bit because it is not part of actual length value
71   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
GetLength()72   int32_t GetLength() REQUIRES_SHARED(Locks::mutator_lock_) {
73     return GetLengthFromCount(GetCount<kVerifyFlags>());
74   }
75 
76   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
GetCount()77   int32_t GetCount() REQUIRES_SHARED(Locks::mutator_lock_) {
78     return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(String, count_));
79   }
80 
SetCount(int32_t new_count)81   void SetCount(int32_t new_count) REQUIRES_SHARED(Locks::mutator_lock_) {
82     // Count is invariant so use non-transactional mode. Also disable check as we may run inside
83     // a transaction.
84     SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count);
85   }
86 
87   int32_t GetHashCode() REQUIRES_SHARED(Locks::mutator_lock_);
88 
89   // Computes, stores, and returns the hash code.
90   int32_t ComputeHashCode() REQUIRES_SHARED(Locks::mutator_lock_);
91 
92   int32_t GetUtfLength() REQUIRES_SHARED(Locks::mutator_lock_);
93 
94   uint16_t CharAt(int32_t index) REQUIRES_SHARED(Locks::mutator_lock_);
95 
96   // Create a new string where all occurences of `old_c` are replaced with `new_c`.
97   // String.doReplace(char, char) is called from String.replace(char, char) when there is a match.
98   static ObjPtr<String> DoReplace(Thread* self, Handle<String> src, uint16_t old_c, uint16_t new_c)
99       REQUIRES_SHARED(Locks::mutator_lock_);
100 
101   ObjPtr<String> Intern() REQUIRES_SHARED(Locks::mutator_lock_);
102 
103   template <bool kIsInstrumented>
104   ALWAYS_INLINE static String* AllocFromByteArray(Thread* self, int32_t byte_length,
105                                                   Handle<ByteArray> array, int32_t offset,
106                                                   int32_t high_byte,
107                                                   gc::AllocatorType allocator_type)
108       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
109 
110   template <bool kIsInstrumented>
111   ALWAYS_INLINE static String* AllocFromCharArray(Thread* self, int32_t count,
112                                                   Handle<CharArray> array, int32_t offset,
113                                                   gc::AllocatorType allocator_type)
114       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
115 
116   template <bool kIsInstrumented>
117   ALWAYS_INLINE static String* AllocFromString(Thread* self, int32_t string_length,
118                                                Handle<String> string, int32_t offset,
119                                                gc::AllocatorType allocator_type)
120       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
121 
122   template <bool kIsInstrumented>
123   ALWAYS_INLINE static String* AllocEmptyString(Thread* self,
124                                                 gc::AllocatorType allocator_type)
125       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
126 
127   static String* AllocFromStrings(Thread* self, Handle<String> string, Handle<String> string2)
128       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
129 
130   static String* AllocFromUtf16(Thread* self, int32_t utf16_length, const uint16_t* utf16_data_in)
131       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
132 
133   static String* AllocFromModifiedUtf8(Thread* self, const char* utf)
134       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
135 
136   static String* AllocFromModifiedUtf8(Thread* self, int32_t utf16_length,
137                                        const char* utf8_data_in, int32_t utf8_length)
138       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
139 
140   static String* AllocFromModifiedUtf8(Thread* self, int32_t utf16_length, const char* utf8_data_in)
141       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
142 
143   // TODO: This is only used in the interpreter to compare against
144   // entries from a dex files constant pool (ArtField names). Should
145   // we unify this with Equals(const StringPiece&); ?
146   bool Equals(const char* modified_utf8) REQUIRES_SHARED(Locks::mutator_lock_);
147 
148   // TODO: This is only used to compare DexCache.location with
149   // a dex_file's location (which is an std::string). Do we really
150   // need this in mirror::String just for that one usage ?
151   bool Equals(const StringPiece& modified_utf8)
152       REQUIRES_SHARED(Locks::mutator_lock_);
153 
154   bool Equals(ObjPtr<String> that) REQUIRES_SHARED(Locks::mutator_lock_);
155 
156   // Compare UTF-16 code point values not in a locale-sensitive manner
157   int Compare(int32_t utf16_length, const char* utf8_data_in);
158 
159   // TODO: do we need this overload? give it a more intention-revealing name.
160   bool Equals(const uint16_t* that_chars, int32_t that_offset,
161               int32_t that_length)
162       REQUIRES_SHARED(Locks::mutator_lock_);
163 
164   // Create a modified UTF-8 encoded std::string from a java/lang/String object.
165   std::string ToModifiedUtf8() REQUIRES_SHARED(Locks::mutator_lock_);
166 
167   int32_t FastIndexOf(int32_t ch, int32_t start) REQUIRES_SHARED(Locks::mutator_lock_);
168 
169   template <typename MemoryType>
170   int32_t FastIndexOf(MemoryType* chars, int32_t ch, int32_t start)
171       REQUIRES_SHARED(Locks::mutator_lock_);
172 
173   int32_t CompareTo(ObjPtr<String> other) REQUIRES_SHARED(Locks::mutator_lock_);
174 
175   CharArray* ToCharArray(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_)
176       REQUIRES(!Roles::uninterruptible_);
177 
178   void GetChars(int32_t start, int32_t end, Handle<CharArray> array, int32_t index)
179       REQUIRES_SHARED(Locks::mutator_lock_);
180 
181   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
IsCompressed()182   bool IsCompressed() REQUIRES_SHARED(Locks::mutator_lock_) {
183     return kUseStringCompression && IsCompressed(GetCount());
184   }
185 
186   bool IsValueNull() REQUIRES_SHARED(Locks::mutator_lock_);
187 
188   template<typename MemoryType>
189   static bool AllASCII(const MemoryType* chars, const int length);
190 
191   static bool DexFileStringAllASCII(const char* chars, const int length);
192 
IsCompressed(int32_t count)193   ALWAYS_INLINE static bool IsCompressed(int32_t count) {
194     return GetCompressionFlagFromCount(count) == StringCompressionFlag::kCompressed;
195   }
196 
GetCompressionFlagFromCount(int32_t count)197   ALWAYS_INLINE static StringCompressionFlag GetCompressionFlagFromCount(int32_t count) {
198     return kUseStringCompression
199         ? static_cast<StringCompressionFlag>(static_cast<uint32_t>(count) & 1u)
200         : StringCompressionFlag::kUncompressed;
201   }
202 
GetLengthFromCount(int32_t count)203   ALWAYS_INLINE static int32_t GetLengthFromCount(int32_t count) {
204     return kUseStringCompression ? static_cast<int32_t>(static_cast<uint32_t>(count) >> 1) : count;
205   }
206 
GetFlaggedCount(int32_t length,bool compressible)207   ALWAYS_INLINE static int32_t GetFlaggedCount(int32_t length, bool compressible) {
208     return kUseStringCompression
209         ? static_cast<int32_t>((static_cast<uint32_t>(length) << 1) |
210                                (static_cast<uint32_t>(compressible
211                                                           ? StringCompressionFlag::kCompressed
212                                                           : StringCompressionFlag::kUncompressed)))
213         : length;
214   }
215 
GetJavaLangString()216   static Class* GetJavaLangString() REQUIRES_SHARED(Locks::mutator_lock_) {
217     DCHECK(!java_lang_String_.IsNull());
218     return java_lang_String_.Read();
219   }
220 
221   static void SetClass(ObjPtr<Class> java_lang_String) REQUIRES_SHARED(Locks::mutator_lock_);
222   static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
223   static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
224 
225   // Returns a human-readable equivalent of 'descriptor'. So "I" would be "int",
226   // "[[I" would be "int[][]", "[Ljava/lang/String;" would be
227   // "java.lang.String[]", and so forth.
228   static std::string PrettyStringDescriptor(ObjPtr<mirror::String> descriptor)
229       REQUIRES_SHARED(Locks::mutator_lock_);
230   std::string PrettyStringDescriptor()
231       REQUIRES_SHARED(Locks::mutator_lock_);
232 
233  private:
IsASCII(uint16_t c)234   static constexpr bool IsASCII(uint16_t c) {
235     // Valid ASCII characters are in range 1..0x7f. Zero is not considered ASCII
236     // because it would complicate the detection of ASCII strings in Modified-UTF8.
237     return (c - 1u) < 0x7fu;
238   }
239 
240   static bool AllASCIIExcept(const uint16_t* chars, int32_t length, uint16_t non_ascii);
241 
SetHashCode(int32_t new_hash_code)242   void SetHashCode(int32_t new_hash_code) REQUIRES_SHARED(Locks::mutator_lock_) {
243     // Hash code is invariant so use non-transactional mode. Also disable check as we may run inside
244     // a transaction.
245     DCHECK_EQ(0, GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_)));
246     SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), new_hash_code);
247   }
248 
249   template <bool kIsInstrumented, typename PreFenceVisitor>
250   ALWAYS_INLINE static String* Alloc(Thread* self, int32_t utf16_length_with_flag,
251                                      gc::AllocatorType allocator_type,
252                                      const PreFenceVisitor& pre_fence_visitor)
253       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
254 
255   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
256 
257   // If string compression is enabled, count_ holds the StringCompressionFlag in the
258   // least significant bit and the length in the remaining bits, length = count_ >> 1.
259   int32_t count_;
260 
261   uint32_t hash_code_;
262 
263   // Compression of all-ASCII into 8-bit memory leads to usage one of these fields
264   union {
265     uint16_t value_[0];
266     uint8_t value_compressed_[0];
267   };
268 
269   static GcRoot<Class> java_lang_String_;
270 
271   friend struct art::StringOffsets;  // for verifying offset information
272   ART_FRIEND_TEST(art::StubTest, ReadBarrierForRoot);  // For java_lang_String_.
273 
274   DISALLOW_IMPLICIT_CONSTRUCTORS(String);
275 };
276 
277 }  // namespace mirror
278 }  // namespace art
279 
280 #endif  // ART_RUNTIME_MIRROR_STRING_H_
281