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 |