OLD | NEW |
1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 library fletchc.codegen_visitor; | 5 library fletchc.codegen_visitor; |
6 | 6 |
7 import 'package:compiler/src/resolution/semantic_visitor.dart'; | 7 import 'package:compiler/src/resolution/semantic_visitor.dart'; |
8 | 8 |
9 import 'package:compiler/src/resolution/operators.dart' show | 9 import 'package:compiler/src/resolution/operators.dart' show |
10 AssignmentOperator, | 10 AssignmentOperator, |
(...skipping 22 matching lines...) Expand all Loading... |
33 import 'package:compiler/src/tree/tree.dart'; | 33 import 'package:compiler/src/tree/tree.dart'; |
34 import 'package:compiler/src/universe/universe.dart'; | 34 import 'package:compiler/src/universe/universe.dart'; |
35 import 'package:compiler/src/util/util.dart' show Spannable; | 35 import 'package:compiler/src/util/util.dart' show Spannable; |
36 import 'package:compiler/src/dart_types.dart'; | 36 import 'package:compiler/src/dart_types.dart'; |
37 | 37 |
38 import 'fletch_context.dart'; | 38 import 'fletch_context.dart'; |
39 | 39 |
40 import 'fletch_backend.dart'; | 40 import 'fletch_backend.dart'; |
41 | 41 |
42 import 'fletch_constants.dart' show | 42 import 'fletch_constants.dart' show |
43 CompiledFunctionConstant, | 43 FletchFunctionBuilderConstant, |
44 FletchClassConstant, | 44 FletchClassConstant, |
45 FletchClassInstanceConstant; | 45 FletchClassInstanceConstant; |
46 | 46 |
47 import '../bytecodes.dart' show | 47 import '../bytecodes.dart' show |
48 Bytecode; | 48 Bytecode; |
49 | 49 |
50 import 'compiled_function.dart' show | 50 import 'fletch_function_builder.dart' show |
51 CompiledFunction; | 51 FletchFunctionBuilder; |
52 | 52 |
53 import 'compiled_class.dart' show | 53 import 'fletch_class_builder.dart' show |
54 CompiledClass; | 54 FletchClassBuilder; |
55 | 55 |
56 import 'fletch_selector.dart'; | 56 import 'fletch_selector.dart'; |
57 | 57 |
58 import 'closure_environment.dart'; | 58 import 'closure_environment.dart'; |
59 | 59 |
60 enum VisitState { | 60 enum VisitState { |
61 Value, | 61 Value, |
62 Effect, | 62 Effect, |
63 Test, | 63 Test, |
64 } | 64 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 final FletchContext context; | 161 final FletchContext context; |
162 | 162 |
163 final CodegenRegistry registry; | 163 final CodegenRegistry registry; |
164 | 164 |
165 final ClosureEnvironment closureEnvironment; | 165 final ClosureEnvironment closureEnvironment; |
166 | 166 |
167 final ExecutableElement element; | 167 final ExecutableElement element; |
168 | 168 |
169 final MemberElement member; | 169 final MemberElement member; |
170 | 170 |
171 final CompiledFunction compiledFunction; | 171 final FletchFunctionBuilder functionBuilder; |
172 | 172 |
173 final Map<Element, LocalValue> scope = <Element, LocalValue>{}; | 173 final Map<Element, LocalValue> scope = <Element, LocalValue>{}; |
174 | 174 |
175 final Map<Node, JumpInfo> jumpInfo = <Node, JumpInfo>{}; | 175 final Map<Node, JumpInfo> jumpInfo = <Node, JumpInfo>{}; |
176 | 176 |
177 // Stack of try blocks (inner-most first), in the lexical scope. | 177 // Stack of try blocks (inner-most first), in the lexical scope. |
178 Link<TryBlock> tryBlockStack = const Link<TryBlock>(); | 178 Link<TryBlock> tryBlockStack = const Link<TryBlock>(); |
179 | 179 |
180 VisitState visitState; | 180 VisitState visitState; |
181 BytecodeLabel trueLabel; | 181 BytecodeLabel trueLabel; |
182 BytecodeLabel falseLabel; | 182 BytecodeLabel falseLabel; |
183 | 183 |
184 // TODO(ajohnsen): Merge computation into constructor. | 184 // TODO(ajohnsen): Merge computation into constructor. |
185 // The slot at which 'this' is stored. In closures, this is overwritten. | 185 // The slot at which 'this' is stored. In closures, this is overwritten. |
186 LocalValue thisValue; | 186 LocalValue thisValue; |
187 | 187 |
188 List<Element> blockLocals = <Element>[]; | 188 List<Element> blockLocals = <Element>[]; |
189 | 189 |
190 CodegenVisitor(CompiledFunction compiledFunction, | 190 CodegenVisitor(FletchFunctionBuilder functionBuilder, |
191 this.context, | 191 this.context, |
192 TreeElements elements, | 192 TreeElements elements, |
193 this.registry, | 193 this.registry, |
194 this.closureEnvironment, | 194 this.closureEnvironment, |
195 this.element) | 195 this.element) |
196 : super(elements), | 196 : super(elements), |
197 this.compiledFunction = compiledFunction, | 197 this.functionBuilder = functionBuilder, |
198 thisValue = new UnboxedLocalValue( | 198 thisValue = new UnboxedLocalValue( |
199 -1 - compiledFunction.builder.functionArity, | 199 -1 - functionBuilder.builder.functionArity, |
200 null); | 200 null); |
201 | 201 |
202 BytecodeBuilder get builder => compiledFunction.builder; | 202 BytecodeBuilder get builder => functionBuilder.builder; |
203 | 203 |
204 SemanticSendVisitor get sendVisitor => this; | 204 SemanticSendVisitor get sendVisitor => this; |
205 SemanticDeclarationVisitor get declVisitor => this; | 205 SemanticDeclarationVisitor get declVisitor => this; |
206 | 206 |
207 void compile(); | 207 void compile(); |
208 | 208 |
209 ConstantExpression compileConstant( | 209 ConstantExpression compileConstant( |
210 Node node, | 210 Node node, |
211 {TreeElements elements, | 211 {TreeElements elements, |
212 bool isConst}) { | 212 bool isConst}) { |
213 if (elements == null) elements = this.elements; | 213 if (elements == null) elements = this.elements; |
214 return context.compileConstant(node, elements, isConst: isConst); | 214 return context.compileConstant(node, elements, isConst: isConst); |
215 } | 215 } |
216 | 216 |
217 int allocateConstantFromNode(Node node, {TreeElements elements}) { | 217 int allocateConstantFromNode(Node node, {TreeElements elements}) { |
218 ConstantExpression expression = compileConstant( | 218 ConstantExpression expression = compileConstant( |
219 node, | 219 node, |
220 elements: elements, | 220 elements: elements, |
221 isConst: false); | 221 isConst: false); |
222 return compiledFunction.allocateConstant( | 222 return functionBuilder.allocateConstant( |
223 context.getConstantValue(expression)); | 223 context.getConstantValue(expression)); |
224 } | 224 } |
225 | 225 |
226 int allocateConstantClassInstance(int classId) { | 226 int allocateConstantClassInstance(int classId) { |
227 var constant = new FletchClassInstanceConstant(classId); | 227 var constant = new FletchClassInstanceConstant(classId); |
228 context.markConstantUsed(constant); | 228 context.markConstantUsed(constant); |
229 return compiledFunction.allocateConstant(constant); | 229 return functionBuilder.allocateConstant(constant); |
230 } | 230 } |
231 | 231 |
232 int allocateStringConstant(String string) { | 232 int allocateStringConstant(String string) { |
233 return compiledFunction.allocateConstant( | 233 return functionBuilder.allocateConstant( |
234 context.backend.constantSystem.createString( | 234 context.backend.constantSystem.createString( |
235 new DartString.literal(string))); | 235 new DartString.literal(string))); |
236 } | 236 } |
237 | 237 |
238 ClosureInfo get closureInfo => closureEnvironment.closures[element]; | 238 ClosureInfo get closureInfo => closureEnvironment.closures[element]; |
239 | 239 |
240 LocalValue createLocalValueFor( | 240 LocalValue createLocalValueFor( |
241 LocalElement element, | 241 LocalElement element, |
242 [int slot]) { | 242 [int slot]) { |
243 if (slot == null) slot = builder.stackSize; | 243 if (slot == null) slot = builder.stackSize; |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 builder.dup(); | 336 builder.dup(); |
337 int constId = allocateConstantFromNode(caseMatch.expression); | 337 int constId = allocateConstantFromNode(caseMatch.expression); |
338 builder.loadConst(constId); | 338 builder.loadConst(constId); |
339 // For debugging, ignore the equality checks in connection | 339 // For debugging, ignore the equality checks in connection |
340 // with case matches by not associating the calls with | 340 // with case matches by not associating the calls with |
341 // any node. | 341 // any node. |
342 invokeMethod(null, new Selector.binaryOperator('==')); | 342 invokeMethod(null, new Selector.binaryOperator('==')); |
343 builder.branchIfTrue(ifTrue); | 343 builder.branchIfTrue(ifTrue); |
344 } | 344 } |
345 | 345 |
346 CompiledFunction requireCompiledFunction(FunctionElement element) { | 346 FletchFunctionBuilder requireFletchFunctionBuilder(FunctionElement element) { |
347 registerStaticInvocation(element); | 347 registerStaticInvocation(element); |
348 return context.backend.createCompiledFunction(element); | 348 return context.backend.createFletchFunctionBuilder(element); |
349 } | 349 } |
350 | 350 |
351 void doStaticFunctionInvoke( | 351 void doStaticFunctionInvoke( |
352 Node node, | 352 Node node, |
353 CompiledFunction function, | 353 FletchFunctionBuilder function, |
354 NodeList arguments, | 354 NodeList arguments, |
355 CallStructure callStructure, | 355 CallStructure callStructure, |
356 {bool factoryInvoke: false}) { | 356 {bool factoryInvoke: false}) { |
357 if (function.hasThisArgument) loadThis(); | 357 if (function.hasThisArgument) loadThis(); |
358 FunctionSignature signature = function.signature; | 358 FunctionSignature signature = function.signature; |
359 int methodId; | 359 int methodId; |
360 int arity; | 360 int arity; |
361 if (signature.hasOptionalParameters && | 361 if (signature.hasOptionalParameters && |
362 signature.optionalParametersAreNamed) { | 362 signature.optionalParametersAreNamed) { |
363 // TODO(ajohnsen): Don't use selectors. | 363 // TODO(ajohnsen): Don't use selectors. |
364 if (function.matchesSelector(callStructure.callSelector)) { | 364 if (function.matchesSelector(callStructure.callSelector)) { |
365 methodId = function.methodId; | 365 methodId = function.methodId; |
366 } else if (function.canBeCalledAs(callStructure.callSelector)) { | 366 } else if (function.canBeCalledAs(callStructure.callSelector)) { |
367 // TODO(ajohnsen): Inline parameter mapping? | 367 // TODO(ajohnsen): Inline parameter mapping? |
368 CompiledFunction stub = function.createParameterMappingFor( | 368 FletchFunctionBuilder stub = function.createParameterMappingFor( |
369 callStructure.callSelector, context); | 369 callStructure.callSelector, context); |
370 methodId = stub.methodId; | 370 methodId = stub.methodId; |
371 } else { | 371 } else { |
372 doUnresolved(function.name); | 372 doUnresolved(function.name); |
373 return; | 373 return; |
374 } | 374 } |
375 for (Node argument in arguments) { | 375 for (Node argument in arguments) { |
376 visitForValue(argument); | 376 visitForValue(argument); |
377 } | 377 } |
378 arity = callStructure.argumentCount; | 378 arity = callStructure.argumentCount; |
379 } else if (callStructure != null && | 379 } else if (callStructure != null && |
380 callStructure.namedArguments.isNotEmpty) { | 380 callStructure.namedArguments.isNotEmpty) { |
381 doUnresolved(function.name); | 381 doUnresolved(function.name); |
382 return; | 382 return; |
383 } else { | 383 } else { |
384 methodId = function.methodId; | 384 methodId = function.methodId; |
385 arity = loadPositionalArguments(arguments, signature, function.name); | 385 arity = loadPositionalArguments(arguments, signature, function.name); |
386 } | 386 } |
387 if (function.hasThisArgument) arity++; | 387 if (function.hasThisArgument) arity++; |
388 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 388 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
389 if (factoryInvoke) { | 389 if (factoryInvoke) { |
390 invokeFactory(node, constId, arity); | 390 invokeFactory(node, constId, arity); |
391 } else { | 391 } else { |
392 invokeStatic(node, constId, arity); | 392 invokeStatic(node, constId, arity); |
393 } | 393 } |
394 } | 394 } |
395 | 395 |
396 void loadThis() { | 396 void loadThis() { |
397 thisValue.load(builder); | 397 thisValue.load(builder); |
398 } | 398 } |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 for (Node argument in arguments) { | 833 for (Node argument in arguments) { |
834 visitForValue(argument); | 834 visitForValue(argument); |
835 } | 835 } |
836 generateIdentical(node); | 836 generateIdentical(node); |
837 } | 837 } |
838 | 838 |
839 void handleStaticFunctionGet( | 839 void handleStaticFunctionGet( |
840 Send node, | 840 Send node, |
841 MethodElement function, | 841 MethodElement function, |
842 _) { | 842 _) { |
843 CompiledFunction compiledFunctionTarget = requireCompiledFunction(function); | 843 FletchFunctionBuilder functionBuilderTarget = requireFletchFunctionBuilder( |
844 CompiledClass compiledClass = context.backend.createTearoffClass( | 844 function); |
845 compiledFunctionTarget); | 845 FletchClassBuilder classBuilder = context.backend.createTearoffClass( |
846 assert(compiledClass.fields == 0); | 846 functionBuilderTarget); |
847 int constId = allocateConstantClassInstance(compiledClass.id); | 847 assert(classBuilder.fields == 0); |
| 848 int constId = allocateConstantClassInstance(classBuilder.id); |
848 builder.loadConst(constId); | 849 builder.loadConst(constId); |
849 applyVisitState(); | 850 applyVisitState(); |
850 } | 851 } |
851 | 852 |
852 void doMainCall(Send node, NodeList arguments) { | 853 void doMainCall(Send node, NodeList arguments) { |
853 FunctionElement function = context.compiler.mainFunction; | 854 FunctionElement function = context.compiler.mainFunction; |
854 if (function.isErroneous) { | 855 if (function.isErroneous) { |
855 doCompileError(); | 856 doCompileError(); |
856 return; | 857 return; |
857 } | 858 } |
858 if (context.compiler.libraryLoader.libraries.any(checkCompileError)) return; | 859 if (context.compiler.libraryLoader.libraries.any(checkCompileError)) return; |
859 registerStaticInvocation(function); | 860 registerStaticInvocation(function); |
860 // Load up to 'parameterCount' arguments, padding with nulls. | 861 // Load up to 'parameterCount' arguments, padding with nulls. |
861 int parameterCount = function.functionSignature.parameterCount; | 862 int parameterCount = function.functionSignature.parameterCount; |
862 int argumentCount = 0; | 863 int argumentCount = 0; |
863 for (Node argument in arguments) { | 864 for (Node argument in arguments) { |
864 if (argumentCount == parameterCount) break; | 865 if (argumentCount == parameterCount) break; |
865 visitForValue(argument); | 866 visitForValue(argument); |
866 argumentCount++; | 867 argumentCount++; |
867 } | 868 } |
868 for (int i = argumentCount; i < parameterCount; i++) { | 869 for (int i = argumentCount; i < parameterCount; i++) { |
869 builder.loadLiteralNull(); | 870 builder.loadLiteralNull(); |
870 } | 871 } |
871 int methodId = context.backend.functionMethodId(function); | 872 int methodId = context.backend.functionMethodId(function); |
872 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 873 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
873 invokeStatic(node, constId, parameterCount); | 874 invokeStatic(node, constId, parameterCount); |
874 } | 875 } |
875 | 876 |
876 void doStaticallyBoundInvoke( | 877 void doStaticallyBoundInvoke( |
877 Send node, | 878 Send node, |
878 MethodElement element, | 879 MethodElement element, |
879 NodeList arguments, | 880 NodeList arguments, |
880 CallStructure callStructure) { | 881 CallStructure callStructure) { |
881 if (checkCompileError(element)) return; | 882 if (checkCompileError(element)) return; |
882 if (element.declaration == context.compiler.identicalFunction) { | 883 if (element.declaration == context.compiler.identicalFunction) { |
883 doIdenticalCall(node, arguments); | 884 doIdenticalCall(node, arguments); |
884 return; | 885 return; |
885 } | 886 } |
886 if (element.isExternal) { | 887 if (element.isExternal) { |
887 // Patch known functions directly. | 888 // Patch known functions directly. |
888 if (element == context.backend.fletchExternalInvokeMain) { | 889 if (element == context.backend.fletchExternalInvokeMain) { |
889 doMainCall(node, arguments); | 890 doMainCall(node, arguments); |
890 return; | 891 return; |
891 } else if (element == context.backend.fletchExternalCoroutineChange) { | 892 } else if (element == context.backend.fletchExternalCoroutineChange) { |
892 for (Node argument in arguments) { | 893 for (Node argument in arguments) { |
893 visitForValue(argument); | 894 visitForValue(argument); |
894 } | 895 } |
895 builder.coroutineChange(); | 896 builder.coroutineChange(); |
896 return; | 897 return; |
897 } | 898 } |
898 // TODO(ajohnsen): Define a known set of external functions we allow | 899 // TODO(ajohnsen): Define a known set of external functions we allow |
899 // calls to? | 900 // calls to? |
900 } | 901 } |
901 CompiledFunction target = requireCompiledFunction(element); | 902 FletchFunctionBuilder target = requireFletchFunctionBuilder(element); |
902 doStaticFunctionInvoke(node, target, arguments, callStructure); | 903 doStaticFunctionInvoke(node, target, arguments, callStructure); |
903 } | 904 } |
904 | 905 |
905 void handleStaticFunctionInvoke( | 906 void handleStaticFunctionInvoke( |
906 Send node, | 907 Send node, |
907 MethodElement element, | 908 MethodElement element, |
908 NodeList arguments, | 909 NodeList arguments, |
909 CallStructure callStructure, | 910 CallStructure callStructure, |
910 _) { | 911 _) { |
911 doStaticallyBoundInvoke( | 912 doStaticallyBoundInvoke( |
912 node, element.declaration, arguments, callStructure); | 913 node, element.declaration, arguments, callStructure); |
913 applyVisitState(); | 914 applyVisitState(); |
914 } | 915 } |
915 | 916 |
916 void visitSuperMethodInvoke( | 917 void visitSuperMethodInvoke( |
917 Send node, | 918 Send node, |
918 MethodElement element, | 919 MethodElement element, |
919 NodeList arguments, | 920 NodeList arguments, |
920 CallStructure callStructure, | 921 CallStructure callStructure, |
921 _) { | 922 _) { |
922 doStaticallyBoundInvoke(node, element, arguments, callStructure); | 923 doStaticallyBoundInvoke(node, element, arguments, callStructure); |
923 applyVisitState(); | 924 applyVisitState(); |
924 } | 925 } |
925 | 926 |
926 void doSuperCall(Node node, FunctionElement function) { | 927 void doSuperCall(Node node, FunctionElement function) { |
927 registerStaticInvocation(function); | 928 registerStaticInvocation(function); |
928 int arity = function.functionSignature.parameterCount + 1; | 929 int arity = function.functionSignature.parameterCount + 1; |
929 int methodId = context.backend.functionMethodId(function); | 930 int methodId = context.backend.functionMethodId(function); |
930 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 931 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
931 invokeStatic(node, constId, arity); | 932 invokeStatic(node, constId, arity); |
932 } | 933 } |
933 | 934 |
934 void visitSuperGetterGet( | 935 void visitSuperGetterGet( |
935 Send node, | 936 Send node, |
936 FunctionElement getter, | 937 FunctionElement getter, |
937 _) { | 938 _) { |
938 loadThis(); | 939 loadThis(); |
939 doSuperCall(node, getter); | 940 doSuperCall(node, getter); |
940 applyVisitState(); | 941 applyVisitState(); |
941 } | 942 } |
942 | 943 |
943 void visitSuperMethodGet( | 944 void visitSuperMethodGet( |
944 Send node, | 945 Send node, |
945 MethodElement method, | 946 MethodElement method, |
946 _) { | 947 _) { |
947 loadThis(); | 948 loadThis(); |
948 CompiledFunction compiledFunctionTarget = requireCompiledFunction(method); | 949 FletchFunctionBuilder functionBuilderTarget = requireFletchFunctionBuilder( |
949 CompiledClass compiledClass = context.backend.createTearoffClass( | 950 method); |
950 compiledFunctionTarget); | 951 FletchClassBuilder classBuilder = context.backend.createTearoffClass( |
951 assert(compiledClass.fields == 1); | 952 functionBuilderTarget); |
952 int constId = compiledFunction.allocateConstantFromClass(compiledClass.id); | 953 assert(classBuilder.fields == 1); |
953 builder.allocate(constId, compiledClass.fields); | 954 int constId = functionBuilder.allocateConstantFromClass(classBuilder.id); |
| 955 builder.allocate(constId, classBuilder.fields); |
954 applyVisitState(); | 956 applyVisitState(); |
955 } | 957 } |
956 | 958 |
957 void visitSuperSetterSet( | 959 void visitSuperSetterSet( |
958 SendSet node, | 960 SendSet node, |
959 FunctionElement setter, | 961 FunctionElement setter, |
960 Node rhs, | 962 Node rhs, |
961 _) { | 963 _) { |
962 loadThis(); | 964 loadThis(); |
963 visitForValue(rhs); | 965 visitForValue(rhs); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 UnaryOperator operator, | 1074 UnaryOperator operator, |
1073 FunctionElement function, | 1075 FunctionElement function, |
1074 _) { | 1076 _) { |
1075 loadThis(); | 1077 loadThis(); |
1076 doSuperCall(node, function); | 1078 doSuperCall(node, function); |
1077 applyVisitState(); | 1079 applyVisitState(); |
1078 } | 1080 } |
1079 | 1081 |
1080 int computeFieldIndex(FieldElement field) { | 1082 int computeFieldIndex(FieldElement field) { |
1081 ClassElement classElement = field.enclosingClass; | 1083 ClassElement classElement = field.enclosingClass; |
1082 // We know the enclosing class is compiled, so we can use the CompiledClass | 1084 // We know the enclosing class is compiled, so we can use the |
1083 // as an optimization for getting the number of super fields, thus we only | 1085 // FletchClassBuilder as an optimization for getting the number of super |
1084 // have to iterate the fields of the enclosing class. | 1086 // fields, thus we only have to iterate the fields of the enclosing class. |
1085 CompiledClass compiledClass = context.backend.registerClassElement( | 1087 FletchClassBuilder classBuilder = context.backend.registerClassElement( |
1086 classElement); | 1088 classElement); |
1087 int i = 0; | 1089 int i = 0; |
1088 int fieldIndex; | 1090 int fieldIndex; |
1089 classElement.implementation.forEachInstanceField((_, FieldElement member) { | 1091 classElement.implementation.forEachInstanceField((_, FieldElement member) { |
1090 if (member == field) { | 1092 if (member == field) { |
1091 assert(fieldIndex == null); | 1093 assert(fieldIndex == null); |
1092 fieldIndex = i; | 1094 fieldIndex = i; |
1093 } | 1095 } |
1094 i++; | 1096 i++; |
1095 }); | 1097 }); |
1096 assert(fieldIndex != null); | 1098 assert(fieldIndex != null); |
1097 fieldIndex += compiledClass.superclassFields; | 1099 fieldIndex += classBuilder.superclassFields; |
1098 return fieldIndex; | 1100 return fieldIndex; |
1099 } | 1101 } |
1100 | 1102 |
1101 void visitSuperFieldGet( | 1103 void visitSuperFieldGet( |
1102 Send node, | 1104 Send node, |
1103 FieldElement field, | 1105 FieldElement field, |
1104 _) { | 1106 _) { |
1105 loadThis(); | 1107 loadThis(); |
1106 builder.loadField(computeFieldIndex(field)); | 1108 builder.loadField(computeFieldIndex(field)); |
1107 applyVisitState(); | 1109 applyVisitState(); |
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1870 } | 1872 } |
1871 builder.pop(); | 1873 builder.pop(); |
1872 } | 1874 } |
1873 | 1875 |
1874 void callConstructor(Node node, | 1876 void callConstructor(Node node, |
1875 ConstructorElement constructor, | 1877 ConstructorElement constructor, |
1876 NodeList arguments, | 1878 NodeList arguments, |
1877 CallStructure callStructure) { | 1879 CallStructure callStructure) { |
1878 registerStaticInvocation(constructor); | 1880 registerStaticInvocation(constructor); |
1879 registerInstantiatedClass(constructor.enclosingClass); | 1881 registerInstantiatedClass(constructor.enclosingClass); |
1880 CompiledFunction compiledFunction = context.backend.compileConstructor( | 1882 FletchFunctionBuilder functionBuilder = context.backend.compileConstructor( |
1881 constructor, | 1883 constructor, |
1882 registry); | 1884 registry); |
1883 doStaticFunctionInvoke( | 1885 doStaticFunctionInvoke( |
1884 node, compiledFunction, arguments, callStructure); | 1886 node, functionBuilder, arguments, callStructure); |
1885 } | 1887 } |
1886 | 1888 |
1887 void doConstConstructorInvoke(ConstantExpression constant) { | 1889 void doConstConstructorInvoke(ConstantExpression constant) { |
1888 var value = context.getConstantValue(constant); | 1890 var value = context.getConstantValue(constant); |
1889 context.markConstantUsed(value); | 1891 context.markConstantUsed(value); |
1890 int constId = compiledFunction.allocateConstant(value); | 1892 int constId = functionBuilder.allocateConstant(value); |
1891 builder.loadConst(constId); | 1893 builder.loadConst(constId); |
1892 } | 1894 } |
1893 | 1895 |
1894 void visitConstConstructorInvoke( | 1896 void visitConstConstructorInvoke( |
1895 NewExpression node, | 1897 NewExpression node, |
1896 ConstructedConstantExpression constant, | 1898 ConstructedConstantExpression constant, |
1897 _) { | 1899 _) { |
1898 doConstConstructorInvoke(constant); | 1900 doConstConstructorInvoke(constant); |
1899 applyVisitState(); | 1901 applyVisitState(); |
1900 } | 1902 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1965 constructor, | 1967 constructor, |
1966 type, | 1968 type, |
1967 implementation.effectiveTarget, | 1969 implementation.effectiveTarget, |
1968 null, | 1970 null, |
1969 arguments, | 1971 arguments, |
1970 callStructure, | 1972 callStructure, |
1971 null); | 1973 null); |
1972 return; | 1974 return; |
1973 } | 1975 } |
1974 // TODO(ahe): Remove ".declaration" when issue 23135 is fixed. | 1976 // TODO(ahe): Remove ".declaration" when issue 23135 is fixed. |
1975 CompiledFunction compiledFunction = | 1977 FletchFunctionBuilder functionBuilder = |
1976 requireCompiledFunction(constructor.declaration); | 1978 requireFletchFunctionBuilder(constructor.declaration); |
1977 doStaticFunctionInvoke( | 1979 doStaticFunctionInvoke( |
1978 node, compiledFunction, arguments, callStructure, factoryInvoke: true); | 1980 node, functionBuilder, arguments, callStructure, factoryInvoke: true); |
1979 applyVisitState(); | 1981 applyVisitState(); |
1980 } | 1982 } |
1981 | 1983 |
1982 void visitConstructorIncompatibleInvoke( | 1984 void visitConstructorIncompatibleInvoke( |
1983 NewExpression node, | 1985 NewExpression node, |
1984 ConstructorElement constructor, | 1986 ConstructorElement constructor, |
1985 InterfaceType type, | 1987 InterfaceType type, |
1986 NodeList arguments, | 1988 NodeList arguments, |
1987 CallStructure callStructure, | 1989 CallStructure callStructure, |
1988 _) { | 1990 _) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2083 applyVisitState(); | 2085 applyVisitState(); |
2084 } | 2086 } |
2085 | 2087 |
2086 void handleStaticGetterGet(Send node, FunctionElement getter, _) { | 2088 void handleStaticGetterGet(Send node, FunctionElement getter, _) { |
2087 if (getter == context.backend.fletchExternalNativeError) { | 2089 if (getter == context.backend.fletchExternalNativeError) { |
2088 builder.loadSlot(0); | 2090 builder.loadSlot(0); |
2089 return; | 2091 return; |
2090 } | 2092 } |
2091 registerStaticInvocation(getter); | 2093 registerStaticInvocation(getter); |
2092 int methodId = context.backend.functionMethodId(getter); | 2094 int methodId = context.backend.functionMethodId(getter); |
2093 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 2095 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
2094 invokeStatic(node, constId, 0); | 2096 invokeStatic(node, constId, 0); |
2095 applyVisitState(); | 2097 applyVisitState(); |
2096 } | 2098 } |
2097 | 2099 |
2098 void handleStaticSetterSet( | 2100 void handleStaticSetterSet( |
2099 Send node, | 2101 Send node, |
2100 FunctionElement setter, | 2102 FunctionElement setter, |
2101 Node rhs, | 2103 Node rhs, |
2102 _) { | 2104 _) { |
2103 visitForValue(rhs); | 2105 visitForValue(rhs); |
2104 registerStaticInvocation(setter); | 2106 registerStaticInvocation(setter); |
2105 int methodId = context.backend.functionMethodId(setter); | 2107 int methodId = context.backend.functionMethodId(setter); |
2106 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 2108 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
2107 invokeStatic(node, constId, 1); | 2109 invokeStatic(node, constId, 1); |
2108 applyVisitState(); | 2110 applyVisitState(); |
2109 } | 2111 } |
2110 | 2112 |
2111 /** | 2113 /** |
2112 * Load the captured variables of [function], expressed in [info]. | 2114 * Load the captured variables of [function], expressed in [info]. |
2113 * | 2115 * |
2114 * If [function] captures itself, its field index is returned. | 2116 * If [function] captures itself, its field index is returned. |
2115 */ | 2117 */ |
2116 int pushCapturedVariables(FunctionElement function) { | 2118 int pushCapturedVariables(FunctionElement function) { |
(...skipping 20 matching lines...) Expand all Loading... |
2137 return thisClosureIndex; | 2139 return thisClosureIndex; |
2138 } | 2140 } |
2139 | 2141 |
2140 void visitFunctionExpression(FunctionExpression node) { | 2142 void visitFunctionExpression(FunctionExpression node) { |
2141 FunctionElement function = elements[node]; | 2143 FunctionElement function = elements[node]; |
2142 | 2144 |
2143 // If the closure captures itself, thisClosureIndex is the field-index in | 2145 // If the closure captures itself, thisClosureIndex is the field-index in |
2144 // the closure. | 2146 // the closure. |
2145 int thisClosureIndex = pushCapturedVariables(function); | 2147 int thisClosureIndex = pushCapturedVariables(function); |
2146 | 2148 |
2147 CompiledClass compiledClass = context.backend.createClosureClass( | 2149 FletchClassBuilder classBuilder = context.backend.createClosureClass( |
2148 function, | 2150 function, |
2149 closureEnvironment); | 2151 closureEnvironment); |
2150 int classConstant = compiledFunction.allocateConstantFromClass( | 2152 int classConstant = functionBuilder.allocateConstantFromClass( |
2151 compiledClass.id); | 2153 classBuilder.id); |
2152 bool immutable = !closureEnvironment.closures[function].free.any( | 2154 bool immutable = !closureEnvironment.closures[function].free.any( |
2153 closureEnvironment.shouldBeBoxed); | 2155 closureEnvironment.shouldBeBoxed); |
2154 builder.allocate(classConstant, compiledClass.fields, immutable: immutable); | 2156 builder.allocate(classConstant, classBuilder.fields, immutable: immutable); |
2155 | 2157 |
2156 if (thisClosureIndex >= 0) { | 2158 if (thisClosureIndex >= 0) { |
2157 builder.dup(); | 2159 builder.dup(); |
2158 builder.storeField(thisClosureIndex); | 2160 builder.storeField(thisClosureIndex); |
2159 } | 2161 } |
2160 | 2162 |
2161 registerStaticInvocation(function); | 2163 registerStaticInvocation(function); |
2162 applyVisitState(); | 2164 applyVisitState(); |
2163 } | 2165 } |
2164 | 2166 |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2653 } | 2655 } |
2654 | 2656 |
2655 // Pop exception slot. | 2657 // Pop exception slot. |
2656 builder.pop(); | 2658 builder.pop(); |
2657 } | 2659 } |
2658 | 2660 |
2659 void doUnresolved(String name) { | 2661 void doUnresolved(String name) { |
2660 var constString = context.backend.constantSystem.createString( | 2662 var constString = context.backend.constantSystem.createString( |
2661 new DartString.literal(name)); | 2663 new DartString.literal(name)); |
2662 context.markConstantUsed(constString); | 2664 context.markConstantUsed(constString); |
2663 builder.loadConst(compiledFunction.allocateConstant(constString)); | 2665 builder.loadConst(functionBuilder.allocateConstant(constString)); |
2664 FunctionElement function = context.backend.fletchUnresolved; | 2666 FunctionElement function = context.backend.fletchUnresolved; |
2665 registerStaticInvocation(function); | 2667 registerStaticInvocation(function); |
2666 int methodId = context.backend.functionMethodId(function); | 2668 int methodId = context.backend.functionMethodId(function); |
2667 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 2669 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
2668 builder.invokeStatic(constId, 1); | 2670 builder.invokeStatic(constId, 1); |
2669 } | 2671 } |
2670 | 2672 |
2671 bool checkCompileError(Element element) { | 2673 bool checkCompileError(Element element) { |
2672 if (context.compiler.elementsWithCompileTimeErrors.contains(element)) { | 2674 if (context.compiler.elementsWithCompileTimeErrors.contains(element)) { |
2673 doCompileError(); | 2675 doCompileError(); |
2674 return true; | 2676 return true; |
2675 } | 2677 } |
2676 return false; | 2678 return false; |
2677 } | 2679 } |
2678 | 2680 |
2679 void doCompileError() { | 2681 void doCompileError() { |
2680 FunctionElement function = context.backend.fletchCompileError; | 2682 FunctionElement function = context.backend.fletchCompileError; |
2681 registerStaticInvocation(function); | 2683 registerStaticInvocation(function); |
2682 int methodId = context.backend.functionMethodId(function); | 2684 int methodId = context.backend.functionMethodId(function); |
2683 int constId = compiledFunction.allocateConstantFromFunction(methodId); | 2685 int constId = functionBuilder.allocateConstantFromFunction(methodId); |
2684 builder.invokeStatic(constId, 0); | 2686 builder.invokeStatic(constId, 0); |
2685 } | 2687 } |
2686 | 2688 |
2687 void visitUnresolvedInvoke( | 2689 void visitUnresolvedInvoke( |
2688 Send node, | 2690 Send node, |
2689 Element element, | 2691 Element element, |
2690 Node arguments, | 2692 Node arguments, |
2691 Selector selector, | 2693 Selector selector, |
2692 _) { | 2694 _) { |
2693 if (!checkCompileError(element)) { | 2695 if (!checkCompileError(element)) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2726 } | 2728 } |
2727 | 2729 |
2728 void internalError(Spannable spannable, String reason) { | 2730 void internalError(Spannable spannable, String reason) { |
2729 context.compiler.internalError(spannable, reason); | 2731 context.compiler.internalError(spannable, reason); |
2730 } | 2732 } |
2731 | 2733 |
2732 void generateUnimplementedError(Spannable spannable, String reason) { | 2734 void generateUnimplementedError(Spannable spannable, String reason) { |
2733 context.backend.generateUnimplementedError( | 2735 context.backend.generateUnimplementedError( |
2734 spannable, | 2736 spannable, |
2735 reason, | 2737 reason, |
2736 compiledFunction); | 2738 functionBuilder); |
2737 } | 2739 } |
2738 | 2740 |
2739 String toString() => "FunctionCompiler(${element.name})"; | 2741 String toString() => "FunctionCompiler(${element.name})"; |
2740 | 2742 |
2741 void handleFinalStaticFieldSet( | 2743 void handleFinalStaticFieldSet( |
2742 SendSet node, | 2744 SendSet node, |
2743 FieldElement field, | 2745 FieldElement field, |
2744 Node rhs, | 2746 Node rhs, |
2745 _) { | 2747 _) { |
2746 generateUnimplementedError( | 2748 generateUnimplementedError( |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2823 } | 2825 } |
2824 | 2826 |
2825 void applyInitializers(FunctionExpression initializers, _) { | 2827 void applyInitializers(FunctionExpression initializers, _) { |
2826 internalError(node, "[applyInitializers] isn't implemented."); | 2828 internalError(node, "[applyInitializers] isn't implemented."); |
2827 } | 2829 } |
2828 | 2830 |
2829 void applyParameters(NodeList parameters, _) { | 2831 void applyParameters(NodeList parameters, _) { |
2830 internalError(node, "[applyParameters] isn't implemented."); | 2832 internalError(node, "[applyParameters] isn't implemented."); |
2831 } | 2833 } |
2832 } | 2834 } |
OLD | NEW |