Introduce callback parameter for Dart_ReadKernelBinary that would free kernel memory.

This is needed to support cases where memory with kernel binary was
allocated outside of Dart VM(for example, in Flutter Engine) has to be
released using appropriate mechanism too.

Bug:
Change-Id: I863db9e5a33469ba8fb5c1f8789c6498ddfbb385
Reviewed-on: https://dart-review.googlesource.com/5121
Commit-Queue: Alexander Aprelev <aam@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Alexander Aprelev 2017-09-13 04:37:07 +00:00 committed by commit-bot@chromium.org
parent cb2fba6dbc
commit 1fe2e4ffd1
6 changed files with 41 additions and 11 deletions

View file

@ -52,6 +52,10 @@ void DFE::SetKernelBinaries(const char* name) {
File::PathSeparator(), kVMServiceIOBinaryName);
}
static void ReleaseFetchedBytes(uint8_t* buffer) {
free(buffer);
}
Dart_Handle DFE::ReadKernelBinary(Dart_Isolate isolate,
const char* url_string) {
ASSERT(!Dart_IsServiceIsolate(isolate) && !Dart_IsKernelIsolate(isolate));
@ -74,7 +78,8 @@ Dart_Handle DFE::ReadKernelBinary(Dart_Isolate isolate,
kernel_ir = kresult.kernel;
kernel_ir_size = kresult.kernel_size;
}
void* kernel_program = Dart_ReadKernelBinary(kernel_ir, kernel_ir_size);
void* kernel_program =
Dart_ReadKernelBinary(kernel_ir, kernel_ir_size, ReleaseFetchedBytes);
ASSERT(kernel_program != NULL);
return Dart_NewExternalTypedData(Dart_TypedData_kUint64, kernel_program, 1);
}
@ -88,7 +93,8 @@ void* DFE::CompileAndReadScript(const char* script_uri,
Dart_CompileToKernel(script_uri, platform_binary_filename_);
switch (result.status) {
case Dart_KernelCompilationStatus_Ok:
return Dart_ReadKernelBinary(result.kernel, result.kernel_size);
return Dart_ReadKernelBinary(result.kernel, result.kernel_size,
ReleaseFetchedBytes);
case Dart_KernelCompilationStatus_Error:
*error = result.error; // Copy error message.
*exit_code = kCompilationErrorExitCode;
@ -118,7 +124,7 @@ void* DFE::ReadScript(const char* script_uri) const {
intptr_t buffer_length = -1;
bool result = TryReadKernelFile(script_uri, &buffer, &buffer_length);
if (result) {
return Dart_ReadKernelBinary(buffer, buffer_length);
return Dart_ReadKernelBinary(buffer, buffer_length, ReleaseFetchedBytes);
}
return NULL;
}

View file

@ -352,6 +352,10 @@ class ScopedDecompress : public ValueObject {
uint8_t* decompressed_;
};
static void ReleaseFetchedBytes(uint8_t* buffer) {
free(buffer);
}
bool Loader::ProcessResultLocked(Loader* loader, Loader::IOResult* result) {
// We have to copy everything we care about out of |result| because after
// dropping the lock below |result| may no longer valid.
@ -470,8 +474,9 @@ bool Loader::ProcessResultLocked(Loader* loader, Loader::IOResult* result) {
// isolates. We currently do not have support for neither
// `Isolate.spawn()` nor `Isolate.spawnUri()` with kernel-based
// frontend.
Dart_Handle kernel_binary = reinterpret_cast<Dart_Handle>(
Dart_ReadKernelBinary(payload, payload_length));
Dart_Handle kernel_binary =
reinterpret_cast<Dart_Handle>(Dart_ReadKernelBinary(
payload, payload_length, ReleaseFetchedBytes));
dart_result = Dart_LoadScript(uri, resolved_uri, kernel_binary, 0, 0);
} else {
dart_result = Dart_LoadScript(uri, resolved_uri, source, 0, 0);

View file

@ -2809,11 +2809,15 @@ DART_EXPORT Dart_Handle Dart_LoadKernel(void* kernel_program);
*
* \param buffer The start of a memory buffer containing the binary format.
* \param buffer_len The length of the memory buffer.
* \param callback If not NULL, is called to when buffer is no longer needed.
* If it is NULL, then free() is used to free buffer.
*
* \return kernel_program The `dart::kernel::Program` object.
*/
typedef void (*Dart_ReleaseBufferCallback)(uint8_t* buffer);
DART_EXPORT void* Dart_ReadKernelBinary(const uint8_t* buffer,
intptr_t buffer_len);
intptr_t buffer_len,
Dart_ReleaseBufferCallback callback);
/**
* Gets the library for the root script for the current isolate.

View file

@ -5141,13 +5141,15 @@ DART_EXPORT Dart_Handle Dart_LoadScriptFromSnapshot(const uint8_t* buffer,
}
DART_EXPORT void* Dart_ReadKernelBinary(const uint8_t* buffer,
intptr_t buffer_len) {
intptr_t buffer_len,
Dart_ReleaseBufferCallback callback) {
#if defined(DART_PRECOMPILED_RUNTIME)
UNREACHABLE();
return NULL;
#else
kernel::Program* program =
ReadPrecompiledKernelFromBuffer(buffer, buffer_len);
program->set_release_buffer_callback(callback);
return program;
#endif
}

View file

@ -52,8 +52,11 @@ enum LogicalOperator { kAnd, kOr };
class Program {
public:
~Program() {
free(const_cast<uint8_t*>(kernel_data_));
kernel_data_ = NULL;
if (kernel_data_ != NULL) {
ASSERT(release_callback != NULL);
release_callback(const_cast<uint8_t*>(kernel_data_));
kernel_data_ = NULL;
}
}
static Program* ReadFrom(Reader* reader);
@ -64,9 +67,13 @@ class Program {
const uint8_t* kernel_data() { return kernel_data_; }
intptr_t kernel_data_size() { return kernel_data_size_; }
intptr_t library_count() { return library_count_; }
void set_release_buffer_callback(Dart_ReleaseBufferCallback callback) {
release_callback = callback;
}
private:
Program() : kernel_data_(NULL), kernel_data_size_(-1) {}
Program()
: kernel_data_(NULL), kernel_data_size_(-1), release_callback(NULL) {}
NameIndex main_method_reference_; // Procedure.
intptr_t library_count_;
@ -82,6 +89,7 @@ class Program {
const uint8_t* kernel_data_;
intptr_t kernel_data_size_;
Dart_ReleaseBufferCallback release_callback;
DISALLOW_COPY_AND_ASSIGN(Program);
};

View file

@ -184,6 +184,10 @@ char* TestCase::CompileTestScriptWithDFE(const char* url,
sourcefiles, kernel_pgm, incrementally);
}
static void ReleaseFetchedBytes(uint8_t* buffer) {
free(buffer);
}
char* TestCase::CompileTestScriptWithDFE(const char* url,
int sourcefiles_count,
Dart_SourceFile sourcefiles[],
@ -202,7 +206,8 @@ char* TestCase::CompileTestScriptWithDFE(const char* url,
if (kernel_file == NULL) {
return OS::SCreate(zone, "front end generated a NULL kernel file");
}
*kernel_pgm = Dart_ReadKernelBinary(kernel_file, kernel_length);
*kernel_pgm =
Dart_ReadKernelBinary(kernel_file, kernel_length, ReleaseFetchedBytes);
if (*kernel_pgm == NULL) {
return OS::SCreate(zone, "Failed to read generated kernel binary");
}