mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
[VM] Optimize performance of dart_boostrap in debug-kernel-strong mode.
Since the kernel reading helpers have been extended to not only work with a kernel blob in C heap, but also work based on a [TypedData] buffer in the VM heap, access to the [TypedData] buffer is on the hot path now. This hot path is slowing things down considerably, in particular due to NoSafepoingScope's. This CL removes a critical NoSafepoingScope when accessing the [TypedData] in read-only mode. It also allows passing in the [Thread] directly, to avoid TLS lookups. Issue https://github.com/dart-lang/sdk/issues/32603 Change-Id: I91955bea5cd4eddbbd21c5d3bc6813504c2cece9 Reviewed-on: https://dart-review.googlesource.com/47222 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
parent
38dc57504b
commit
31dd6683f8
5 changed files with 45 additions and 15 deletions
|
@ -286,6 +286,12 @@ class Utils {
|
|||
static uint32_t HostToLittleEndian32(uint32_t host_value);
|
||||
static uint64_t HostToLittleEndian64(uint64_t host_value);
|
||||
|
||||
static uint32_t BigEndianToHost32(uint32_t be_value) {
|
||||
// Going between Host <-> BE is the same operation for all practical
|
||||
// purposes.
|
||||
return HostToBigEndian32(be_value);
|
||||
}
|
||||
|
||||
static bool DoublesBitEqual(const double a, const double b) {
|
||||
return bit_cast<int64_t, double>(a) == bit_cast<int64_t, double>(b);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,9 @@ void StackResource::UnwindAbove(Thread* thread, StackResource* new_top) {
|
|||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
NoSafepointScope::NoSafepointScope() : StackResource(Thread::Current()) {
|
||||
NoSafepointScope::NoSafepointScope(Thread* current_thread)
|
||||
: StackResource(current_thread != nullptr ? current_thread
|
||||
: Thread::Current()) {
|
||||
thread()->IncrementNoSafepointScopeDepth();
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class ZoneAllocated {
|
|||
#if defined(DEBUG)
|
||||
class NoSafepointScope : public StackResource {
|
||||
public:
|
||||
NoSafepointScope();
|
||||
explicit NoSafepointScope(Thread* thread = nullptr);
|
||||
~NoSafepointScope();
|
||||
|
||||
private:
|
||||
|
@ -91,7 +91,7 @@ class NoSafepointScope : public StackResource {
|
|||
#else // defined(DEBUG)
|
||||
class NoSafepointScope : public ValueObject {
|
||||
public:
|
||||
NoSafepointScope() {}
|
||||
explicit NoSafepointScope(Thread* thread = nullptr) {}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
|
||||
|
|
|
@ -163,10 +163,15 @@ static const int MetadataPayloadOffset = HeaderSize; // Right after header.
|
|||
class Reader {
|
||||
public:
|
||||
Reader(const uint8_t* buffer, intptr_t size)
|
||||
: raw_buffer_(buffer), typed_data_(NULL), size_(size), offset_(0) {}
|
||||
: thread_(NULL),
|
||||
raw_buffer_(buffer),
|
||||
typed_data_(NULL),
|
||||
size_(size),
|
||||
offset_(0) {}
|
||||
|
||||
explicit Reader(const TypedData& typed_data)
|
||||
: raw_buffer_(NULL),
|
||||
: thread_(Thread::Current()),
|
||||
raw_buffer_(NULL),
|
||||
typed_data_(&typed_data),
|
||||
size_(typed_data.IsNull() ? 0 : typed_data.Length()),
|
||||
offset_(0) {}
|
||||
|
@ -184,11 +189,13 @@ class Reader {
|
|||
|
||||
uint32_t ReadUInt32At(intptr_t offset) const {
|
||||
ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4));
|
||||
|
||||
const uint8_t* buffer = this->buffer();
|
||||
uint32_t value = (buffer[offset + 0] << 24) | (buffer[offset + 1] << 16) |
|
||||
(buffer[offset + 2] << 8) | (buffer[offset + 3] << 0);
|
||||
return value;
|
||||
uint32_t value;
|
||||
if (raw_buffer_ != NULL) {
|
||||
value = *reinterpret_cast<const uint32_t*>(raw_buffer_ + offset);
|
||||
} else {
|
||||
value = typed_data_->GetUint32(offset);
|
||||
}
|
||||
return Utils::BigEndianToHost32(value);
|
||||
}
|
||||
|
||||
uint32_t ReadFromIndexNoReset(intptr_t end_offset,
|
||||
|
@ -323,14 +330,14 @@ class Reader {
|
|||
void CopyDataToVMHeap(const TypedData& typed_data,
|
||||
intptr_t offset,
|
||||
intptr_t size) {
|
||||
NoSafepointScope no_safepoint;
|
||||
NoSafepointScope no_safepoint(thread_);
|
||||
memmove(typed_data.DataAddr(0), buffer() + offset, size);
|
||||
}
|
||||
|
||||
uint8_t* CopyDataIntoZone(Zone* zone, intptr_t offset, intptr_t length) {
|
||||
uint8_t* buffer_ = zone->Alloc<uint8_t>(length);
|
||||
{
|
||||
NoSafepointScope no_safepoint;
|
||||
NoSafepointScope no_safepoint(thread_);
|
||||
memmove(buffer_, buffer() + offset, length);
|
||||
}
|
||||
return buffer_;
|
||||
|
@ -341,10 +348,11 @@ class Reader {
|
|||
if (raw_buffer_ != NULL) {
|
||||
return raw_buffer_;
|
||||
}
|
||||
NoSafepointScope no_safepoint;
|
||||
NoSafepointScope no_safepoint(thread_);
|
||||
return reinterpret_cast<uint8_t*>(typed_data_->DataAddr(0));
|
||||
}
|
||||
|
||||
Thread* thread_;
|
||||
const uint8_t* raw_buffer_;
|
||||
const TypedData* typed_data_;
|
||||
intptr_t size_;
|
||||
|
|
|
@ -8168,8 +8168,10 @@ class TypedData : public Instance {
|
|||
|
||||
#define TYPED_GETTER_SETTER(name, type) \
|
||||
type Get##name(intptr_t byte_offset) const { \
|
||||
NoSafepointScope no_safepoint; \
|
||||
return ReadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset))); \
|
||||
ASSERT((byte_offset >= 0) && \
|
||||
(byte_offset + static_cast<intptr_t>(sizeof(type)) - 1) < \
|
||||
LengthInBytes()); \
|
||||
return ReadUnaligned(ReadOnlyDataAddr<type>(byte_offset)); \
|
||||
} \
|
||||
void Set##name(intptr_t byte_offset, type value) const { \
|
||||
NoSafepointScope no_safepoint; \
|
||||
|
@ -8295,6 +8297,18 @@ class TypedData : public Instance {
|
|||
}
|
||||
|
||||
private:
|
||||
// Provides const access to non-pointer, non-aligned data within the object.
|
||||
// Such access does not need a write barrier, but it is *not* GC-safe, since
|
||||
// the object might move.
|
||||
//
|
||||
// Therefore this method is private and the call-sites in this class need to
|
||||
// ensure the returned pointer does not escape.
|
||||
template <typename FieldType>
|
||||
const FieldType* ReadOnlyDataAddr(intptr_t byte_offset) const {
|
||||
return reinterpret_cast<const FieldType*>((raw_ptr()->data()) +
|
||||
byte_offset);
|
||||
}
|
||||
|
||||
static intptr_t element_size(intptr_t index) {
|
||||
ASSERT(0 <= index && index < kNumElementSizes);
|
||||
intptr_t size = element_size_table[index];
|
||||
|
|
Loading…
Reference in a new issue