// Copyright (c) 2015, 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_PROGRAM_VISITOR_H_ #define RUNTIME_VM_PROGRAM_VISITOR_H_ #if !defined(DART_PRECOMPILED_RUNTIME) #include "vm/allocation.h" namespace dart { // Currently, we have three types of abstract visitors that can be extended and // used for program walking: // // * ClassVisitor, a visitor for classes in the program. // * FunctionVisitor, a visitor for functions in the program. // * CodeVisitor, a visitor for code objects in the program. // // To find the functions in a program, we must traverse the classes in the // program, and similarly for code objects and functions. Thus, each // FunctionVisitor is also a ClassVisitor, and each CodeVisitor is also a // FunctionVisitor (and thus a ClassVisitor). // // Only the most specific visitor method is abstract. Derived visitors have a // default empty implementation for base visitor methods to limit boilerplate // needed when extending. For example, subclasses of CodeVisitor that only do // per-Code work do not need to add empty implementations for VisitClass and // VisitFunction. // // There are no guarantees for the order in which objects of a given type will // be visited, but each object will be visited only once. In addition, each // object is visited before any visitable sub-objects it contains. For example, // this means a FunctionVisitor with a VisitClass implementation that drops // methods from a class will not visit the dropped methods unless they are also // found via another source of function objects. // // Note that WalkProgram only visits objects in the isolate heap. Deduplicating // visitors that want to use VM objects as canonical when possible should // instead add the appropriate VM objects first in their constructor. class Class; class Code; class Function; class CodeVisitor; class FunctionVisitor; class ClassVisitor : public ValueObject { public: virtual ~ClassVisitor() {} virtual bool IsFunctionVisitor() const { return false; } const FunctionVisitor* AsFunctionVisitor() const { return const_cast( const_cast(this)->AsFunctionVisitor()); } FunctionVisitor* AsFunctionVisitor() { if (!IsFunctionVisitor()) return nullptr; return reinterpret_cast(this); } virtual bool IsCodeVisitor() const { return false; } const CodeVisitor* AsCodeVisitor() const { return const_cast( const_cast(this)->AsCodeVisitor()); } CodeVisitor* AsCodeVisitor() { if (!IsCodeVisitor()) return nullptr; return reinterpret_cast(this); } virtual void VisitClass(const Class& cls) = 0; }; class FunctionVisitor : public ClassVisitor { public: bool IsFunctionVisitor() const { return true; } virtual void VisitClass(const Class& cls) {} virtual void VisitFunction(const Function& function) = 0; }; class CodeVisitor : public FunctionVisitor { public: bool IsCodeVisitor() const { return true; } virtual void VisitFunction(const Function& function) {} virtual void VisitCode(const Code& code) = 0; }; class Thread; class IsolateGroup; class ProgramVisitor : public AllStatic { public: // Walks all non-null class, function, and code objects in the program as // necessary for the given visitor. static void WalkProgram(Zone* zone, IsolateGroup* isolate_group, ClassVisitor* visitor); static void Dedup(Thread* thread); #if defined(DART_PRECOMPILER) static void AssignUnits(Thread* thread); static uint32_t Hash(Thread* thread); #endif private: static void BindStaticCalls(Thread* thread); static void ShareMegamorphicBuckets(Thread* thread); static void NormalizeAndDedupCompressedStackMaps(Thread* thread); static void DedupPcDescriptors(Thread* thread); static void DedupDeoptEntries(Thread* thread); #if defined(DART_PRECOMPILER) static void DedupCatchEntryMovesMaps(Thread* thread); static void DedupUnlinkedCalls(Thread* thread); static void PruneSubclasses(Thread* thread); #endif static void DedupCodeSourceMaps(Thread* thread); static void DedupLists(Thread* thread); static void DedupInstructions(Thread* thread); }; } // namespace dart #endif // !defined(DART_PRECOMPILED_RUNTIME) #endif // RUNTIME_VM_PROGRAM_VISITOR_H_