[vm/kernel] Use GC-tracked ExternalTypedData/TypedDataView for kernel buffers
Until now we often leaked kernel buffers (e.g. hot reload buffers) because various
objects were referencing ExternalTypedData objects pointing into the middle of
c-allocated memory. This made it impossible for the GC to determine when the last
reference is gone.
This CL ensures that the actual buffers are *always* made available via
ExternalTypedData and any inner pointers into it are created via TypedDataViews.
The embedder guarantees to the free kernel buffers it has provided to:
- Dart_CreateIsolateFromKernel
- Dart_LoadScriptFromKernel
- Dart_LoadLibraryFromKernel
- Dart_SetDartLibrarySourcesKernel
on isolate shutdown.
All other kernel buffers will get a finalizer attached, which ensures the
kernel buffers get freed by the GC once they are no longer referenced:
- Kernel blobs for expression evaluation
- Kernel blobs for Hot-Reload
- Kernel blobs for cc tests
Fixes https://github.com/dart-lang/sdk/issues/33973
Fixes https://github.com/dart-lang/sdk/issues/36857
Issue https://github.com/dart-lang/sdk/issues/37030
Change-Id: I1cc410c94c0f4b229413e793728a261afcb10aaf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103130
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index f144ed4..8da776e 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2841,8 +2841,8 @@
* of an application is needed and the VM is 'use dart front end' mode.
* The dart front end typically compiles all the scripts, imports and part
* files into one intermediate file hence we don't use the source/import or
- * script tags. The return value should be an error or a TypedData containing
- * the kernel bytes.
+ * script tags. The return value should be an error or an external TypedData
+ * containing the kernel bytes.
*
* Dart_kImportExtensionTag
*
diff --git a/runtime/vm/base64.cc b/runtime/vm/base64.cc
index 60e919d..b27cf74 100644
--- a/runtime/vm/base64.cc
+++ b/runtime/vm/base64.cc
@@ -35,7 +35,7 @@
static const char PAD = '=';
-uint8_t* DecodeBase64(Zone* zone, const char* str, intptr_t* out_decoded_len) {
+uint8_t* DecodeBase64(const char* str, intptr_t* out_decoded_len) {
intptr_t len = strlen(str);
if (len == 0 || (len % 4 != 0)) {
return nullptr;
@@ -48,7 +48,7 @@
if (current_code_unit == PAD) pad_length++;
}
intptr_t decoded_en = ((len * 6) >> 3) - pad_length;
- uint8_t* bytes = zone->Alloc<uint8_t>(decoded_en);
+ uint8_t* bytes = new uint8_t[decoded_en];
for (int i = 0, o = 0; o < decoded_en;) {
// Accumulate 4 valid 6 bit Base 64 characters into an int.
diff --git a/runtime/vm/base64.h b/runtime/vm/base64.h
index 575b61b..d2a80f3 100644
--- a/runtime/vm/base64.h
+++ b/runtime/vm/base64.h
@@ -5,11 +5,12 @@
#ifndef RUNTIME_VM_BASE64_H_
#define RUNTIME_VM_BASE64_H_
-#include "vm/zone.h"
+#include "platform/globals.h"
namespace dart {
-uint8_t* DecodeBase64(Zone* zone, const char* str, intptr_t* out_decoded_len);
+// If non-null, the returned buffer has to be freed via delete[].
+uint8_t* DecodeBase64(const char* str, intptr_t* out_decoded_len);
} // namespace dart
diff --git a/runtime/vm/base64_test.cc b/runtime/vm/base64_test.cc
index 406a431..8bb8423 100644
--- a/runtime/vm/base64_test.cc
+++ b/runtime/vm/base64_test.cc
@@ -11,22 +11,21 @@
TEST_CASE(Base64Decode) {
intptr_t decoded_len;
- uint8_t* decoded_bytes =
- DecodeBase64(thread->zone(), "SGVsbG8sIHdvcmxkIQo=", &decoded_len);
+ uint8_t* decoded_bytes = DecodeBase64("SGVsbG8sIHdvcmxkIQo=", &decoded_len);
const char expected_bytes[] = "Hello, world!\n";
intptr_t expected_len = strlen(expected_bytes);
EXPECT(!memcmp(expected_bytes, decoded_bytes, expected_len));
EXPECT_EQ(expected_len, decoded_len);
+ delete[] decoded_bytes;
}
TEST_CASE(Base64DecodeMalformed) {
intptr_t decoded_len;
- EXPECT(DecodeBase64(thread->zone(), "SomethingMalformed", &decoded_len) ==
- nullptr);
+ EXPECT(DecodeBase64("SomethingMalformed", &decoded_len) == nullptr);
}
TEST_CASE(Base64DecodeEmpty) {
intptr_t decoded_len;
- EXPECT(DecodeBase64(thread->zone(), "", &decoded_len) == nullptr);
+ EXPECT(DecodeBase64("", &decoded_len) == nullptr);
}
} // namespace dart
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 8c05417..a1921bf 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -79,8 +79,15 @@
intptr_t kernel_buffer_size) {
Zone* zone = thread->zone();
const char* error = nullptr;
- kernel::Program* program = kernel::Program::ReadFromBuffer(
- kernel_buffer, kernel_buffer_size, &error);
+
+ // NOTE: We do not attach a finalizer for this object, because the embedder
+ // will free it once the isolate has shutdown.
+ // (The embedder provides this buffer to [Dart_CreateIsolateFromKernel])
+ const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
+ kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(kernel_buffer),
+ kernel_buffer_size, Heap::kOld));
+
+ kernel::Program* program = kernel::Program::ReadFromTypedData(td, &error);
if (program == nullptr) {
const intptr_t kMessageBufferSize = 512;
char message_buffer[kMessageBufferSize];
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index dba74ea..b226d6e 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1591,11 +1591,19 @@
void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
Bytecode& bytecode = Bytecode::Handle(zone);
- ExternalTypedData& binary = ExternalTypedData::Handle(zone);
+ TypedDataBase& binary = TypedDataBase::Handle(zone);
for (intptr_t i = start_index_; i < stop_index_; i++) {
bytecode ^= refs.At(i);
binary = bytecode.GetBinary(zone);
+
+ // The deserialization cluster for kBytecodeCid might be before
+ // kTypedDataViewCids, which means the inner pointer might not have been
+ // updated yet.
+ if (binary.IsTypedDataView()) {
+ TypedDataView::Cast(binary).raw()->RecomputeDataField();
+ }
+
bytecode.set_instructions(reinterpret_cast<uword>(
binary.DataAddr(bytecode.instructions_binary_offset())));
}
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 690d873..602d55b 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -2164,7 +2164,7 @@
KernelReaderHelper reader_helper(
zone, &translation_helper, script,
- ExternalTypedData::Handle(zone, function.KernelData()),
+ TypedDataBase::Handle(zone, function.KernelData()),
function.KernelDataProgramOffset());
ActiveClass active_class;
@@ -2202,7 +2202,7 @@
KernelReaderHelper reader_helper(
zone, &translation_helper, script,
- ExternalTypedData::Handle(zone, annotation_field.KernelData()),
+ TypedDataBase::Handle(zone, annotation_field.KernelData()),
annotation_field.KernelDataProgramOffset());
ActiveClass active_class;
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index 701cc2d..05ee4c2 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -267,7 +267,7 @@
class BytecodeSourcePositionsIterator : ValueObject {
public:
BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode)
- : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
+ : reader_(TypedDataBase::Handle(zone, bytecode.GetBinary(zone))),
pairs_remaining_(0),
pc_shifter_(
Isolate::Current()->is_using_old_bytecode_instructions() ? 2 : 0),
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 706d2e6..590d0ef 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -225,8 +225,7 @@
for (intptr_t i = 0; i < class_fields.Length(); ++i) {
class_field ^= class_fields.At(i);
if (!class_field.is_static()) {
- ExternalTypedData& kernel_data =
- ExternalTypedData::Handle(Z, class_field.KernelData());
+ auto& kernel_data = TypedDataBase::Handle(Z, class_field.KernelData());
ASSERT(!kernel_data.IsNull());
intptr_t field_offset = class_field.kernel_offset();
AlternativeReadingScope alt(&reader_, &kernel_data, field_offset);
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 2006924..cc489c0 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -22,7 +22,7 @@
class StreamingFlowGraphBuilder : public KernelReaderHelper {
public:
StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t data_program_offset)
: KernelReaderHelper(
flow_graph_builder->zone_,
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 2ac1adf..0680579e 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -18,7 +18,7 @@
KernelFingerprintHelper(Zone* zone,
TranslationHelper* translation_helper,
const Script& script,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t data_program_offset)
: KernelReaderHelper(zone,
translation_helper,
@@ -838,7 +838,7 @@
KernelFingerprintHelper helper(
zone, &translation_helper, script,
- ExternalTypedData::Handle(zone, field.KernelData()),
+ TypedDataBase::Handle(zone, field.KernelData()),
field.KernelDataProgramOffset());
helper.SetOffset(field.kernel_offset());
return helper.CalculateFieldFingerprint();
@@ -853,10 +853,9 @@
TranslationHelper translation_helper(thread);
translation_helper.InitFromScript(script);
- KernelFingerprintHelper helper(
- zone, &translation_helper, script,
- ExternalTypedData::Handle(zone, func.KernelData()),
- func.KernelDataProgramOffset());
+ KernelFingerprintHelper helper(zone, &translation_helper, script,
+ TypedDataBase::Handle(zone, func.KernelData()),
+ func.KernelDataProgramOffset());
helper.SetOffset(func.kernel_offset());
return helper.CalculateFunctionFingerprint();
}
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 6049959..485e7e7 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -724,7 +724,7 @@
#endif
StreamingFlowGraphBuilder streaming_flow_graph_builder(
- this, ExternalTypedData::Handle(Z, function.KernelData()),
+ this, TypedDataBase::Handle(Z, function.KernelData()),
function.KernelDataProgramOffset());
return streaming_flow_graph_builder.BuildGraph();
}
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 26f5476..9073d5c 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -27,10 +27,10 @@
isolate_(thread->isolate()),
allocation_space_(Heap::kNew),
string_offsets_(TypedData::Handle(Z)),
- string_data_(ExternalTypedData::Handle(Z)),
+ string_data_(TypedDataBase::Handle(Z)),
canonical_names_(TypedData::Handle(Z)),
- metadata_payloads_(ExternalTypedData::Handle(Z)),
- metadata_mappings_(ExternalTypedData::Handle(Z)),
+ metadata_payloads_(TypedDataBase::Handle(Z)),
+ metadata_mappings_(TypedDataBase::Handle(Z)),
constants_(Array::Handle(Z)),
info_(KernelProgramInfo::Handle(Z)),
name_index_handle_(Smi::Handle(Z)) {}
@@ -41,20 +41,20 @@
isolate_(thread->isolate()),
allocation_space_(space),
string_offsets_(TypedData::Handle(Z)),
- string_data_(ExternalTypedData::Handle(Z)),
+ string_data_(TypedDataBase::Handle(Z)),
canonical_names_(TypedData::Handle(Z)),
- metadata_payloads_(ExternalTypedData::Handle(Z)),
- metadata_mappings_(ExternalTypedData::Handle(Z)),
+ metadata_payloads_(TypedDataBase::Handle(Z)),
+ metadata_mappings_(TypedDataBase::Handle(Z)),
constants_(Array::Handle(Z)),
info_(KernelProgramInfo::Handle(Z)),
name_index_handle_(Smi::Handle(Z)) {}
void TranslationHelper::Reset() {
string_offsets_ = TypedData::null();
- string_data_ = ExternalTypedData::null();
+ string_data_ = TypedDataBase::null();
canonical_names_ = TypedData::null();
- metadata_payloads_ = ExternalTypedData::null();
- metadata_mappings_ = ExternalTypedData::null();
+ metadata_payloads_ = TypedDataBase::null();
+ metadata_mappings_ = TypedDataBase::null();
constants_ = Array::null();
}
@@ -74,10 +74,10 @@
void TranslationHelper::InitFromKernelProgramInfo(
const KernelProgramInfo& info) {
SetStringOffsets(TypedData::Handle(Z, info.string_offsets()));
- SetStringData(ExternalTypedData::Handle(Z, info.string_data()));
+ SetStringData(TypedDataBase::Handle(Z, info.string_data()));
SetCanonicalNames(TypedData::Handle(Z, info.canonical_names()));
- SetMetadataPayloads(ExternalTypedData::Handle(Z, info.metadata_payloads()));
- SetMetadataMappings(ExternalTypedData::Handle(Z, info.metadata_mappings()));
+ SetMetadataPayloads(TypedDataBase::Handle(Z, info.metadata_payloads()));
+ SetMetadataMappings(TypedDataBase::Handle(Z, info.metadata_mappings()));
SetConstants(Array::Handle(Z, info.constants()));
SetKernelProgramInfo(info);
}
@@ -97,7 +97,7 @@
string_offsets_ = string_offsets.raw();
}
-void TranslationHelper::SetStringData(const ExternalTypedData& string_data) {
+void TranslationHelper::SetStringData(const TypedDataBase& string_data) {
ASSERT(string_data_.IsNull());
string_data_ = string_data.raw();
}
@@ -108,14 +108,14 @@
}
void TranslationHelper::SetMetadataPayloads(
- const ExternalTypedData& metadata_payloads) {
+ const TypedDataBase& metadata_payloads) {
ASSERT(metadata_payloads_.IsNull());
ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));
metadata_payloads_ = metadata_payloads.raw();
}
void TranslationHelper::SetMetadataMappings(
- const ExternalTypedData& metadata_mappings) {
+ const TypedDataBase& metadata_mappings) {
ASSERT(metadata_mappings_.IsNull());
metadata_mappings_ = metadata_mappings.raw();
}
@@ -151,7 +151,7 @@
// expression will try to return the address that is one past the backing
// store of the string_data_ table. Though this is safe in C++ as long as the
// address is not dereferenced, it will trigger the assert in
- // ExternalTypedData::DataAddr.
+ // TypedDataBase::DataAddr.
ASSERT(Thread::Current()->no_safepoint_scope_depth() > 0);
return reinterpret_cast<uint8_t*>(string_data_.DataAddr(0)) +
StringOffset(string_index);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 9508b70..eb3d31f 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -44,17 +44,17 @@
const TypedData& string_offsets() { return string_offsets_; }
void SetStringOffsets(const TypedData& string_offsets);
- const ExternalTypedData& string_data() { return string_data_; }
- void SetStringData(const ExternalTypedData& string_data);
+ const TypedDataBase& string_data() { return string_data_; }
+ void SetStringData(const TypedDataBase& string_data);
const TypedData& canonical_names() { return canonical_names_; }
void SetCanonicalNames(const TypedData& canonical_names);
- const ExternalTypedData& metadata_payloads() { return metadata_payloads_; }
- void SetMetadataPayloads(const ExternalTypedData& metadata_payloads);
+ const TypedDataBase& metadata_payloads() { return metadata_payloads_; }
+ void SetMetadataPayloads(const TypedDataBase& metadata_payloads);
- const ExternalTypedData& metadata_mappings() { return metadata_mappings_; }
- void SetMetadataMappings(const ExternalTypedData& metadata_mappings);
+ const TypedDataBase& metadata_mappings() { return metadata_mappings_; }
+ void SetMetadataMappings(const TypedDataBase& metadata_mappings);
const Array& constants() { return constants_; }
void SetConstants(const Array& constants);
@@ -200,10 +200,10 @@
Heap::Space allocation_space_;
TypedData& string_offsets_;
- ExternalTypedData& string_data_;
+ TypedDataBase& string_data_;
TypedData& canonical_names_;
- ExternalTypedData& metadata_payloads_;
- ExternalTypedData& metadata_mappings_;
+ TypedDataBase& metadata_payloads_;
+ TypedDataBase& metadata_mappings_;
Array& constants_;
KernelProgramInfo& info_;
Smi& name_index_handle_;
@@ -967,7 +967,7 @@
KernelReaderHelper(Zone* zone,
TranslationHelper* translation_helper,
const Script& script,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t data_program_offset)
: zone_(zone),
translation_helper_(*translation_helper),
@@ -975,17 +975,6 @@
script_(script),
data_program_offset_(data_program_offset) {}
- KernelReaderHelper(Zone* zone,
- TranslationHelper* translation_helper,
- const uint8_t* data_buffer,
- intptr_t buffer_length,
- intptr_t data_program_offset)
- : zone_(zone),
- translation_helper_(*translation_helper),
- reader_(data_buffer, buffer_length),
- script_(Script::Handle(zone_)),
- data_program_offset_(data_program_offset) {}
-
virtual ~KernelReaderHelper() = default;
void SetOffset(intptr_t offset);
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index dde3667..e043d3c 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -57,8 +57,7 @@
zone_,
&translation_helper_,
Script::Handle(Z, parsed_function->function().script()),
- ExternalTypedData::Handle(Z,
- parsed_function->function().KernelData()),
+ TypedDataBase::Handle(Z, parsed_function->function().KernelData()),
parsed_function->function().KernelDataProgramOffset()),
inferred_type_metadata_helper_(&helper_),
procedure_attributes_metadata_helper_(&helper_),
@@ -185,8 +184,8 @@
for (intptr_t i = 0; i < class_fields.Length(); ++i) {
class_field ^= class_fields.At(i);
if (!class_field.is_static()) {
- ExternalTypedData& kernel_data =
- ExternalTypedData::Handle(Z, class_field.KernelData());
+ auto& kernel_data =
+ TypedDataBase::Handle(Z, class_field.KernelData());
ASSERT(!kernel_data.IsNull());
intptr_t field_offset = class_field.kernel_offset();
AlternativeReadingScope alt(&helper_.reader_, &kernel_data,
@@ -450,8 +449,7 @@
for (intptr_t i = 0; i < class_fields.Length(); ++i) {
class_field ^= class_fields.At(i);
if (!class_field.is_static()) {
- ExternalTypedData& kernel_data =
- ExternalTypedData::Handle(Z, class_field.KernelData());
+ auto& kernel_data = TypedDataBase::Handle(Z, class_field.KernelData());
ASSERT(!kernel_data.IsNull());
intptr_t field_offset = class_field.kernel_offset();
AlternativeReadingScope alt(&helper_.reader_, &kernel_data,
@@ -1705,8 +1703,7 @@
StringIndex ScopeBuilder::GetNameFromVariableDeclaration(
intptr_t kernel_offset,
const Function& function) {
- ExternalTypedData& kernel_data =
- ExternalTypedData::Handle(Z, function.KernelData());
+ auto& kernel_data = TypedDataBase::Handle(Z, function.KernelData());
ASSERT(!kernel_data.IsNull());
// Temporarily go to the variable declaration, read the name.
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index d10c8c4..5a3cc98 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -243,10 +243,17 @@
const uint8_t* kernel_bytes = compilation_result.kernel;
intptr_t kernel_length = compilation_result.kernel_size;
+ const auto& kernel_td = ExternalTypedData::Handle(ExternalTypedData::New(
+ kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(kernel_bytes),
+ kernel_length, Heap::kOld));
+ kernel_td.AddFinalizer(
+ const_cast<uint8_t*>(kernel_bytes),
+ [](void* _, Dart_WeakPersistentHandle h, void* peer) { free(peer); },
+ kernel_length);
+
val = Instance::Cast(obj).EvaluateCompiledExpression(
- receiver_cls, kernel_bytes, kernel_length, Array::empty_array(),
- Array::empty_array(), TypeArguments::null_type_arguments());
- free(const_cast<uint8_t*>(kernel_bytes));
+ receiver_cls, kernel_td, Array::empty_array(), Array::empty_array(),
+ TypeArguments::null_type_arguments());
}
EXPECT(!val.IsNull());
EXPECT(!val.IsError());
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 7f7a646..16abbaa 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5045,9 +5045,14 @@
// instead of freelists.
BumpAllocateScope bump_allocate_scope(T);
+ // NOTE: We do not attach a finalizer for this object, because the embedder
+ // will free it once the isolate has shutdown.
+ const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
+ kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
+ buffer_size, Heap::kOld));
+
const char* error = nullptr;
- kernel::Program* program =
- kernel::Program::ReadFromBuffer(buffer, buffer_size, &error);
+ kernel::Program* program = kernel::Program::ReadFromTypedData(td, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}
@@ -5291,9 +5296,15 @@
// instead of freelists.
BumpAllocateScope bump_allocate_scope(T);
+ // NOTE: We do not attach a finalizer for this object, because the embedder
+ // will/should free it once the isolate has shutdown.
+ // See also http://dartbug.com/37030.
+ const auto& td = ExternalTypedData::Handle(ExternalTypedData::New(
+ kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(buffer),
+ buffer_size, Heap::kOld));
+
const char* error = nullptr;
- kernel::Program* program =
- kernel::Program::ReadFromBuffer(buffer, buffer_size, &error);
+ kernel::Program* program = kernel::Program::ReadFromTypedData(td, &error);
if (program == nullptr) {
return Api::NewError("Can't load Kernel binary: %s.", error);
}
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 13e4621..e84a517 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1294,16 +1294,14 @@
}
RawObject* ActivationFrame::EvaluateCompiledExpression(
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_td,
const Array& type_definitions,
const Array& arguments,
const TypeArguments& type_arguments) {
if (function().is_static()) {
const Class& cls = Class::Handle(function().Owner());
- return cls.EvaluateCompiledExpression(kernel_bytes, kernel_length,
- type_definitions, arguments,
- type_arguments);
+ return cls.EvaluateCompiledExpression(kernel_td, type_definitions,
+ arguments, type_arguments);
} else {
const Object& receiver = Object::Handle(GetReceiver());
const Class& method_cls = Class::Handle(function().origin());
@@ -1312,9 +1310,8 @@
return Object::null();
}
const Instance& inst = Instance::Cast(receiver);
- return inst.EvaluateCompiledExpression(method_cls, kernel_bytes,
- kernel_length, type_definitions,
- arguments, type_arguments);
+ return inst.EvaluateCompiledExpression(
+ method_cls, kernel_td, type_definitions, arguments, type_arguments);
}
}
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 05230cd..2541c2d 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -332,8 +332,7 @@
const GrowableObjectArray& param_values,
const GrowableObjectArray& type_params_names);
- RawObject* EvaluateCompiledExpression(const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ RawObject* EvaluateCompiledExpression(const ExternalTypedData& kernel_td,
const Array& arguments,
const Array& type_definitions,
const TypeArguments& type_arguments);
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index e9a303f..0072067 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -192,16 +192,24 @@
const uint8_t* kernel_bytes = compilation_result.kernel;
intptr_t kernel_length = compilation_result.kernel_size;
+
+ const auto& kernel_td = ExternalTypedData::Handle(ExternalTypedData::New(
+ kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(kernel_bytes),
+ kernel_length, Heap::kOld));
+ kernel_td.AddFinalizer(
+ const_cast<uint8_t*>(kernel_bytes),
+ [](void* _, Dart_WeakPersistentHandle h, void* peer) { free(peer); },
+ kernel_length);
+
Dart_Handle result = Api::NewHandle(
T,
- lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
+ lib.EvaluateCompiledExpression(kernel_td,
/* type_definitions= */
Array::empty_array(),
/* param_values= */
Array::empty_array(),
/* type_param_values= */
TypeArguments::null_type_arguments()));
- free(const_cast<uint8_t*>(kernel_bytes));
return result;
}
}
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index ba66dcd..4d4f057 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+#include <utility>
+
#include "vm/isolate.h"
#include "include/dart_api.h"
@@ -902,7 +904,6 @@
tag_table_(GrowableObjectArray::null()),
deoptimized_code_array_(GrowableObjectArray::null()),
sticky_error_(Error::null()),
- reloaded_kernel_blobs_(GrowableObjectArray::null()),
field_list_mutex_(NOT_IN_PRODUCT("Isolate::field_list_mutex_")),
boxed_field_list_(GrowableObjectArray::null()),
spawn_count_monitor_(),
@@ -1115,14 +1116,6 @@
return result;
}
-void Isolate::RetainKernelBlob(const ExternalTypedData& kernel_blob) {
- if (reloaded_kernel_blobs_ == Object::null()) {
- reloaded_kernel_blobs_ = GrowableObjectArray::New();
- }
- auto& kernel_blobs = GrowableObjectArray::Handle(reloaded_kernel_blobs_);
- kernel_blobs.Add(kernel_blob);
-}
-
Thread* Isolate::mutator_thread() const {
ASSERT(thread_registry() != nullptr);
return thread_registry()->mutator_thread();
@@ -1939,7 +1932,6 @@
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&deoptimized_code_array_));
visitor->VisitPointer(reinterpret_cast<RawObject**>(&sticky_error_));
- visitor->VisitPointer(reinterpret_cast<RawObject**>(&reloaded_kernel_blobs_));
#if !defined(PRODUCT)
visitor->VisitPointer(
reinterpret_cast<RawObject**>(&pending_service_extension_calls_));
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 914a40f..0fa13bd 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -613,8 +613,6 @@
RawError* sticky_error() const { return sticky_error_; }
DART_WARN_UNUSED_RESULT RawError* StealStickyError();
- void RetainKernelBlob(const ExternalTypedData& kernel_blob);
-
bool compilation_allowed() const {
return CompilationAllowedBit::decode(isolate_flags_);
}
@@ -1035,12 +1033,6 @@
RawError* sticky_error_;
- // Issue(dartbug.com/33973): We keep a reference to [ExternalTypedData]s with
- // finalizers to ensure we keep the hot-reloaded kernel blobs alive.
- //
- // -> We should get rid of this field once Issue 33973 is fixed.
- RawGrowableObjectArray* reloaded_kernel_blobs_;
-
// Isolate list next pointer.
Isolate* next_ = nullptr;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 2cd529b..5717e48 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -612,7 +612,8 @@
kernel_program.set(kernel::Program::ReadFromFile(root_script_url));
if (kernel_program.get() != NULL) {
num_received_libs_ = kernel_program.get()->library_count();
- bytes_received_libs_ = kernel_program.get()->kernel_data_size();
+ bytes_received_libs_ =
+ kernel_program.get()->kernel_data().LengthInBytes();
p_num_received_classes = &num_received_classes_;
p_num_received_procedures = &num_received_procedures_;
} else {
@@ -662,13 +663,6 @@
void* data) { free(data); },
retval.kernel_size);
- // TODO(dartbug.com/33973): Change the heap objects to have a proper
- // retaining path to the kernel blob and ensure the finalizer will free it
- // once there are no longer references to it.
- // (The [ExternalTypedData] currently referenced by e.g. functions point
- // into the middle of c-allocated buffer and don't have a finalizer).
- I->RetainKernelBlob(typed_data);
-
kernel_program.set(kernel::Program::ReadFromTypedData(typed_data));
}
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index a4a6eea..5c5b1ab 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -28,7 +28,7 @@
KernelReaderHelper kernel_reader_helper(
zone, &translation_helper, Script::Handle(zone, field.Script()),
- ExternalTypedData::Handle(zone, field.KernelData()),
+ TypedDataBase::Handle(zone, field.KernelData()),
field.KernelDataProgramOffset());
kernel_reader_helper.SetOffset(field.kernel_offset());
kernel::FieldHelper field_helper(&kernel_reader_helper);
@@ -148,7 +148,7 @@
Zone* zone,
TranslationHelper* translation_helper,
const Script& script,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t data_program_offset,
intptr_t initial_script_index,
intptr_t record_for_script_id,
@@ -257,7 +257,7 @@
}
static void ProcessTokenPositionsEntry(
- const ExternalTypedData& kernel_data,
+ const TypedDataBase& kernel_data,
const Script& script,
const Script& entry_script,
intptr_t kernel_offset,
@@ -293,7 +293,7 @@
Library& lib = Library::Handle(zone);
Object& entry = Object::Handle(zone);
Script& entry_script = Script::Handle(zone);
- ExternalTypedData& data = ExternalTypedData::Handle(zone);
+ TypedDataBase& data = TypedDataBase::Handle(zone);
auto& temp_array = Array::Handle(zone);
auto& temp_field = Field::Handle(zone);
@@ -304,7 +304,7 @@
DictionaryIterator it(lib);
while (it.HasNext()) {
entry = it.GetNext();
- data = ExternalTypedData::null();
+ data = TypedDataBase::null();
if (entry.IsClass()) {
const Class& klass = Class::Cast(entry);
if (klass.script() == interesting_script.raw()) {
@@ -416,7 +416,7 @@
MetadataEvaluator(Zone* zone,
TranslationHelper* translation_helper,
const Script& script,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t data_program_offset,
ActiveClass* active_class)
: KernelReaderHelper(zone,
@@ -480,7 +480,7 @@
MetadataEvaluator metadata_evaluator(
zone, &helper, script,
- ExternalTypedData::Handle(zone, metadata_field.KernelData()),
+ TypedDataBase::Handle(zone, metadata_field.KernelData()),
metadata_field.KernelDataProgramOffset(), &active_class);
return metadata_evaluator.EvaluateMetadata(metadata_field.kernel_offset(),
@@ -496,7 +496,7 @@
ParameterDescriptorBuilder(TranslationHelper* translation_helper,
const Script& script,
Zone* zone,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t data_program_offset,
ActiveClass* active_class)
: KernelReaderHelper(zone,
@@ -589,7 +589,7 @@
ParameterDescriptorBuilder builder(
&helper, Script::Handle(zone, function.script()), zone,
- ExternalTypedData::Handle(zone, function.KernelData()),
+ TypedDataBase::Handle(zone, function.KernelData()),
function.KernelDataProgramOffset(), &active_class);
return builder.BuildParameterDescriptor(function.kernel_offset());
@@ -614,7 +614,7 @@
KernelReaderHelper reader_helper(
zone, &translation_helper, script,
- ExternalTypedData::Handle(zone, function.KernelData()),
+ TypedDataBase::Handle(zone, function.KernelData()),
function.KernelDataProgramOffset());
if (function.is_declared_in_bytecode()) {
@@ -710,7 +710,7 @@
static ProcedureAttributesMetadata ProcedureAttributesOf(
Zone* zone,
const Script& script,
- const ExternalTypedData& kernel_data,
+ const TypedDataBase& kernel_data,
intptr_t kernel_data_program_offset,
intptr_t kernel_offset) {
TranslationHelper translation_helper(Thread::Current());
@@ -729,7 +729,7 @@
Zone* zone) {
const Script& script = Script::Handle(zone, function.script());
return ProcedureAttributesOf(
- zone, script, ExternalTypedData::Handle(zone, function.KernelData()),
+ zone, script, TypedDataBase::Handle(zone, function.KernelData()),
function.KernelDataProgramOffset(), function.kernel_offset());
}
@@ -738,7 +738,7 @@
const Class& parent = Class::Handle(zone, field.Owner());
const Script& script = Script::Handle(zone, parent.script());
return ProcedureAttributesOf(
- zone, script, ExternalTypedData::Handle(zone, field.KernelData()),
+ zone, script, TypedDataBase::Handle(zone, field.KernelData()),
field.KernelDataProgramOffset(), field.kernel_offset());
}
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 0de9d5d..d9a5ca1 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -66,9 +66,6 @@
static Program* ReadFromFile(const char* script_uri,
const char** error = nullptr);
- static Program* ReadFromBuffer(const uint8_t* buffer,
- intptr_t buffer_length,
- const char** error = nullptr);
static Program* ReadFromTypedData(const ExternalTypedData& typed_data,
const char** error = nullptr);
@@ -85,12 +82,12 @@
return metadata_mappings_offset_;
}
intptr_t constant_table_offset() { return constant_table_offset_; }
- const uint8_t* kernel_data() { return kernel_data_; }
- intptr_t kernel_data_size() { return kernel_data_size_; }
intptr_t library_count() { return library_count_; }
+ const TypedDataBase& kernel_data() const { return *kernel_data_; }
+
private:
- Program() : kernel_data_(NULL), kernel_data_size_(-1) {}
+ Program() : kernel_data_(NULL) {}
bool single_program_;
uint32_t binary_version_;
@@ -115,8 +112,8 @@
// The offset from the start of the binary to the start of the string table.
intptr_t string_table_offset_;
- const uint8_t* kernel_data_;
- intptr_t kernel_data_size_;
+ // The kernel buffer for this program.
+ const TypedDataBase* kernel_data_;
DISALLOW_COPY_AND_ASSIGN(Program);
};
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index d3f2838..ae850f3 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -78,8 +78,8 @@
Program* program = new Program();
program->binary_version_ = formatVersion;
- program->kernel_data_ = reader->buffer();
- program->kernel_data_size_ = reader->size();
+ program->kernel_data_ =
+ &TypedDataBase::ZoneHandle(reader->typed_data()->raw());
// Dill files can be concatenated (e.g. cat a.dill b.dill > c.dill). Find out
// if this dill contains more than one program.
@@ -126,45 +126,25 @@
if (script_uri == NULL) {
return NULL;
}
- kernel::Program* kernel_program = NULL;
const String& uri = String::Handle(String::New(script_uri));
const Object& ret = Object::Handle(thread->isolate()->CallTagHandler(
Dart_kKernelTag, Object::null_object(), uri));
- Api::Scope api_scope(thread);
- Dart_Handle retval = Api::NewHandle(thread, ret.raw());
- {
+ if (ret.IsError()) {
+ Api::Scope api_scope(thread);
+ Dart_Handle retval = Api::NewHandle(thread, ret.raw());
TransitionVMToNative transition(thread);
- if (!Dart_IsError(retval)) {
- Dart_TypedData_Type data_type;
- uint8_t* data;
- ASSERT(Dart_IsTypedData(retval));
-
- uint8_t* kernel_buffer;
- intptr_t kernel_buffer_size;
- Dart_Handle val = Dart_TypedDataAcquireData(
- retval, &data_type, reinterpret_cast<void**>(&data),
- &kernel_buffer_size);
- ASSERT(!Dart_IsError(val));
- ASSERT(data_type == Dart_TypedData_kUint8);
- kernel_buffer = reinterpret_cast<uint8_t*>(malloc(kernel_buffer_size));
- memmove(kernel_buffer, data, kernel_buffer_size);
- Dart_TypedDataReleaseData(retval);
-
- kernel_program = kernel::Program::ReadFromBuffer(
- kernel_buffer, kernel_buffer_size, error);
- } else if (error != nullptr) {
+ if (error != nullptr) {
*error = Dart_GetError(retval);
}
+ return nullptr;
}
- return kernel_program;
-}
-Program* Program::ReadFromBuffer(const uint8_t* buffer,
- intptr_t buffer_length,
- const char** error) {
- kernel::Reader reader(buffer, buffer_length);
- return kernel::Program::ReadFrom(&reader, error);
+ // NOTE: We require the embedder to supply an external typed data (with a
+ // finalizer) so we can simply use it and don't need to make a copy.
+ RELEASE_ASSERT(ret.IsExternalTypedData());
+ const auto& td = ExternalTypedData::Cast(ret);
+ return kernel::Program::ReadFromTypedData(td, error);
}
Program* Program::ReadFromTypedData(const ExternalTypedData& typed_data,
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 760c6ac..2da794b 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -170,19 +170,23 @@
class Reader : public ValueObject {
public:
- Reader(const uint8_t* buffer, intptr_t size)
- : thread_(NULL),
- raw_buffer_(buffer),
- typed_data_(NULL),
- size_(size),
- offset_(0) {}
-
- explicit Reader(const ExternalTypedData& typed_data)
+ explicit Reader(const TypedDataBase& typed_data)
: thread_(Thread::Current()),
- raw_buffer_(NULL),
typed_data_(&typed_data),
size_(typed_data.IsNull() ? 0 : typed_data.Length()),
- offset_(0) {}
+ 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
+ }
uint32_t ReadFromIndex(intptr_t end_offset,
intptr_t fields_before,
@@ -198,11 +202,7 @@
uint32_t ReadUInt32At(intptr_t offset) const {
ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4));
uint32_t value;
- if (raw_buffer_ != NULL) {
- value = *reinterpret_cast<const uint32_t*>(raw_buffer_ + offset);
- } else {
- value = typed_data_->GetUint32(offset);
- }
+ value = typed_data_->GetUint32(offset);
return Utils::BigEndianToHost32(value);
}
@@ -347,20 +347,11 @@
intptr_t size() const { return size_; }
void set_size(intptr_t size) { size_ = size; }
- const ExternalTypedData* typed_data() const { return typed_data_; }
- void set_typed_data(const ExternalTypedData* typed_data) {
+ const TypedDataBase* typed_data() const { return typed_data_; }
+ void set_typed_data(const TypedDataBase* typed_data) {
typed_data_ = typed_data;
}
- const uint8_t* raw_buffer() const { return raw_buffer_; }
- void set_raw_buffer(const uint8_t* raw_buffer) { raw_buffer_ = raw_buffer; }
-
- RawExternalTypedData* ExternalDataFromTo(intptr_t start, intptr_t end) {
- return ExternalTypedData::New(kExternalTypedDataUint8ArrayCid,
- const_cast<uint8_t*>(buffer() + start),
- end - start, Heap::kOld);
- }
-
const uint8_t* BufferAt(intptr_t offset) {
ASSERT((offset >= 0) && (offset < size_));
return &buffer()[offset];
@@ -368,16 +359,12 @@
private:
const uint8_t* buffer() const {
- if (raw_buffer_ != NULL) {
- return raw_buffer_;
- }
NoSafepointScope no_safepoint(thread_);
return reinterpret_cast<uint8_t*>(typed_data_->DataAddr(0));
}
Thread* thread_;
- const uint8_t* raw_buffer_;
- const ExternalTypedData* typed_data_;
+ const TypedDataBase* typed_data_;
intptr_t size_;
intptr_t offset_;
TokenPosition max_position_;
@@ -395,21 +382,18 @@
AlternativeReadingScope(Reader* reader, intptr_t new_position)
: reader_(reader),
saved_size_(reader_->size()),
- saved_raw_buffer_(reader_->raw_buffer()),
saved_typed_data_(reader_->typed_data()),
saved_offset_(reader_->offset()) {
reader_->set_offset(new_position);
}
AlternativeReadingScope(Reader* reader,
- const ExternalTypedData* new_typed_data,
+ const TypedDataBase* new_typed_data,
intptr_t new_position)
: reader_(reader),
saved_size_(reader_->size()),
- saved_raw_buffer_(reader_->raw_buffer()),
saved_typed_data_(reader_->typed_data()),
saved_offset_(reader_->offset()) {
- reader_->set_raw_buffer(NULL);
reader_->set_typed_data(new_typed_data);
reader_->set_size(new_typed_data->Length());
reader_->set_offset(new_position);
@@ -418,12 +402,10 @@
explicit AlternativeReadingScope(Reader* reader)
: reader_(reader),
saved_size_(reader_->size()),
- saved_raw_buffer_(reader_->raw_buffer()),
saved_typed_data_(reader_->typed_data()),
saved_offset_(reader_->offset()) {}
~AlternativeReadingScope() {
- reader_->set_raw_buffer(saved_raw_buffer_);
reader_->set_typed_data(saved_typed_data_);
reader_->set_size(saved_size_);
reader_->set_offset(saved_offset_);
@@ -434,8 +416,7 @@
private:
Reader* reader_;
intptr_t saved_size_;
- const uint8_t* saved_raw_buffer_;
- const ExternalTypedData* saved_typed_data_;
+ const TypedDataBase* saved_typed_data_;
intptr_t saved_offset_;
DISALLOW_COPY_AND_ASSIGN(AlternativeReadingScope);
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 962d878..9c89a2d 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -143,7 +143,7 @@
return loader_->LookupClass(library_lookup_handle_, klass);
}
-LibraryIndex::LibraryIndex(const ExternalTypedData& kernel_data,
+LibraryIndex::LibraryIndex(const TypedDataBase& kernel_data,
int32_t binary_version)
: reader_(kernel_data), binary_version_(binary_version) {
intptr_t data_size = reader_.size();
@@ -160,15 +160,7 @@
}
}
-ClassIndex::ClassIndex(const uint8_t* buffer,
- intptr_t buffer_size,
- intptr_t class_offset,
- intptr_t class_size)
- : reader_(buffer, buffer_size) {
- Init(class_offset, class_size);
-}
-
-ClassIndex::ClassIndex(const ExternalTypedData& library_kernel_data,
+ClassIndex::ClassIndex(const TypedDataBase& library_kernel_data,
intptr_t class_offset,
intptr_t class_size)
: reader_(library_kernel_data) {
@@ -193,13 +185,13 @@
library_kernel_offset_(-1), // Set to the correct value in LoadLibrary
correction_offset_(-1), // Set to the correct value in LoadLibrary
loading_native_wrappers_library_(false),
- library_kernel_data_(ExternalTypedData::ZoneHandle(zone_)),
+ library_kernel_data_(TypedDataBase::ZoneHandle(zone_)),
kernel_program_info_(KernelProgramInfo::ZoneHandle(zone_)),
translation_helper_(this, thread_, Heap::kOld),
helper_(zone_,
&translation_helper_,
- program_->kernel_data(),
- program_->kernel_data_size(),
+ Script::Handle(thread_->zone()),
+ program->kernel_data(),
0),
type_translator_(&helper_, &active_class_, /* finalize= */ false),
inferred_type_metadata_helper_(&helper_),
@@ -236,9 +228,11 @@
return Object::Handle(loader.LoadProgram(process_pending_classes));
}
- kernel::Reader reader(program->kernel_data(), program->kernel_data_size());
GrowableArray<intptr_t> subprogram_file_starts;
- index_programs(&reader, &subprogram_file_starts);
+ {
+ kernel::Reader reader(program->kernel_data());
+ index_programs(&reader, &subprogram_file_starts);
+ }
Zone* zone = thread->zone();
Library& library = Library::Handle(zone);
@@ -247,15 +241,19 @@
// First index all source tables.
UriToSourceTable uri_to_source_table;
UriToSourceTableEntry wrapper;
+ auto& subprogram_view = TypedDataView::Handle(zone);
for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
intptr_t subprogram_start = subprogram_file_starts.At(i);
intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
Thread* thread_ = Thread::Current();
Zone* zone_ = thread_->zone();
TranslationHelper translation_helper(thread);
- KernelReaderHelper helper_(zone_, &translation_helper,
- program->kernel_data() + subprogram_start,
- subprogram_end - subprogram_start, 0);
+
+ subprogram_view = program->kernel_data().CreateUint8View(
+ subprogram_start, subprogram_end - subprogram_start);
+
+ KernelReaderHelper helper_(zone_, &translation_helper, Script::Handle(),
+ subprogram_view, 0);
const intptr_t source_table_size = helper_.SourceTableSize();
for (intptr_t index = 0; index < source_table_size; ++index) {
const String& uri_string = helper_.SourceTableUriFor(index);
@@ -287,11 +285,13 @@
// Create "fake programs" for each sub-program.
for (intptr_t i = subprogram_count - 1; i >= 0; --i) {
- intptr_t subprogram_start = subprogram_file_starts.At(i);
- intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
- reader.set_raw_buffer(program->kernel_data() + subprogram_start);
- reader.set_size(subprogram_end - subprogram_start);
- reader.set_offset(0);
+ const intptr_t subprogram_start = subprogram_file_starts.At(i);
+ const intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
+
+ subprogram_view = program->kernel_data().CreateUint8View(
+ subprogram_start, subprogram_end - subprogram_start);
+
+ kernel::Reader reader(subprogram_view);
Program* subprogram = Program::ReadFrom(&reader);
ASSERT(subprogram->is_single_program());
KernelLoader loader(subprogram, &uri_to_source_table);
@@ -334,14 +334,13 @@
subprogram_file_starts->Reverse();
}
-RawString* KernelLoader::FindSourceForScript(const uint8_t* kernel_buffer,
- intptr_t kernel_buffer_length,
+RawString* KernelLoader::FindSourceForScript(const ExternalTypedData& kernel_td,
const String& uri) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
TranslationHelper translation_helper(thread);
- KernelReaderHelper reader(zone, &translation_helper, kernel_buffer,
- kernel_buffer_length, 0);
+ KernelReaderHelper reader(zone, &translation_helper, Script::Handle(zone),
+ kernel_td, 0);
intptr_t source_table_size = reader.SourceTableSize();
for (intptr_t i = 0; i < source_table_size; ++i) {
const String& source_uri = reader.SourceTableUriFor(i);
@@ -360,7 +359,7 @@
// Copy the Kernel string offsets out of the binary and into the VM's heap.
ASSERT(program_->string_table_offset() >= 0);
- Reader reader(program_->kernel_data(), program_->kernel_data_size());
+ Reader reader(program_->kernel_data());
reader.set_offset(program_->string_table_offset());
intptr_t count = reader.ReadUInt() + 1;
TypedData& offsets = TypedData::Handle(
@@ -372,16 +371,18 @@
offsets.SetUint32(i << 2, end_offset);
}
+ const auto& kernel_data = *reader.typed_data();
+
// Create view of the string data.
- const ExternalTypedData& data = ExternalTypedData::Handle(
- Z,
- reader.ExternalDataFromTo(reader.offset(), reader.offset() + end_offset));
+ const auto& data = TypedDataBase::Handle(
+ Z, kernel_data.CreateUint8View(reader.offset(), end_offset));
// Create a view of the constants table. The trailing ComponentIndex is
// negligible in size.
- const ExternalTypedData& constants_table = ExternalTypedData::Handle(
- Z, reader.ExternalDataFromTo(program_->constant_table_offset(),
- program_->kernel_data_size()));
+ const auto& constants_table = TypedDataBase::Handle(
+ Z, kernel_data.CreateUint8View(
+ program_->constant_table_offset(),
+ kernel_data.LengthInBytes() - program_->constant_table_offset()));
// Copy the canonical names into the VM's heap. Encode them as unsigned, so
// the parent indexes are adjusted when extracted.
@@ -394,15 +395,18 @@
}
// Create view of metadata payloads.
- const ExternalTypedData& metadata_payloads = ExternalTypedData::Handle(
- Z, reader.ExternalDataFromTo(program_->metadata_payloads_offset(),
- program_->metadata_mappings_offset()));
+ const auto& metadata_payloads = TypedDataBase::Handle(
+ Z, kernel_data.CreateUint8View(program_->metadata_payloads_offset(),
+ program_->metadata_mappings_offset() -
+ program_->metadata_payloads_offset()));
+
ASSERT(Utils::IsAligned(metadata_payloads.DataAddr(0), kWordSize));
// Create view of metadata mappings.
- const ExternalTypedData& metadata_mappings = ExternalTypedData::Handle(
- Z, reader.ExternalDataFromTo(program_->metadata_mappings_offset(),
- program_->string_table_offset()));
+ const auto& metadata_mappings = TypedDataBase::Handle(
+ Z, kernel_data.CreateUint8View(program_->metadata_mappings_offset(),
+ program_->string_table_offset() -
+ program_->metadata_mappings_offset()));
const Array& libraries_cache =
Array::Handle(Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
@@ -431,7 +435,7 @@
}
KernelLoader::KernelLoader(const Script& script,
- const ExternalTypedData& kernel_data,
+ const TypedDataBase& kernel_data,
intptr_t data_program_offset)
: program_(NULL),
thread_(Thread::Current()),
@@ -441,7 +445,7 @@
library_kernel_offset_(data_program_offset),
correction_offset_(0),
loading_native_wrappers_library_(false),
- library_kernel_data_(ExternalTypedData::ZoneHandle(zone_)),
+ library_kernel_data_(TypedDataBase::ZoneHandle(zone_)),
kernel_program_info_(
KernelProgramInfo::ZoneHandle(zone_, script.kernel_program_info())),
translation_helper_(this, thread_, Heap::kOld),
@@ -759,7 +763,7 @@
// c) update all scripts with the constants array
ASSERT(kernel_program_info_.constants() == Array::null());
kernel_program_info_.set_constants(constants);
- kernel_program_info_.set_constants_table(ExternalTypedData::Handle(Z));
+ kernel_program_info_.set_constants_table(TypedDataBase::Handle(Z));
// d) evaluate pending field initializers
Error& error = Error::Handle(Z);
@@ -825,8 +829,8 @@
// Make the expression evaluation function have the right kernel data and
// parent.
- auto& eval_data = ExternalTypedData::Handle(
- Z, expression_evaluation_library_.kernel_data());
+ auto& eval_data =
+ TypedDataBase::Handle(Z, expression_evaluation_library_.kernel_data());
auto& eval_script =
Script::Handle(Z, expression_evaluation_function_.script());
expression_evaluation_function_.SetKernelDataAndScript(
@@ -877,18 +881,24 @@
loader.walk_incremental_kernel(modified_libs, is_empty_program,
p_num_classes, p_num_procedures);
}
- kernel::Reader reader(program->kernel_data(), program->kernel_data_size());
+
GrowableArray<intptr_t> subprogram_file_starts;
- index_programs(&reader, &subprogram_file_starts);
+ {
+ kernel::Reader reader(program->kernel_data());
+ index_programs(&reader, &subprogram_file_starts);
+ }
// Create "fake programs" for each sub-program.
intptr_t subprogram_count = subprogram_file_starts.length() - 1;
+ auto& subprogram_view = TypedDataView::Handle(zone);
for (intptr_t i = 0; i < subprogram_count; ++i) {
intptr_t subprogram_start = subprogram_file_starts.At(i);
intptr_t subprogram_end = subprogram_file_starts.At(i + 1);
- reader.set_raw_buffer(program->kernel_data() + subprogram_start);
- reader.set_size(subprogram_end - subprogram_start);
- reader.set_offset(0);
+
+ subprogram_view = program->kernel_data().CreateUint8View(
+ subprogram_start, subprogram_end - subprogram_start);
+
+ kernel::Reader reader(subprogram_view);
Program* subprogram = Program::ReadFrom(&reader);
ASSERT(subprogram->is_single_program());
KernelLoader loader(subprogram, /*uri_to_source_table=*/nullptr);
@@ -922,8 +932,8 @@
}
if (collect_library_stats) {
intptr_t library_end = library_offset(i + 1);
- library_kernel_data_ =
- helper_.reader_.ExternalDataFromTo(kernel_offset, library_end);
+ library_kernel_data_ = helper_.reader_.typed_data()->CreateUint8View(
+ kernel_offset, library_end - kernel_offset);
LibraryIndex library_index(library_kernel_data_,
program_->binary_version());
@@ -1012,8 +1022,8 @@
ASSERT(!library_helper.IsExternal() || library.Loaded());
if (library.Loaded()) return library.raw();
- library_kernel_data_ = helper_.reader_.ExternalDataFromTo(
- library_kernel_offset_, library_kernel_offset_ + library_size);
+ library_kernel_data_ = helper_.reader_.typed_data()->CreateUint8View(
+ library_kernel_offset_, library_size);
library.set_kernel_data(library_kernel_data_);
library.set_kernel_offset(library_kernel_offset_);
@@ -1389,8 +1399,8 @@
intptr_t class_end,
Class* out_class) {
intptr_t class_offset = helper_.ReaderOffset();
- ClassIndex class_index(program_->kernel_data(), program_->kernel_data_size(),
- class_offset, class_end - class_offset);
+ ClassIndex class_index(program_->kernel_data(), class_offset,
+ class_end - class_offset);
ClassHelper class_helper(&helper_);
class_helper.ReadUntilIncluding(ClassHelper::kCanonicalName);
@@ -1689,8 +1699,8 @@
const Script& script = Script::Handle(zone, klass.script());
const Library& library = Library::Handle(zone, klass.library());
const Class& toplevel_class = Class::Handle(zone, library.toplevel_class());
- const ExternalTypedData& library_kernel_data =
- ExternalTypedData::Handle(zone, library.kernel_data());
+ const TypedDataBase& library_kernel_data =
+ TypedDataBase::Handle(zone, library.kernel_data());
ASSERT(!library_kernel_data.IsNull());
const intptr_t library_kernel_offset = library.kernel_offset();
ASSERT(library_kernel_offset > 0);
@@ -1766,8 +1776,7 @@
// constants in the annotation list to later.
*is_potential_native = true;
- ASSERT(kernel_program_info_.constants_table() !=
- ExternalTypedData::null());
+ ASSERT(kernel_program_info_.constants_table() != TypedDataBase::null());
// For pragma annotations, we seek into the constants table and peek
// into the Kernel representation of the constant.
@@ -1785,8 +1794,7 @@
AlternativeReadingScope scope(
&helper_.reader_,
- &ExternalTypedData::Handle(Z,
- kernel_program_info_.constants_table()),
+ &TypedDataBase::Handle(Z, kernel_program_info_.constants_table()),
0);
// Seek into the position within the constant table where we can inspect
@@ -2266,7 +2274,7 @@
PatchClass::Handle(zone, PatchClass::New(field_owner, script));
const Library& lib = Library::Handle(zone, field_owner.library());
initializer_owner.set_library_kernel_data(
- ExternalTypedData::Handle(zone, lib.kernel_data()));
+ TypedDataBase::Handle(zone, lib.kernel_data()));
initializer_owner.set_library_kernel_offset(lib.kernel_offset());
// Create a static initializer.
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index 79c58b6..e0cd207 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -84,7 +84,7 @@
// |kernel_data| is the kernel data for one library alone.
// binary_version can be -1 in which case some parts of the index might not
// be read.
- explicit LibraryIndex(const ExternalTypedData& kernel_data,
+ explicit LibraryIndex(const TypedDataBase& kernel_data,
int32_t binary_version);
intptr_t class_count() const { return class_count_; }
@@ -130,16 +130,9 @@
class ClassIndex {
public:
- // |class_offset| is the offset of class' kernel data in |buffer| of
- // size |size|. The size of the class' kernel data is |class_size|.
- ClassIndex(const uint8_t* buffer,
- intptr_t buffer_size,
- intptr_t class_offset,
- intptr_t class_size);
-
// |class_offset| is the offset of class' kernel data in |kernel_data|.
// The size of the class' kernel data is |class_size|.
- ClassIndex(const ExternalTypedData& kernel_data,
+ ClassIndex(const TypedDataBase& kernel_data,
intptr_t class_offset,
intptr_t class_size);
@@ -215,8 +208,7 @@
intptr_t* p_num_classes,
intptr_t* p_num_procedures);
- static RawString* FindSourceForScript(const uint8_t* kernel_buffer,
- intptr_t kernel_buffer_length,
+ static RawString* FindSourceForScript(const ExternalTypedData& kernel_td,
const String& url);
RawLibrary* LoadLibrary(intptr_t index);
@@ -265,16 +257,14 @@
}
intptr_t library_offset(intptr_t index) {
- kernel::Reader reader(program_->kernel_data(),
- program_->kernel_data_size());
+ kernel::Reader reader(program_->kernel_data());
return reader.ReadFromIndexNoReset(reader.size(),
LibraryCountFieldCountFromEnd + 1,
program_->library_count() + 1, index);
}
NameIndex library_canonical_name(intptr_t index) {
- kernel::Reader reader(program_->kernel_data(),
- program_->kernel_data_size());
+ kernel::Reader reader(program_->kernel_data());
reader.set_offset(library_offset(index));
// Start reading library.
@@ -288,7 +278,7 @@
friend class BuildingTranslationHelper;
KernelLoader(const Script& script,
- const ExternalTypedData& kernel_data,
+ const TypedDataBase& kernel_data,
intptr_t data_program_offset);
void InitializeFields(
@@ -411,7 +401,7 @@
NameIndex skip_vmservice_library_;
- ExternalTypedData& library_kernel_data_;
+ TypedDataBase& library_kernel_data_;
KernelProgramInfo& kernel_program_info_;
BuildingTranslationHelper translation_helper_;
KernelReaderHelper helper_;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index bbad5ca..eb7824b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3540,8 +3540,7 @@
}
static RawObject* EvaluateCompiledExpressionHelper(
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_data,
const Array& type_definitions,
const String& library_url,
const String& klass,
@@ -3549,8 +3548,7 @@
const TypeArguments& type_arguments);
RawObject* Class::EvaluateCompiledExpression(
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_data,
const Array& type_definitions,
const Array& arguments,
const TypeArguments& type_arguments) const {
@@ -3563,7 +3561,7 @@
}
return EvaluateCompiledExpressionHelper(
- kernel_bytes, kernel_length, type_definitions,
+ kernel_data, type_definitions,
String::Handle(Library::Handle(library()).url()),
IsTopLevel() ? String::Handle() : String::Handle(UserVisibleName()),
arguments, type_arguments);
@@ -4013,8 +4011,7 @@
if (scr.kind() == RawScript::kKernelTag) {
ASSERT(kernel_offset() > 0);
const Library& lib = Library::Handle(zone, library());
- const ExternalTypedData& kernel_data =
- ExternalTypedData::Handle(zone, lib.kernel_data());
+ const auto& kernel_data = TypedDataBase::Handle(zone, lib.kernel_data());
ASSERT(!kernel_data.IsNull());
const intptr_t library_kernel_offset = lib.kernel_offset();
ASSERT(library_kernel_offset > 0);
@@ -5628,7 +5625,7 @@
StorePointer(&raw_ptr()->script_, value.raw());
}
-void PatchClass::set_library_kernel_data(const ExternalTypedData& data) const {
+void PatchClass::set_library_kernel_data(const TypedDataBase& data) const {
StorePointer(&raw_ptr()->library_kernel_data_, data.raw());
}
@@ -7693,7 +7690,7 @@
}
void Function::SetKernelDataAndScript(const Script& script,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t offset) {
Array& data_field = Array::Handle(Array::New(3));
data_field.SetAt(0, script);
@@ -7735,12 +7732,12 @@
return Class::Cast(obj).script();
}
-RawExternalTypedData* Function::KernelData() const {
+RawTypedDataBase* Function::KernelData() const {
Object& data = Object::Handle(raw_ptr()->data_);
if (data.IsArray()) {
Object& script = Object::Handle(Array::Cast(data).At(0));
if (script.IsScript()) {
- return ExternalTypedData::RawCast(Array::Cast(data).At(1));
+ return TypedDataBase::RawCast(Array::Cast(data).At(1));
}
}
if (IsClosureFunction()) {
@@ -8363,7 +8360,7 @@
return PatchClass::Cast(obj).script();
}
-RawExternalTypedData* Field::KernelData() const {
+RawTypedDataBase* Field::KernelData() const {
const Object& obj = Object::Handle(this->raw_ptr()->owner_);
// During background JIT compilation field objects are copied
// and copy points to the original field via the owner field.
@@ -9204,11 +9201,10 @@
}
#if !defined(DART_PRECOMPILED_RUNTIME)
-void Script::LoadSourceFromKernel(const uint8_t* kernel_buffer,
- intptr_t kernel_buffer_len) const {
+void Script::LoadSourceFromKernel(const ExternalTypedData& kernel_td) const {
String& uri = String::Handle(resolved_url());
- String& source = String::Handle(kernel::KernelLoader::FindSourceForScript(
- kernel_buffer, kernel_buffer_len, uri));
+ String& source =
+ String::Handle(kernel::KernelLoader::FindSourceForScript(kernel_td, uri));
set_source(source);
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@@ -9784,7 +9780,7 @@
StorePointer(&raw_ptr()->url_, name.raw());
}
-void Library::set_kernel_data(const ExternalTypedData& data) const {
+void Library::set_kernel_data(const TypedDataBase& data) const {
StorePointer(&raw_ptr()->kernel_data_, data.raw());
}
@@ -11182,14 +11178,13 @@
}
RawObject* Library::EvaluateCompiledExpression(
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_data,
const Array& type_definitions,
const Array& arguments,
const TypeArguments& type_arguments) const {
return EvaluateCompiledExpressionHelper(
- kernel_bytes, kernel_length, type_definitions, String::Handle(url()),
- String::Handle(), arguments, type_arguments);
+ kernel_data, type_definitions, String::Handle(url()), String::Handle(),
+ arguments, type_arguments);
}
void Library::InitNativeWrappersLibrary(Isolate* isolate, bool is_kernel) {
@@ -11247,8 +11242,7 @@
typedef UnorderedHashMap<LibraryLookupTraits> LibraryLookupMap;
static RawObject* EvaluateCompiledExpressionHelper(
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_td,
const Array& type_definitions,
const String& library_url,
const String& klass,
@@ -11259,8 +11253,7 @@
String::New("Expression evaluation not available in precompiled mode."));
return ApiError::New(error_str);
#else
- kernel::Program* kernel_pgm =
- kernel::Program::ReadFromBuffer(kernel_bytes, kernel_length);
+ kernel::Program* kernel_pgm = kernel::Program::ReadFromTypedData(kernel_td);
if (kernel_pgm == NULL) {
return ApiError::New(String::Handle(
@@ -12027,11 +12020,11 @@
RawKernelProgramInfo* KernelProgramInfo::New(
const TypedData& string_offsets,
- const ExternalTypedData& string_data,
+ const TypedDataBase& string_data,
const TypedData& canonical_names,
- const ExternalTypedData& metadata_payloads,
- const ExternalTypedData& metadata_mappings,
- const ExternalTypedData& constants_table,
+ const TypedDataBase& metadata_payload,
+ const TypedDataBase& metadata_mappings,
+ const TypedDataBase& constants_table,
const Array& scripts,
const Array& libraries_cache,
const Array& classes_cache) {
@@ -12041,7 +12034,7 @@
info.StorePointer(&info.raw_ptr()->string_data_, string_data.raw());
info.StorePointer(&info.raw_ptr()->canonical_names_, canonical_names.raw());
info.StorePointer(&info.raw_ptr()->metadata_payloads_,
- metadata_payloads.raw());
+ metadata_payload.raw());
info.StorePointer(&info.raw_ptr()->metadata_mappings_,
metadata_mappings.raw());
info.StorePointer(&info.raw_ptr()->scripts_, scripts.raw());
@@ -12069,8 +12062,7 @@
StorePointer(&raw_ptr()->constants_, constants.raw());
}
-void KernelProgramInfo::set_constants_table(
- const ExternalTypedData& value) const {
+void KernelProgramInfo::set_constants_table(const TypedDataBase& value) const {
StorePointer(&raw_ptr()->constants_table_, value.raw());
}
@@ -15134,10 +15126,10 @@
return result.raw();
}
-RawExternalTypedData* Bytecode::GetBinary(Zone* zone) const {
+RawTypedDataBase* Bytecode::GetBinary(Zone* zone) const {
const Function& func = Function::Handle(zone, function());
if (func.IsNull()) {
- return ExternalTypedData::null();
+ return TypedDataBase::null();
}
const Script& script = Script::Handle(zone, func.script());
const KernelProgramInfo& info =
@@ -16103,8 +16095,7 @@
RawObject* Instance::EvaluateCompiledExpression(
const Class& method_cls,
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_data,
const Array& type_definitions,
const Array& arguments,
const TypeArguments& type_arguments) const {
@@ -16118,7 +16109,7 @@
}
return EvaluateCompiledExpressionHelper(
- kernel_bytes, kernel_length, type_definitions,
+ kernel_data, type_definitions,
String::Handle(Library::Handle(method_cls.library()).url()),
String::Handle(method_cls.UserVisibleName()), arguments_with_receiver,
type_arguments);
@@ -21139,6 +21130,20 @@
return nullptr;
}
+RawTypedDataView* TypedDataBase::CreateUint8View(intptr_t offset_in_bytes,
+ intptr_t length_in_bytes,
+ Heap::Space space) const {
+ auto& backing_store = TypedDataBase::Handle(raw());
+ if (IsTypedDataView()) {
+ const auto& this_view = TypedDataView::Cast(*this);
+ offset_in_bytes += ValueFromRawSmi(this_view.offset_in_bytes());
+ backing_store = this_view.typed_data();
+ }
+ ASSERT((offset_in_bytes + length_in_bytes) <= backing_store.LengthInBytes());
+ return TypedDataView::New(kTypedDataUint8ArrayViewCid, backing_store,
+ offset_in_bytes, length_in_bytes, space);
+}
+
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 499939e..d9cf880 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1235,8 +1235,7 @@
// (type_)param_names, and is invoked with the (type)argument values given in
// (type_)param_values.
RawObject* EvaluateCompiledExpression(
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_data,
const Array& type_definitions,
const Array& param_values,
const TypeArguments& type_param_values) const;
@@ -1463,10 +1462,10 @@
RawClass* patched_class() const { return raw_ptr()->patched_class_; }
RawClass* origin_class() const { return raw_ptr()->origin_class_; }
RawScript* script() const { return raw_ptr()->script_; }
- RawExternalTypedData* library_kernel_data() const {
+ RawTypedDataBase* library_kernel_data() const {
return raw_ptr()->library_kernel_data_;
}
- void set_library_kernel_data(const ExternalTypedData& data) const;
+ void set_library_kernel_data(const TypedDataBase& data) const;
intptr_t library_kernel_offset() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -2525,12 +2524,12 @@
}
void SetKernelDataAndScript(const Script& script,
- const ExternalTypedData& data,
+ const TypedDataBase& data,
intptr_t offset);
intptr_t KernelDataProgramOffset() const;
- RawExternalTypedData* KernelData() const;
+ RawTypedDataBase* KernelData() const;
bool IsOptimizable() const;
void SetIsOptimizable(bool value) const;
@@ -3302,7 +3301,7 @@
void InheritBinaryDeclarationFrom(const Field& src) const;
- RawExternalTypedData* KernelData() const;
+ RawTypedDataBase* KernelData() const;
intptr_t KernelDataProgramOffset() const;
@@ -3721,8 +3720,7 @@
RawScript::Kind kind);
#if !defined(DART_PRECOMPILED_RUNTIME)
- void LoadSourceFromKernel(const uint8_t* kernel_buffer,
- intptr_t kernel_buffer_len) const;
+ void LoadSourceFromKernel(const ExternalTypedData& kernel_td) const;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
private:
@@ -3850,8 +3848,7 @@
// parameters given in (type_)param_names, and is invoked with the (type)
// argument values given in (type_)param_values.
RawObject* EvaluateCompiledExpression(
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_data,
const Array& type_definitions,
const Array& param_values,
const TypeArguments& type_param_values) const;
@@ -4002,8 +3999,8 @@
inline intptr_t UrlHash() const;
- RawExternalTypedData* kernel_data() const { return raw_ptr()->kernel_data_; }
- void set_kernel_data(const ExternalTypedData& data) const;
+ RawTypedDataBase* kernel_data() const { return raw_ptr()->kernel_data_; }
+ void set_kernel_data(const TypedDataBase& data) const;
intptr_t kernel_offset() const {
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -4190,11 +4187,11 @@
class KernelProgramInfo : public Object {
public:
static RawKernelProgramInfo* New(const TypedData& string_offsets,
- const ExternalTypedData& string_data,
+ const TypedDataBase& string_data,
const TypedData& canonical_names,
- const ExternalTypedData& metadata_payload,
- const ExternalTypedData& metadata_mappings,
- const ExternalTypedData& constants_table,
+ const TypedDataBase& metadata_payload,
+ const TypedDataBase& metadata_mappings,
+ const TypedDataBase& constants_table,
const Array& scripts,
const Array& libraries_cache,
const Array& classes_cache);
@@ -4205,23 +4202,23 @@
RawTypedData* string_offsets() const { return raw_ptr()->string_offsets_; }
- RawExternalTypedData* string_data() const { return raw_ptr()->string_data_; }
+ RawTypedDataBase* string_data() const { return raw_ptr()->string_data_; }
RawTypedData* canonical_names() const { return raw_ptr()->canonical_names_; }
- RawExternalTypedData* metadata_payloads() const {
+ RawTypedDataBase* metadata_payloads() const {
return raw_ptr()->metadata_payloads_;
}
- RawExternalTypedData* metadata_mappings() const {
+ RawTypedDataBase* metadata_mappings() const {
return raw_ptr()->metadata_mappings_;
}
- RawExternalTypedData* constants_table() const {
+ RawTypedDataBase* constants_table() const {
return raw_ptr()->constants_table_;
}
- void set_constants_table(const ExternalTypedData& value) const;
+ void set_constants_table(const TypedDataBase& value) const;
RawArray* scripts() const { return raw_ptr()->scripts_; }
void set_scripts(const Array& scripts) const;
@@ -5486,7 +5483,7 @@
intptr_t instructions_offset,
const ObjectPool& object_pool);
- RawExternalTypedData* GetBinary(Zone* zone) const;
+ RawTypedDataBase* GetBinary(Zone* zone) const;
TokenPosition GetTokenIndexOfPC(uword pc) const;
@@ -6069,8 +6066,7 @@
// argument values given in (type_)param_values.
RawObject* EvaluateCompiledExpression(
const Class& method_cls,
- const uint8_t* kernel_bytes,
- intptr_t kernel_length,
+ const ExternalTypedData& kernel_data,
const Array& type_definitions,
const Array& param_values,
const TypeArguments& type_param_values) const;
@@ -8421,6 +8417,19 @@
return element_size(ElementType(raw()->GetClassId()));
}
+ void* DataAddr(intptr_t byte_offset) const {
+ ASSERT(byte_offset == 0 ||
+ (byte_offset > 0 && byte_offset < LengthInBytes()));
+#if defined(DEBUG)
+ ValidateInvariant();
+#endif
+ return reinterpret_cast<void*>(raw_ptr()->data_ + byte_offset);
+ }
+
+ RawTypedDataView* CreateUint8View(intptr_t offset_in_bytes,
+ intptr_t length_in_bytes,
+ Heap::Space space = Heap::kNew) const;
+
static intptr_t ElementSizeInBytes(classid_t cid) {
return element_size(ElementType(cid));
}
@@ -8444,12 +8453,45 @@
}
}
+#define TYPED_GETTER_SETTER(name, type) \
+ type Get##name(intptr_t byte_offset) const { \
+ ASSERT(byte_offset >= 0 && \
+ (byte_offset + static_cast<intptr_t>(sizeof(type)) - 1) < \
+ LengthInBytes()); \
+ return ReadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset))); \
+ } \
+ void Set##name(intptr_t byte_offset, type value) const { \
+ ASSERT(byte_offset >= 0 && \
+ (byte_offset + static_cast<intptr_t>(sizeof(type)) - 1) < \
+ LengthInBytes()); \
+ NoSafepointScope no_safepoint; \
+ StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value); \
+ }
+
+ TYPED_GETTER_SETTER(Int8, int8_t)
+ TYPED_GETTER_SETTER(Uint8, uint8_t)
+ TYPED_GETTER_SETTER(Int16, int16_t)
+ TYPED_GETTER_SETTER(Uint16, uint16_t)
+ TYPED_GETTER_SETTER(Int32, int32_t)
+ TYPED_GETTER_SETTER(Uint32, uint32_t)
+ TYPED_GETTER_SETTER(Int64, int64_t)
+ TYPED_GETTER_SETTER(Uint64, uint64_t)
+ TYPED_GETTER_SETTER(Float32, float)
+ TYPED_GETTER_SETTER(Float64, double)
+ TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
+ TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
+ TYPED_GETTER_SETTER(Float64x2, simd128_value_t)
+
+#undef TYPED_GETTER_SETTER
+
protected:
void SetLength(intptr_t value) const {
ASSERT(value <= Smi::kMaxValue);
StoreSmi(&raw_ptr()->length_, Smi::New(value));
}
+ virtual void ValidateInvariant() const {}
+
private:
friend class Class;
@@ -8473,44 +8515,9 @@
// architecture.
static const intptr_t kHashBits = 30;
- void* DataAddr(intptr_t byte_offset) const {
- ASSERT((byte_offset == 0) ||
- ((byte_offset > 0) && (byte_offset < LengthInBytes())));
- return reinterpret_cast<void*>(UnsafeMutableNonPointer(raw_ptr()->data()) +
- byte_offset);
- }
-
virtual bool CanonicalizeEquals(const Instance& other) const;
virtual uint32_t CanonicalizeHash() const;
-#define TYPED_GETTER_SETTER(name, type) \
- type Get##name(intptr_t byte_offset) const { \
- 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; \
- StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value); \
- }
-
- TYPED_GETTER_SETTER(Int8, int8_t)
- TYPED_GETTER_SETTER(Uint8, uint8_t)
- TYPED_GETTER_SETTER(Int16, int16_t)
- TYPED_GETTER_SETTER(Uint16, uint16_t)
- TYPED_GETTER_SETTER(Int32, int32_t)
- TYPED_GETTER_SETTER(Uint32, uint32_t)
- TYPED_GETTER_SETTER(Int64, int64_t)
- TYPED_GETTER_SETTER(Uint64, uint64_t)
- TYPED_GETTER_SETTER(Float32, float)
- TYPED_GETTER_SETTER(Float64, double)
- TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
- TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
- TYPED_GETTER_SETTER(Float64x2, simd128_value_t)
-
-#undef TYPED_GETTER_SETTER
-
static intptr_t data_offset() { return RawTypedData::payload_offset(); }
static intptr_t InstanceSize() {
@@ -8595,6 +8602,10 @@
protected:
void RecomputeDataField() { raw()->RecomputeDataField(); }
+ virtual void ValidateInvariant() const {
+ ASSERT(raw_ptr()->data_ == raw_ptr()->internal_data());
+ }
+
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
@@ -8620,35 +8631,6 @@
// snapshot. Should be independent of word size.
static const int kDataSerializationAlignment = 8;
- void* DataAddr(intptr_t byte_offset) const {
- ASSERT((byte_offset == 0) ||
- ((byte_offset > 0) && (byte_offset < LengthInBytes())));
- return reinterpret_cast<void*>(raw_ptr()->data_ + byte_offset);
- }
-
-#define TYPED_GETTER_SETTER(name, type) \
- type Get##name(intptr_t byte_offset) const { \
- return ReadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset))); \
- } \
- void Set##name(intptr_t byte_offset, type value) const { \
- StoreUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset)), value); \
- }
- TYPED_GETTER_SETTER(Int8, int8_t)
- TYPED_GETTER_SETTER(Uint8, uint8_t)
- TYPED_GETTER_SETTER(Int16, int16_t)
- TYPED_GETTER_SETTER(Uint16, uint16_t)
- TYPED_GETTER_SETTER(Int32, int32_t)
- TYPED_GETTER_SETTER(Uint32, uint32_t)
- TYPED_GETTER_SETTER(Int64, int64_t)
- TYPED_GETTER_SETTER(Uint64, uint64_t)
- TYPED_GETTER_SETTER(Float32, float)
- TYPED_GETTER_SETTER(Float64, double)
- TYPED_GETTER_SETTER(Float32x4, simd128_value_t)
- TYPED_GETTER_SETTER(Int32x4, simd128_value_t)
- TYPED_GETTER_SETTER(Float64x2, simd128_value_t)
-
-#undef TYPED_GETTER_SETTER
-
FinalizablePersistentHandle* AddFinalizer(
void* peer,
Dart_WeakPersistentHandleFinalizer callback,
@@ -8733,7 +8715,7 @@
return OFFSET_OF(RawTypedDataView, offset_in_bytes_);
}
- RawInstance* typed_data() const { return raw_ptr()->typed_data_; }
+ RawTypedDataBase* typed_data() const { return raw_ptr()->typed_data_; }
void InitializeWith(const TypedDataBase& typed_data,
intptr_t offset_in_bytes,
@@ -8751,6 +8733,9 @@
RawSmi* offset_in_bytes() const { return raw_ptr()->offset_in_bytes_; }
+ protected:
+ virtual void ValidateInvariant() const { raw()->ValidateInnerPointer(); }
+
private:
void RecomputeDataField() { raw()->RecomputeDataField(); }
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index f9eb462..dd6cc87 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -362,7 +362,7 @@
PatchClass::Handle(PatchClass::New(*this, Script::Handle(script())));
ASSERT(!patch.IsNull());
const Library& lib = Library::Handle(library());
- patch.set_library_kernel_data(ExternalTypedData::Handle(lib.kernel_data()));
+ patch.set_library_kernel_data(TypedDataBase::Handle(lib.kernel_data()));
patch.set_library_kernel_offset(lib.kernel_offset());
const Array& funcs = Array::Handle(functions());
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 75e7a92..2325fa2 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -812,7 +812,7 @@
RawClass* patched_class_;
RawClass* origin_class_;
RawScript* script_;
- RawExternalTypedData* library_kernel_data_;
+ RawTypedDataBase* library_kernel_data_;
VISIT_TO(RawObject*, library_kernel_data_);
RawObject** to_snapshot(Snapshot::Kind kind) {
@@ -1154,7 +1154,7 @@
RawArray* imports_; // List of Namespaces imported without prefix.
RawArray* exports_; // List of re-exported Namespaces.
RawInstance* load_error_; // Error iff load_state_ == kLoadError.
- RawExternalTypedData* kernel_data_;
+ RawTypedDataBase* kernel_data_;
RawObject** to_snapshot(Snapshot::Kind kind) {
switch (kind) {
case Snapshot::kFullAOT:
@@ -1209,16 +1209,16 @@
VISIT_FROM(RawObject*, string_offsets_);
RawTypedData* string_offsets_;
- RawExternalTypedData* string_data_;
+ RawTypedDataBase* string_data_;
RawTypedData* canonical_names_;
- RawExternalTypedData* metadata_payloads_;
- RawExternalTypedData* metadata_mappings_;
+ RawTypedDataBase* metadata_payloads_;
+ RawTypedDataBase* metadata_mappings_;
RawArray* scripts_;
RawArray* constants_;
RawArray* bytecode_component_;
RawGrowableObjectArray* potential_natives_;
RawGrowableObjectArray* potential_pragma_functions_;
- RawExternalTypedData* constants_table_;
+ RawTypedDataBase* constants_table_;
RawArray* libraries_cache_;
RawArray* classes_cache_;
VISIT_TO(RawObject*, classes_cache_);
@@ -2080,6 +2080,7 @@
private:
friend class RawTypedDataView;
+ friend class TypedDataView;
RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataBase);
};
@@ -2135,8 +2136,8 @@
ptr()->data_ = payload + offset_in_bytes;
}
- // Recopute [data_] based on internal [typed_data_] - needs to be called by GC
- // whenever the backing store moved.
+ // Recompute [data_] based on internal [typed_data_] - needs to be called by
+ // GC whenever the backing store moved.
//
// NOTICE: This method assumes [this] is the forwarded object and the
// [typed_data_] pointer points to the new backing store. The backing store's
@@ -2148,7 +2149,7 @@
ptr()->data_ = payload + offset_in_bytes;
}
- void ValidateInnerPointer() {
+ void ValidateInnerPointer() const {
if (ptr()->typed_data_->GetClassId() == kNullCid) {
// The view object must have gotten just initialized.
if (ptr()->data_ != nullptr ||
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 50ba1c5..1532bf9 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -2878,7 +2878,17 @@
intptr_t kernel_length;
const char* kernel_bytes_str = js->LookupParam("kernelBytes");
- uint8_t* kernel_bytes = DecodeBase64(zone, kernel_bytes_str, &kernel_length);
+ uint8_t* kernel_bytes = DecodeBase64(kernel_bytes_str, &kernel_length);
+
+ const auto& kernel_td = ExternalTypedData::Handle(
+ ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, kernel_bytes,
+ kernel_length, Heap::kOld));
+ kernel_td.AddFinalizer(
+ kernel_bytes,
+ [](void* _, Dart_WeakPersistentHandle h, void* peer) {
+ delete[] reinterpret_cast<uint8_t*>(peer);
+ },
+ kernel_length);
if (js->HasParam("frameIndex")) {
DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
@@ -2896,7 +2906,7 @@
const Object& result = Object::Handle(
zone,
frame->EvaluateCompiledExpression(
- kernel_bytes, kernel_length,
+ kernel_td,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
@@ -2929,7 +2939,7 @@
const Object& result = Object::Handle(
zone,
lib.EvaluateCompiledExpression(
- kernel_bytes, kernel_length,
+ kernel_td,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
@@ -2941,7 +2951,7 @@
const Object& result = Object::Handle(
zone,
cls.EvaluateCompiledExpression(
- kernel_bytes, kernel_length,
+ kernel_td,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
@@ -2956,7 +2966,7 @@
const Object& result = Object::Handle(
zone,
instance.EvaluateCompiledExpression(
- receiver_cls, kernel_bytes, kernel_length,
+ receiver_cls, kernel_td,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
@@ -4395,7 +4405,16 @@
const uint8_t* kernel_buffer = Service::dart_library_kernel();
const intptr_t kernel_buffer_len =
Service::dart_library_kernel_length();
- script.LoadSourceFromKernel(kernel_buffer, kernel_buffer_len);
+
+ // NOTE: We do not add a finalizer to this buffer since the embedder
+ // will free it once the VM shuts down (it was provided via
+ // [Dart_SetDartLibrarySourcesKernel]).
+ const auto& kernel_td = ExternalTypedData::Handle(
+ ExternalTypedData::New(kExternalTypedDataUint8ArrayCid,
+ const_cast<uint8_t*>(kernel_buffer),
+ kernel_buffer_len, Heap::kOld));
+
+ script.LoadSourceFromKernel(kernel_td);
}
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 398ecc8..8cbd3fc 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -682,8 +682,16 @@
const uint8_t* kernel_bytes = compilation_result.kernel;
intptr_t kernel_length = compilation_result.kernel_size;
- val = lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
- Array::empty_array(), param_values,
+ const auto& kernel_td = ExternalTypedData::Handle(ExternalTypedData::New(
+ kExternalTypedDataUint8ArrayCid, const_cast<uint8_t*>(kernel_bytes),
+ kernel_length, Heap::kOld));
+ kernel_td.AddFinalizer(
+ const_cast<uint8_t*>(kernel_bytes),
+ [](void* _, Dart_WeakPersistentHandle h, void* peer) { free(peer); },
+ kernel_length);
+
+ val = lib.EvaluateCompiledExpression(kernel_td, Array::empty_array(),
+ param_values,
TypeArguments::null_type_arguments());
free(const_cast<uint8_t*>(kernel_bytes));