[vm] Benchmark for reading kernel bytecode
Change-Id: I07617a553193495fcc4fc0ce4a6382996ee7dc51
Reviewed-on: https://dart-review.googlesource.com/75821
Commit-Queue: Zach Anderson <zra@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index c6bb522..ec7e381 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -1149,7 +1149,6 @@
args = [
"--gen-bytecode",
"--no-embed-sources",
- "--drop-ast",
"--platform",
rebase_path(platform_dill),
"--output",
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index b401d37..9959ef4 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -169,6 +169,8 @@
*/
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll();
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_ReadAllBytecode();
+
/**
* Parses all loaded functions in the current isolate..
*
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 9170ada..459a5a1 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -101,6 +101,7 @@
cc/Profiler_ContextAllocation: Fail, Pass # Flaky on Windows --- sometimes give "profiler_test.cc: 1107: error: expected: !walker.Down()"
cc/Service_Profile: Skip
cc/GenKernelKernelLoadKernel: Skip # Issue 34542.
+cc/GenKernelKernelReadAllBytecode: Skip # Issue 34393.
[ !$strong ]
dart/callee_side_type_checks_test: SkipByDesign
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index e2b2d9a..e699f47 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -178,6 +178,8 @@
free(script);
}
+#endif // !PRODUCT
+
// This file is created by the target //runtime/bin:gen_kernel_bytecode_dill
// which is depended on by run_vm_tests.
static char* ComputeGenKernelKernelPath(const char* arg) {
@@ -230,9 +232,47 @@
int64_t elapsed_time = timer.TotalElapsedTime();
benchmark->set_score(elapsed_time);
free(dill_path);
+ free(kernel_buffer);
}
-#endif // !PRODUCT
+BENCHMARK(GenKernelKernelReadAllBytecode) {
+ bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
+ bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary);
+ bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary);
+ char* dill_path = ComputeGenKernelKernelPath(Benchmark::Executable());
+ File* file = File::Open(NULL, dill_path, File::kRead);
+ EXPECT(file != NULL);
+ bin::RefCntReleaseScope<File> rs(file);
+ intptr_t kernel_buffer_size = file->Length();
+ uint8_t* kernel_buffer =
+ reinterpret_cast<uint8_t*>(malloc(kernel_buffer_size));
+ EXPECT(kernel_buffer != NULL);
+ bool read_fully = file->ReadFully(kernel_buffer, kernel_buffer_size);
+ EXPECT(read_fully);
+
+ bool enable_interpreter_orig = FLAG_enable_interpreter;
+ FLAG_enable_interpreter = true;
+
+ Dart_Handle result =
+ Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
+ EXPECT_VALID(result);
+
+ result = Dart_FinalizeLoading(false);
+ EXPECT_VALID(result);
+
+ Timer timer(true, "GenKernelKernelLoadKernel benchmark");
+ timer.Start();
+
+ result = Dart_ReadAllBytecode();
+ EXPECT_VALID(result);
+
+ timer.Stop();
+ int64_t elapsed_time = timer.TotalElapsedTime();
+ benchmark->set_score(elapsed_time);
+ FLAG_enable_interpreter = enable_interpreter_orig;
+ free(dill_path);
+ free(kernel_buffer);
+}
//
// Measure creation of core isolate from a snapshot.
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 4695d22..e2e44ad 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -1425,6 +1425,34 @@
return Error::null();
}
+RawError* Compiler::ReadAllBytecode(const Class& cls) {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
+ ASSERT(error.IsNull());
+ Array& functions = Array::Handle(zone, cls.functions());
+ Function& func = Function::Handle(zone);
+ // Class dynamic lives in the vm isolate. Its array fields cannot be set to
+ // an empty array.
+ if (functions.IsNull()) {
+ ASSERT(cls.IsDynamicClass());
+ return Error::null();
+ }
+ // Compile all the regular functions.
+ for (int i = 0; i < functions.Length(); i++) {
+ func ^= functions.At(i);
+ ASSERT(!func.IsNull());
+ if (func.IsBytecodeAllowed(zone) && !func.HasBytecode()) {
+ RawError* error =
+ kernel::BytecodeReader::ReadFunctionBytecode(thread, func);
+ if (error != Error::null()) {
+ return error;
+ }
+ }
+ }
+ return Error::null();
+}
+
RawError* Compiler::ParseAllFunctions(const Class& cls) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h
index 9dc8396..5d5d3bd 100644
--- a/runtime/vm/compiler/jit/compiler.h
+++ b/runtime/vm/compiler/jit/compiler.h
@@ -154,6 +154,9 @@
static RawError* CompileAllFunctions(const Class& cls);
static RawError* ParseAllFunctions(const Class& cls);
+ // Eagerly read all bytecode.
+ static RawError* ReadAllBytecode(const Class& cls);
+
// Notify the compiler that background (optimized) compilation has failed
// because the mutator thread changed the state (e.g., deoptimization,
// deferred loading). The background compilation may retry to compile
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 5ffbc1b..49cbe58 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -197,6 +197,26 @@
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
+DART_EXPORT Dart_Handle Dart_ReadAllBytecode() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ return Api::NewError("%s: Cannot read bytecode on an AOT runtime.",
+ CURRENT_FUNC);
+#else
+ DARTSCOPE(Thread::Current());
+ API_TIMELINE_DURATION(T);
+ Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
+ if (::Dart_IsError(result)) {
+ return result;
+ }
+ CHECK_CALLBACK_STATE(T);
+ const Error& error = Error::Handle(T->zone(), Library::ReadAllBytecode());
+ if (!error.IsNull()) {
+ return Api::NewHandle(T, error.raw());
+ }
+ return Api::Success();
+#endif // defined(DART_PRECOMPILED_RUNTIME)
+}
+
DART_EXPORT Dart_Handle Dart_ParseAll() {
#if defined(DART_PRECOMPILED_RUNTIME)
return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index bfccccf..1f464d2 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -13,6 +13,7 @@
#include "vm/compiler/aot/precompiler.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/kernel_fingerprints.h"
#include "vm/compiler/frontend/kernel_translation_helper.h"
#include "vm/compiler/intrinsifier.h"
@@ -13321,6 +13322,51 @@
return Error::null();
}
+#if !defined(DART_PRECOMPILED_RUNTIME)
+RawError* Library::ReadAllBytecode() {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ Error& error = Error::Handle(zone);
+ const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+ Isolate::Current()->object_store()->libraries());
+ Library& lib = Library::Handle(zone);
+ Class& cls = Class::Handle(zone);
+ for (int i = 0; i < libs.Length(); i++) {
+ lib ^= libs.At(i);
+ ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+ while (it.HasNext()) {
+ cls = it.GetNextClass();
+ error = cls.EnsureIsFinalized(thread);
+ if (!error.IsNull()) {
+ return error.raw();
+ }
+ error = Compiler::ReadAllBytecode(cls);
+ if (!error.IsNull()) {
+ return error.raw();
+ }
+ }
+ }
+
+ // Inner functions get added to the closures array. As part of compilation
+ // more closures can be added to the end of the array. Compile all the
+ // closures until we have reached the end of the "worklist".
+ const GrowableObjectArray& closures = GrowableObjectArray::Handle(
+ zone, Isolate::Current()->object_store()->closure_functions());
+ Function& func = Function::Handle(zone);
+ for (int i = 0; i < closures.Length(); i++) {
+ func ^= closures.At(i);
+ if (func.IsBytecodeAllowed(zone) && !func.HasBytecode()) {
+ RawError* error =
+ kernel::BytecodeReader::ReadFunctionBytecode(thread, func);
+ if (error != Error::null()) {
+ return error;
+ }
+ }
+ }
+ return Error::null();
+}
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+
RawError* Library::ParseAll(Thread* thread) {
Zone* zone = thread->zone();
Error& error = Error::Handle(zone);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 11a91e3..608c670 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4101,6 +4101,10 @@
// Eagerly compile all classes and functions in the library.
static RawError* CompileAll();
static RawError* ParseAll(Thread* thread);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ // Eagerly read all bytecode.
+ static RawError* ReadAllBytecode();
+#endif
#if defined(DART_NO_SNAPSHOT)
// Checks function fingerprints. Prints mismatches and aborts if