Chromium Code Reviews| 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..46c9b1673ae75273158fc2e23bcd016c71699a4b 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 kNumArgsChecked = ic_data_.NumArgsTested(); |
|
Florian Schneider
2016/12/15 19:09:35
s/kNumArgsChecked/num_args_checked/
rmacnak
2016/12/15 21:27:19
Done.
|
| + js_icdata.AddProperty("argsTested", kNumArgsChecked); |
| + JSONArray js_entries(&js_icdata, "entries"); |
| + for (intptr_t check = 0; check < ic_data_.NumberOfChecks(); |
| + check++) { |
| + GrowableArray<intptr_t> class_ids(kNumArgsChecked); |
| + ic_data_.GetClassIdsAt(check, &class_ids); |
| + for (intptr_t k = 0; k < kNumArgsChecked; 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() { |