Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Unified Diff: runtime/vm/dart_api_impl.cc

Issue 2922913004: Add Dart_Save/LoadCompilationTrace. (Closed)
Patch Set: zone Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/include/dart_api.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/dart_api_impl.cc
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index fd6ff190f364a23ea0dca9ab485680cb8e79b777..dc37989111bbf679ddc4e4399f44ba57490c11b0 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -23,25 +23,25 @@
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
-#include "vm/lockers.h"
#include "vm/isolate_reload.h"
#include "vm/kernel_isolate.h"
+#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
-#include "vm/os_thread.h"
#include "vm/os.h"
+#include "vm/os_thread.h"
#include "vm/port.h"
#include "vm/precompiler.h"
#include "vm/profiler.h"
#include "vm/program_visitor.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
+#include "vm/service.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
-#include "vm/service.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
@@ -52,6 +52,7 @@
#include "vm/uri.h"
#include "vm/verifier.h"
#include "vm/version.h"
+#include "vm/zone_text_buffer.h"
namespace dart {
@@ -6488,6 +6489,264 @@ DART_EXPORT void Dart_SetThreadName(const char* name) {
}
+class CompilationTraceSaver : public FunctionVisitor {
zra 2017/06/05 22:08:57 Since this source file is already 7k+ lines, consi
rmacnak 2017/06/05 23:14:08 Done.
+ public:
+ explicit CompilationTraceSaver(Zone* zone)
+ : buf_(zone, 4 * KB),
+ func_name_(String::Handle(zone)),
+ cls_(Class::Handle(zone)),
+ cls_name_(String::Handle(zone)),
+ lib_(Library::Handle(zone)),
+ uri_(String::Handle(zone)) {}
+
+ void Visit(const Function& function) {
+ if (!function.HasCode()) return;
zra 2017/06/05 22:08:57 curly braces.
rmacnak 2017/06/05 23:14:08 Done.
+
+ 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());
+ }
+
+ void StealBuffer(uint8_t** buffer, intptr_t* buffer_length) {
+ *buffer = reinterpret_cast<uint8_t*>(buf_.buffer());
+ *buffer_length = buf_.length() + 1; // Include terminating NUL.
+ }
+
+ private:
+ ZoneTextBuffer buf_;
+ String& func_name_;
+ Class& cls_;
+ String& cls_name_;
+ Library& lib_;
+ String& uri_;
+};
+
+
+DART_EXPORT
+Dart_Handle Dart_SaveCompilationTrace(uint8_t** buffer,
+ intptr_t* buffer_length) {
+ API_TIMELINE_DURATION;
+ Thread* thread = Thread::Current();
+ DARTSCOPE(thread);
+ CHECK_NULL(buffer);
+ CHECK_NULL(buffer_length);
+ CompilationTraceSaver saver(thread->zone());
+ ProgramVisitor::VisitFunctions(&saver);
+ saver.StealBuffer(buffer, buffer_length);
+ return Api::Success();
+}
+
+
+class CompilationTraceLoader : public ValueObject {
+ public:
+ explicit 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_)),
+ error_(Object::Handle(zone_)) {}
+
+ RawObject* CompileTrace(char* buffer) {
+ // First compile function named in the trace.
zra 2017/06/05 22:08:57 functions
rmacnak 2017/06/05 23:14:08 Done.
+ char* cursor = buffer;
+ while (cursor != NULL) {
+ char* uri = cursor;
+ char* comma1 = strchr(uri, ',');
+ if (comma1 == NULL) break;
+ *comma1 = 0;
+ char* cls_name = comma1 + 1;
+ char* comma2 = strchr(cls_name, ',');
+ if (comma2 == NULL) break;
+ *comma2 = 0;
+ char* func_name = comma2 + 1;
+ char* newline = strchr(func_name, '\n');
+ if (newline == NULL) break;
+ *newline = 0;
+ error_ = CompileTriple(uri, cls_name, func_name);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ cursor = newline + 1;
+ }
+
+ // Next, compile common dispatchers. This aren't found with the normal
zra 2017/06/05 22:08:57 These aren't
rmacnak 2017/06/05 23:14:08 Done.
+ // 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()->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;
+ arguments_descriptor = ArgumentsDescriptor::New(kTypeArgsLen, argc);
+ dispatcher = closure_class.GetInvocationDispatcher(
+ Symbols::Call(), arguments_descriptor,
+ RawFunction::kInvokeFieldDispatcher, true /* create_if_absent */);
+ error_ = CompileFunction(dispatcher);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ }
+
+ // Finally, compile closures in all compiled functions.
+ const GrowableObjectArray& closure_functions = GrowableObjectArray::Handle(
+ zone_, thread_->isolate()->object_store()->closure_functions());
+ for (intptr_t i = 0; i < closure_functions.Length(); i++) {
+ function_ ^= closure_functions.At(i);
+ function2_ = function_.parent_function();
+ if (function2_.HasCode()) {
+ error_ = CompileFunction(function_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ }
+ }
+
+ return Object::null();
+ }
+
+ private:
+ RawObject* 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.
+ return Object::null();
+ }
+
+ lib_ = Library::LookupLibrary(thread_, uri_);
+ if (lib_.IsNull()) {
+ // Missing library.
+ return Object::null();
+ }
+
+ bool is_getter = Field::IsGetterName(function_name_);
+ bool add_closure = 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_);
+ }
+ } else {
+ cls_ = lib_.SlowLookupClassAllowMultiPartPrivate(class_name_);
+ if (cls_.IsNull()) {
+ // Missing class.
+ return Object::null();
+ }
+
+ error_ = cls_.EnsureIsFinalized(thread_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+
+ function_ = cls_.LookupFunctionAllowPrivate(function_name_);
+ field_ = cls_.LookupFieldAllowPrivate(function_name_);
+ if (field_.IsNull() && is_getter) {
+ // Maybe this is 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()) {
+ return error_.raw();
+ }
+ }
+ }
+ }
+ }
+
+ if (!field_.IsNull() && field_.is_const() && field_.is_static()) {
+ if (field_.StaticValue() == Object::sentinel().raw()) {
zra 2017/06/05 22:08:57 && instead of nested if?
rmacnak 2017/06/05 23:14:08 Done.
+ // TODO(rmacnak): How to capture an error?
+ field_.EvaluateInitializer();
+ }
+ }
+
+ if (!function_.IsNull()) {
+ error_ = CompileFunction(function_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ if (add_closure) {
+ function_ = function_.ImplicitClosureFunction();
+ error_ = CompileFunction(function_);
+ if (error_.IsError()) {
+ return error_.raw();
+ }
+ }
+ }
+
+ return Object::null();
+ }
+
+ RawObject* CompileFunction(const Function& function) {
+ if (function.is_abstract()) {
+ return Object::null();
+ }
+ return Compiler::CompileFunction(thread_, 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_;
+ Object& error_;
+};
+
+
+DART_EXPORT
+Dart_Handle Dart_LoadCompilationTrace(uint8_t* buffer, intptr_t buffer_length) {
+ Thread* thread = Thread::Current();
+ API_TIMELINE_DURATION;
+ DARTSCOPE(thread);
+ CHECK_NULL(buffer);
+ CompilationTraceLoader loader(thread);
+ const Object& error =
+ Object::Handle(loader.CompileTrace(reinterpret_cast<char*>(buffer)));
+ if (error.IsError()) {
+ return Api::NewHandle(T, Error::Cast(error).raw());
+ }
+ return Api::Success();
+}
+
+
DART_EXPORT
Dart_Handle Dart_SaveJITFeedback(uint8_t** buffer, intptr_t* buffer_length) {
#if defined(DART_PRECOMPILED_RUNTIME)
« no previous file with comments | « runtime/include/dart_api.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698