summaryrefslogtreecommitdiff
path: root/runtime/mirror/string-alloc-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/mirror/string-alloc-inl.h')
-rw-r--r--runtime/mirror/string-alloc-inl.h60
1 files changed, 60 insertions, 0 deletions
diff --git a/runtime/mirror/string-alloc-inl.h b/runtime/mirror/string-alloc-inl.h
index 925427a73b..cb2dcb2c85 100644
--- a/runtime/mirror/string-alloc-inl.h
+++ b/runtime/mirror/string-alloc-inl.h
@@ -18,6 +18,7 @@
#include "string-inl.h"
+#include "android-base/endian.h"
#include "android-base/stringprintf.h"
#include "array.h"
@@ -89,6 +90,41 @@ class SetStringCountAndBytesVisitor {
};
// Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
+class SetStringCountAndUtf16BytesVisitor {
+ public:
+ SetStringCountAndUtf16BytesVisitor(int32_t count, Handle<ByteArray> src_array, int32_t offset)
+ : count_(count), src_array_(src_array), offset_(offset) {
+ }
+
+ void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Avoid AsString as object is not yet in live bitmap or allocation stack.
+ ObjPtr<String> string = ObjPtr<String>::DownCast(obj);
+ string->SetCount(count_);
+ DCHECK_IMPLIES(string->IsCompressed(), kUseStringCompression);
+ uint32_t length = String::GetLengthFromCount(count_);
+ const uint8_t* const src = reinterpret_cast<uint8_t*>(src_array_->GetData()) + offset_;
+ if (UNLIKELY(string->IsCompressed())) {
+ uint8_t* valueCompressed = string->GetValueCompressed();
+ for (uint32_t i = 0; i < length; i++) {
+ valueCompressed[i] = (src[i << 1] & 0xFF);
+ }
+ } else {
+ uint16_t* value = string->GetValue();
+ for (uint32_t i = 0; i < length; i++) {
+ uint32_t index = (i << 1);
+ value[i] = (src[index] & 0xFF) + ((src[index + 1] & 0xFF) << 8);
+ }
+ }
+ }
+
+ private:
+ const int32_t count_;
+ Handle<ByteArray> src_array_;
+ const int32_t offset_;
+};
+
+// Sets string count and value in the allocation code path to ensure it is guarded by a CAS.
class SetStringCountAndValueVisitorFromCharArray {
public:
SetStringCountAndValueVisitorFromCharArray(int32_t count, Handle<CharArray> src_array,
@@ -225,6 +261,30 @@ inline ObjPtr<String> String::AllocFromByteArray(Thread* self,
}
template <bool kIsInstrumented>
+inline ObjPtr<String> String::AllocFromUtf16ByteArray(Thread* self,
+ int32_t char_count,
+ Handle<ByteArray> array,
+ int32_t offset,
+ gc::AllocatorType allocator_type) {
+ static_assert(__BYTE_ORDER == __LITTLE_ENDIAN,
+ "Please update this function and java-side callers to support big endian.");
+ const uint8_t* const src = reinterpret_cast<uint8_t*>(array->GetData()) + offset;
+ bool compressible = kUseStringCompression;
+ if (compressible) {
+ uint32_t byte_count = (static_cast<uint32_t>(char_count) << 1);
+ for (uint32_t i = 0; i < byte_count; i += 2) {
+ if (!IsASCII((src[i] & 0xff) + ((src[i + 1] & 0xff) << 8))) {
+ compressible = false;
+ break;
+ }
+ }
+ }
+ const int32_t length_with_flag = String::GetFlaggedCount(char_count, compressible);
+ SetStringCountAndUtf16BytesVisitor visitor(length_with_flag, array, offset);
+ return Alloc<kIsInstrumented>(self, length_with_flag, allocator_type, visitor);
+}
+
+template <bool kIsInstrumented>
inline ObjPtr<String> String::AllocFromCharArray(Thread* self,
int32_t count,
Handle<CharArray> array,