blob: 8f5a7d42573d1ba51c1505086775dfbaec0c57a8 [file] [log] [blame]
Ian Rogersb0fa5dc2014-04-28 16:47:08 -07001/*
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"
Mingyao Yang98d1cc82014-05-15 17:02:16 -070021#include "class.h"
Jeff Hao848f70a2014-01-15 13:49:50 -080022#include "gc/heap-inl.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070023#include "intern_table.h"
24#include "runtime.h"
25#include "string.h"
26#include "thread.h"
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070027#include "utf.h"
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070028
29namespace art {
30namespace mirror {
31
Mingyao Yang98d1cc82014-05-15 17:02:16 -070032inline uint32_t String::ClassSize() {
Jeff Hao848f70a2014-01-15 13:49:50 -080033 uint32_t vtable_entries = Object::kVTableLength + 52;
Fred Shih37f05ef2014-07-16 18:38:08 -070034 return Class::ComputeClassSize(true, vtable_entries, 0, 1, 0, 1, 2);
Mingyao Yang98d1cc82014-05-15 17:02:16 -070035}
36
Jeff Hao848f70a2014-01-15 13:49:50 -080037// Sets string count in the allocation code path to ensure it is guarded by a CAS.
38class SetStringCountVisitor {
39 public:
40 explicit SetStringCountVisitor(int32_t count) : count_(count) {
41 }
Narayan Kamatha5afcfc2015-01-29 20:06:46 +000042
Jeff Hao848f70a2014-01-15 13:49:50 -080043 void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const
44 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
45 // Avoid AsString as object is not yet in live bitmap or allocation stack.
46 String* string = down_cast<String*>(obj);
47 string->SetCount(count_);
48 }
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070049
Jeff Hao848f70a2014-01-15 13:49:50 -080050 private:
51 const int32_t count_;
52};
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070053
Jeff Hao848f70a2014-01-15 13:49:50 -080054// Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
55class SetStringCountAndBytesVisitor {
56 public:
57 SetStringCountAndBytesVisitor(int32_t count, uint8_t* src, int32_t high_byte)
58 : count_(count), src_(src), high_byte_(high_byte) {
59 }
60
61 void operator()(Object* obj, size_t usable_size ATTRIBUTE_UNUSED) const
62 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
63 // Avoid AsString as object is not yet in live bitmap or allocation stack.
64 String* string = down_cast<String*>(obj);
65 string->SetCount(count_);
66 uint16_t* value = string->GetValue();
67 for (int i = 0; i < count_; i++) {
68 value[i] = high_byte_ + (src_[i] & 0xFF);
69 }
70 }
71
72 private:
73 const int32_t count_;
74 const uint8_t* const src_;
75 const int32_t high_byte_;
76};
77
78// Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
79class SetStringCountAndValueVisitor {
80 public:
81 SetStringCountAndValueVisitor(int32_t count, uint16_t* src) : count_(count), src_(src) {
82 }
83
84 void operator()(Object* obj, size_t usable_size) const
85 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
86 UNUSED(usable_size);
87 // Avoid AsString as object is not yet in live bitmap or allocation stack.
88 String* string = down_cast<String*>(obj);
89 string->SetCount(count_);
90 memcpy(string->GetValue(), src_, count_ * sizeof(uint16_t));
91 }
92
93 private:
94 const int32_t count_;
95 const uint16_t* const src_;
96};
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070097
98inline String* String::Intern() {
99 return Runtime::Current()->GetInternTable()->InternWeak(this);
100}
101
Jeff Hao848f70a2014-01-15 13:49:50 -0800102inline uint16_t String::CharAt(int32_t index) {
103 int32_t count = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_));
104 if (UNLIKELY((index < 0) || (index >= count))) {
105 Thread* self = Thread::Current();
106 self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
107 "length=%i; index=%i", count, index);
108 return 0;
109 }
110 return GetValue()[index];
111}
112
113template<VerifyObjectFlags kVerifyFlags>
114inline size_t String::SizeOf() {
115 return sizeof(String) + (sizeof(uint16_t) * GetLength<kVerifyFlags>());
116}
117
118template <bool kIsInstrumented, typename PreFenceVisitor>
119inline String* String::Alloc(Thread* self, int32_t utf16_length, gc::AllocatorType allocator_type,
120 const PreFenceVisitor& pre_fence_visitor) {
121 size_t header_size = sizeof(String);
122 size_t data_size = sizeof(uint16_t) * utf16_length;
123 size_t size = header_size + data_size;
124 Class* string_class = GetJavaLangString();
125
126 // Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
127 if (UNLIKELY(size < data_size)) {
128 self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow",
129 PrettyDescriptor(string_class).c_str(),
130 utf16_length).c_str());
131 return nullptr;
132 }
133 gc::Heap* heap = Runtime::Current()->GetHeap();
134 return down_cast<String*>(
135 heap->AllocObjectWithAllocator<kIsInstrumented, false>(self, string_class, size,
136 allocator_type, pre_fence_visitor));
137}
138
139template <bool kIsInstrumented>
140inline String* String::AllocFromByteArray(Thread* self, int32_t byte_length,
141 Handle<ByteArray> array, int32_t offset,
142 int32_t high_byte, gc::AllocatorType allocator_type) {
143 uint8_t* data = reinterpret_cast<uint8_t*>(array->GetData()) + offset;
144 SetStringCountAndBytesVisitor visitor(byte_length, data, high_byte << 8);
145 String* string = Alloc<kIsInstrumented>(self, byte_length, allocator_type, visitor);
146 return string;
147}
148
149template <bool kIsInstrumented>
150inline String* String::AllocFromCharArray(Thread* self, int32_t array_length,
151 Handle<CharArray> array, int32_t offset,
152 gc::AllocatorType allocator_type) {
153 uint16_t* data = array->GetData() + offset;
154 SetStringCountAndValueVisitor visitor(array_length, data);
155 String* new_string = Alloc<kIsInstrumented>(self, array_length, allocator_type, visitor);
156 return new_string;
157}
158
159template <bool kIsInstrumented>
160inline String* String::AllocFromString(Thread* self, int32_t string_length, Handle<String> string,
161 int32_t offset, gc::AllocatorType allocator_type) {
162 uint16_t* data = string->GetValue() + offset;
163 SetStringCountAndValueVisitor visitor(string_length, data);
164 String* new_string = Alloc<kIsInstrumented>(self, string_length, allocator_type, visitor);
165 return new_string;
166}
167
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700168inline int32_t String::GetHashCode() {
169 int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_));
170 if (UNLIKELY(result == 0)) {
171 result = ComputeHashCode();
172 }
Jeff Hao848f70a2014-01-15 13:49:50 -0800173 DCHECK(result != 0 || ComputeUtf16Hash(GetValue(), GetLength()) == 0)
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700174 << ToModifiedUtf8() << " " << result;
175 return result;
176}
177
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700178} // namespace mirror
179} // namespace art
180
181#endif // ART_RUNTIME_MIRROR_STRING_INL_H_