diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index 8b3db04615d..df755a73717 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc @@ -116,8 +116,6 @@ static const char* const kSnapshotKindNames[] = { V(assembly, assembly_filename) \ V(elf, elf_filename) \ V(loading_unit_manifest, loading_unit_manifest_filename) \ - V(load_compilation_trace, load_compilation_trace_filename) \ - V(load_type_feedback, load_type_feedback_filename) \ V(save_debugging_info, debugging_info_filename) \ V(save_obfuscation_map, obfuscation_map_filename) @@ -390,34 +388,6 @@ static void MaybeLoadCode() { Dart_Handle result = Dart_CompileAll(); CHECK_RESULT(result); } - - if ((load_compilation_trace_filename != NULL) && - ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) { - // Finalize all classes. This ensures that there are no non-finalized - // classes in the gaps between cid ranges. Such classes prevent merging of - // cid ranges. - Dart_Handle result = Dart_FinalizeAllClasses(); - CHECK_RESULT(result); - // Sort classes to have better cid ranges. - result = Dart_SortClasses(); - CHECK_RESULT(result); - uint8_t* buffer = NULL; - intptr_t size = 0; - ReadFile(load_compilation_trace_filename, &buffer, &size); - result = Dart_LoadCompilationTrace(buffer, size); - free(buffer); - CHECK_RESULT(result); - } - - if ((load_type_feedback_filename != NULL) && - ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) { - uint8_t* buffer = NULL; - intptr_t size = 0; - ReadFile(load_type_feedback_filename, &buffer, &size); - Dart_Handle result = Dart_LoadTypeFeedback(buffer, size); - free(buffer); - CHECK_RESULT(result); - } } static void CreateAndWriteCoreSnapshot() { diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc index 5b4601df9f0..96101530974 100644 --- a/runtime/bin/main.cc +++ b/runtime/bin/main.cc @@ -73,8 +73,6 @@ static bool kernel_isolate_is_running = false; static Dart_Isolate main_isolate = NULL; -static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size); - #define SAVE_ERROR_AND_EXIT(result) \ *error = Utils::StrDup(Dart_GetError(result)); \ if (Dart_IsCompilationError(result)) { \ @@ -925,32 +923,6 @@ static void EmbedderInformationCallback(Dart_EmbedderInformation* info) { ErrorExit(exit_code, "%s\n", Dart_GetError(result)); \ } -static void WriteFile(const char* filename, - const uint8_t* buffer, - const intptr_t size) { - File* file = File::Open(NULL, filename, File::kWriteTruncate); - if (file == NULL) { - ErrorExit(kErrorExitCode, "Unable to open file %s\n", filename); - } - if (!file->WriteFully(buffer, size)) { - ErrorExit(kErrorExitCode, "Unable to write file %s\n", filename); - } - file->Release(); -} - -static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size) { - File* file = File::Open(NULL, filename, File::kRead); - if (file == NULL) { - ErrorExit(kErrorExitCode, "Unable to open file %s\n", filename); - } - *size = file->Length(); - *buffer = reinterpret_cast(malloc(*size)); - if (!file->ReadFully(*buffer, *size)) { - ErrorExit(kErrorExitCode, "Unable to read file %s\n", filename); - } - file->Release(); -} - void RunMainIsolate(const char* script_name, const char* package_config_override, CommandLineOptions* dart_options) { @@ -1017,23 +989,6 @@ void RunMainIsolate(const char* script_name, script_name); } - if (Options::load_compilation_trace_filename() != NULL) { - uint8_t* buffer = NULL; - intptr_t size = 0; - ReadFile(Options::load_compilation_trace_filename(), &buffer, &size); - result = Dart_LoadCompilationTrace(buffer, size); - free(buffer); - CHECK_RESULT(result); - } - if (Options::load_type_feedback_filename() != NULL) { - uint8_t* buffer = NULL; - intptr_t size = 0; - ReadFile(Options::load_type_feedback_filename(), &buffer, &size); - result = Dart_LoadTypeFeedback(buffer, size); - free(buffer); - CHECK_RESULT(result); - } - // Create a closure for the main entry point which is in the exported // namespace of the root library or invoke a getter of the same name // in the exported namespace and return the resulting closure. @@ -1068,21 +1023,6 @@ void RunMainIsolate(const char* script_name, } } CHECK_RESULT(result); - - if (Options::save_compilation_trace_filename() != NULL) { - uint8_t* buffer = NULL; - intptr_t size = 0; - result = Dart_SaveCompilationTrace(&buffer, &size); - CHECK_RESULT(result); - WriteFile(Options::save_compilation_trace_filename(), buffer, size); - } - if (Options::save_type_feedback_filename() != NULL) { - uint8_t* buffer = NULL; - intptr_t size = 0; - result = Dart_SaveTypeFeedback(&buffer, &size); - CHECK_RESULT(result); - WriteFile(Options::save_type_feedback_filename(), buffer, size); - } } WriteDepsFile(isolate); diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h index 4fab09cc36d..8f9736d8167 100644 --- a/runtime/bin/main_options.h +++ b/runtime/bin/main_options.h @@ -23,10 +23,6 @@ namespace bin { V(snapshot_depfile, snapshot_deps_filename) \ V(depfile, depfile) \ V(depfile_output_filename, depfile_output_filename) \ - V(save_compilation_trace, save_compilation_trace_filename) \ - V(load_compilation_trace, load_compilation_trace_filename) \ - V(save_type_feedback, save_type_feedback_filename) \ - V(load_type_feedback, load_type_feedback_filename) \ V(root_certs_file, root_certs_file) \ V(root_certs_cache, root_certs_cache) \ V(namespace, namespc) \ diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index d8db5978a57..a328eb749b6 100644 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h @@ -3690,58 +3690,6 @@ DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate); */ DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port, char** error); -/* - * ==================== - * Compilation Feedback - * ==================== - */ - -/** - * Record all functions which have been compiled in the current isolate. - * - * \param buffer Returns a pointer to a buffer containing the trace. - * This buffer is scope allocated and is only valid until the next call to - * Dart_ExitScope. - * \param size Returns the size of the buffer. - * \return Returns an valid handle upon success. - */ -DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle -Dart_SaveCompilationTrace(uint8_t** buffer, intptr_t* buffer_length); - -/** - * Compile all functions from data from Dart_SaveCompilationTrace. Unlike JIT - * feedback, this data is fuzzy: loading does not need to happen in the exact - * program that was saved, the saver and loader do not need to agree on checked - * mode versus production mode or debug/release/product. - * - * \return Returns an error handle if a compilation error was encountered. - */ -DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle -Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length); - -/** - * Record runtime feedback for the current isolate, including type feedback - * and usage counters. - * - * \param buffer Returns a pointer to a buffer containing the trace. - * This buffer is scope allocated and is only valid until the next call to - * Dart_ExitScope. - * \param size Returns the size of the buffer. - * \return Returns an valid handle upon success. - */ -DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle -Dart_SaveTypeFeedback(uint8_t** buffer, intptr_t* buffer_length); - -/** - * Compile functions using data from Dart_SaveTypeFeedback. The data must from a - * VM with the same version and compiler flags. - * - * \return Returns an error handle if a compilation error was encountered or a - * version mismatch is detected. - */ -DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle -Dart_LoadTypeFeedback(uint8_t* buffer, intptr_t buffer_length); - /* * ============== * Precompilation diff --git a/runtime/tests/vm/dart/compilation_trace_test.dart b/runtime/tests/vm/dart/compilation_trace_test.dart deleted file mode 100644 index 4ebafb577a4..00000000000 --- a/runtime/tests/vm/dart/compilation_trace_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -// 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 "dart:async"; -import "dart:io"; - -import "package:path/path.dart" as p; - -import "snapshot_test_helper.dart"; - -int fib(int n) { - if (n <= 1) return 1; - return fib(n - 1) + fib(n - 2); -} - -Future main(List args) async { - if (args.contains("--child")) { - print(fib(35)); - return; - } - - if (!Platform.script.toString().endsWith(".dart")) { - print("This test must run from source"); - return; - } - - await withTempDir((String tmp) async { - final String tracePath = p.join(tmp, "compilation_trace.txt"); - - final result1 = await runDart("generate compilation trace", [ - "--save_compilation_trace=$tracePath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result1); - - final result2 = await runDart("use compilation trace", [ - "--load_compilation_trace=$tracePath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result2); - }); -} diff --git a/runtime/tests/vm/dart/type_feedback_test.dart b/runtime/tests/vm/dart/type_feedback_test.dart deleted file mode 100644 index 6211c7084b1..00000000000 --- a/runtime/tests/vm/dart/type_feedback_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -// 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 "dart:async"; -import "dart:io"; - -import "package:path/path.dart" as p; - -import "snapshot_test_helper.dart"; - -int fib(int n) { - if (n <= 1) return 1; - return fib(n - 1) + fib(n - 2); -} - -Future main(List args) async { - if (args.contains("--child")) { - print(fib(35)); - return; - } - - if (!Platform.script.toString().endsWith(".dart")) { - print("This test must run from source"); - return; - } - - await withTempDir((String tmp) async { - final String feedbackPath = p.join(tmp, "type_feedback.bin"); - - final result1 = await runDart("generate type feedback", [ - "--save_type_feedback=$feedbackPath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result1); - - final result2 = await runDart("use type feedback", [ - "--load_type_feedback=$feedbackPath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result2); - }); -} diff --git a/runtime/tests/vm/dart_2/compilation_trace_test.dart b/runtime/tests/vm/dart_2/compilation_trace_test.dart deleted file mode 100644 index 4ebafb577a4..00000000000 --- a/runtime/tests/vm/dart_2/compilation_trace_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -// 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 "dart:async"; -import "dart:io"; - -import "package:path/path.dart" as p; - -import "snapshot_test_helper.dart"; - -int fib(int n) { - if (n <= 1) return 1; - return fib(n - 1) + fib(n - 2); -} - -Future main(List args) async { - if (args.contains("--child")) { - print(fib(35)); - return; - } - - if (!Platform.script.toString().endsWith(".dart")) { - print("This test must run from source"); - return; - } - - await withTempDir((String tmp) async { - final String tracePath = p.join(tmp, "compilation_trace.txt"); - - final result1 = await runDart("generate compilation trace", [ - "--save_compilation_trace=$tracePath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result1); - - final result2 = await runDart("use compilation trace", [ - "--load_compilation_trace=$tracePath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result2); - }); -} diff --git a/runtime/tests/vm/dart_2/type_feedback_test.dart b/runtime/tests/vm/dart_2/type_feedback_test.dart deleted file mode 100644 index 6211c7084b1..00000000000 --- a/runtime/tests/vm/dart_2/type_feedback_test.dart +++ /dev/null @@ -1,45 +0,0 @@ -// 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 "dart:async"; -import "dart:io"; - -import "package:path/path.dart" as p; - -import "snapshot_test_helper.dart"; - -int fib(int n) { - if (n <= 1) return 1; - return fib(n - 1) + fib(n - 2); -} - -Future main(List args) async { - if (args.contains("--child")) { - print(fib(35)); - return; - } - - if (!Platform.script.toString().endsWith(".dart")) { - print("This test must run from source"); - return; - } - - await withTempDir((String tmp) async { - final String feedbackPath = p.join(tmp, "type_feedback.bin"); - - final result1 = await runDart("generate type feedback", [ - "--save_type_feedback=$feedbackPath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result1); - - final result2 = await runDart("use type feedback", [ - "--load_type_feedback=$feedbackPath", - Platform.script.toFilePath(), - "--child", - ]); - expectOutput("14930352", result2); - }); -} diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status index 653d67a5cf9..45d402d3273 100644 --- a/runtime/tests/vm/vm.status +++ b/runtime/tests/vm/vm.status @@ -460,7 +460,6 @@ dart_2/isolates/thread_pool_test: Skip # Only AOT has lightweight enough isolate [ $hot_reload || $hot_reload_rollback ] dart/appjit*: SkipByDesign # Cannot reload with URI pointing to app snapshot. -dart/compilation_trace_test: Pass, Slow dart/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses dart/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented. dart/issue_31959_31960_test: SkipSlow @@ -472,9 +471,7 @@ dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloa dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads. dart/splay_test: SkipSlow dart/stack_overflow_shared_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled. -dart/type_feedback_test: Pass, Slow dart_2/appjit*: SkipByDesign # Cannot reload with URI pointing to app snapshot. -dart_2/compilation_trace_test: Pass, Slow dart_2/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses dart_2/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented. dart_2/issue_31959_31960_test: SkipSlow @@ -486,7 +483,6 @@ dart_2/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it rel dart_2/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads. dart_2/splay_test: SkipSlow dart_2/stack_overflow_shared_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled. -dart_2/type_feedback_test: Pass, Slow [ $hot_reload || $hot_reload_rollback || $compiler != dartk && $compiler != dartkp ] dart/entrypoints/*: SkipByDesign # These tests are for compiler optimizations and very sensitive to when functions are optimized, so they are disabled on hotreload and optcounter bots. diff --git a/runtime/tools/create_snapshot_bin.py b/runtime/tools/create_snapshot_bin.py index 65c35a85846..10519b27be9 100755 --- a/runtime/tools/create_snapshot_bin.py +++ b/runtime/tools/create_snapshot_bin.py @@ -26,13 +26,6 @@ def BuildOptions(): type="string", help="kind of snapshot to generate", default="core") - result.add_option( - "--load_compilation_trace", - action="store", - type="string", - help= - "path to a compilation trace to load before generating a core-jit snapshot" - ) result.add_option( "--vm_flag", action="append", @@ -139,10 +132,6 @@ def Main(): for flag in options.vm_flag: script_args.append(flag) - if options.load_compilation_trace: - script_args.append(''.join( - ["--load_compilation_trace=", options.load_compilation_trace])) - # Pass along the packages if there is one. if options.packages: script_args.append(''.join(["--packages=", options.packages])) diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc deleted file mode 100644 index 7afcf228a03..00000000000 --- a/runtime/vm/compilation_trace.cc +++ /dev/null @@ -1,1028 +0,0 @@ -// Copyright (c) 2017, 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. - -#include "vm/compilation_trace.h" - -#include "vm/closure_functions_cache.h" -#include "vm/compiler/jit/compiler.h" -#include "vm/globals.h" -#include "vm/log.h" -#include "vm/longjump.h" -#include "vm/object_store.h" -#include "vm/resolver.h" -#include "vm/symbols.h" -#include "vm/version.h" - -namespace dart { - -#if !defined(DART_PRECOMPILED_RUNTIME) - -DEFINE_FLAG(bool, trace_compilation_trace, false, "Trace compilation trace."); - -CompilationTraceSaver::CompilationTraceSaver(Zone* zone) - : buf_(zone, 1 * MB), - func_name_(String::Handle(zone)), - cls_(Class::Handle(zone)), - cls_name_(String::Handle(zone)), - lib_(Library::Handle(zone)), - uri_(String::Handle(zone)) {} - -void CompilationTraceSaver::VisitFunction(const Function& function) { - if (!function.HasCode()) { - return; // Not compiled. - } - if (function.parent_function() != Function::null()) { - // Lookup works poorly for local functions. We compile all local functions - // in a compiled function instead. - return; - } - - func_name_ = function.name(); - func_name_ = String::RemovePrivateKey(func_name_); - cls_ = function.Owner(); - cls_name_ = cls_.Name(); - cls_name_ = String::RemovePrivateKey(cls_name_); - lib_ = cls_.library(); - uri_ = lib_.url(); - buf_.Printf("%s,%s,%s\n", uri_.ToCString(), cls_name_.ToCString(), - func_name_.ToCString()); -} - -CompilationTraceLoader::CompilationTraceLoader(Thread* thread) - : thread_(thread), - zone_(thread->zone()), - uri_(String::Handle(zone_)), - class_name_(String::Handle(zone_)), - function_name_(String::Handle(zone_)), - function_name2_(String::Handle(zone_)), - lib_(Library::Handle(zone_)), - cls_(Class::Handle(zone_)), - function_(Function::Handle(zone_)), - function2_(Function::Handle(zone_)), - field_(Field::Handle(zone_)), - sites_(Array::Handle(zone_)), - site_(ICData::Handle(zone_)), - static_type_(AbstractType::Handle(zone_)), - receiver_cls_(Class::Handle(zone_)), - target_(Function::Handle(zone_)), - selector_(String::Handle(zone_)), - args_desc_(Array::Handle(zone_)), - error_(Object::Handle(zone_)) {} - -static char* FindCharacter(char* str, char goal, char* limit) { - while (str < limit) { - if (*str == goal) { - return str; - } - str++; - } - return NULL; -} - -ObjectPtr CompilationTraceLoader::CompileTrace(uint8_t* buffer, intptr_t size) { - // First compile functions named in the trace. - char* cursor = reinterpret_cast(buffer); - char* limit = cursor + size; - while (cursor < limit) { - char* uri = cursor; - char* comma1 = FindCharacter(uri, ',', limit); - if (comma1 == NULL) { - break; - } - *comma1 = 0; - char* cls_name = comma1 + 1; - char* comma2 = FindCharacter(cls_name, ',', limit); - if (comma2 == NULL) { - break; - } - *comma2 = 0; - char* func_name = comma2 + 1; - char* newline = FindCharacter(func_name, '\n', limit); - if (newline == NULL) { - break; - } - *newline = 0; - error_ = CompileTriple(uri, cls_name, func_name); - if (error_.IsError()) { - return error_.ptr(); - } - cursor = newline + 1; - } - - // Next, compile common dispatchers. These aren't found with the normal - // lookup above because they have irregular lookup that depends on the - // arguments descriptor (e.g. call() versus call(x)). - const Class& closure_class = Class::Handle( - zone_, thread_->isolate_group()->object_store()->closure_class()); - Array& arguments_descriptor = Array::Handle(zone_); - Function& dispatcher = Function::Handle(zone_); - for (intptr_t argc = 1; argc <= 4; argc++) { - const intptr_t kTypeArgsLen = 0; - - // TODO(dartbug.com/33549): Update this code to use the size of the - // parameters when supporting calls to closures with unboxed parameters. - arguments_descriptor = ArgumentsDescriptor::NewBoxed(kTypeArgsLen, argc); - dispatcher = closure_class.GetInvocationDispatcher( - Symbols::Call(), arguments_descriptor, - UntaggedFunction::kInvokeFieldDispatcher, true /* create_if_absent */); - error_ = CompileFunction(dispatcher); - if (error_.IsError()) { - return error_.ptr(); - } - } - - // Finally, compile closures in all compiled functions. Note: We rely on the - // fact that parent functions are visited before children. - error_ = Object::null(); - auto& result = Object::Handle(zone_); - ClosureFunctionsCache::ForAllClosureFunctions([&](const Function& func) { - function2_ = func.parent_function(); - if (function2_.HasCode()) { - result = CompileFunction(function_); - if (result.IsError()) { - error_ = result.ptr(); - return false; // Stop iteration. - } - } - return true; - }); - - return Object::null(); -} - -// Use a fuzzy match to find the right function to compile. This allows a -// compilation trace to remain mostly valid in the face of program changes, and -// deals with implicit/dispatcher functions that don't have proper names. -// - Ignore private name mangling -// - If looking for a getter and we only have the corresponding regular method, -// compile the regular method, create its implicit closure and compile that. -// - If looking for a regular method and we only have the corresponding getter, -// compile the getter, create its method extractor and compile that. -// - If looking for a getter and we only have a const field, evaluate the const -// field. -ObjectPtr CompilationTraceLoader::CompileTriple(const char* uri_cstr, - const char* cls_cstr, - const char* func_cstr) { - uri_ = Symbols::New(thread_, uri_cstr); - class_name_ = Symbols::New(thread_, cls_cstr); - function_name_ = Symbols::New(thread_, func_cstr); - - if (function_name_.Equals("_getMainClosure")) { - // The scheme for invoking main relies on compiling _getMainClosure after - // synthetically importing the root library. - if (FLAG_trace_compilation_trace) { - THR_Print("Compilation trace: skip %s,%s,%s\n", uri_.ToCString(), - class_name_.ToCString(), function_name_.ToCString()); - } - return Object::null(); - } - - lib_ = Library::LookupLibrary(thread_, uri_); - if (lib_.IsNull()) { - // Missing library. - if (FLAG_trace_compilation_trace) { - THR_Print("Compilation trace: missing library %s,%s,%s\n", - uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString()); - } - return Object::null(); - } - - bool is_dyn = Function::IsDynamicInvocationForwarderName(function_name_); - if (is_dyn) { - function_name_ = - Function::DemangleDynamicInvocationForwarderName(function_name_); - } - - bool is_getter = Field::IsGetterName(function_name_); - bool is_init = Field::IsInitName(function_name_); - bool add_closure = false; - bool processed = false; - - if (class_name_.Equals(Symbols::TopLevel())) { - function_ = lib_.LookupFunctionAllowPrivate(function_name_); - field_ = lib_.LookupFieldAllowPrivate(function_name_); - if (function_.IsNull() && is_getter) { - // Maybe this was a tear off. - add_closure = true; - function_name2_ = Field::NameFromGetter(function_name_); - function_ = lib_.LookupFunctionAllowPrivate(function_name2_); - field_ = lib_.LookupFieldAllowPrivate(function_name2_); - } - if (field_.IsNull() && is_getter) { - function_name2_ = Field::NameFromGetter(function_name_); - field_ = lib_.LookupFieldAllowPrivate(function_name2_); - } - if (field_.IsNull() && is_init) { - function_name2_ = Field::NameFromInit(function_name_); - field_ = lib_.LookupFieldAllowPrivate(function_name2_); - } - } else { - cls_ = lib_.SlowLookupClassAllowMultiPartPrivate(class_name_); - if (cls_.IsNull()) { - // Missing class. - if (FLAG_trace_compilation_trace) { - THR_Print("Compilation trace: missing class %s,%s,%s\n", - uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString()); - } - return Object::null(); - } - - error_ = cls_.EnsureIsFinalized(thread_); - if (error_.IsError()) { - // Non-finalized class. - if (FLAG_trace_compilation_trace) { - THR_Print("Compilation trace: non-finalized class %s,%s,%s (%s)\n", - uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString(), - Error::Cast(error_).ToErrorCString()); - } - return error_.ptr(); - } - - function_ = cls_.LookupFunctionAllowPrivate(function_name_); - field_ = cls_.LookupFieldAllowPrivate(function_name_); - if (function_.IsNull() && is_getter) { - // Maybe this was a tear off. - add_closure = true; - function_name2_ = Field::NameFromGetter(function_name_); - function_ = cls_.LookupFunctionAllowPrivate(function_name2_); - field_ = cls_.LookupFieldAllowPrivate(function_name2_); - if (!function_.IsNull() && !function_.is_static()) { - // Maybe this was a method extractor. - function2_ = - Resolver::ResolveDynamicAnyArgs(zone_, cls_, function_name_); - if (!function2_.IsNull()) { - error_ = CompileFunction(function2_); - if (error_.IsError()) { - if (FLAG_trace_compilation_trace) { - THR_Print( - "Compilation trace: error compiling extractor %s for " - "%s,%s,%s (%s)\n", - function2_.ToCString(), uri_.ToCString(), - class_name_.ToCString(), function_name_.ToCString(), - Error::Cast(error_).ToErrorCString()); - } - return error_.ptr(); - } - } - } - } - if (field_.IsNull() && is_getter) { - function_name2_ = Field::NameFromGetter(function_name_); - field_ = cls_.LookupFieldAllowPrivate(function_name2_); - } - if (field_.IsNull() && is_init) { - function_name2_ = Field::NameFromInit(function_name_); - field_ = cls_.LookupFieldAllowPrivate(function_name2_); - } - } - - if (!field_.IsNull() && field_.is_const() && field_.is_static() && - (field_.StaticValue() == Object::sentinel().ptr())) { - processed = true; - error_ = field_.InitializeStatic(); - if (error_.IsError()) { - if (FLAG_trace_compilation_trace) { - THR_Print( - "Compilation trace: error initializing field %s for %s,%s,%s " - "(%s)\n", - field_.ToCString(), uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString(), Error::Cast(error_).ToErrorCString()); - } - return error_.ptr(); - } - } - - if (!function_.IsNull()) { - processed = true; - error_ = CompileFunction(function_); - if (error_.IsError()) { - if (FLAG_trace_compilation_trace) { - THR_Print("Compilation trace: error compiling %s,%s,%s (%s)\n", - uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString(), - Error::Cast(error_).ToErrorCString()); - } - return error_.ptr(); - } - if (add_closure) { - function_ = function_.ImplicitClosureFunction(); - error_ = CompileFunction(function_); - if (error_.IsError()) { - if (FLAG_trace_compilation_trace) { - THR_Print( - "Compilation trace: error compiling closure %s,%s,%s (%s)\n", - uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString(), Error::Cast(error_).ToErrorCString()); - } - return error_.ptr(); - } - } else if (is_dyn) { - function_name_ = function_.name(); // With private mangling. - function_name_ = - Function::CreateDynamicInvocationForwarderName(function_name_); - function_ = function_.GetDynamicInvocationForwarder(function_name_); - error_ = CompileFunction(function_); - if (error_.IsError()) { - if (FLAG_trace_compilation_trace) { - THR_Print( - "Compilation trace: error compiling dynamic forwarder %s,%s,%s " - "(%s)\n", - uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString(), Error::Cast(error_).ToErrorCString()); - } - return error_.ptr(); - } - } - } - - if (!field_.IsNull() && field_.is_static() && !field_.is_const() && - field_.has_nontrivial_initializer()) { - processed = true; - function_ = field_.EnsureInitializerFunction(); - error_ = CompileFunction(function_); - if (error_.IsError()) { - if (FLAG_trace_compilation_trace) { - THR_Print( - "Compilation trace: error compiling initializer %s,%s,%s (%s)\n", - uri_.ToCString(), class_name_.ToCString(), - function_name_.ToCString(), Error::Cast(error_).ToErrorCString()); - } - return error_.ptr(); - } - } - - if (FLAG_trace_compilation_trace) { - if (!processed) { - THR_Print("Compilation trace: ignored %s,%s,%s\n", uri_.ToCString(), - class_name_.ToCString(), function_name_.ToCString()); - } - } - return Object::null(); -} - -ObjectPtr CompilationTraceLoader::CompileFunction(const Function& function) { - if (function.is_abstract() || function.HasCode()) { - return Object::null(); - } - - error_ = Compiler::CompileFunction(thread_, function); - if (error_.IsError()) { - return error_.ptr(); - } - - SpeculateInstanceCallTargets(function); - - return error_.ptr(); -} - -// For instance calls, if the receiver's static type has one concrete -// implementation, lookup the target for that implementation and add it -// to the ICData's entries. -// For some well-known interfaces, do the same for the most common concrete -// implementation (e.g., int -> _Smi). -void CompilationTraceLoader::SpeculateInstanceCallTargets( - const Function& function) { - sites_ = function.ic_data_array(); - if (sites_.IsNull()) { - return; - } - for (intptr_t i = 1; i < sites_.Length(); i++) { - site_ ^= sites_.At(i); - if (site_.rebind_rule() != ICData::kInstance) { - continue; - } - if (site_.NumArgsTested() != 1) { - continue; - } - - static_type_ = site_.receivers_static_type(); - if (static_type_.IsNull()) { - continue; - } else if (static_type_.IsDoubleType()) { - receiver_cls_ = IsolateGroup::Current()->class_table()->At(kDoubleCid); - } else if (static_type_.IsIntType()) { - receiver_cls_ = IsolateGroup::Current()->class_table()->At(kSmiCid); - } else if (static_type_.IsStringType()) { - receiver_cls_ = - IsolateGroup::Current()->class_table()->At(kOneByteStringCid); - } else if (static_type_.IsDartFunctionType() || - static_type_.IsDartClosureType()) { - receiver_cls_ = IsolateGroup::Current()->class_table()->At(kClosureCid); - } else if (static_type_.HasTypeClass()) { - receiver_cls_ = static_type_.type_class(); - if (receiver_cls_.is_implemented() || receiver_cls_.is_abstract()) { - continue; - } - } else { - continue; - } - - selector_ = site_.target_name(); - args_desc_ = site_.arguments_descriptor(); - target_ = Resolver::ResolveDynamicForReceiverClass( - receiver_cls_, selector_, ArgumentsDescriptor(args_desc_)); - if (!target_.IsNull() && !site_.HasReceiverClassId(receiver_cls_.id())) { - intptr_t count = 0; // Don't pollute type feedback and coverage data. - site_.AddReceiverCheck(receiver_cls_.id(), target_, count); - } - } -} - -TypeFeedbackSaver::TypeFeedbackSaver(BaseWriteStream* stream) - : stream_(stream), - cls_(Class::Handle()), - lib_(Library::Handle()), - str_(String::Handle()), - fields_(Array::Handle()), - field_(Field::Handle()), - code_(Code::Handle()), - call_sites_(Array::Handle()), - call_site_(ICData::Handle()) {} - -// These flags affect deopt ids. -static char* CompilerFlags() { - TextBuffer buffer(64); - -#define ADD_FLAG(flag) buffer.AddString(FLAG_##flag ? " " #flag : " no-" #flag) - ADD_FLAG(enable_asserts); - ADD_FLAG(use_field_guards); - ADD_FLAG(use_osr); - ADD_FLAG(fields_may_be_reset); -#undef ADD_FLAG - - return buffer.Steal(); -} - -void TypeFeedbackSaver::WriteHeader() { - const char* expected_version = Version::SnapshotString(); - ASSERT(expected_version != NULL); - const intptr_t version_len = strlen(expected_version); - stream_->WriteBytes(reinterpret_cast(expected_version), - version_len); - - char* expected_features = CompilerFlags(); - ASSERT(expected_features != NULL); - const intptr_t features_len = strlen(expected_features); - stream_->WriteBytes(reinterpret_cast(expected_features), - features_len + 1); - free(expected_features); -} - -void TypeFeedbackSaver::SaveClasses() { - ClassTable* table = IsolateGroup::Current()->class_table(); - - intptr_t num_cids = table->NumCids(); - WriteInt(num_cids); - - for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { - cls_ = table->At(cid); - WriteClassByName(cls_); - } -} - -void TypeFeedbackSaver::SaveFields() { - ClassTable* table = IsolateGroup::Current()->class_table(); - intptr_t num_cids = table->NumCids(); - for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { - cls_ = table->At(cid); - WriteClassByName(cls_); - - fields_ = cls_.fields(); - WriteInt(fields_.Length()); - for (intptr_t i = 0; i < fields_.Length(); i++) { - field_ ^= fields_.At(i); - - str_ = field_.name(); - str_ = String::RemovePrivateKey(str_); - WriteString(str_); - - WriteInt(field_.guarded_cid()); - WriteInt(static_cast(field_.is_nullable())); - } - } -} - -void TypeFeedbackSaver::VisitFunction(const Function& function) { - if (!function.HasCode()) { - return; // Not compiled. - } - - cls_ = function.Owner(); - WriteClassByName(cls_); - - str_ = function.name(); - str_ = String::RemovePrivateKey(str_); - WriteString(str_); - - WriteInt(function.kind()); - WriteInt(function.token_pos().Serialize()); - - code_ = function.CurrentCode(); - intptr_t usage = function.usage_counter(); - if (usage < 0) { - // Usage is set to INT32_MIN while in the background compilation queue ... - usage = (usage - INT32_MIN) + FLAG_optimization_counter_threshold; - } else if (code_.is_optimized()) { - // ... and set to 0 when an optimizing compile completes. - usage = usage + FLAG_optimization_counter_threshold; - } - WriteInt(usage); - - WriteInt(function.inlining_depth()); - - call_sites_ = function.ic_data_array(); - if (call_sites_.IsNull()) { - call_sites_ = Object::empty_array().ptr(); // Remove edge case. - } - - // First element is edge counters. - WriteInt(call_sites_.Length() - 1); - for (intptr_t i = 1; i < call_sites_.Length(); i++) { - call_site_ ^= call_sites_.At(i); - - WriteInt(call_site_.deopt_id()); - WriteInt(call_site_.rebind_rule()); - - str_ = call_site_.target_name(); - str_ = String::RemovePrivateKey(str_); - WriteString(str_); - - intptr_t num_checked_arguments = call_site_.NumArgsTested(); - WriteInt(num_checked_arguments); - - intptr_t num_entries = call_site_.NumberOfChecks(); - WriteInt(num_entries); - - for (intptr_t entry_index = 0; entry_index < num_entries; entry_index++) { - WriteInt(call_site_.GetCountAt(entry_index)); - - for (intptr_t argument_index = 0; argument_index < num_checked_arguments; - argument_index++) { - WriteInt(call_site_.GetClassIdAt(entry_index, argument_index)); - } - } - } -} - -void TypeFeedbackSaver::WriteClassByName(const Class& cls) { - lib_ = cls.library(); - - str_ = lib_.url(); - WriteString(str_); - - str_ = cls_.Name(); - str_ = String::RemovePrivateKey(str_); - WriteString(str_); -} - -void TypeFeedbackSaver::WriteString(const String& value) { - const char* cstr = value.ToCString(); - intptr_t len = strlen(cstr); - stream_->WriteUnsigned(len); - stream_->WriteBytes(cstr, len); -} - -TypeFeedbackLoader::TypeFeedbackLoader(Thread* thread) - : thread_(thread), - zone_(thread->zone()), - stream_(nullptr), - cid_map_(nullptr), - uri_(String::Handle(zone_)), - lib_(Library::Handle(zone_)), - cls_name_(String::Handle(zone_)), - cls_(Class::Handle(zone_)), - field_name_(String::Handle(zone_)), - fields_(Array::Handle(zone_)), - field_(Field::Handle(zone_)), - func_name_(String::Handle(zone_)), - func_(Function::Handle(zone_)), - call_sites_(Array::Handle(zone_)), - call_site_(ICData::Handle(zone_)), - target_name_(String::Handle(zone_)), - target_(Function::Handle(zone_)), - args_desc_(Array::Handle(zone_)), - functions_to_compile_( - GrowableObjectArray::Handle(zone_, GrowableObjectArray::New())), - error_(Error::Handle(zone_)) {} - -TypeFeedbackLoader::~TypeFeedbackLoader() { - delete[] cid_map_; -} - -ObjectPtr TypeFeedbackLoader::LoadFeedback(ReadStream* stream) { - stream_ = stream; - - error_ = CheckHeader(); - if (error_.IsError()) { - return error_.ptr(); - } - - error_ = LoadClasses(); - if (error_.IsError()) { - return error_.ptr(); - } - - error_ = LoadFields(); - if (error_.IsError()) { - return error_.ptr(); - } - - while (stream_->PendingBytes() > 0) { - error_ = LoadFunction(); - if (error_.IsError()) { - return error_.ptr(); - } - } - - while (functions_to_compile_.Length() > 0) { - func_ ^= functions_to_compile_.RemoveLast(); - - if (Compiler::CanOptimizeFunction(thread_, func_) && - (func_.usage_counter() >= FLAG_optimization_counter_threshold)) { - error_ = Compiler::CompileOptimizedFunction(thread_, func_); - if (error_.IsError()) { - return error_.ptr(); - } - } - } - - if (FLAG_trace_compilation_trace) { - THR_Print("Done loading feedback\n"); - } - - return Error::null(); -} - -ObjectPtr TypeFeedbackLoader::CheckHeader() { - const char* expected_version = Version::SnapshotString(); - ASSERT(expected_version != NULL); - const intptr_t version_len = strlen(expected_version); - if (stream_->PendingBytes() < version_len) { - const intptr_t kMessageBufferSize = 128; - char message_buffer[kMessageBufferSize]; - Utils::SNPrint(message_buffer, kMessageBufferSize, - "No snapshot version found, expected '%s'", - expected_version); - const String& msg = String::Handle(String::New(message_buffer, Heap::kOld)); - return ApiError::New(msg, Heap::kOld); - } - - const char* version = - reinterpret_cast(stream_->AddressOfCurrentPosition()); - ASSERT(version != NULL); - if (strncmp(version, expected_version, version_len) != 0) { - const intptr_t kMessageBufferSize = 256; - char message_buffer[kMessageBufferSize]; - char* actual_version = Utils::StrNDup(version, version_len); - Utils::SNPrint(message_buffer, kMessageBufferSize, - "Wrong snapshot version, expected '%s' found '%s'", - expected_version, actual_version); - free(actual_version); - const String& msg = String::Handle(String::New(message_buffer, Heap::kOld)); - return ApiError::New(msg, Heap::kOld); - } - stream_->Advance(version_len); - - char* expected_features = CompilerFlags(); - ASSERT(expected_features != NULL); - const intptr_t expected_len = strlen(expected_features); - - const char* features = - reinterpret_cast(stream_->AddressOfCurrentPosition()); - ASSERT(features != NULL); - intptr_t buffer_len = Utils::StrNLen(features, stream_->PendingBytes()); - if ((buffer_len != expected_len) || - (strncmp(features, expected_features, expected_len) != 0)) { - const String& msg = String::Handle(String::NewFormatted( - Heap::kOld, - "Feedback not compatible with the current VM configuration: " - "the feedback requires '%.*s' but the VM has '%s'", - static_cast(buffer_len > 1024 ? 1024 : buffer_len), features, - expected_features)); - free(expected_features); - return ApiError::New(msg, Heap::kOld); - } - free(expected_features); - stream_->Advance(expected_len + 1); - return Error::null(); -} - -ObjectPtr TypeFeedbackLoader::LoadClasses() { - num_cids_ = ReadInt(); - - cid_map_ = new intptr_t[num_cids_]; - for (intptr_t cid = 0; cid < num_cids_; cid++) { - cid_map_[cid] = kIllegalCid; - } - for (intptr_t cid = kInstanceCid; cid < kNumPredefinedCids; cid++) { - cid_map_[cid] = cid; - } - - for (intptr_t cid = kNumPredefinedCids; cid < num_cids_; cid++) { - cls_ = ReadClassByName(); - if (!cls_.IsNull()) { - cid_map_[cid] = cls_.id(); - } - } - - return Error::null(); -} - -ObjectPtr TypeFeedbackLoader::LoadFields() { - for (intptr_t cid = kNumPredefinedCids; cid < num_cids_; cid++) { - cls_ = ReadClassByName(); - bool skip = cls_.IsNull(); - - intptr_t num_fields = ReadInt(); - if (!skip && (num_fields > 0)) { - error_ = cls_.EnsureIsFinalized(thread_); - if (error_.IsError()) { - return error_.ptr(); - } - fields_ = cls_.fields(); - } - - SafepointWriteRwLocker ml(thread_, - thread_->isolate_group()->program_lock()); - for (intptr_t i = 0; i < num_fields; i++) { - field_name_ = ReadString(); - intptr_t guarded_cid = cid_map_[ReadInt()]; - intptr_t is_nullable = ReadInt(); - - if (skip) { - continue; - } - - if (i >= fields_.Length()) { - if (FLAG_trace_compilation_trace) { - THR_Print("Missing field %s\n", field_name_.ToCString()); - } - continue; - } - - field_ ^= fields_.At(i); - if (!String::EqualsIgnoringPrivateKey(String::Handle(field_.name()), - field_name_)) { - if (FLAG_trace_compilation_trace) { - THR_Print("Missing field %s\n", field_name_.ToCString()); - } - continue; - } - - if (guarded_cid == kIllegalCid) { - // Guarded CID from feedback is not in current program: assume the field - // will become polymorphic. - field_.set_guarded_cid(kDynamicCid); - field_.set_is_nullable(true); - } else if ((field_.guarded_cid() != kIllegalCid) && - (field_.guarded_cid() == guarded_cid)) { - // Guarded CID from feedback is different from initialized guarded CID - // in the current program: assume the field will become polymorphic. - field_.set_guarded_cid(kDynamicCid); - field_.set_is_nullable(true); - } else { - field_.set_guarded_cid(guarded_cid); - field_.set_is_nullable((is_nullable != 0) || field_.is_nullable()); - } - - // TODO(rmacnak): Merge other field type feedback. - field_.set_guarded_list_length(Field::kNoFixedLength); - field_.set_guarded_list_length_in_object_offset( - Field::kUnknownLengthOffset); - field_.set_static_type_exactness_state( - StaticTypeExactnessState::NotTracking()); - field_.DeoptimizeDependentCode(); - } - } - - return Error::null(); -} - -ObjectPtr TypeFeedbackLoader::LoadFunction() { - bool skip = false; - - cls_ = ReadClassByName(); - if (!cls_.IsNull()) { - error_ = cls_.EnsureIsFinalized(thread_); - if (error_.IsError()) { - return error_.ptr(); - } - } else { - skip = true; - } - - func_name_ = ReadString(); // Without private mangling. - UntaggedFunction::Kind kind = static_cast(ReadInt()); - const TokenPosition& token_pos = TokenPosition::Deserialize(ReadInt()); - intptr_t usage = ReadInt(); - intptr_t inlining_depth = ReadInt(); - intptr_t num_call_sites = ReadInt(); - - if (!skip) { - func_ = FindFunction(kind, token_pos); - if (func_.IsNull()) { - skip = true; - if (FLAG_trace_compilation_trace) { - THR_Print("Missing function %s %s\n", func_name_.ToCString(), - Function::KindToCString(kind)); - } - } - } - - if (!skip) { - error_ = Compiler::CompileFunction(thread_, func_); - if (error_.IsError()) { - return error_.ptr(); - } - call_sites_ = func_.ic_data_array(); - if (call_sites_.IsNull()) { - call_sites_ = Object::empty_array().ptr(); // Remove edge case. - } - if (call_sites_.Length() != num_call_sites + 1) { - skip = true; - if (FLAG_trace_compilation_trace) { - THR_Print("Mismatched call site count %s %" Pd " %" Pd "\n", - func_name_.ToCString(), call_sites_.Length(), num_call_sites); - } - } - } - - // First element is edge counters. - for (intptr_t i = 1; i <= num_call_sites; i++) { - intptr_t deopt_id = ReadInt(); - intptr_t rebind_rule = ReadInt(); - target_name_ = ReadString(); - intptr_t num_checked_arguments = ReadInt(); - intptr_t num_entries = ReadInt(); - - if (!skip) { - call_site_ ^= call_sites_.At(i); - if ((call_site_.deopt_id() != deopt_id) || - (call_site_.rebind_rule() != rebind_rule) || - (call_site_.NumArgsTested() != num_checked_arguments)) { - skip = true; - if (FLAG_trace_compilation_trace) { - THR_Print("Mismatched call site %s\n", call_site_.ToCString()); - } - } - } - - for (intptr_t entry_index = 0; entry_index < num_entries; entry_index++) { - intptr_t entry_usage = ReadInt(); - bool skip_entry = skip; - GrowableArray cids(num_checked_arguments); - - for (intptr_t argument_index = 0; argument_index < num_checked_arguments; - argument_index++) { - intptr_t cid = cid_map_[ReadInt()]; - cids.Add(cid); - if (cid == kIllegalCid) { - // Alternative: switch to a sentinel value such as kDynamicCid and - // have the optimizer generate a megamorphic call. - skip_entry = true; - } - } - - if (skip_entry) { - continue; - } - - intptr_t reuse_index = call_site_.FindCheck(cids); - if (reuse_index == -1) { - cls_ = thread_->isolate_group()->class_table()->At(cids[0]); - // Use target name and args descriptor from the current program - // instead of saved feedback to get the correct private mangling and - // ensure no arity mismatch crashes. - target_name_ = call_site_.target_name(); - args_desc_ = call_site_.arguments_descriptor(); - if (cls_.EnsureIsFinalized(thread_) == Error::null()) { - target_ = Resolver::ResolveDynamicForReceiverClass( - cls_, target_name_, ArgumentsDescriptor(args_desc_)); - } - if (!target_.IsNull()) { - if (num_checked_arguments == 1) { - call_site_.AddReceiverCheck(cids[0], target_, entry_usage); - } else { - call_site_.AddCheck(cids, target_, entry_usage); - } - } - } else { - call_site_.IncrementCountAt(reuse_index, entry_usage); - } - } - } - - if (!skip) { - func_.set_usage_counter(usage); - func_.set_inlining_depth(inlining_depth); - - // Delay compilation until all feedback is loaded so feedback is available - // for inlined functions. - functions_to_compile_.Add(func_); - } - - return Error::null(); -} - -FunctionPtr TypeFeedbackLoader::FindFunction(UntaggedFunction::Kind kind, - const TokenPosition& token_pos) { - if (cls_name_.Equals(Symbols::TopLevel())) { - func_ = lib_.LookupFunctionAllowPrivate(func_name_); - } else { - func_ = cls_.LookupFunctionAllowPrivate(func_name_); - } - - if (!func_.IsNull()) { - // Found regular method. - } else if (kind == UntaggedFunction::kMethodExtractor) { - ASSERT(Field::IsGetterName(func_name_)); - // Without private mangling: - String& name = String::Handle(zone_, Field::NameFromGetter(func_name_)); - func_ = cls_.LookupFunctionAllowPrivate(name); - if (!func_.IsNull() && func_.IsDynamicFunction()) { - name = func_.name(); // With private mangling. - name = Field::GetterName(name); - func_ = func_.GetMethodExtractor(name); - } else { - func_ = Function::null(); - } - } else if (kind == UntaggedFunction::kDynamicInvocationForwarder) { - // Without private mangling: - String& name = String::Handle( - zone_, Function::DemangleDynamicInvocationForwarderName(func_name_)); - func_ = cls_.LookupFunctionAllowPrivate(name); - if (!func_.IsNull() && func_.IsDynamicFunction()) { - name = func_.name(); // With private mangling. - name = Function::CreateDynamicInvocationForwarderName(name); - SafepointWriteRwLocker ml(thread_, - thread_->isolate_group()->program_lock()); - func_ = func_.CreateDynamicInvocationForwarder(name); - } else { - func_ = Function::null(); - } - } else if (kind == UntaggedFunction::kClosureFunction) { - // Note this lookup relies on parent functions appearing before child - // functions in the serialized feedback, so the parent will have already - // been unoptimized compilated and the child function created and added to - // ObjectStore::closure_functions_. - func_ = ClosureFunctionsCache::LookupClosureFunction(cls_, token_pos); - } else { - // This leaves unhandled: - // - kInvokeFieldDispatcher (how to get a valid args descriptor?) - // - static field getters - // - static field initializers (not retained by the field object) - } - - if (!func_.IsNull()) { - if (kind == UntaggedFunction::kImplicitClosureFunction) { - func_ = func_.ImplicitClosureFunction(); - } - if (func_.is_abstract() || (func_.kind() != kind)) { - func_ = Function::null(); - } - } - - return func_.ptr(); -} - -ClassPtr TypeFeedbackLoader::ReadClassByName() { - uri_ = ReadString(); - cls_name_ = ReadString(); - - lib_ = Library::LookupLibrary(thread_, uri_); - if (lib_.IsNull()) { - if (FLAG_trace_compilation_trace) { - THR_Print("Missing library %s\n", uri_.ToCString()); - } - return Class::null(); - } - - if (cls_name_.Equals(Symbols::TopLevel())) { - cls_ = lib_.toplevel_class(); - } else { - cls_ = lib_.SlowLookupClassAllowMultiPartPrivate(cls_name_); - if (cls_.IsNull()) { - if (FLAG_trace_compilation_trace) { - THR_Print("Missing class %s %s\n", uri_.ToCString(), - cls_name_.ToCString()); - } - } - } - return cls_.ptr(); -} - -StringPtr TypeFeedbackLoader::ReadString() { - intptr_t len = stream_->ReadUnsigned(); - const char* cstr = - reinterpret_cast(stream_->AddressOfCurrentPosition()); - stream_->Advance(len); - return Symbols::New(thread_, cstr, len); -} - -#endif // !defined(DART_PRECOMPILED_RUNTIME) - -} // namespace dart diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h deleted file mode 100644 index 14996ecaedb..00000000000 --- a/runtime/vm/compilation_trace.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2017, 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. - -#ifndef RUNTIME_VM_COMPILATION_TRACE_H_ -#define RUNTIME_VM_COMPILATION_TRACE_H_ - -#include "platform/assert.h" -#include "vm/object.h" -#include "vm/program_visitor.h" -#include "vm/zone_text_buffer.h" - -#if !defined(DART_PRECOMPILED_RUNTIME) - -namespace dart { - -class CompilationTraceSaver : public FunctionVisitor { - public: - explicit CompilationTraceSaver(Zone* zone); - void VisitFunction(const Function& function); - - void StealBuffer(uint8_t** buffer, intptr_t* buffer_length) { - *buffer = reinterpret_cast(buf_.buffer()); - *buffer_length = buf_.length(); - } - - private: - ZoneTextBuffer buf_; - String& func_name_; - Class& cls_; - String& cls_name_; - Library& lib_; - String& uri_; -}; - -class CompilationTraceLoader : public ValueObject { - public: - explicit CompilationTraceLoader(Thread* thread); - - ObjectPtr CompileTrace(uint8_t* buffer, intptr_t buffer_length); - - private: - ObjectPtr CompileTriple(const char* uri_cstr, - const char* cls_cstr, - const char* func_cstr); - ObjectPtr CompileFunction(const Function& function); - void SpeculateInstanceCallTargets(const Function& function); - - Thread* thread_; - Zone* zone_; - String& uri_; - String& class_name_; - String& function_name_; - String& function_name2_; - Library& lib_; - Class& cls_; - Function& function_; - Function& function2_; - Field& field_; - Array& sites_; - ICData& site_; - AbstractType& static_type_; - Class& receiver_cls_; - Function& target_; - String& selector_; - Array& args_desc_; - Object& error_; -}; - -class TypeFeedbackSaver : public FunctionVisitor { - public: - explicit TypeFeedbackSaver(BaseWriteStream* stream); - - void WriteHeader(); - void SaveClasses(); - void SaveFields(); - void VisitFunction(const Function& function); - - private: - void WriteClassByName(const Class& cls); - void WriteString(const String& value); - void WriteInt(intptr_t value) { stream_->Write(static_cast(value)); } - - BaseWriteStream* const stream_; - Class& cls_; - Library& lib_; - String& str_; - Array& fields_; - Field& field_; - Code& code_; - Array& call_sites_; - ICData& call_site_; -}; - -class TypeFeedbackLoader : public ValueObject { - public: - explicit TypeFeedbackLoader(Thread* thread); - ~TypeFeedbackLoader(); - - ObjectPtr LoadFeedback(ReadStream* stream); - - private: - ObjectPtr CheckHeader(); - ObjectPtr LoadClasses(); - ObjectPtr LoadFields(); - ObjectPtr LoadFunction(); - FunctionPtr FindFunction(UntaggedFunction::Kind kind, - const TokenPosition& token_pos); - - ClassPtr ReadClassByName(); - StringPtr ReadString(); - intptr_t ReadInt() { return stream_->Read(); } - - Thread* thread_; - Zone* zone_; - ReadStream* stream_; - intptr_t num_cids_; - intptr_t* cid_map_; - String& uri_; - Library& lib_; - String& cls_name_; - Class& cls_; - String& field_name_; - Array& fields_; - Field& field_; - String& func_name_; - Function& func_; - Array& call_sites_; - ICData& call_site_; - String& target_name_; - Function& target_; - Array& args_desc_; - GrowableObjectArray& functions_to_compile_; - Object& error_; -}; - -} // namespace dart - -#endif // !defined(DART_PRECOMPILED_RUNTIME) - -#endif // RUNTIME_VM_COMPILATION_TRACE_H_ diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 8b0cd3d91aa..7ba1fc0760b 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc @@ -13,7 +13,6 @@ #include "platform/unicode.h" #include "vm/class_finalizer.h" #include "vm/clustered_snapshot.h" -#include "vm/compilation_trace.h" #include "vm/compiler/jit/compiler.h" #include "vm/dart.h" #include "vm/dart_api_impl.h" @@ -6410,94 +6409,6 @@ DART_EXPORT void Dart_SetThreadName(const char* name) { thread->SetName(name); } -DART_EXPORT -Dart_Handle Dart_SaveCompilationTrace(uint8_t** buffer, - intptr_t* buffer_length) { -#if defined(DART_PRECOMPILED_RUNTIME) - return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC); -#else - Thread* thread = Thread::Current(); - API_TIMELINE_DURATION(thread); - DARTSCOPE(thread); - CHECK_NULL(buffer); - CHECK_NULL(buffer_length); - CompilationTraceSaver saver(thread->zone()); - ProgramVisitor::WalkProgram(thread->zone(), thread->isolate_group(), &saver); - saver.StealBuffer(buffer, buffer_length); - return Api::Success(); -#endif // defined(DART_PRECOMPILED_RUNTIME) -} - -DART_EXPORT -Dart_Handle Dart_SaveTypeFeedback(uint8_t** buffer, intptr_t* buffer_length) { -#if defined(DART_PRECOMPILED_RUNTIME) - return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC); -#else - Thread* thread = Thread::Current(); - API_TIMELINE_DURATION(thread); - DARTSCOPE(thread); - CHECK_NULL(buffer); - CHECK_NULL(buffer_length); - - ZoneWriteStream stream(Api::TopScope(thread)->zone(), MB); - TypeFeedbackSaver saver(&stream); - saver.WriteHeader(); - saver.SaveClasses(); - saver.SaveFields(); - ProgramVisitor::WalkProgram(thread->zone(), thread->isolate_group(), &saver); - *buffer = stream.buffer(); - *buffer_length = stream.bytes_written(); - - return Api::Success(); -#endif // defined(DART_PRECOMPILED_RUNTIME) -} - -DART_EXPORT -Dart_Handle Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length) { -#if defined(DART_PRECOMPILED_RUNTIME) - return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC); -#else - Thread* thread = Thread::Current(); - API_TIMELINE_DURATION(thread); - DARTSCOPE(thread); - CHECK_NULL(buffer); - Dart_Handle state = Api::CheckAndFinalizePendingClasses(T); - if (Api::IsError(state)) { - return state; - } - CompilationTraceLoader loader(thread); - const Object& error = - Object::Handle(loader.CompileTrace(buffer, buffer_length)); - if (error.IsError()) { - return Api::NewHandle(T, Error::Cast(error).ptr()); - } - return Api::Success(); -#endif // defined(DART_PRECOMPILED_RUNTIME) -} - -DART_EXPORT -Dart_Handle Dart_LoadTypeFeedback(uint8_t* buffer, intptr_t buffer_length) { -#if defined(DART_PRECOMPILED_RUNTIME) - return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC); -#else - Thread* thread = Thread::Current(); - API_TIMELINE_DURATION(thread); - DARTSCOPE(thread); - CHECK_NULL(buffer); - Dart_Handle state = Api::CheckAndFinalizePendingClasses(T); - if (Api::IsError(state)) { - return state; - } - ReadStream stream(buffer, buffer_length); - TypeFeedbackLoader loader(thread); - const Object& error = Object::Handle(loader.LoadFeedback(&stream)); - if (error.IsError()) { - return Api::NewHandle(T, Error::Cast(error).ptr()); - } - return Api::Success(); -#endif // defined(DART_PRECOMPILED_RUNTIME) -} - DART_EXPORT Dart_Handle Dart_SortClasses() { #if defined(DART_PRECOMPILED_RUNTIME) return Api::NewError("%s: Cannot compile on an AOT runtime.", CURRENT_FUNC); diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni index 2d68f1ec34a..8d6dcb200da 100644 --- a/runtime/vm/vm_sources.gni +++ b/runtime/vm/vm_sources.gni @@ -45,8 +45,6 @@ vm_sources = [ "code_patcher_arm64.cc", "code_patcher_ia32.cc", "code_patcher_x64.cc", - "compilation_trace.cc", - "compilation_trace.h", "constants_arm.cc", "constants_arm.h", "constants_arm64.cc",