OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dartino 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.md file. | |
4 | |
5 library fletchc.fletch_system; | |
6 | |
7 import 'package:compiler/src/constants/values.dart' show | |
8 ConstantValue; | |
9 | |
10 import 'package:compiler/src/elements/elements.dart' show | |
11 ClassElement, | |
12 ConstructorElement, | |
13 Element, | |
14 FieldElement, | |
15 FunctionSignature; | |
16 | |
17 import 'package:compiler/src/universe/call_structure.dart' show | |
18 CallStructure; | |
19 | |
20 import 'package:persistent/persistent.dart' show | |
21 PersistentMap; | |
22 | |
23 import 'bytecodes.dart'; | |
24 import 'vm_commands.dart'; | |
25 | |
26 import 'src/fletch_selector.dart' show | |
27 FletchSelector; | |
28 | |
29 import 'src/fletch_system_printer.dart' show | |
30 FletchSystemPrinter; | |
31 | |
32 enum FletchFunctionKind { | |
33 NORMAL, | |
34 LAZY_FIELD_INITIALIZER, | |
35 INITIALIZER_LIST, | |
36 PARAMETER_STUB, | |
37 ACCESSOR | |
38 } | |
39 | |
40 // TODO(ajohnsen): Move to separate file. | |
41 class FletchConstant { | |
42 final int id; | |
43 final MapId mapId; | |
44 const FletchConstant(this.id, this.mapId); | |
45 | |
46 String toString() => "FletchConstant($id, $mapId)"; | |
47 } | |
48 | |
49 // TODO(ajohnsen): Move to separate file. | |
50 class FletchClass { | |
51 final int classId; | |
52 final String name; | |
53 final ClassElement element; | |
54 final int superclassId; | |
55 final int superclassFields; | |
56 final PersistentMap<int, int> methodTable; | |
57 final List<FieldElement> fields; | |
58 | |
59 const FletchClass( | |
60 this.classId, | |
61 this.name, | |
62 this.element, | |
63 this.superclassId, | |
64 this.superclassFields, | |
65 this.methodTable, | |
66 this.fields); | |
67 | |
68 bool get hasSuperclassId => superclassId >= 0; | |
69 | |
70 String toString() => "FletchClass($classId, '$name')"; | |
71 } | |
72 | |
73 // TODO(ajohnsen): Move to separate file. | |
74 abstract class FletchFunctionBase { | |
75 final int functionId; | |
76 final FletchFunctionKind kind; | |
77 // TODO(ajohnsen): Merge with function signature? | |
78 final int arity; | |
79 // TODO(ajohnsen): Remove name? | |
80 final String name; | |
81 final Element element; | |
82 | |
83 /** | |
84 * The signature of the FletchFunctionBuilder. | |
85 * | |
86 * Some compiled functions does not have a signature (for example, generated | |
87 * accessors). | |
88 */ | |
89 final FunctionSignature signature; | |
90 final int memberOf; | |
91 | |
92 const FletchFunctionBase( | |
93 this.functionId, | |
94 this.kind, | |
95 this.arity, | |
96 this.name, | |
97 this.element, | |
98 this.signature, | |
99 this.memberOf); | |
100 | |
101 bool get isInstanceMember => memberOf != null; | |
102 bool get isInternal => element == null; | |
103 | |
104 bool get isLazyFieldInitializer { | |
105 return kind == FletchFunctionKind.LAZY_FIELD_INITIALIZER; | |
106 } | |
107 | |
108 bool get isInitializerList { | |
109 return kind == FletchFunctionKind.INITIALIZER_LIST; | |
110 } | |
111 | |
112 bool get isAccessor { | |
113 return kind == FletchFunctionKind.ACCESSOR; | |
114 } | |
115 | |
116 bool get isParameterStub { | |
117 return kind == FletchFunctionKind.PARAMETER_STUB; | |
118 } | |
119 | |
120 bool get isConstructor => element != null && element.isConstructor; | |
121 | |
122 String verboseToString(); | |
123 } | |
124 | |
125 // TODO(ajohnsen): Move to separate file. | |
126 class FletchFunction extends FletchFunctionBase { | |
127 final List<Bytecode> bytecodes; | |
128 final List<FletchConstant> constants; | |
129 | |
130 const FletchFunction( | |
131 int functionId, | |
132 FletchFunctionKind kind, | |
133 int arity, | |
134 String name, | |
135 Element element, | |
136 FunctionSignature signature, | |
137 this.bytecodes, | |
138 this.constants, | |
139 int memberOf) | |
140 : super(functionId, kind, arity, name, element, signature, memberOf); | |
141 | |
142 FletchFunction withReplacedConstants(List<FletchConstant> constants) { | |
143 return new FletchFunction( | |
144 functionId, | |
145 kind, | |
146 arity, | |
147 name, | |
148 element, | |
149 signature, | |
150 bytecodes, | |
151 constants, | |
152 memberOf); | |
153 } | |
154 | |
155 /// Represents a function we have lost track off, for example, -1 in a | |
156 /// backtrace from the Fletch VM. | |
157 const FletchFunction.missing() | |
158 : this( | |
159 -1, FletchFunctionKind.NORMAL, 0, "<missing>", null, null, | |
160 const <Bytecode>[], const <FletchConstant>[], null); | |
161 | |
162 String toString() { | |
163 StringBuffer buffer = new StringBuffer(); | |
164 buffer.write("FletchFunction($functionId, '$name'"); | |
165 if (isInstanceMember) { | |
166 buffer.write(", memberOf=$memberOf"); | |
167 } | |
168 buffer.write(")"); | |
169 return buffer.toString(); | |
170 } | |
171 | |
172 String verboseToString() { | |
173 StringBuffer sb = new StringBuffer(); | |
174 | |
175 sb.writeln("Function $functionId, Arity=$arity"); | |
176 sb.writeln("Constants:"); | |
177 for (int i = 0; i < constants.length; i++) { | |
178 FletchConstant constant = constants[i]; | |
179 sb.writeln(" #$i: $constant"); | |
180 } | |
181 | |
182 sb.writeln("Bytecodes:"); | |
183 Bytecode.prettyPrint(sb, bytecodes); | |
184 | |
185 return '$sb'; | |
186 } | |
187 } | |
188 | |
189 class ParameterStubSignature { | |
190 final int functionId; | |
191 final CallStructure callStructure; | |
192 | |
193 const ParameterStubSignature(this.functionId, this.callStructure); | |
194 | |
195 int get hashCode => functionId ^ callStructure.hashCode; | |
196 | |
197 bool operator==(other) { | |
198 return other is ParameterStubSignature && | |
199 other.functionId == functionId && | |
200 other.callStructure == callStructure; | |
201 } | |
202 } | |
203 | |
204 class FletchSystem { | |
205 // functionsByElement is a subset of functionsById: Some functions do not | |
206 // have an element reference. | |
207 final PersistentMap<int, FletchFunction> functionsById; | |
208 final PersistentMap<Element, FletchFunction> functionsByElement; | |
209 | |
210 final PersistentMap<ConstructorElement, FletchFunction> | |
211 constructorInitializersByElement; | |
212 | |
213 final PersistentMap<int, int> tearoffsById; | |
214 | |
215 // classesByElement is a subset of classesById: Some classes do not | |
216 // have an element reference. | |
217 final PersistentMap<int, FletchClass> classesById; | |
218 final PersistentMap<ClassElement, FletchClass> classesByElement; | |
219 | |
220 final PersistentMap<int, FletchConstant> constantsById; | |
221 final PersistentMap<ConstantValue, FletchConstant> constantsByValue; | |
222 | |
223 final PersistentMap<int, String> symbolByFletchSelectorId; | |
224 | |
225 final PersistentMap<int, int> gettersByFieldIndex; | |
226 | |
227 final PersistentMap<int, int> settersByFieldIndex; | |
228 | |
229 final PersistentMap<ParameterStubSignature, FletchFunction> parameterStubs; | |
230 | |
231 const FletchSystem( | |
232 this.functionsById, | |
233 this.functionsByElement, | |
234 this.constructorInitializersByElement, | |
235 this.tearoffsById, | |
236 this.classesById, | |
237 this.classesByElement, | |
238 this.constantsById, | |
239 this.constantsByValue, | |
240 this.symbolByFletchSelectorId, | |
241 this.gettersByFieldIndex, | |
242 this.settersByFieldIndex, | |
243 this.parameterStubs); | |
244 | |
245 bool get isEmpty => functionsById.isEmpty; | |
246 | |
247 String lookupSymbolBySelector(int fletchSelector) { | |
248 return symbolByFletchSelectorId[FletchSelector.decodeId(fletchSelector)]; | |
249 } | |
250 | |
251 FletchFunction lookupFunctionById(int functionId) { | |
252 return functionsById[functionId]; | |
253 } | |
254 | |
255 FletchFunction lookupFunctionByElement(Element element) { | |
256 return functionsByElement[element]; | |
257 } | |
258 | |
259 Iterable<FletchFunction> functionsWhere(bool f(FletchFunction function)) { | |
260 return functionsById.values.where(f); | |
261 } | |
262 | |
263 FletchConstant lookupConstantById(int constantId) { | |
264 return constantsById[constantId]; | |
265 } | |
266 | |
267 FletchConstant lookupConstantByValue(ConstantValue value) { | |
268 return constantsByValue[value]; | |
269 } | |
270 | |
271 FletchFunction lookupConstructorInitializerByElement( | |
272 ConstructorElement element) { | |
273 return constructorInitializersByElement[element]; | |
274 } | |
275 | |
276 /// Map from the ID of a [FletchFunction] to the ID of its corresponding | |
277 /// tear-off [FletchFunction]. | |
278 /// | |
279 /// To obtain the tear-off corresponding to an [Element], look up the | |
280 /// function in [functionsByElement]. | |
281 int lookupTearOffById(int functionId) => tearoffsById[functionId]; | |
282 | |
283 /// Instance field getters can be reused between classes. This method returns | |
284 /// a getter that gets the field at [fieldIndex]. Returns `null` if no such | |
285 /// getter exists. | |
286 int lookupGetterByFieldIndex(int fieldIndex) { | |
287 return gettersByFieldIndex[fieldIndex]; | |
288 } | |
289 | |
290 /// Instance field setters can be reused between classes. This method returns | |
291 /// a setter that sets the field at [fieldIndex]. Returns `null` if no such | |
292 /// setter exists. | |
293 int lookupSetterByFieldIndex(int fieldIndex) { | |
294 return settersByFieldIndex[fieldIndex]; | |
295 } | |
296 | |
297 FletchClass lookupClassById(int classId) { | |
298 return classesById[classId]; | |
299 } | |
300 | |
301 FletchClass lookupClassByElement(ClassElement element) { | |
302 return classesByElement[element]; | |
303 } | |
304 | |
305 FletchFunction lookupParameterStub(ParameterStubSignature signature) { | |
306 return parameterStubs[signature]; | |
307 } | |
308 | |
309 int computeMaxFunctionId() { | |
310 return functionsById.keys.fold(-1, (x, y) => x > y ? x : y); | |
311 } | |
312 | |
313 int computeMaxClassId() { | |
314 return classesById.keys.fold(-1, (x, y) => x > y ? x : y); | |
315 } | |
316 | |
317 String toDebugString(Uri base) { | |
318 return new FletchSystemPrinter(this, base).generateDebugString(); | |
319 } | |
320 } | |
321 | |
322 class FletchDelta { | |
323 final FletchSystem system; | |
324 final FletchSystem predecessorSystem; | |
325 final List<VmCommand> commands; | |
326 | |
327 const FletchDelta(this.system, this.predecessorSystem, this.commands); | |
328 } | |
OLD | NEW |