|  | // Copyright (c) 2020, 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_COMPILER_AOT_PRECOMPILER_TRACER_H_ | 
|  | #define RUNTIME_VM_COMPILER_AOT_PRECOMPILER_TRACER_H_ | 
|  |  | 
|  | #if defined(DART_PRECOMPILED_RUNTIME) | 
|  | #error "AOT runtime should not use compiler sources (including header files)" | 
|  | #endif  // defined(DART_PRECOMPILED_RUNTIME) | 
|  |  | 
|  | #include "vm/allocation.h" | 
|  | #include "vm/hash_table.h" | 
|  | #include "vm/symbols.h" | 
|  |  | 
|  | namespace dart { | 
|  |  | 
|  | // Forward declarations. | 
|  | class Precompiler; | 
|  |  | 
|  | #if defined(DART_PRECOMPILER) | 
|  | // Tracer which produces machine readable precompiler tracer, which captures | 
|  | // information about all compiled functions and dependencies between them. | 
|  | // See pkg/vm_snapshot_analysis/README.md for the definition of the | 
|  | // format. | 
|  | class PrecompilerTracer : public ZoneAllocated { | 
|  | public: | 
|  | static PrecompilerTracer* StartTracingIfRequested(Precompiler* precompiler); | 
|  |  | 
|  | void Finalize(); | 
|  |  | 
|  | void WriteEntityRef(const Object& field) { | 
|  | Write("%" Pd ",", InternEntity(field)); | 
|  | } | 
|  |  | 
|  | void WriteFieldRef(const Field& field) { WriteEntityRef(field); } | 
|  |  | 
|  | void WriteFunctionRef(const Function& function) { WriteEntityRef(function); } | 
|  |  | 
|  | void WriteSelectorRef(const String& selector) { | 
|  | Write("\"S\",%" Pd ",", InternString(selector)); | 
|  | } | 
|  |  | 
|  | void WriteTableSelectorRef(intptr_t id) { Write("\"T\",%" Pd ",", id); } | 
|  |  | 
|  | void WriteClassInstantiationRef(const Class& cls) { WriteEntityRef(cls); } | 
|  |  | 
|  | void WriteCompileFunctionEvent(const Function& function) { | 
|  | Write("\"C\","); | 
|  | WriteEntityRef(function); | 
|  | } | 
|  |  | 
|  | private: | 
|  | struct CString { | 
|  | const char* str; | 
|  | const intptr_t length; | 
|  | uword hash; | 
|  | }; | 
|  |  | 
|  | struct StringTableTraits { | 
|  | static bool ReportStats() { return false; } | 
|  | static const char* Name() { return "StringTableTraits"; } | 
|  |  | 
|  | static bool IsMatch(const Object& a, const Object& b) { | 
|  | return String::Cast(a).Equals(String::Cast(b)); | 
|  | } | 
|  |  | 
|  | static bool IsMatch(const CString& cstr, const Object& other) { | 
|  | const String& other_str = String::Cast(other); | 
|  | if (other_str.Hash() != cstr.hash) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (other_str.Length() != cstr.length) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return other_str.Equals(cstr.str); | 
|  | } | 
|  |  | 
|  | static uword Hash(const CString& cstr) { return cstr.hash; } | 
|  |  | 
|  | static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); } | 
|  |  | 
|  | static ObjectPtr NewKey(const CString& cstr) { | 
|  | return Symbols::New(Thread::Current(), cstr.str); | 
|  | } | 
|  | }; | 
|  |  | 
|  | struct EntityTableTraits { | 
|  | static bool ReportStats() { return false; } | 
|  | static const char* Name() { return "EntityTableTraits"; } | 
|  |  | 
|  | static bool IsMatch(const Object& a, const Object& b) { | 
|  | return a.ptr() == b.ptr(); | 
|  | } | 
|  |  | 
|  | static uword Hash(const Object& obj) { | 
|  | if (obj.IsFunction()) { | 
|  | return Function::Cast(obj).Hash(); | 
|  | } else if (obj.IsClass()) { | 
|  | return Class::Cast(obj).Hash(); | 
|  | } else if (obj.IsField()) { | 
|  | return Field::Cast(obj).Hash(); | 
|  | } | 
|  | return obj.GetClassId(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | using StringTable = UnorderedHashMap<StringTableTraits>; | 
|  | using EntityTable = UnorderedHashMap<EntityTableTraits>; | 
|  |  | 
|  | PrecompilerTracer(Precompiler* precompiler, void* stream); | 
|  |  | 
|  | intptr_t InternString(const CString& cstr); | 
|  | intptr_t InternString(const String& str); | 
|  | intptr_t InternEntity(const Object& obj); | 
|  |  | 
|  | void Write(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) { | 
|  | va_list va; | 
|  | va_start(va, format); | 
|  | buffer_.VPrintf(format, va); | 
|  | va_end(va); | 
|  | } | 
|  |  | 
|  | CString NameForTrace(const Function& f); | 
|  |  | 
|  | void WriteEntityTable(); | 
|  | void WriteStringTable(); | 
|  |  | 
|  | Zone* zone_; | 
|  | Precompiler* precompiler_; | 
|  | TextBuffer buffer_; | 
|  | void* stream_; | 
|  | StringTable strings_; | 
|  | EntityTable entities_; | 
|  |  | 
|  | Object& object_; | 
|  | Class& cls_; | 
|  | }; | 
|  | #endif  // defined(DART_PRECOMPILER) | 
|  |  | 
|  | }  // namespace dart | 
|  |  | 
|  | #endif  // RUNTIME_VM_COMPILER_AOT_PRECOMPILER_TRACER_H_ |