3b7716ab00
Fixes https://github.com/dart-lang/sdk/issues/59810 TEST=ci Change-Id: I8dca122538195c8aad98e0d0fb64c7ea8e0d2e1a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/402421 Reviewed-by: Brian Quinlan <bquinlan@google.com> Commit-Queue: Alexander Aprelev <aam@google.com>
158 lines
5.2 KiB
C++
158 lines
5.2 KiB
C++
// Copyright (c) 2024, 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.
|
|
|
|
// Executes `main` function from given Dart kernel binary (by default uses
|
|
// compiled ./hello.dart).
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include "bin/dartutils.h"
|
|
#include "bin/dfe.h"
|
|
#include "bin/platform.h"
|
|
#include "include/dart_api.h"
|
|
#include "include/dart_embedder_api.h"
|
|
#include "platform/assert.h"
|
|
|
|
Dart_Handle CheckHandle(Dart_Handle handle,
|
|
const char* context = "unknown context") {
|
|
if (Dart_IsError(handle)) {
|
|
FATAL("Dart error (%s): %s", context, Dart_GetError(handle));
|
|
}
|
|
return handle;
|
|
}
|
|
|
|
void CheckError(bool condition, const char* error, const char* context) {
|
|
if (!condition) {
|
|
FATAL("Dart error (%s): %s", context, error);
|
|
}
|
|
}
|
|
|
|
void CheckError(const char* error, const char* context) {
|
|
if (error != nullptr) {
|
|
FATAL("Dart error (%s): %s", context, error);
|
|
}
|
|
}
|
|
|
|
Dart_InitializeParams CreateInitializeParams() {
|
|
Dart_InitializeParams params;
|
|
memset(¶ms, 0, sizeof(params));
|
|
params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
|
|
return params;
|
|
}
|
|
|
|
std::string GetExecutablePath() {
|
|
const size_t kPathBufSize = PATH_MAX + 1;
|
|
char executable_path[kPathBufSize] = {};
|
|
|
|
intptr_t path_length = dart::bin::Platform::ResolveExecutablePathInto(
|
|
executable_path, kPathBufSize);
|
|
CheckError(path_length > 0, "empty executable path",
|
|
"ResolveExecutablePathInfo");
|
|
return std::string(executable_path, path_length);
|
|
}
|
|
|
|
std::string GetDefaultSnapshotPath() {
|
|
std::string executable_path = GetExecutablePath();
|
|
std::string directory =
|
|
executable_path.substr(0, executable_path.find_last_of("/\\"));
|
|
return directory + "/gen/hello_kernel.dart.snapshot";
|
|
}
|
|
|
|
std::string ReadSnapshot(std::string_view path) {
|
|
std::string path_string{path};
|
|
std::ifstream source_file{path_string, std::ios::binary};
|
|
|
|
ASSERT(source_file.good());
|
|
source_file.seekg(0, source_file.end);
|
|
uint64_t length = source_file.tellg();
|
|
source_file.seekg(0, source_file.beg);
|
|
|
|
char* bytes = static_cast<char*>(std::malloc(length));
|
|
source_file.read(bytes, length);
|
|
auto result = std::string(bytes, length);
|
|
std::free(bytes);
|
|
return result;
|
|
}
|
|
|
|
Dart_Handle ToDartStringList(const std::vector<std::string>& values) {
|
|
Dart_Handle string_type =
|
|
CheckHandle(dart::bin::DartUtils::GetDartType("dart:core", "String"));
|
|
Dart_Handle filler = CheckHandle(Dart_NewStringFromCString(""));
|
|
|
|
Dart_Handle result =
|
|
CheckHandle(Dart_NewListOfTypeFilled(string_type, filler, values.size()));
|
|
for (size_t i = 0; i < values.size(); i++) {
|
|
Dart_Handle element =
|
|
CheckHandle(Dart_NewStringFromCString(values[i].c_str()));
|
|
CheckHandle(Dart_ListSetAt(result, i, element));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
std::string snapshot_path =
|
|
argc == 1 ? GetDefaultSnapshotPath() : std::string(argv[1]);
|
|
|
|
std::string snapshot_name =
|
|
snapshot_path.substr(snapshot_path.find_last_of("/\\") + 1);
|
|
std::string snapshot_data = ReadSnapshot(snapshot_path);
|
|
std::string snapshot_uri = "file://" + snapshot_path;
|
|
std::cout << "Snapshot path: " << snapshot_path << std::endl;
|
|
char* error;
|
|
|
|
// Start Dart VM.
|
|
bool result = dart::embedder::InitOnce(&error);
|
|
CheckError(result, error, "dart::embedder::InitOnce");
|
|
|
|
std::vector<const char*> flags{};
|
|
CheckError(Dart_SetVMFlags(flags.size(), flags.data()), "Dart_SetVMFlags");
|
|
|
|
Dart_InitializeParams initialize_params = CreateInitializeParams();
|
|
CheckError(Dart_Initialize(&initialize_params), "Dart_Initialize");
|
|
|
|
dart::bin::DFE dfe;
|
|
dfe.Init();
|
|
const uint8_t* platform_buffer = nullptr;
|
|
intptr_t platform_buffer_size = 0;
|
|
|
|
dfe.LoadPlatform(&platform_buffer, &platform_buffer_size);
|
|
|
|
// Start an isolate from a platform kernel.
|
|
Dart_IsolateFlags isolate_flags;
|
|
Dart_IsolateFlagsInitialize(&isolate_flags);
|
|
|
|
Dart_CreateIsolateGroupFromKernel(
|
|
/*script_uri=*/snapshot_uri.c_str(),
|
|
/*name=*/snapshot_name.c_str(),
|
|
/*kernel_buffer=*/platform_buffer,
|
|
/*kernel_buffer_size=*/platform_buffer_size,
|
|
/*flags=*/&isolate_flags,
|
|
/*isolate_group_data=*/nullptr,
|
|
/*isolate_data=*/nullptr, &error);
|
|
CheckError(error, "Dart_CreateIsolateGroupFromKernel");
|
|
Dart_EnterScope();
|
|
CheckHandle(dart::bin::DartUtils::PrepareForScriptLoading(
|
|
/*is_service_isolate=*/false, /*trace_loading=*/false),
|
|
"PrepareForScriptLoading");
|
|
|
|
// Load kernel snapshot to run `main` from.
|
|
Dart_Handle library =
|
|
CheckHandle(Dart_LoadLibraryFromKernel(
|
|
reinterpret_cast<const uint8_t*>(snapshot_data.c_str()),
|
|
snapshot_data.size()),
|
|
"Dart_LoadLibraryFromKernel");
|
|
|
|
// Call main function with args.
|
|
std::initializer_list<Dart_Handle> main_args{ToDartStringList({"universe"})};
|
|
CheckHandle(Dart_Invoke(library, Dart_NewStringFromCString("main"), 1,
|
|
const_cast<Dart_Handle*>(main_args.begin())),
|
|
"Dart_Invoke('main')");
|
|
Dart_ExitScope();
|
|
Dart_ShutdownIsolate();
|
|
}
|