diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h index 2da794bc789..1dd091921e4 100644 --- a/runtime/vm/kernel_binary.h +++ b/runtime/vm/kernel_binary.h @@ -177,15 +177,7 @@ class Reader : public ValueObject { offset_(0) { // The reader expects that the actual data is external, though allows // having a view into this external typed data. -#if defined(DEBUG) - if (typed_data_->IsTypedDataView()) { - const auto& backing_store = - TypedDataBase::Handle(TypedDataView::Cast(*typed_data_).typed_data()); - ASSERT(backing_store.IsExternalTypedData()); - } else { - ASSERT(typed_data_->IsExternalTypedData()); - } -#endif + DEBUG_ASSERT(typed_data_->IsBackedByExternalTypedData()); } uint32_t ReadFromIndex(intptr_t end_offset, @@ -199,10 +191,15 @@ class Reader : public ValueObject { return result; } - uint32_t ReadUInt32At(intptr_t offset) const { - ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4)); - uint32_t value; - value = typed_data_->GetUint32(offset); + DART_FORCE_INLINE uint32_t ReadUInt32At(intptr_t offset) const { + ASSERT(size_ >= 4 && offset >= 0 && (offset <= size_ - 4)); + // We validated in the [Reader] constructor that we have either an + // ExternalTypedData or a view on top of an ExternalTypedData. + // + // This means the data pointer will not change and we can use + // [DataAddrUnsafe]. + const uint32_t value = + *static_cast(typed_data_->DataAddrUnsafe(offset)); return Utils::BigEndianToHost32(value); } @@ -358,9 +355,13 @@ class Reader : public ValueObject { } private: - const uint8_t* buffer() const { - NoSafepointScope no_safepoint(thread_); - return reinterpret_cast(typed_data_->DataAddr(0)); + DART_FORCE_INLINE const uint8_t* buffer() const { + // We validated in the [Reader] constructor that we have either an + // ExternalTypedData or a view on top of an ExternalTypedData. + // + // This means the data pointer will not change and we can use + // [DataAddrUnsafe]. + return reinterpret_cast(typed_data_->DataAddrUnsafe(0)); } Thread* thread_; diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 8045887ece0..6523ccb38db 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -21169,6 +21169,19 @@ RawTypedDataView* TypedDataBase::CreateUint8View(intptr_t offset_in_bytes, offset_in_bytes, length_in_bytes, space); } +#if defined(DEBUG) +bool TypedDataBase::IsBackedByExternalTypedData() const { + if (IsExternalTypedData()) { + return true; + } + if (IsTypedDataView()) { + const auto& view = TypedDataView::Cast(*this); + return TypedDataBase::Handle(view.typed_data()).IsExternalTypedData(); + } + return false; +} +#endif + const char* TypedDataView::ToCString() const { auto zone = Thread::Current()->zone(); return OS::SCreate(zone, "TypedDataView(cid: %" Pd ")", GetClassId()); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 08216a25a19..9e7b6c222d6 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -8410,6 +8410,13 @@ class TypedDataBase : public Instance { #if defined(DEBUG) ValidateInvariant(); #endif + return DataAddrUnsafe(byte_offset); + } + + // To speed up debug mode (e.g. for kernel reading - which uses typed data + // for kernel buffers) we expose the data pointer without asserts for bounds + // checks and invariants. + DART_FORCE_INLINE void* DataAddrUnsafe(intptr_t byte_offset) const { return reinterpret_cast(raw_ptr()->data_ + byte_offset); } @@ -8471,6 +8478,10 @@ class TypedDataBase : public Instance { #undef TYPED_GETTER_SETTER +#if defined(DEBUG) + bool IsBackedByExternalTypedData() const; +#endif + protected: void SetLength(intptr_t value) const { ASSERT(value <= Smi::kMaxValue);