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_INL_H_ 18#define ART_RUNTIME_MIRROR_STRING_INL_H_ 19 20#include "array.h" 21#include "class.h" 22#include "gc/heap-inl.h" 23#include "intern_table.h" 24#include "runtime.h" 25#include "string.h" 26#include "thread.h" 27#include "utf.h" 28#include "utils.h" 29 30namespace art { 31namespace mirror { 32 33inline uint32_t String::ClassSize(size_t pointer_size) { 34 uint32_t vtable_entries = Object::kVTableLength + 52; 35 return Class::ComputeClassSize(true, vtable_entries, 0, 1, 0, 1, 2, pointer_size); 36} 37 38// Sets string count in the allocation code path to ensure it is guarded by a CAS. 39class SetStringCountVisitor { 40 public: 41 explicit SetStringCountVisitor(int32_t count) : count_(count) { 42 } 43 44 void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const 45 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 46 // Avoid AsString as object is not yet in live bitmap or allocation stack. 47 String* string = down_cast<String*>(obj); 48 string->SetCount(count_); 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. 56class 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()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const 64 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 65 // Avoid AsString as object is not yet in live bitmap or allocation stack. 66 String* string = down_cast<String*>(obj); 67 string->SetCount(count_); 68 uint16_t* value = string->GetValue(); 69 const uint8_t* const src = reinterpret_cast<uint8_t*>(src_array_->GetData()) + offset_; 70 for (int i = 0; i < count_; i++) { 71 value[i] = high_byte_ + (src[i] & 0xFF); 72 } 73 } 74 75 private: 76 const int32_t count_; 77 Handle<ByteArray> src_array_; 78 const int32_t offset_; 79 const int32_t high_byte_; 80}; 81 82// Sets string count and value in the allocation code path to ensure it is guarded by a CAS. 83class SetStringCountAndValueVisitorFromCharArray { 84 public: 85 SetStringCountAndValueVisitorFromCharArray(int32_t count, Handle<CharArray> src_array, 86 int32_t offset) : 87 count_(count), src_array_(src_array), offset_(offset) { 88 } 89 90 void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const 91 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 92 // Avoid AsString as object is not yet in live bitmap or allocation stack. 93 String* string = down_cast<String*>(obj); 94 string->SetCount(count_); 95 const uint16_t* const src = src_array_->GetData() + offset_; 96 memcpy(string->GetValue(), src, count_ * sizeof(uint16_t)); 97 } 98 99 private: 100 const int32_t count_; 101 Handle<CharArray> src_array_; 102 const int32_t offset_; 103}; 104 105// Sets string count and value in the allocation code path to ensure it is guarded by a CAS. 106class SetStringCountAndValueVisitorFromString { 107 public: 108 SetStringCountAndValueVisitorFromString(int32_t count, Handle<String> src_string, 109 int32_t offset) : 110 count_(count), src_string_(src_string), offset_(offset) { 111 } 112 113 void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const 114 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 115 // Avoid AsString as object is not yet in live bitmap or allocation stack. 116 String* string = down_cast<String*>(obj); 117 string->SetCount(count_); 118 const uint16_t* const src = src_string_->GetValue() + offset_; 119 memcpy(string->GetValue(), src, count_ * sizeof(uint16_t)); 120 } 121 122 private: 123 const int32_t count_; 124 Handle<String> src_string_; 125 const int32_t offset_; 126}; 127 128inline String* String::Intern() { 129 return Runtime::Current()->GetInternTable()->InternWeak(this); 130} 131 132inline uint16_t String::CharAt(int32_t index) { 133 int32_t count = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_)); 134 if (UNLIKELY((index < 0) || (index >= count))) { 135 Thread* self = Thread::Current(); 136 self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;", 137 "length=%i; index=%i", count, index); 138 return 0; 139 } 140 return GetValue()[index]; 141} 142 143template<VerifyObjectFlags kVerifyFlags> 144inline size_t String::SizeOf() { 145 return sizeof(String) + (sizeof(uint16_t) * GetLength<kVerifyFlags>()); 146} 147 148template <bool kIsInstrumented, typename PreFenceVisitor> 149inline String* String::Alloc(Thread* self, int32_t utf16_length, gc::AllocatorType allocator_type, 150 const PreFenceVisitor& pre_fence_visitor) { 151 size_t header_size = sizeof(String); 152 size_t data_size = sizeof(uint16_t) * utf16_length; 153 size_t size = header_size + data_size; 154 Class* string_class = GetJavaLangString(); 155 156 // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. 157 if (UNLIKELY(size < data_size)) { 158 self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow", 159 PrettyDescriptor(string_class).c_str(), 160 utf16_length).c_str()); 161 return nullptr; 162 } 163 gc::Heap* heap = Runtime::Current()->GetHeap(); 164 return down_cast<String*>( 165 heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, string_class, size, 166 allocator_type, pre_fence_visitor)); 167} 168 169template <bool kIsInstrumented> 170inline String* String::AllocFromByteArray(Thread* self, int32_t byte_length, 171 Handle<ByteArray> array, int32_t offset, 172 int32_t high_byte, gc::AllocatorType allocator_type) { 173 SetStringCountAndBytesVisitor visitor(byte_length, array, offset, high_byte << 8); 174 String* string = Alloc<kIsInstrumented>(self, byte_length, allocator_type, visitor); 175 return string; 176} 177 178template <bool kIsInstrumented> 179inline String* String::AllocFromCharArray(Thread* self, int32_t array_length, 180 Handle<CharArray> array, int32_t offset, 181 gc::AllocatorType allocator_type) { 182 SetStringCountAndValueVisitorFromCharArray visitor(array_length, array, offset); 183 String* new_string = Alloc<kIsInstrumented>(self, array_length, allocator_type, visitor); 184 return new_string; 185} 186 187template <bool kIsInstrumented> 188inline String* String::AllocFromString(Thread* self, int32_t string_length, Handle<String> string, 189 int32_t offset, gc::AllocatorType allocator_type) { 190 SetStringCountAndValueVisitorFromString visitor(string_length, string, offset); 191 String* new_string = Alloc<kIsInstrumented>(self, string_length, allocator_type, visitor); 192 return new_string; 193} 194 195inline int32_t String::GetHashCode() { 196 int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_)); 197 if (UNLIKELY(result == 0)) { 198 result = ComputeHashCode(); 199 } 200 DCHECK(result != 0 || ComputeUtf16Hash(GetValue(), GetLength()) == 0) 201 << ToModifiedUtf8() << " " << result; 202 return result; 203} 204 205} // namespace mirror 206} // namespace art 207 208#endif // ART_RUNTIME_MIRROR_STRING_INL_H_ 209