[vm/compiler] Speed up the compiler part which deals with kernel reading up in DEBUG mode
This reduces our AOT compiler's time - gen_snapshot - by half in DEBUG mode.
Issue https://github.com/dart-lang/sdk/issues/32603
Change-Id: I235afc40acba32036d4127c31c93f3b22f522314
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103441
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 2da794b..1dd0919 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -177,15 +177,7 @@
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 @@
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<uint32_t*>(typed_data_->DataAddrUnsafe(offset));
return Utils::BigEndianToHost32(value);
}
@@ -358,9 +355,13 @@
}
private:
- const uint8_t* buffer() const {
- NoSafepointScope no_safepoint(thread_);
- return reinterpret_cast<uint8_t*>(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<uint8_t*>(typed_data_->DataAddrUnsafe(0));
}
Thread* thread_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 8045887..6523ccb 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -21169,6 +21169,19 @@
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 08216a2..9e7b6c2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -8410,6 +8410,13 @@
#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<void*>(raw_ptr()->data_ + byte_offset);
}
@@ -8471,6 +8478,10 @@
#undef TYPED_GETTER_SETTER
+#if defined(DEBUG)
+ bool IsBackedByExternalTypedData() const;
+#endif
+
protected:
void SetLength(intptr_t value) const {
ASSERT(value <= Smi::kMaxValue);