diff --git a/runtime/observatory/tests/service/evaluate_with_escaping_closure_test.dart b/runtime/observatory/tests/service/evaluate_with_escaping_closure_test.dart new file mode 100644 index 00000000000..bb871307dc6 --- /dev/null +++ b/runtime/observatory/tests/service/evaluate_with_escaping_closure_test.dart @@ -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 = [ + (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); diff --git a/runtime/vm/base64.cc b/runtime/vm/base64.cc index 60e919d3e57..ec003ae0328 100644 --- a/runtime/vm/base64.cc +++ b/runtime/vm/base64.cc @@ -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(decoded_en); + uint8_t* bytes = static_cast(malloc(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 575b61b515f..079850f16d8 100644 --- a/runtime/vm/base64.h +++ b/runtime/vm/base64.h @@ -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 diff --git a/runtime/vm/base64_test.cc b/runtime/vm/base64_test.cc index 406a431b158..cd501ca01c1 100644 --- a/runtime/vm/base64_test.cc +++ b/runtime/vm/base64_test.cc @@ -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 diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc index 9155f084b61..2ea85b16f62 100644 --- a/runtime/vm/compiler_test.cc +++ b/runtime/vm/compiler_test.cc @@ -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(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(kernel_bytes)); + receiver_cls, kernel_buffer, Array::empty_array(), Array::empty_array(), + TypeArguments::null_type_arguments()); } EXPECT(!val.IsNull()); EXPECT(!val.IsError()); diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index c5ce88af5d9..2efdac300b5 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -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); } } diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h index b1fdd4019f0..390b124aa49 100644 --- a/runtime/vm/debugger.h +++ b/runtime/vm/debugger.h @@ -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); diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc index ddcbb7cfa52..8ca5a6792f4 100644 --- a/runtime/vm/debugger_api_impl_test.cc +++ b/runtime/vm/debugger_api_impl_test.cc @@ -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(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(kernel_bytes)); return result; } } diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index 0655dc88917..a7dda01bf02 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -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(&deoptimized_code_array_)); visitor->VisitPointer(reinterpret_cast(&sticky_error_)); - visitor->VisitPointer(reinterpret_cast(&reloaded_kernel_blobs_)); #if !defined(PRODUCT) visitor->VisitPointer( reinterpret_cast(&pending_service_extension_calls_)); diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index b5913f83352..c8cf0251f79 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h @@ -868,8 +868,6 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry { 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 { 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 7cb3ca60825..c93c2632c64 100644 --- a/runtime/vm/isolate_reload.cc +++ b/runtime/vm/isolate_reload.cc @@ -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(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(kernel_buffer), - kernel_buffer_size, Heap::kOld)); - typed_data.AddFinalizer( - const_cast(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_ = diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h index bd3f86d44be..ba6ba598b0a 100644 --- a/runtime/vm/isolate_reload.h +++ b/runtime/vm/isolate_reload.h @@ -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, diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h index 9afdc32c3f4..43babb89751 100644 --- a/runtime/vm/kernel.h +++ b/runtime/vm/kernel.h @@ -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_; diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc index 50e5e42d110..c1103d1adc5 100644 --- a/runtime/vm/kernel_binary.cc +++ b/runtime/vm/kernel_binary.cc @@ -124,6 +124,7 @@ std::unique_ptr Program::ReadFrom(Reader* reader, const char** error) { std::unique_ptr program(new Program()); program->binary_version_ = formatVersion; + program->typed_data_ = reader->typed_data(); program->kernel_data_ = reader->buffer(); program->kernel_data_size_ = reader->size(); diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc index 343dcb1e5f8..22089d6f162 100644 --- a/runtime/vm/kernel_loader.cc +++ b/runtime/vm/kernel_loader.cc @@ -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_); diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 5d6ae8f8d7e..30804a6ac3a 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -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 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_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(); { diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 4bd6f50f4a8..402e025e54d 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -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(); diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 23d384ae305..2a0f479a968 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -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_; diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc index 079cbe71741..c46b0868e2e 100644 --- a/runtime/vm/raw_object_fields.cc +++ b/runtime/vm/raw_object_fields.cc @@ -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_) \ diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc index a90b073726d..02c49f9cf7f 100644 --- a/runtime/vm/service.cc +++ b/runtime/vm/service.cc @@ -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)); diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc index e6b60bb98a8..a6b01615998 100644 --- a/runtime/vm/unit_test.cc +++ b/runtime/vm/unit_test.cc @@ -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(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(kernel_bytes)); } return Api::NewHandle(thread, val.raw()); }