1// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_PROGRAM_VISITOR_H_
6#define RUNTIME_VM_PROGRAM_VISITOR_H_
7
8#include "vm/allocation.h"
9
10namespace dart {
11
12// Currently, we have three types of abstract visitors that can be extended and
13// used for program walking:
14//
15// * ClassVisitor, a visitor for classes in the program.
16// * FunctionVisitor, a visitor for functions in the program.
17// * CodeVisitor, a visitor for code objects in the program.
18//
19// To find the functions in a program, we must traverse the classes in the
20// program, and similarly for code objects and functions. Thus, each
21// FunctionVisitor is also a ClassVisitor, and each CodeVisitor is also a
22// FunctionVisitor (and thus a ClassVisitor).
23//
24// Only the most specific visitor method is abstract. Derived visitors have a
25// default empty implementation for base visitor methods to limit boilerplate
26// needed when extending. For example, subclasses of CodeVisitor that only do
27// per-Code work do not need to add empty implementations for VisitClass and
28// VisitFunction.
29//
30// There are no guarantees for the order in which objects of a given type will
31// be visited, but each object will be visited only once. In addition, each
32// object is visited before any visitable sub-objects it contains. For example,
33// this means a FunctionVisitor with a VisitClass implementation that drops
34// methods from a class will not visit the dropped methods unless they are also
35// found via another source of function objects.
36//
37// Note that WalkProgram only visits objects in the isolate heap. Deduplicating
38// visitors that want to use VM objects as canonical when possible should
39// instead add the appropriate VM objects first in their constructor.
40
41class Class;
42class Code;
43class Function;
44
45class CodeVisitor;
46class FunctionVisitor;
47
48class ClassVisitor : public ValueObject {
49 public:
50 virtual ~ClassVisitor() {}
51
52 virtual bool IsFunctionVisitor() const { return false; }
53 const FunctionVisitor* AsFunctionVisitor() const {
54 return const_cast<FunctionVisitor*>(
55 const_cast<ClassVisitor*>(this)->AsFunctionVisitor());
56 }
57 FunctionVisitor* AsFunctionVisitor() {
58 if (!IsFunctionVisitor()) return nullptr;
59 return reinterpret_cast<FunctionVisitor*>(this);
60 }
61
62 virtual bool IsCodeVisitor() const { return false; }
63 const CodeVisitor* AsCodeVisitor() const {
64 return const_cast<CodeVisitor*>(
65 const_cast<ClassVisitor*>(this)->AsCodeVisitor());
66 }
67 CodeVisitor* AsCodeVisitor() {
68 if (!IsCodeVisitor()) return nullptr;
69 return reinterpret_cast<CodeVisitor*>(this);
70 }
71
72 virtual void VisitClass(const Class& cls) = 0;
73};
74
75class FunctionVisitor : public ClassVisitor {
76 public:
77 bool IsFunctionVisitor() const { return true; }
78 virtual void VisitClass(const Class& cls) {}
79 virtual void VisitFunction(const Function& function) = 0;
80};
81
82class CodeVisitor : public FunctionVisitor {
83 public:
84 bool IsCodeVisitor() const { return true; }
85 virtual void VisitFunction(const Function& function) {}
86 virtual void VisitCode(const Code& code) = 0;
87};
88
89class Thread;
90class Isolate;
91
92class ProgramVisitor : public AllStatic {
93 public:
94 // Walks all non-null class, function, and code objects in the program as
95 // necessary for the given visitor.
96 static void WalkProgram(Zone* zone, Isolate* isolate, ClassVisitor* visitor);
97
98 static void Dedup(Thread* thread);
99#if defined(DART_PRECOMPILER)
100 static void AssignUnits(Thread* thread);
101 static uint32_t Hash(Thread* thread);
102#endif
103
104 private:
105#if !defined(DART_PRECOMPILED_RUNTIME)
106 static void BindStaticCalls(Zone* zone, Isolate* isolate);
107 static void ShareMegamorphicBuckets(Zone* zone, Isolate* isolate);
108 static void NormalizeAndDedupCompressedStackMaps(Zone* zone,
109 Isolate* isolate);
110 static void DedupPcDescriptors(Zone* zone, Isolate* isolate);
111 static void DedupDeoptEntries(Zone* zone, Isolate* isolate);
112#if defined(DART_PRECOMPILER)
113 static void DedupCatchEntryMovesMaps(Zone* zone, Isolate* isolate);
114 static void DedupUnlinkedCalls(Zone* zone, Isolate* isolate);
115#endif
116 static void DedupCodeSourceMaps(Zone* zone, Isolate* isolate);
117 static void DedupLists(Zone* zone, Isolate* isolate);
118 static void DedupInstructions(Zone* zone, Isolate* isolate);
119#endif // !defined(DART_PRECOMPILED_RUNTIME)
120};
121
122} // namespace dart
123
124#endif // RUNTIME_VM_PROGRAM_VISITOR_H_
125