| 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 |