[vm] Make kernel buffers live exactly as long as their derived views.

When creating a KernelProgramInfo, we create several logical views into the kernel buffer. These are fresh ExternalTypedDatas, rather than proper TypedDataViews, so they do not automically keep the original ExternalTypedData alive. Create an explicit reference to the orginal ExternalTypedData in the KernelProgramInfo. When creating snapshots, this reference is ignored/null'd and the views are turned into copies, effectively dropping the parts of the original buffer that do not have views.

Fixes a leak with reload and a use-after-free with eval.

Bug: https://github.com/dart-lang/sdk/issues/33973
Bug: https://github.com/dart-lang/sdk/issues/39610
Change-Id: I09d3830133314ccbaa0341d904127c2b6925c4ec
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/126825
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Ryan Macnak
2019-12-03 22:00:48 +00:00
committed by commit-bot@chromium.org
parent 5ecfd7058a
commit f4e44dd705
21 changed files with 116 additions and 108 deletions
@@ -0,0 +1,29 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// 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.
import 'package:observatory/service_io.dart';
import 'package:unittest/unittest.dart';
import 'test_helper.dart';
dynamic escapedClosure;
testeeMain() {}
var tests = <IsolateTest>[
(Isolate isolate) async {
Library lib = await isolate.rootLibrary.load();
Instance result = await lib.evaluate("escapedClosure = (x, y) => x + y");
print(result);
expect(result.clazz.name, startsWith('_Closure'));
for (var i = 0; i < 100; i++) {
result = await lib.evaluate("escapedClosure(3, 4)");
print(result);
expect(result.valueAsString, equals('7'));
}
},
];
main(args) => runIsolateTests(args, tests, testeeBefore: testeeMain);
+2 -2
View File
@@ -35,7 +35,7 @@ static const int8_t decode_table[] = {
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 @@ uint8_t* DecodeBase64(Zone* zone, const char* str, intptr_t* out_decoded_len) {
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 = static_cast<uint8_t*>(malloc(decoded_en));
for (int i = 0, o = 0; o < decoded_en;) {
// Accumulate 4 valid 6 bit Base 64 characters into an int.
+2 -2
View File
@@ -5,11 +5,11 @@
#ifndef RUNTIME_VM_BASE64_H_
#define RUNTIME_VM_BASE64_H_
#include "vm/zone.h"
#include "vm/globals.h"
namespace dart {
uint8_t* DecodeBase64(Zone* zone, const char* str, intptr_t* out_decoded_len);
uint8_t* DecodeBase64(const char* str, intptr_t* out_decoded_len);
} // namespace dart
+4 -5
View File
@@ -11,22 +11,21 @@ namespace dart {
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);
free(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
+6 -5
View File
@@ -230,13 +230,14 @@ TEST_CASE(EvalExpression) {
/* is_static= */ false);
EXPECT_EQ(Dart_KernelCompilationStatus_Ok, compilation_result.status);
const uint8_t* kernel_bytes = compilation_result.kernel;
intptr_t kernel_length = compilation_result.kernel_size;
const ExternalTypedData& kernel_buffer =
ExternalTypedData::Handle(ExternalTypedData::NewFinalizeWithFree(
const_cast<uint8_t*>(compilation_result.kernel),
compilation_result.kernel_size));
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_buffer, Array::empty_array(), Array::empty_array(),
TypeArguments::null_type_arguments());
}
EXPECT(!val.IsNull());
EXPECT(!val.IsError());
+5 -8
View File
@@ -1463,16 +1463,14 @@ static bool IsPrivateVariableName(const String& var_name) {
}
RawObject* ActivationFrame::EvaluateCompiledExpression(
const uint8_t* kernel_bytes,
intptr_t kernel_length,
const ExternalTypedData& kernel_buffer,
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_buffer, type_definitions,
arguments, type_arguments);
} else {
const Object& receiver = Object::Handle(GetReceiver());
const Class& method_cls = Class::Handle(function().origin());
@@ -1481,9 +1479,8 @@ RawObject* ActivationFrame::EvaluateCompiledExpression(
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_buffer, type_definitions, arguments, type_arguments);
}
}
+1 -2
View File
@@ -353,8 +353,7 @@ class ActivationFrame : public ZoneAllocated {
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_data,
const Array& arguments,
const Array& type_definitions,
const TypeArguments& type_arguments);
+6 -4
View File
@@ -190,18 +190,20 @@ DART_EXPORT Dart_Handle Dart_EvaluateStaticExpr(Dart_Handle lib_handle,
return Api::NewError("Failed to compile expression.");
}
const uint8_t* kernel_bytes = compilation_result.kernel;
intptr_t kernel_length = compilation_result.kernel_size;
const ExternalTypedData& kernel_buffer =
ExternalTypedData::Handle(ExternalTypedData::NewFinalizeWithFree(
const_cast<uint8_t*>(compilation_result.kernel),
compilation_result.kernel_size));
Dart_Handle result = Api::NewHandle(
T,
lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
lib.EvaluateCompiledExpression(kernel_buffer,
/* 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;
}
}
-10
View File
@@ -1258,7 +1258,6 @@ Isolate::Isolate(IsolateGroup* isolate_group,
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_(),
@@ -1489,14 +1488,6 @@ Isolate* Isolate::InitIsolate(const char* name_prefix,
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 mutator_thread_;
@@ -2330,7 +2321,6 @@ void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
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_));
-8
View File
@@ -868,8 +868,6 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
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_);
}
@@ -1269,12 +1267,6 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
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;
+3 -25
View File
@@ -597,7 +597,9 @@ bool IsolateGroupReloadContext::Reload(bool force_reload,
}
}
const auto& typed_data = ExternalTypedData::Handle(
Z, MakeRetainedTypedData(kernel_buffer, kernel_buffer_size));
Z, ExternalTypedData::NewFinalizeWithFree(
const_cast<uint8_t*>(kernel_buffer), kernel_buffer_size));
kernel_program = kernel::Program::ReadFromTypedData(typed_data);
}
@@ -936,30 +938,6 @@ char* IsolateGroupReloadContext::CompileToKernel(bool force_reload,
return nullptr;
}
RawExternalTypedData* IsolateGroupReloadContext::MakeRetainedTypedData(
const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size) {
// The ownership of the kernel buffer goes now to the VM.
const auto& typed_data = ExternalTypedData::Handle(
Z, ExternalTypedData::New(kExternalTypedDataUint8ArrayCid,
const_cast<uint8_t*>(kernel_buffer),
kernel_buffer_size, Heap::kOld));
typed_data.AddFinalizer(
const_cast<uint8_t*>(kernel_buffer),
[](void* isolate_callback_data, Dart_WeakPersistentHandle handle,
void* data) { free(data); },
kernel_buffer_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).
first_isolate_->RetainKernelBlob(typed_data);
return typed_data.raw();
}
void IsolateReloadContext::ReloadPhase1AllocateStorageMapsAndCheckpoint() {
// Preallocate storage for maps.
old_classes_set_storage_ =
-2
View File
@@ -216,8 +216,6 @@ class IsolateGroupReloadContext {
const char* packages_url,
const uint8_t** kernel_buffer,
intptr_t* kernel_buffer_size);
RawExternalTypedData* MakeRetainedTypedData(const uint8_t* kernel_buffer,
intptr_t kernel_buffer_size);
void FindModifiedSources(bool force_reload,
Dart_SourceFile** modified_sources,
intptr_t* count,
+3 -1
View File
@@ -88,12 +88,13 @@ class Program {
return metadata_mappings_offset_;
}
intptr_t constant_table_offset() { return constant_table_offset_; }
const ExternalTypedData* typed_data() { return typed_data_; }
const uint8_t* kernel_data() { return kernel_data_; }
intptr_t kernel_data_size() { return kernel_data_size_; }
intptr_t library_count() { return library_count_; }
private:
Program() : kernel_data_(NULL), kernel_data_size_(-1) {}
Program() : typed_data_(NULL), kernel_data_(NULL), kernel_data_size_(-1) {}
bool single_program_;
uint32_t binary_version_;
@@ -118,6 +119,7 @@ class Program {
// The offset from the start of the binary to the start of the string table.
intptr_t string_table_offset_;
const ExternalTypedData* typed_data_;
const uint8_t* kernel_data_;
intptr_t kernel_data_size_;
+1
View File
@@ -124,6 +124,7 @@ std::unique_ptr<Program> Program::ReadFrom(Reader* reader, const char** error) {
std::unique_ptr<Program> program(new Program());
program->binary_version_ = formatVersion;
program->typed_data_ = reader->typed_data();
program->kernel_data_ = reader->buffer();
program->kernel_data_size_ = reader->size();
+2
View File
@@ -418,6 +418,8 @@ void KernelLoader::InitializeFields(UriToSourceTable* uri_to_source_table) {
kernel_program_info_ = KernelProgramInfo::New(
offsets, data, names, metadata_payloads, metadata_mappings,
constants_table, scripts, libraries_cache, classes_cache,
program_->typed_data() == nullptr ? Object::null_object()
: *program_->typed_data(),
program_->binary_version());
H.InitFromKernelProgramInfo(kernel_program_info_);
+25 -15
View File
@@ -3698,8 +3698,7 @@ RawObject* Class::Invoke(const String& function_name,
}
static RawObject* EvaluateCompiledExpressionHelper(
const uint8_t* kernel_bytes,
intptr_t kernel_length,
const ExternalTypedData& kernel_buffer,
const Array& type_definitions,
const String& library_url,
const String& klass,
@@ -3707,8 +3706,7 @@ static RawObject* EvaluateCompiledExpressionHelper(
const TypeArguments& type_arguments);
RawObject* Class::EvaluateCompiledExpression(
const uint8_t* kernel_bytes,
intptr_t kernel_length,
const ExternalTypedData& kernel_buffer,
const Array& type_definitions,
const Array& arguments,
const TypeArguments& type_arguments) const {
@@ -3721,7 +3719,7 @@ RawObject* Class::EvaluateCompiledExpression(
}
return EvaluateCompiledExpressionHelper(
kernel_bytes, kernel_length, type_definitions,
kernel_buffer, type_definitions,
String::Handle(Library::Handle(library()).url()),
IsTopLevel() ? String::Handle() : String::Handle(UserVisibleName()),
arguments, type_arguments);
@@ -11538,14 +11536,13 @@ RawObject* Library::Invoke(const String& function_name,
}
RawObject* Library::EvaluateCompiledExpression(
const uint8_t* kernel_bytes,
intptr_t kernel_length,
const ExternalTypedData& kernel_buffer,
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_buffer, type_definitions, String::Handle(url()), String::Handle(),
arguments, type_arguments);
}
void Library::InitNativeWrappersLibrary(Isolate* isolate, bool is_kernel) {
@@ -11603,8 +11600,7 @@ class LibraryLookupTraits {
typedef UnorderedHashMap<LibraryLookupTraits> LibraryLookupMap;
static RawObject* EvaluateCompiledExpressionHelper(
const uint8_t* kernel_bytes,
intptr_t kernel_length,
const ExternalTypedData& kernel_buffer,
const Array& type_definitions,
const String& library_url,
const String& klass,
@@ -11618,7 +11614,7 @@ static RawObject* EvaluateCompiledExpressionHelper(
return ApiError::New(error_str);
#else
std::unique_ptr<kernel::Program> kernel_pgm =
kernel::Program::ReadFromBuffer(kernel_bytes, kernel_length);
kernel::Program::ReadFromTypedData(kernel_buffer);
if (kernel_pgm == NULL) {
return ApiError::New(String::Handle(
@@ -12186,6 +12182,7 @@ RawKernelProgramInfo* KernelProgramInfo::New(
const Array& scripts,
const Array& libraries_cache,
const Array& classes_cache,
const Object& retained_kernel_blob,
const uint32_t binary_version) {
const KernelProgramInfo& info =
KernelProgramInfo::Handle(KernelProgramInfo::New());
@@ -12200,6 +12197,8 @@ RawKernelProgramInfo* KernelProgramInfo::New(
info.StorePointer(&info.raw_ptr()->constants_table_, constants_table.raw());
info.StorePointer(&info.raw_ptr()->libraries_cache_, libraries_cache.raw());
info.StorePointer(&info.raw_ptr()->classes_cache_, classes_cache.raw());
info.StorePointer(&info.raw_ptr()->retained_kernel_blob_,
retained_kernel_blob.raw());
info.set_kernel_binary_version(binary_version);
return info.raw();
}
@@ -16473,8 +16472,7 @@ RawObject* Instance::Invoke(const String& function_name,
RawObject* Instance::EvaluateCompiledExpression(
const Class& method_cls,
const uint8_t* kernel_bytes,
intptr_t kernel_length,
const ExternalTypedData& kernel_buffer,
const Array& type_definitions,
const Array& arguments,
const TypeArguments& type_arguments) const {
@@ -16488,7 +16486,7 @@ RawObject* Instance::EvaluateCompiledExpression(
}
return EvaluateCompiledExpressionHelper(
kernel_bytes, kernel_length, type_definitions,
kernel_buffer, type_definitions,
String::Handle(Library::Handle(method_cls.library()).url()),
String::Handle(method_cls.UserVisibleName()), arguments_with_receiver,
type_arguments);
@@ -21686,6 +21684,18 @@ RawExternalTypedData* ExternalTypedData::New(intptr_t class_id,
return result.raw();
}
RawExternalTypedData* ExternalTypedData::NewFinalizeWithFree(uint8_t* data,
intptr_t len) {
ExternalTypedData& result = ExternalTypedData::Handle(ExternalTypedData::New(
kExternalTypedDataUint8ArrayCid, data, len, Heap::kOld));
result.AddFinalizer(
data,
[](void* isolate_callback_data, Dart_WeakPersistentHandle handle,
void* data) { free(data); },
len);
return result.raw();
}
RawTypedDataView* TypedDataView::New(intptr_t class_id, Heap::Space space) {
auto& result = TypedDataView::Handle();
{
+6 -6
View File
@@ -1374,8 +1374,7 @@ class Class : public Object {
// (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_buffer,
const Array& type_definitions,
const Array& param_values,
const TypeArguments& type_param_values) const;
@@ -4154,8 +4153,7 @@ class Library : public Object {
// 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_buffer,
const Array& type_definitions,
const Array& param_values,
const TypeArguments& type_param_values) const;
@@ -4581,6 +4579,7 @@ class KernelProgramInfo : public Object {
const Array& scripts,
const Array& libraries_cache,
const Array& classes_cache,
const Object& retained_kernel_blob,
const uint32_t binary_version);
static intptr_t InstanceSize() {
@@ -6553,8 +6552,7 @@ class Instance : public Object {
// 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_buffer,
const Array& type_definitions,
const Array& param_values,
const TypeArguments& type_param_values) const;
@@ -9232,6 +9230,8 @@ class ExternalTypedData : public TypedDataBase {
intptr_t len,
Heap::Space space = Heap::kNew);
static RawExternalTypedData* NewFinalizeWithFree(uint8_t* data, intptr_t len);
static bool IsExternalTypedData(const Instance& obj) {
ASSERT(!obj.IsNull());
intptr_t cid = obj.raw()->GetClassId();
+2 -1
View File
@@ -1287,7 +1287,8 @@ class RawKernelProgramInfo : public RawObject {
RawExternalTypedData* constants_table_;
RawArray* libraries_cache_;
RawArray* classes_cache_;
VISIT_TO(RawObject*, classes_cache_);
RawObject* retained_kernel_blob_;
VISIT_TO(RawObject*, retained_kernel_blob_);
uint32_t kernel_binary_version_;
+1
View File
@@ -93,6 +93,7 @@ namespace dart {
F(KernelProgramInfo, constants_table_) \
F(KernelProgramInfo, libraries_cache_) \
F(KernelProgramInfo, classes_cache_) \
F(KernelProgramInfo, retained_kernel_blob_) \
F(Code, object_pool_) \
F(Code, instructions_) \
F(Code, owner_) \
+12 -7
View File
@@ -2870,6 +2870,12 @@ static const MethodParameter* evaluate_compiled_expression_params[] = {
NULL,
};
RawExternalTypedData* DecodeKernelBuffer(const char* kernel_buffer_base64) {
intptr_t kernel_length;
uint8_t* kernel_buffer = DecodeBase64(kernel_buffer_base64, &kernel_length);
return ExternalTypedData::NewFinalizeWithFree(kernel_buffer, kernel_length);
}
static bool EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
if (CheckDebuggerDisabled(thread, js)) {
return true;
@@ -2898,9 +2904,8 @@ static bool EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
const GrowableObjectArray& type_params_names =
GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
intptr_t kernel_length;
const char* kernel_bytes_str = js->LookupParam("kernelBytes");
uint8_t* kernel_bytes = DecodeBase64(zone, kernel_bytes_str, &kernel_length);
const ExternalTypedData& kernel_data = ExternalTypedData::Handle(
zone, DecodeKernelBuffer(js->LookupParam("kernelBytes")));
if (js->HasParam("frameIndex")) {
DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
@@ -2918,7 +2923,7 @@ static bool EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
const Object& result = Object::Handle(
zone,
frame->EvaluateCompiledExpression(
kernel_bytes, kernel_length,
kernel_data,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
@@ -2951,7 +2956,7 @@ static bool EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
const Object& result = Object::Handle(
zone,
lib.EvaluateCompiledExpression(
kernel_bytes, kernel_length,
kernel_data,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
@@ -2963,7 +2968,7 @@ static bool EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
const Object& result = Object::Handle(
zone,
cls.EvaluateCompiledExpression(
kernel_bytes, kernel_length,
kernel_data,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
@@ -2978,7 +2983,7 @@ static bool EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
const Object& result = Object::Handle(
zone,
instance.EvaluateCompiledExpression(
receiver_cls, kernel_bytes, kernel_length,
receiver_cls, kernel_data,
Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
Array::Handle(zone, Array::MakeFixedLength(param_values)),
type_arguments));
+6 -5
View File
@@ -700,13 +700,14 @@ Dart_Handle TestCase::EvaluateExpression(const Library& lib,
return Api::NewError("%s", compilation_result.error);
}
const uint8_t* kernel_bytes = compilation_result.kernel;
intptr_t kernel_length = compilation_result.kernel_size;
const ExternalTypedData& kernel_buffer =
ExternalTypedData::Handle(ExternalTypedData::NewFinalizeWithFree(
const_cast<uint8_t*>(compilation_result.kernel),
compilation_result.kernel_size));
val = lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
Array::empty_array(), param_values,
val = lib.EvaluateCompiledExpression(kernel_buffer, Array::empty_array(),
param_values,
TypeArguments::null_type_arguments());
free(const_cast<uint8_t*>(kernel_bytes));
}
return Api::NewHandle(thread, val.raw());
}