| 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.compiled_function; | |
| 6 | |
| 7 import 'package:compiler/src/constants/values.dart' show | |
| 8 ConstantValue; | |
| 9 | |
| 10 import 'package:compiler/src/elements/elements.dart'; | |
| 11 | |
| 12 import 'fletch_constants.dart' show | |
| 13 FletchFunctionConstant, | |
| 14 FletchClassConstant; | |
| 15 | |
| 16 import '../bytecodes.dart' show | |
| 17 Bytecode, | |
| 18 Opcode; | |
| 19 | |
| 20 import 'fletch_context.dart'; | |
| 21 import 'bytecode_assembler.dart'; | |
| 22 | |
| 23 import '../fletch_system.dart'; | |
| 24 import '../vm_commands.dart'; | |
| 25 | |
| 26 class FletchFunctionBuilder extends FletchFunctionBase { | |
| 27 final BytecodeAssembler assembler; | |
| 28 | |
| 29 /** | |
| 30 * If the functions is an instance member, [memberOf] is set to the id of the | |
| 31 * class. | |
| 32 * | |
| 33 * If [memberOf] is set, the compiled function takes an 'this' argument in | |
| 34 * addition to that of [signature]. | |
| 35 */ | |
| 36 final Map<ConstantValue, int> constants = <ConstantValue, int>{}; | |
| 37 final Map<int, ConstantValue> functionConstantValues = <int, ConstantValue>{}; | |
| 38 final Map<int, ConstantValue> classConstantValues = <int, ConstantValue>{}; | |
| 39 | |
| 40 FletchFunctionBuilder.fromFletchFunction(FletchFunction function) | |
| 41 : this( | |
| 42 function.functionId, | |
| 43 function.kind, | |
| 44 function.arity, | |
| 45 name: function.name, | |
| 46 element: function.element, | |
| 47 memberOf: function.memberOf); | |
| 48 | |
| 49 FletchFunctionBuilder( | |
| 50 int functionId, | |
| 51 FletchFunctionKind kind, | |
| 52 int arity, | |
| 53 {String name, | |
| 54 Element element, | |
| 55 FunctionSignature signature, | |
| 56 int memberOf}) | |
| 57 : super(functionId, kind, arity, name, element, signature, memberOf), | |
| 58 assembler = new BytecodeAssembler(arity) { | |
| 59 assert(signature == null || | |
| 60 arity == (signature.parameterCount + (isInstanceMember ? 1 : 0))); | |
| 61 } | |
| 62 | |
| 63 void reuse() { | |
| 64 assembler.reuse(); | |
| 65 constants.clear(); | |
| 66 functionConstantValues.clear(); | |
| 67 classConstantValues.clear(); | |
| 68 } | |
| 69 | |
| 70 int allocateConstant(ConstantValue constant) { | |
| 71 if (constant == null) throw "bad constant"; | |
| 72 return constants.putIfAbsent(constant, () => constants.length); | |
| 73 } | |
| 74 | |
| 75 int allocateConstantFromFunction(int functionId) { | |
| 76 FletchFunctionConstant constant = | |
| 77 functionConstantValues.putIfAbsent( | |
| 78 functionId, () => new FletchFunctionConstant(functionId)); | |
| 79 return allocateConstant(constant); | |
| 80 } | |
| 81 | |
| 82 int allocateConstantFromClass(int classId) { | |
| 83 FletchClassConstant constant = | |
| 84 classConstantValues.putIfAbsent( | |
| 85 classId, () => new FletchClassConstant(classId)); | |
| 86 return allocateConstant(constant); | |
| 87 } | |
| 88 | |
| 89 // TODO(ajohnsen): Remove this function when usage is avoided in | |
| 90 // FletchBackend. | |
| 91 void copyFrom(FletchFunctionBuilder function) { | |
| 92 assembler.bytecodes.addAll(function.assembler.bytecodes); | |
| 93 assembler.catchRanges.addAll(function.assembler.catchRanges); | |
| 94 constants.addAll(function.constants); | |
| 95 functionConstantValues.addAll(function.functionConstantValues); | |
| 96 classConstantValues.addAll(function.classConstantValues); | |
| 97 } | |
| 98 | |
| 99 FletchFunction finalizeFunction( | |
| 100 FletchContext context, | |
| 101 List<VmCommand> commands) { | |
| 102 int constantCount = constants.length; | |
| 103 for (int i = 0; i < constantCount; i++) { | |
| 104 commands.add(const PushNull()); | |
| 105 } | |
| 106 | |
| 107 assert(assembler.bytecodes.last.opcode == Opcode.MethodEnd); | |
| 108 | |
| 109 commands.add( | |
| 110 new PushNewFunction( | |
| 111 assembler.functionArity, | |
| 112 constantCount, | |
| 113 assembler.bytecodes, | |
| 114 assembler.catchRanges)); | |
| 115 | |
| 116 commands.add(new PopToMap(MapId.methods, functionId)); | |
| 117 | |
| 118 return new FletchFunction( | |
| 119 functionId, | |
| 120 kind, | |
| 121 arity, | |
| 122 name, | |
| 123 element, | |
| 124 signature, | |
| 125 assembler.bytecodes, | |
| 126 createFletchConstants(context), | |
| 127 memberOf); | |
| 128 } | |
| 129 | |
| 130 List<FletchConstant> createFletchConstants(FletchContext context) { | |
| 131 List<FletchConstant> fletchConstants = <FletchConstant>[]; | |
| 132 | |
| 133 constants.forEach((constant, int index) { | |
| 134 if (constant is ConstantValue) { | |
| 135 if (constant is FletchFunctionConstant) { | |
| 136 fletchConstants.add( | |
| 137 new FletchConstant(constant.functionId, MapId.methods)); | |
| 138 } else if (constant is FletchClassConstant) { | |
| 139 fletchConstants.add( | |
| 140 new FletchConstant(constant.classId, MapId.classes)); | |
| 141 } else { | |
| 142 int id = context.lookupConstantIdByValue(constant); | |
| 143 if (id == null) { | |
| 144 throw "Unsupported constant: ${constant.toStructuredString()}"; | |
| 145 } | |
| 146 fletchConstants.add( | |
| 147 new FletchConstant(id, MapId.constants)); | |
| 148 } | |
| 149 } else { | |
| 150 throw "Unsupported constant: ${constant.runtimeType}"; | |
| 151 } | |
| 152 }); | |
| 153 | |
| 154 return fletchConstants; | |
| 155 } | |
| 156 | |
| 157 String verboseToString() { | |
| 158 StringBuffer sb = new StringBuffer(); | |
| 159 | |
| 160 sb.writeln("Function $functionId, Arity=${assembler.functionArity}"); | |
| 161 sb.writeln("Constants:"); | |
| 162 constants.forEach((constant, int index) { | |
| 163 if (constant is ConstantValue) { | |
| 164 constant = constant.toStructuredString(); | |
| 165 } | |
| 166 sb.writeln(" #$index: $constant"); | |
| 167 }); | |
| 168 | |
| 169 sb.writeln("Bytecodes (${assembler.byteSize} bytes):"); | |
| 170 Bytecode.prettyPrint(sb, assembler.bytecodes); | |
| 171 | |
| 172 return '$sb'; | |
| 173 } | |
| 174 } | |
| OLD | NEW |