Index: runtime/vm/dart_api_impl.cc |
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc |
index 2bec82533531ee0781624ea9868de20ec54dcead..27ad7ae5c18d5973ffa2dce77808b4c099ece66f 100644 |
--- a/runtime/vm/dart_api_impl.cc |
+++ b/runtime/vm/dart_api_impl.cc |
@@ -36,6 +36,7 @@ |
#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_event.h" |
@@ -112,9 +113,9 @@ const char* CanonicalFunction(const char* func) { |
// An object visitor which will iterate over all the function objects in the |
// heap and check if the result type and parameter types are canonicalized |
// or not. An assertion is raised if a type is not canonicalized. |
-class FunctionVisitor : public ObjectVisitor { |
+class CheckFunctionTypesVisitor : public ObjectVisitor { |
public: |
- explicit FunctionVisitor(Thread* thread) |
+ explicit CheckFunctionTypesVisitor(Thread* thread) |
: classHandle_(Class::Handle(thread->zone())), |
funcHandle_(Function::Handle(thread->zone())), |
typeHandle_(AbstractType::Handle(thread->zone())) {} |
@@ -1572,7 +1573,7 @@ Dart_CreateSnapshot(uint8_t** vm_isolate_snapshot_buffer, |
#if defined(DEBUG) |
I->heap()->CollectAllGarbage(); |
- FunctionVisitor check_canonical(T); |
+ CheckFunctionTypesVisitor check_canonical(T); |
I->heap()->IterateObjects(&check_canonical); |
#endif // #if defined(DEBUG) |
@@ -1611,7 +1612,7 @@ static Dart_Handle createLibrarySnapshot(Dart_Handle library, |
#if defined(DEBUG) |
I->heap()->CollectAllGarbage(); |
- FunctionVisitor check_canonical(T); |
+ CheckFunctionTypesVisitor check_canonical(T); |
I->heap()->IterateObjects(&check_canonical); |
#endif // #if defined(DEBUG) |
@@ -6426,47 +6427,175 @@ DART_EXPORT void Dart_SetThreadName(const char* name) { |
} |
-// The precompiler is included in dart_bootstrap and dart_noopt, and |
-// excluded from dart and dart_precompiled_runtime. |
-#if !defined(DART_PRECOMPILER) |
+DART_EXPORT |
+Dart_Handle Dart_SaveJITFeedback(uint8_t** buffer, intptr_t* buffer_length) { |
+#if defined(DART_PRECOMPILED_RUNTIME) |
+ return Api::NewError("No JIT feedback to save on an AOT runtime."); |
+#elif defined(PRODUCT) |
+ // TOOD(rmacnak): We'd need to include the JSON printing code again. |
+ return Api::NewError("Dart_SaveJITFeedback not supported in PRODUCT mode."); |
+#else |
+ Thread* thread = Thread::Current(); |
+ DARTSCOPE(thread); |
+ Isolate* isolate = thread->isolate(); |
+ Zone* zone = thread->zone(); |
-DART_EXPORT Dart_Handle |
-Dart_Precompile(Dart_QualifiedFunctionName entry_points[], bool reset_fields) { |
- return Api::NewError( |
- "This VM was built without support for AOT compilation."); |
-} |
+ if (buffer == NULL) { |
+ RETURN_NULL_ERROR(buffer); |
+ } |
+ if (buffer_length == NULL) { |
+ RETURN_NULL_ERROR(buffer_length); |
+ } |
+ JSONStream js_stream; |
+ { |
+ JSONObject js_profile(&js_stream); |
+ js_profile.AddProperty("vmVersion", Version::CommitString()); |
+ js_profile.AddProperty("asserts", FLAG_enable_asserts); |
+ js_profile.AddProperty("typeChecks", FLAG_enable_type_checks); |
+ |
+ { |
+ JSONArray js_scripts(&js_profile, "scripts"); |
+ |
+ const GrowableObjectArray& libraries = GrowableObjectArray::Handle( |
+ zone, isolate->object_store()->libraries()); |
+ Library& library = Library::Handle(zone); |
+ Array& scripts = Array::Handle(zone); |
+ Script& script = Script::Handle(zone); |
+ String& uri = String::Handle(zone); |
+ for (intptr_t i = 0; i < libraries.Length(); i++) { |
+ library ^= libraries.At(i); |
+ scripts = library.LoadedScripts(); |
+ for (intptr_t j = 0; j < scripts.Length(); j++) { |
+ script ^= scripts.At(j); |
+ JSONObject js_script(&js_scripts); |
+ uri = script.url(); |
+ js_script.AddProperty("uri", uri.ToCString()); |
+ int64_t fp = script.SourceFingerprint(); |
+ js_script.AddProperty64("checksum", fp); |
+ } |
+ } |
+ } |
-DART_EXPORT Dart_Handle |
-Dart_CreatePrecompiledSnapshotAssembly(uint8_t** assembly_buffer, |
- intptr_t* assembly_size) { |
- return Api::NewError( |
- "This VM was built without support for AOT compilation."); |
- return 0; |
-} |
+ { |
+ JSONArray js_classes(&js_profile, "classes"); |
+ |
+ ClassTable* classes = isolate->class_table(); |
+ Class& cls = Class::Handle(zone); |
+ Library& library = Library::Handle(zone); |
+ String& uri = String::Handle(zone); |
+ String& name = String::Handle(zone); |
+ for (intptr_t cid = kNumPredefinedCids; cid < classes->NumCids(); cid++) { |
+ if (!classes->HasValidClassAt(cid)) continue; |
+ cls ^= classes->At(cid); |
+ library = cls.library(); |
+ JSONObject js_class(&js_classes); |
+ js_class.AddProperty("cid", cid); |
+ uri = library.url(); |
+ js_class.AddProperty("uri", uri.ToCString()); |
+ name = cls.Name(); |
+ name = String::RemovePrivateKey(name); |
+ js_class.AddProperty("name", name.ToCString()); |
+ } |
+ } |
+ { |
+ JSONArray js_functions(&js_profile, "functions"); |
+ |
+ class JITFeedbackFunctionVisitor : public FunctionVisitor { |
+ public: |
+ JITFeedbackFunctionVisitor(JSONArray* js_functions, Zone* zone) |
+ : js_functions_(js_functions), |
+ function_(Function::Handle(zone)), |
+ owner_(Class::Handle(zone)), |
+ name_(String::Handle(zone)), |
+ ic_datas_(Array::Handle(zone)), |
+ ic_data_(ICData::Handle(zone)), |
+ entry_(Object::Handle(zone)) {} |
+ |
+ void Visit(const Function& function) { |
+ if (function.usage_counter() == 0) return; |
+ |
+ JSONObject js_function(js_functions_); |
+ name_ = function.name(); |
+ name_ = String::RemovePrivateKey(name_); |
+ js_function.AddProperty("name", name_.ToCString()); |
+ owner_ ^= function.Owner(); |
+ js_function.AddProperty("class", owner_.id()); |
+ js_function.AddProperty("tokenPos", function.token_pos().value()); |
+ js_function.AddProperty("kind", |
+ static_cast<intptr_t>(function.kind())); |
+ intptr_t usage = function.usage_counter(); |
+ if (usage < 0) { |
+ // Function was in the background compiler's queue. |
+ usage = FLAG_optimization_counter_threshold; |
+ } |
+ js_function.AddProperty("usageCounter", usage); |
+ |
+ ic_datas_ = function.ic_data_array(); |
+ JSONArray js_icdatas(&js_function, "ics"); |
+ if (ic_datas_.IsNull()) return; |
+ |
+ for (intptr_t j = 0; j < ic_datas_.Length(); j++) { |
+ entry_ = ic_datas_.At(j); |
+ if (!entry_.IsICData()) continue; // Skip edge counters. |
+ ic_data_ ^= entry_.raw(); |
+ |
+ JSONObject js_icdata(&js_icdatas); |
+ js_icdata.AddProperty("deoptId", ic_data_.deopt_id()); |
+ name_ = ic_data_.target_name(); |
+ name_ = String::RemovePrivateKey(name_); |
+ js_icdata.AddProperty("selector", name_.ToCString()); |
+ js_icdata.AddProperty("isStaticCall", ic_data_.is_static_call()); |
+ intptr_t num_args_checked = ic_data_.NumArgsTested(); |
+ js_icdata.AddProperty("argsTested", num_args_checked); |
+ JSONArray js_entries(&js_icdata, "entries"); |
+ for (intptr_t check = 0; check < ic_data_.NumberOfChecks(); |
+ check++) { |
+ GrowableArray<intptr_t> class_ids(num_args_checked); |
+ ic_data_.GetClassIdsAt(check, &class_ids); |
+ for (intptr_t k = 0; k < num_args_checked; k++) { |
+ ASSERT(class_ids[k] != kIllegalCid); |
+ js_entries.AddValue(class_ids[k]); |
+ } |
+ js_entries.AddValue(ic_data_.GetCountAt(check)); |
+ } |
+ } |
+ } |
-DART_EXPORT Dart_Handle |
-Dart_CreatePrecompiledSnapshotBlob(uint8_t** vm_isolate_snapshot_buffer, |
- intptr_t* vm_isolate_snapshot_size, |
- uint8_t** isolate_snapshot_buffer, |
- intptr_t* isolate_snapshot_size, |
- uint8_t** instructions_blob_buffer, |
- intptr_t* instructions_blob_size, |
- uint8_t** rodata_blob_buffer, |
- intptr_t* rodata_blob_size) { |
- return Api::NewError( |
- "This VM was built without support for AOT compilation."); |
+ private: |
+ JSONArray* js_functions_; |
+ Function& function_; |
+ Class& owner_; |
+ String& name_; |
+ Array& ic_datas_; |
+ ICData& ic_data_; |
+ Object& entry_; |
+ }; |
+ |
+ JITFeedbackFunctionVisitor visitor(&js_functions, zone); |
+ ProgramVisitor::VisitFunctions(&visitor); |
+ } |
+ } |
+ |
+ js_stream.Steal(reinterpret_cast<char**>(buffer), buffer_length); |
+ return Api::Success(); |
+#endif |
} |
-#else // DART_PRECOMPILER |
DART_EXPORT Dart_Handle |
-Dart_Precompile(Dart_QualifiedFunctionName entry_points[], bool reset_fields) { |
+Dart_Precompile(Dart_QualifiedFunctionName entry_points[], |
+ bool reset_fields, |
+ uint8_t* jit_feedback, |
+ intptr_t jit_feedback_length) { |
#if defined(TARGET_ARCH_IA32) |
- return Api::NewError("Precompilation is not supported on IA32."); |
+ return Api::NewError("AOT compilation is not supported on IA32."); |
#elif defined(TARGET_ARCH_DBC) |
- return Api::NewError("Precompilation is not supported on DBC."); |
+ return Api::NewError("AOT compilation is not supported on DBC."); |
+#elif !defined(DART_PRECOMPILER) |
+ return Api::NewError( |
+ "This VM was built without support for AOT compilation."); |
#else |
API_TIMELINE_BEGIN_END; |
DARTSCOPE(Thread::Current()); |
@@ -6478,8 +6607,8 @@ Dart_Precompile(Dart_QualifiedFunctionName entry_points[], bool reset_fields) { |
return result; |
} |
CHECK_CALLBACK_STATE(T); |
- const Error& error = |
- Error::Handle(Precompiler::CompileAll(entry_points, reset_fields)); |
+ const Error& error = Error::Handle(Precompiler::CompileAll( |
+ entry_points, reset_fields, jit_feedback, jit_feedback_length)); |
if (!error.IsNull()) { |
return Api::NewHandle(T, error.raw()); |
} |
@@ -6492,9 +6621,12 @@ DART_EXPORT Dart_Handle |
Dart_CreatePrecompiledSnapshotAssembly(uint8_t** assembly_buffer, |
intptr_t* assembly_size) { |
#if defined(TARGET_ARCH_IA32) |
- return Api::NewError("Precompilation is not supported on IA32."); |
+ return Api::NewError("AOT compilation is not supported on IA32."); |
#elif defined(TARGET_ARCH_DBC) |
- return Api::NewError("Precompilation is not supported on DBC."); |
+ return Api::NewError("AOT compilation is not supported on DBC."); |
+#elif !defined(DART_PRECOMPILER) |
+ return Api::NewError( |
+ "This VM was built without support for AOT compilation."); |
#else |
API_TIMELINE_DURATION; |
DARTSCOPE(Thread::Current()); |
@@ -6540,9 +6672,12 @@ Dart_CreatePrecompiledSnapshotBlob(uint8_t** vm_isolate_snapshot_buffer, |
uint8_t** rodata_blob_buffer, |
intptr_t* rodata_blob_size) { |
#if defined(TARGET_ARCH_IA32) |
- return Api::NewError("Precompilation is not supported on IA32."); |
+ return Api::NewError("AOT compilation is not supported on IA32."); |
#elif defined(TARGET_ARCH_DBC) |
- return Api::NewError("Precompilation is not supported on DBC."); |
+ return Api::NewError("AOT compilation is not supported on DBC."); |
+#elif !defined(DART_PRECOMPILER) |
+ return Api::NewError( |
+ "This VM was built without support for AOT compilation."); |
#else |
API_TIMELINE_DURATION; |
DARTSCOPE(Thread::Current()); |
@@ -6596,7 +6731,6 @@ Dart_CreatePrecompiledSnapshotBlob(uint8_t** vm_isolate_snapshot_buffer, |
return Api::Success(); |
#endif |
} |
-#endif // DART_PRECOMPILER |
DART_EXPORT Dart_Handle Dart_PrecompileJIT() { |