1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_MIRROR_STRING_ALLOC_INL_H_
17*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_MIRROR_STRING_ALLOC_INL_H_
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "string-inl.h"
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker #include "android-base/endian.h"
22*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker #include "array.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
26*795d594fSAndroid Build Coastguard Worker #include "class.h"
27*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "gc/allocator_type.h"
29*795d594fSAndroid Build Coastguard Worker #include "gc/heap-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h"
31*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
32*795d594fSAndroid Build Coastguard Worker #include "runtime_globals.h"
33*795d594fSAndroid Build Coastguard Worker #include "thread.h"
34*795d594fSAndroid Build Coastguard Worker
35*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
36*795d594fSAndroid Build Coastguard Worker namespace mirror {
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker // Sets string count in the allocation code path to ensure it is guarded by a CAS.
39*795d594fSAndroid Build Coastguard Worker class SetStringCountVisitor {
40*795d594fSAndroid Build Coastguard Worker public:
SetStringCountVisitor(int32_t count)41*795d594fSAndroid Build Coastguard Worker explicit SetStringCountVisitor(int32_t count) : count_(count) {
42*795d594fSAndroid Build Coastguard Worker }
43*795d594fSAndroid Build Coastguard Worker
operator()44*795d594fSAndroid Build Coastguard Worker void operator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) const
45*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
46*795d594fSAndroid Build Coastguard Worker // Avoid AsString as object is not yet in live bitmap or allocation stack.
47*795d594fSAndroid Build Coastguard Worker ObjPtr<String> string = ObjPtr<String>::DownCast(obj);
48*795d594fSAndroid Build Coastguard Worker string->SetCount(count_);
49*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(string->IsCompressed(), kUseStringCompression);
50*795d594fSAndroid Build Coastguard Worker }
51*795d594fSAndroid Build Coastguard Worker
52*795d594fSAndroid Build Coastguard Worker private:
53*795d594fSAndroid Build Coastguard Worker const int32_t count_;
54*795d594fSAndroid Build Coastguard Worker };
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker // Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
57*795d594fSAndroid Build Coastguard Worker class SetStringCountAndBytesVisitor {
58*795d594fSAndroid Build Coastguard Worker public:
SetStringCountAndBytesVisitor(int32_t count,Handle<ByteArray> src_array,int32_t offset,int32_t high_byte)59*795d594fSAndroid Build Coastguard Worker SetStringCountAndBytesVisitor(int32_t count, Handle<ByteArray> src_array, int32_t offset,
60*795d594fSAndroid Build Coastguard Worker int32_t high_byte)
61*795d594fSAndroid Build Coastguard Worker : count_(count), src_array_(src_array), offset_(offset), high_byte_(high_byte) {
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker
operator()64*795d594fSAndroid Build Coastguard Worker void operator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) const
65*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
66*795d594fSAndroid Build Coastguard Worker // Avoid AsString as object is not yet in live bitmap or allocation stack.
67*795d594fSAndroid Build Coastguard Worker ObjPtr<String> string = ObjPtr<String>::DownCast(obj);
68*795d594fSAndroid Build Coastguard Worker string->SetCount(count_);
69*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(string->IsCompressed(), kUseStringCompression);
70*795d594fSAndroid Build Coastguard Worker int32_t length = String::GetLengthFromCount(count_);
71*795d594fSAndroid Build Coastguard Worker const uint8_t* const src = reinterpret_cast<uint8_t*>(src_array_->GetData()) + offset_;
72*795d594fSAndroid Build Coastguard Worker if (string->IsCompressed()) {
73*795d594fSAndroid Build Coastguard Worker uint8_t* valueCompressed = string->GetValueCompressed();
74*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < length; i++) {
75*795d594fSAndroid Build Coastguard Worker valueCompressed[i] = (src[i] & 0xFF);
76*795d594fSAndroid Build Coastguard Worker }
77*795d594fSAndroid Build Coastguard Worker } else {
78*795d594fSAndroid Build Coastguard Worker uint16_t* value = string->GetValue();
79*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < length; i++) {
80*795d594fSAndroid Build Coastguard Worker value[i] = high_byte_ + (src[i] & 0xFF);
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker private:
86*795d594fSAndroid Build Coastguard Worker const int32_t count_;
87*795d594fSAndroid Build Coastguard Worker Handle<ByteArray> src_array_;
88*795d594fSAndroid Build Coastguard Worker const int32_t offset_;
89*795d594fSAndroid Build Coastguard Worker const int32_t high_byte_;
90*795d594fSAndroid Build Coastguard Worker };
91*795d594fSAndroid Build Coastguard Worker
92*795d594fSAndroid Build Coastguard Worker // Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
93*795d594fSAndroid Build Coastguard Worker class SetStringCountAndUtf16BytesVisitor {
94*795d594fSAndroid Build Coastguard Worker public:
SetStringCountAndUtf16BytesVisitor(int32_t count,Handle<ByteArray> src_array,int32_t offset)95*795d594fSAndroid Build Coastguard Worker SetStringCountAndUtf16BytesVisitor(int32_t count, Handle<ByteArray> src_array, int32_t offset)
96*795d594fSAndroid Build Coastguard Worker : count_(count), src_array_(src_array), offset_(offset) {
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker
operator()99*795d594fSAndroid Build Coastguard Worker void operator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) const
100*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
101*795d594fSAndroid Build Coastguard Worker // Avoid AsString as object is not yet in live bitmap or allocation stack.
102*795d594fSAndroid Build Coastguard Worker ObjPtr<String> string = ObjPtr<String>::DownCast(obj);
103*795d594fSAndroid Build Coastguard Worker string->SetCount(count_);
104*795d594fSAndroid Build Coastguard Worker DCHECK_IMPLIES(string->IsCompressed(), kUseStringCompression);
105*795d594fSAndroid Build Coastguard Worker uint32_t length = String::GetLengthFromCount(count_);
106*795d594fSAndroid Build Coastguard Worker const uint8_t* const src = reinterpret_cast<uint8_t*>(src_array_->GetData()) + offset_;
107*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(string->IsCompressed())) {
108*795d594fSAndroid Build Coastguard Worker uint8_t* valueCompressed = string->GetValueCompressed();
109*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < length; i++) {
110*795d594fSAndroid Build Coastguard Worker valueCompressed[i] = (src[i << 1] & 0xFF);
111*795d594fSAndroid Build Coastguard Worker }
112*795d594fSAndroid Build Coastguard Worker } else {
113*795d594fSAndroid Build Coastguard Worker uint16_t* value = string->GetValue();
114*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < length; i++) {
115*795d594fSAndroid Build Coastguard Worker uint32_t index = (i << 1);
116*795d594fSAndroid Build Coastguard Worker value[i] = (src[index] & 0xFF) + ((src[index + 1] & 0xFF) << 8);
117*795d594fSAndroid Build Coastguard Worker }
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker }
120*795d594fSAndroid Build Coastguard Worker
121*795d594fSAndroid Build Coastguard Worker private:
122*795d594fSAndroid Build Coastguard Worker const int32_t count_;
123*795d594fSAndroid Build Coastguard Worker Handle<ByteArray> src_array_;
124*795d594fSAndroid Build Coastguard Worker const int32_t offset_;
125*795d594fSAndroid Build Coastguard Worker };
126*795d594fSAndroid Build Coastguard Worker
127*795d594fSAndroid Build Coastguard Worker // Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
128*795d594fSAndroid Build Coastguard Worker class SetStringCountAndValueVisitorFromCharArray {
129*795d594fSAndroid Build Coastguard Worker public:
SetStringCountAndValueVisitorFromCharArray(int32_t count,Handle<CharArray> src_array,int32_t offset)130*795d594fSAndroid Build Coastguard Worker SetStringCountAndValueVisitorFromCharArray(int32_t count, Handle<CharArray> src_array,
131*795d594fSAndroid Build Coastguard Worker int32_t offset) :
132*795d594fSAndroid Build Coastguard Worker count_(count), src_array_(src_array), offset_(offset) {
133*795d594fSAndroid Build Coastguard Worker }
134*795d594fSAndroid Build Coastguard Worker
operator()135*795d594fSAndroid Build Coastguard Worker void operator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) const
136*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
137*795d594fSAndroid Build Coastguard Worker // Avoid AsString as object is not yet in live bitmap or allocation stack.
138*795d594fSAndroid Build Coastguard Worker ObjPtr<String> string = ObjPtr<String>::DownCast(obj);
139*795d594fSAndroid Build Coastguard Worker string->SetCount(count_);
140*795d594fSAndroid Build Coastguard Worker const uint16_t* const src = src_array_->GetData() + offset_;
141*795d594fSAndroid Build Coastguard Worker const int32_t length = String::GetLengthFromCount(count_);
142*795d594fSAndroid Build Coastguard Worker if (kUseStringCompression && String::IsCompressed(count_)) {
143*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < length; ++i) {
144*795d594fSAndroid Build Coastguard Worker string->GetValueCompressed()[i] = static_cast<uint8_t>(src[i]);
145*795d594fSAndroid Build Coastguard Worker }
146*795d594fSAndroid Build Coastguard Worker } else {
147*795d594fSAndroid Build Coastguard Worker memcpy(string->GetValue(), src, length * sizeof(uint16_t));
148*795d594fSAndroid Build Coastguard Worker }
149*795d594fSAndroid Build Coastguard Worker }
150*795d594fSAndroid Build Coastguard Worker
151*795d594fSAndroid Build Coastguard Worker private:
152*795d594fSAndroid Build Coastguard Worker const int32_t count_;
153*795d594fSAndroid Build Coastguard Worker Handle<CharArray> src_array_;
154*795d594fSAndroid Build Coastguard Worker const int32_t offset_;
155*795d594fSAndroid Build Coastguard Worker };
156*795d594fSAndroid Build Coastguard Worker
157*795d594fSAndroid Build Coastguard Worker // Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
158*795d594fSAndroid Build Coastguard Worker class SetStringCountAndValueVisitorFromString {
159*795d594fSAndroid Build Coastguard Worker public:
SetStringCountAndValueVisitorFromString(int32_t count,Handle<String> src_string,int32_t offset)160*795d594fSAndroid Build Coastguard Worker SetStringCountAndValueVisitorFromString(int32_t count,
161*795d594fSAndroid Build Coastguard Worker Handle<String> src_string,
162*795d594fSAndroid Build Coastguard Worker int32_t offset) :
163*795d594fSAndroid Build Coastguard Worker count_(count), src_string_(src_string), offset_(offset) {
164*795d594fSAndroid Build Coastguard Worker }
165*795d594fSAndroid Build Coastguard Worker
operator()166*795d594fSAndroid Build Coastguard Worker void operator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) const
167*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
168*795d594fSAndroid Build Coastguard Worker // Avoid AsString as object is not yet in live bitmap or allocation stack.
169*795d594fSAndroid Build Coastguard Worker ObjPtr<String> string = ObjPtr<String>::DownCast(obj);
170*795d594fSAndroid Build Coastguard Worker string->SetCount(count_);
171*795d594fSAndroid Build Coastguard Worker const int32_t length = String::GetLengthFromCount(count_);
172*795d594fSAndroid Build Coastguard Worker bool compressible = kUseStringCompression && String::IsCompressed(count_);
173*795d594fSAndroid Build Coastguard Worker if (src_string_->IsCompressed()) {
174*795d594fSAndroid Build Coastguard Worker const uint8_t* const src = src_string_->GetValueCompressed() + offset_;
175*795d594fSAndroid Build Coastguard Worker memcpy(string->GetValueCompressed(), src, length * sizeof(uint8_t));
176*795d594fSAndroid Build Coastguard Worker } else {
177*795d594fSAndroid Build Coastguard Worker const uint16_t* const src = src_string_->GetValue() + offset_;
178*795d594fSAndroid Build Coastguard Worker if (compressible) {
179*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < length; ++i) {
180*795d594fSAndroid Build Coastguard Worker string->GetValueCompressed()[i] = static_cast<uint8_t>(src[i]);
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker } else {
183*795d594fSAndroid Build Coastguard Worker memcpy(string->GetValue(), src, length * sizeof(uint16_t));
184*795d594fSAndroid Build Coastguard Worker }
185*795d594fSAndroid Build Coastguard Worker }
186*795d594fSAndroid Build Coastguard Worker }
187*795d594fSAndroid Build Coastguard Worker
188*795d594fSAndroid Build Coastguard Worker private:
189*795d594fSAndroid Build Coastguard Worker const int32_t count_;
190*795d594fSAndroid Build Coastguard Worker Handle<String> src_string_;
191*795d594fSAndroid Build Coastguard Worker const int32_t offset_;
192*795d594fSAndroid Build Coastguard Worker };
193*795d594fSAndroid Build Coastguard Worker
194*795d594fSAndroid Build Coastguard Worker template <bool kIsInstrumented, typename PreFenceVisitor>
Alloc(Thread * self,int32_t utf16_length_with_flag,gc::AllocatorType allocator_type,const PreFenceVisitor & pre_fence_visitor)195*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> String::Alloc(Thread* self,
196*795d594fSAndroid Build Coastguard Worker int32_t utf16_length_with_flag,
197*795d594fSAndroid Build Coastguard Worker gc::AllocatorType allocator_type,
198*795d594fSAndroid Build Coastguard Worker const PreFenceVisitor& pre_fence_visitor) {
199*795d594fSAndroid Build Coastguard Worker constexpr size_t header_size = sizeof(String);
200*795d594fSAndroid Build Coastguard Worker const bool compressible = kUseStringCompression && String::IsCompressed(utf16_length_with_flag);
201*795d594fSAndroid Build Coastguard Worker const size_t block_size = (compressible) ? sizeof(uint8_t) : sizeof(uint16_t);
202*795d594fSAndroid Build Coastguard Worker size_t length = String::GetLengthFromCount(utf16_length_with_flag);
203*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(length) <= sizeof(size_t),
204*795d594fSAndroid Build Coastguard Worker "static_cast<size_t>(utf16_length) must not lose bits.");
205*795d594fSAndroid Build Coastguard Worker size_t data_size = block_size * length;
206*795d594fSAndroid Build Coastguard Worker size_t size = header_size + data_size;
207*795d594fSAndroid Build Coastguard Worker // String.equals() intrinsics assume zero-padding up to kObjectAlignment,
208*795d594fSAndroid Build Coastguard Worker // so make sure the allocator clears the padding as well.
209*795d594fSAndroid Build Coastguard Worker // http://b/23528461
210*795d594fSAndroid Build Coastguard Worker size_t alloc_size = RoundUp(size, kObjectAlignment);
211*795d594fSAndroid Build Coastguard Worker
212*795d594fSAndroid Build Coastguard Worker Runtime* runtime = Runtime::Current();
213*795d594fSAndroid Build Coastguard Worker ObjPtr<Class> string_class = GetClassRoot<String>(runtime->GetClassLinker());
214*795d594fSAndroid Build Coastguard Worker // Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
215*795d594fSAndroid Build Coastguard Worker // Do this by comparing with the maximum length that will _not_ cause an overflow.
216*795d594fSAndroid Build Coastguard Worker const size_t overflow_length = (-header_size) / block_size; // Unsigned arithmetic.
217*795d594fSAndroid Build Coastguard Worker const size_t max_alloc_length = overflow_length - 1u;
218*795d594fSAndroid Build Coastguard Worker static_assert(IsAligned<sizeof(uint16_t)>(kObjectAlignment),
219*795d594fSAndroid Build Coastguard Worker "kObjectAlignment must be at least as big as Java char alignment");
220*795d594fSAndroid Build Coastguard Worker const size_t max_length = RoundDown(max_alloc_length, kObjectAlignment / block_size);
221*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(length > max_length)) {
222*795d594fSAndroid Build Coastguard Worker self->ThrowOutOfMemoryError(
223*795d594fSAndroid Build Coastguard Worker android::base::StringPrintf("%s of length %d would overflow",
224*795d594fSAndroid Build Coastguard Worker Class::PrettyDescriptor(string_class).c_str(),
225*795d594fSAndroid Build Coastguard Worker static_cast<int>(length)).c_str());
226*795d594fSAndroid Build Coastguard Worker return nullptr;
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker
229*795d594fSAndroid Build Coastguard Worker gc::Heap* heap = runtime->GetHeap();
230*795d594fSAndroid Build Coastguard Worker return ObjPtr<String>::DownCast(
231*795d594fSAndroid Build Coastguard Worker heap->AllocObjectWithAllocator<kIsInstrumented>(self,
232*795d594fSAndroid Build Coastguard Worker string_class,
233*795d594fSAndroid Build Coastguard Worker alloc_size,
234*795d594fSAndroid Build Coastguard Worker allocator_type,
235*795d594fSAndroid Build Coastguard Worker pre_fence_visitor));
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker
238*795d594fSAndroid Build Coastguard Worker template <bool kIsInstrumented>
AllocEmptyString(Thread * self,gc::AllocatorType allocator_type)239*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> String::AllocEmptyString(Thread* self, gc::AllocatorType allocator_type) {
240*795d594fSAndroid Build Coastguard Worker const int32_t length_with_flag = String::GetFlaggedCount(0, /* compressible= */ true);
241*795d594fSAndroid Build Coastguard Worker SetStringCountVisitor visitor(length_with_flag);
242*795d594fSAndroid Build Coastguard Worker return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor);
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker
245*795d594fSAndroid Build Coastguard Worker template <bool kIsInstrumented>
AllocFromByteArray(Thread * self,int32_t byte_length,Handle<ByteArray> array,int32_t offset,int32_t high_byte,gc::AllocatorType allocator_type)246*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> String::AllocFromByteArray(Thread* self,
247*795d594fSAndroid Build Coastguard Worker int32_t byte_length,
248*795d594fSAndroid Build Coastguard Worker Handle<ByteArray> array,
249*795d594fSAndroid Build Coastguard Worker int32_t offset,
250*795d594fSAndroid Build Coastguard Worker int32_t high_byte,
251*795d594fSAndroid Build Coastguard Worker gc::AllocatorType allocator_type) {
252*795d594fSAndroid Build Coastguard Worker const uint8_t* const src = reinterpret_cast<uint8_t*>(array->GetData()) + offset;
253*795d594fSAndroid Build Coastguard Worker high_byte &= 0xff; // Extract the relevant bits before determining `compressible`.
254*795d594fSAndroid Build Coastguard Worker const bool compressible =
255*795d594fSAndroid Build Coastguard Worker kUseStringCompression &&
256*795d594fSAndroid Build Coastguard Worker String::AllASCII<uint8_t>(src, byte_length) &&
257*795d594fSAndroid Build Coastguard Worker (high_byte == 0 || byte_length == 0);
258*795d594fSAndroid Build Coastguard Worker const int32_t length_with_flag = String::GetFlaggedCount(byte_length, compressible);
259*795d594fSAndroid Build Coastguard Worker SetStringCountAndBytesVisitor visitor(length_with_flag, array, offset, high_byte << 8);
260*795d594fSAndroid Build Coastguard Worker return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor);
261*795d594fSAndroid Build Coastguard Worker }
262*795d594fSAndroid Build Coastguard Worker
263*795d594fSAndroid Build Coastguard Worker template <bool kIsInstrumented>
AllocFromUtf16ByteArray(Thread * self,int32_t char_count,Handle<ByteArray> array,int32_t offset,gc::AllocatorType allocator_type)264*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> String::AllocFromUtf16ByteArray(Thread* self,
265*795d594fSAndroid Build Coastguard Worker int32_t char_count,
266*795d594fSAndroid Build Coastguard Worker Handle<ByteArray> array,
267*795d594fSAndroid Build Coastguard Worker int32_t offset,
268*795d594fSAndroid Build Coastguard Worker gc::AllocatorType allocator_type) {
269*795d594fSAndroid Build Coastguard Worker static_assert(__BYTE_ORDER == __LITTLE_ENDIAN,
270*795d594fSAndroid Build Coastguard Worker "Please update this function and java-side callers to support big endian.");
271*795d594fSAndroid Build Coastguard Worker const uint8_t* const src = reinterpret_cast<uint8_t*>(array->GetData()) + offset;
272*795d594fSAndroid Build Coastguard Worker bool compressible = kUseStringCompression;
273*795d594fSAndroid Build Coastguard Worker if (compressible) {
274*795d594fSAndroid Build Coastguard Worker uint32_t byte_count = (static_cast<uint32_t>(char_count) << 1);
275*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < byte_count; i += 2) {
276*795d594fSAndroid Build Coastguard Worker if (!IsASCII((src[i] & 0xff) + ((src[i + 1] & 0xff) << 8))) {
277*795d594fSAndroid Build Coastguard Worker compressible = false;
278*795d594fSAndroid Build Coastguard Worker break;
279*795d594fSAndroid Build Coastguard Worker }
280*795d594fSAndroid Build Coastguard Worker }
281*795d594fSAndroid Build Coastguard Worker }
282*795d594fSAndroid Build Coastguard Worker const int32_t length_with_flag = String::GetFlaggedCount(char_count, compressible);
283*795d594fSAndroid Build Coastguard Worker SetStringCountAndUtf16BytesVisitor visitor(length_with_flag, array, offset);
284*795d594fSAndroid Build Coastguard Worker return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor);
285*795d594fSAndroid Build Coastguard Worker }
286*795d594fSAndroid Build Coastguard Worker
287*795d594fSAndroid Build Coastguard Worker template <bool kIsInstrumented>
AllocFromCharArray(Thread * self,int32_t count,Handle<CharArray> array,int32_t offset,gc::AllocatorType allocator_type)288*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> String::AllocFromCharArray(Thread* self,
289*795d594fSAndroid Build Coastguard Worker int32_t count,
290*795d594fSAndroid Build Coastguard Worker Handle<CharArray> array,
291*795d594fSAndroid Build Coastguard Worker int32_t offset,
292*795d594fSAndroid Build Coastguard Worker gc::AllocatorType allocator_type) {
293*795d594fSAndroid Build Coastguard Worker // It is a caller error to have a count less than the actual array's size.
294*795d594fSAndroid Build Coastguard Worker DCHECK_GE(array->GetLength(), count);
295*795d594fSAndroid Build Coastguard Worker const bool compressible = kUseStringCompression &&
296*795d594fSAndroid Build Coastguard Worker String::AllASCII<uint16_t>(array->GetData() + offset, count);
297*795d594fSAndroid Build Coastguard Worker const int32_t length_with_flag = String::GetFlaggedCount(count, compressible);
298*795d594fSAndroid Build Coastguard Worker SetStringCountAndValueVisitorFromCharArray visitor(length_with_flag, array, offset);
299*795d594fSAndroid Build Coastguard Worker return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor);
300*795d594fSAndroid Build Coastguard Worker }
301*795d594fSAndroid Build Coastguard Worker
302*795d594fSAndroid Build Coastguard Worker template <bool kIsInstrumented>
AllocFromString(Thread * self,int32_t string_length,Handle<String> string,int32_t offset,gc::AllocatorType allocator_type)303*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> String::AllocFromString(Thread* self,
304*795d594fSAndroid Build Coastguard Worker int32_t string_length,
305*795d594fSAndroid Build Coastguard Worker Handle<String> string,
306*795d594fSAndroid Build Coastguard Worker int32_t offset,
307*795d594fSAndroid Build Coastguard Worker gc::AllocatorType allocator_type) {
308*795d594fSAndroid Build Coastguard Worker const bool compressible = kUseStringCompression &&
309*795d594fSAndroid Build Coastguard Worker ((string->IsCompressed()) ? true : String::AllASCII<uint16_t>(string->GetValue() + offset,
310*795d594fSAndroid Build Coastguard Worker string_length));
311*795d594fSAndroid Build Coastguard Worker const int32_t length_with_flag = String::GetFlaggedCount(string_length, compressible);
312*795d594fSAndroid Build Coastguard Worker SetStringCountAndValueVisitorFromString visitor(length_with_flag, string, offset);
313*795d594fSAndroid Build Coastguard Worker return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor);
314*795d594fSAndroid Build Coastguard Worker }
315*795d594fSAndroid Build Coastguard Worker
316*795d594fSAndroid Build Coastguard Worker } // namespace mirror
317*795d594fSAndroid Build Coastguard Worker } // namespace art
318*795d594fSAndroid Build Coastguard Worker
319*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_MIRROR_STRING_ALLOC_INL_H_
320