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 #ifndef ART_RUNTIME_MIRROR_STRING_ALLOC_INL_H_ 17 #define ART_RUNTIME_MIRROR_STRING_ALLOC_INL_H_ 18 19 #include "string-inl.h" 20 21 #include "android-base/stringprintf.h" 22 23 #include "array.h" 24 #include "base/bit_utils.h" 25 #include "class.h" 26 #include "class_root-inl.h" 27 #include "gc/allocator_type.h" 28 #include "gc/heap-inl.h" 29 #include "obj_ptr.h" 30 #include "runtime.h" 31 #include "runtime_globals.h" 32 #include "thread.h" 33 34 namespace art { 35 namespace mirror { 36 37 // Sets string count in the allocation code path to ensure it is guarded by a CAS. 38 class SetStringCountVisitor { 39 public: 40 explicit SetStringCountVisitor(int32_t count) : count_(count) { 41 } 42 43 void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const 44 REQUIRES_SHARED(Locks::mutator_lock_) { 45 // Avoid AsString as object is not yet in live bitmap or allocation stack. 46 ObjPtr<String> string = ObjPtr<String>::DownCast(obj); 47 string->SetCount(count_); 48 DCHECK(!string->IsCompressed() || kUseStringCompression); 49 } 50 51 private: 52 const int32_t count_; 53 }; 54 55 // Sets string count and value in the allocation code path to ensure it is guarded by a CAS. 56 class SetStringCountAndBytesVisitor { 57 public: 58 SetStringCountAndBytesVisitor(int32_t count, Handle<ByteArray> src_array, int32_t offset, 59 int32_t high_byte) 60 : count_(count), src_array_(src_array), offset_(offset), high_byte_(high_byte) { 61 } 62 63 void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const 64 REQUIRES_SHARED(Locks::mutator_lock_) { 65 // Avoid AsString as object is not yet in live bitmap or allocation stack. 66 ObjPtr<String> string = ObjPtr<String>::DownCast(obj); 67 string->SetCount(count_); 68 DCHECK(!string->IsCompressed() || kUseStringCompression); 69 int32_t length = String::GetLengthFromCount(count_); 70 const uint8_t* const src = reinterpret_cast<uint8_t*>(src_array_->GetData()) + offset_; 71 if (string->IsCompressed()) { 72 uint8_t* valueCompressed = string->GetValueCompressed(); 73 for (int i = 0; i < length; i++) { 74 valueCompressed[i] = (src[i] & 0xFF); 75 } 76 } else { 77 uint16_t* value = string->GetValue(); 78 for (int i = 0; i < length; i++) { 79 value[i] = high_byte_ + (src[i] & 0xFF); 80 } 81 } 82 } 83 84 private: 85 const int32_t count_; 86 Handle<ByteArray> src_array_; 87 const int32_t offset_; 88 const int32_t high_byte_; 89 }; 90 91 // Sets string count and value in the allocation code path to ensure it is guarded by a CAS. 92 class SetStringCountAndValueVisitorFromCharArray { 93 public: 94 SetStringCountAndValueVisitorFromCharArray(int32_t count, Handle<CharArray> src_array, 95 int32_t offset) : 96 count_(count), src_array_(src_array), offset_(offset) { 97 } 98 99 void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const 100 REQUIRES_SHARED(Locks::mutator_lock_) { 101 // Avoid AsString as object is not yet in live bitmap or allocation stack. 102 ObjPtr<String> string = ObjPtr<String>::DownCast(obj); 103 string->SetCount(count_); 104 const uint16_t* const src = src_array_->GetData() + offset_; 105 const int32_t length = String::GetLengthFromCount(count_); 106 if (kUseStringCompression && String::IsCompressed(count_)) { 107 for (int i = 0; i < length; ++i) { 108 string->GetValueCompressed()[i] = static_cast<uint8_t>(src[i]); 109 } 110 } else { 111 memcpy(string->GetValue(), src, length * sizeof(uint16_t)); 112 } 113 } 114 115 private: 116 const int32_t count_; 117 Handle<CharArray> src_array_; 118 const int32_t offset_; 119 }; 120 121 // Sets string count and value in the allocation code path to ensure it is guarded by a CAS. 122 class SetStringCountAndValueVisitorFromString { 123 public: 124 SetStringCountAndValueVisitorFromString(int32_t count, 125 Handle<String> src_string, 126 int32_t offset) : 127 count_(count), src_string_(src_string), offset_(offset) { 128 } 129 130 void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const 131 REQUIRES_SHARED(Locks::mutator_lock_) { 132 // Avoid AsString as object is not yet in live bitmap or allocation stack. 133 ObjPtr<String> string = ObjPtr<String>::DownCast(obj); 134 string->SetCount(count_); 135 const int32_t length = String::GetLengthFromCount(count_); 136 bool compressible = kUseStringCompression && String::IsCompressed(count_); 137 if (src_string_->IsCompressed()) { 138 const uint8_t* const src = src_string_->GetValueCompressed() + offset_; 139 memcpy(string->GetValueCompressed(), src, length * sizeof(uint8_t)); 140 } else { 141 const uint16_t* const src = src_string_->GetValue() + offset_; 142 if (compressible) { 143 for (int i = 0; i < length; ++i) { 144 string->GetValueCompressed()[i] = static_cast<uint8_t>(src[i]); 145 } 146 } else { 147 memcpy(string->GetValue(), src, length * sizeof(uint16_t)); 148 } 149 } 150 } 151 152 private: 153 const int32_t count_; 154 Handle<String> src_string_; 155 const int32_t offset_; 156 }; 157 158 template <bool kIsInstrumented, typename PreFenceVisitor> 159 inline ObjPtr<String> String::Alloc(Thread* self, 160 int32_t utf16_length_with_flag, 161 gc::AllocatorType allocator_type, 162 const PreFenceVisitor& pre_fence_visitor) { 163 constexpr size_t header_size = sizeof(String); 164 const bool compressible = kUseStringCompression && String::IsCompressed(utf16_length_with_flag); 165 const size_t block_size = (compressible) ? sizeof(uint8_t) : sizeof(uint16_t); 166 size_t length = String::GetLengthFromCount(utf16_length_with_flag); 167 static_assert(sizeof(length) <= sizeof(size_t), 168 "static_cast<size_t>(utf16_length) must not lose bits."); 169 size_t data_size = block_size * length; 170 size_t size = header_size + data_size; 171 // String.equals() intrinsics assume zero-padding up to kObjectAlignment, 172 // so make sure the allocator clears the padding as well. 173 // http://b/23528461 174 size_t alloc_size = RoundUp(size, kObjectAlignment); 175 176 Runtime* runtime = Runtime::Current(); 177 ObjPtr<Class> string_class = GetClassRoot<String>(runtime->GetClassLinker()); 178 // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. 179 // Do this by comparing with the maximum length that will _not_ cause an overflow. 180 const size_t overflow_length = (-header_size) / block_size; // Unsigned arithmetic. 181 const size_t max_alloc_length = overflow_length - 1u; 182 static_assert(IsAligned<sizeof(uint16_t)>(kObjectAlignment), 183 "kObjectAlignment must be at least as big as Java char alignment"); 184 const size_t max_length = RoundDown(max_alloc_length, kObjectAlignment / block_size); 185 if (UNLIKELY(length > max_length)) { 186 self->ThrowOutOfMemoryError( 187 android::base::StringPrintf("%s of length %d would overflow", 188 Class::PrettyDescriptor(string_class).c_str(), 189 static_cast<int>(length)).c_str()); 190 return nullptr; 191 } 192 193 gc::Heap* heap = runtime->GetHeap(); 194 return ObjPtr<String>::DownCast( 195 heap->AllocObjectWithAllocator<kIsInstrumented>(self, 196 string_class, 197 alloc_size, 198 allocator_type, 199 pre_fence_visitor)); 200 } 201 202 template <bool kIsInstrumented> 203 inline ObjPtr<String> String::AllocEmptyString(Thread* self, gc::AllocatorType allocator_type) { 204 const int32_t length_with_flag = String::GetFlaggedCount(0, /* compressible= */ true); 205 SetStringCountVisitor visitor(length_with_flag); 206 return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor); 207 } 208 209 template <bool kIsInstrumented> 210 inline ObjPtr<String> String::AllocFromByteArray(Thread* self, 211 int32_t byte_length, 212 Handle<ByteArray> array, 213 int32_t offset, 214 int32_t high_byte, 215 gc::AllocatorType allocator_type) { 216 const uint8_t* const src = reinterpret_cast<uint8_t*>(array->GetData()) + offset; 217 high_byte &= 0xff; // Extract the relevant bits before determining `compressible`. 218 const bool compressible = 219 kUseStringCompression && String::AllASCII<uint8_t>(src, byte_length) && (high_byte == 0); 220 const int32_t length_with_flag = String::GetFlaggedCount(byte_length, compressible); 221 SetStringCountAndBytesVisitor visitor(length_with_flag, array, offset, high_byte << 8); 222 return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor); 223 } 224 225 template <bool kIsInstrumented> 226 inline ObjPtr<String> String::AllocFromCharArray(Thread* self, 227 int32_t count, 228 Handle<CharArray> array, 229 int32_t offset, 230 gc::AllocatorType allocator_type) { 231 // It is a caller error to have a count less than the actual array's size. 232 DCHECK_GE(array->GetLength(), count); 233 const bool compressible = kUseStringCompression && 234 String::AllASCII<uint16_t>(array->GetData() + offset, count); 235 const int32_t length_with_flag = String::GetFlaggedCount(count, compressible); 236 SetStringCountAndValueVisitorFromCharArray visitor(length_with_flag, array, offset); 237 return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor); 238 } 239 240 template <bool kIsInstrumented> 241 inline ObjPtr<String> String::AllocFromString(Thread* self, 242 int32_t string_length, 243 Handle<String> string, 244 int32_t offset, 245 gc::AllocatorType allocator_type) { 246 const bool compressible = kUseStringCompression && 247 ((string->IsCompressed()) ? true : String::AllASCII<uint16_t>(string->GetValue() + offset, 248 string_length)); 249 const int32_t length_with_flag = String::GetFlaggedCount(string_length, compressible); 250 SetStringCountAndValueVisitorFromString visitor(length_with_flag, string, offset); 251 return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor); 252 } 253 254 } // namespace mirror 255 } // namespace art 256 257 #endif // ART_RUNTIME_MIRROR_STRING_ALLOC_INL_H_ 258