// Sets string count in the allocation code path to ensure it is guarded by a CAS. class SetStringCountVisitor { public: explicit SetStringCountVisitor(int32_t count) : count_(count) {
}
voidoperator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) 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);
}
private: const int32_t count_;
};
// Sets string count and value in the allocation code path to ensure it is guarded by a CAS. class SetStringCountAndBytesVisitor { public:
SetStringCountAndBytesVisitor(int32_t count, Handle<ByteArray> src_array, int32_t offset,
int32_t high_byte)
: count_(count), src_array_(src_array), offset_(offset), high_byte_(high_byte) {
}
voidoperator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) 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);
int32_t length = String::GetLengthFromCount(count_); const uint8_t* const src = reinterpret_cast<uint8_t*>(src_array_->GetData()) + offset_; if (string->IsCompressed()) {
uint8_t* valueCompressed = string->GetValueCompressed(); for (int i = 0; i < length; i++) {
valueCompressed[i] = (src[i] & 0xFF);
}
} else {
uint16_t* value = string->GetValue(); for (int i = 0; i < length; i++) {
value[i] = high_byte_ + (src[i] & 0xFF);
}
}
}
// 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) {
}
voidoperator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) 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);
}
}
}
// 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,
int32_t offset) :
count_(count), src_array_(src_array), offset_(offset) {
}
voidoperator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) 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_); const uint16_t* const src = src_array_->GetData() + offset_; const int32_t length = String::GetLengthFromCount(count_); if (kUseStringCompression && String::IsCompressed(count_)) { for (int i = 0; i < length; ++i) {
string->GetValueCompressed()[i] = static_cast<uint8_t>(src[i]);
}
} else {
memcpy(string->GetValue(), src, length * sizeof(uint16_t));
}
}
// Sets string count and value in the allocation code path to ensure it is guarded by a CAS. class SetStringCountAndValueVisitorFromString { public:
SetStringCountAndValueVisitorFromString(int32_t count,
Handle<String> src_string,
int32_t offset) :
count_(count), src_string_(src_string), offset_(offset) {
}
voidoperator()(ObjPtr<Object> obj, [[maybe_unused]] size_t usable_size) 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_); const int32_t length = String::GetLengthFromCount(count_); bool compressible = kUseStringCompression && String::IsCompressed(count_); if (src_string_->IsCompressed()) { const uint8_t* const src = src_string_->GetValueCompressed() + offset_;
memcpy(string->GetValueCompressed(), src, length * sizeof(uint8_t));
} else { const uint16_t* const src = src_string_->GetValue() + offset_; if (compressible) { for (int i = 0; i < length; ++i) {
string->GetValueCompressed()[i] = static_cast<uint8_t>(src[i]);
}
} else {
memcpy(string->GetValue(), src, length * sizeof(uint16_t));
}
}
}
template <bool kIsInstrumented, typename PreFenceVisitor> inline ObjPtr<String> String::Alloc(Thread* self,
int32_t utf16_length_with_flag,
gc::AllocatorType allocator_type, const PreFenceVisitor& pre_fence_visitor) {
constexpr size_t header_size = sizeof(String); constbool compressible = kUseStringCompression && String::IsCompressed(utf16_length_with_flag); const size_t block_size = (compressible) ? sizeof(uint8_t) : sizeof(uint16_t);
size_t length = String::GetLengthFromCount(utf16_length_with_flag);
static_assert(sizeof(length) <= sizeof(size_t), "static_cast<size_t>(utf16_length) must not lose bits.");
size_t data_size = block_size * length;
size_t size = header_size + data_size; // String.equals() intrinsics assume zero-padding up to kObjectAlignment, // so make sure the allocator clears the padding as well. // http://b/23528461
size_t alloc_size = RoundUp(size, kObjectAlignment);
Runtime* runtime = Runtime::Current();
ObjPtr<Class> string_class = GetClassRoot<String>(runtime->GetClassLinker()); // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. // Do this by comparing with the maximum length that will _not_ cause an overflow. const size_t overflow_length = (-header_size) / block_size; // Unsigned arithmetic. const size_t max_alloc_length = overflow_length - 1u;
static_assert(IsAligned<sizeof(uint16_t)>(kObjectAlignment), "kObjectAlignment must be at least as big as Java char alignment"); const size_t max_length = RoundDown(max_alloc_length, kObjectAlignment / block_size); if (UNLIKELY(length > max_length)) {
self->ThrowOutOfMemoryError(
android::base::StringPrintf("%s of length %d would overflow", Class::PrettyDescriptor(string_class).c_str(), static_cast<int>(length)).c_str()); return nullptr;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.