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