Chromium Code Reviews| 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, |
| 11 BinaryOperator, | 11 BinaryOperator, |
| 12 IncDecOperator, | 12 IncDecOperator, |
| 13 UnaryOperator; | 13 UnaryOperator; |
| 14 | 14 |
| 15 import 'package:compiler/src/constants/expressions.dart' show | 15 import 'package:compiler/src/constants/expressions.dart' show |
| 16 BoolFromEnvironmentConstantExpression, | 16 BoolFromEnvironmentConstantExpression, |
| 17 IntFromEnvironmentConstantExpression, | 17 IntFromEnvironmentConstantExpression, |
| 18 StringFromEnvironmentConstantExpression, | 18 StringFromEnvironmentConstantExpression, |
| 19 ConstantExpression, | 19 ConstantExpression, |
| 20 ConstructedConstantExpression, | 20 ConstructedConstantExpression, |
| 21 TypeConstantExpression; | 21 TypeConstantExpression; |
| 22 | 22 |
| 23 import 'package:compiler/src/dart2jslib.dart' show | 23 import 'package:compiler/src/resolution/tree_elements.dart' show |
| 24 MessageKind, | 24 TreeElements; |
| 25 Registry; | |
| 26 | 25 |
| 27 import 'package:compiler/src/util/util.dart' show | 26 import 'package:compiler/src/util/util.dart' show |
| 28 Link; | 27 Link; |
| 29 | 28 |
| 29 import 'package:compiler/src/common/names.dart' show | |
| 30 Names, | |
| 31 Selectors; | |
| 32 | |
| 33 import 'package:compiler/src/universe/use.dart' show DynamicUse, StaticUse; | |
| 34 | |
| 30 import 'package:compiler/src/elements/elements.dart'; | 35 import 'package:compiler/src/elements/elements.dart'; |
| 31 import 'package:compiler/src/resolution/resolution.dart'; | |
| 32 import 'package:compiler/src/tree/tree.dart'; | 36 import 'package:compiler/src/tree/tree.dart'; |
| 33 import 'package:compiler/src/universe/universe.dart'; | 37 import 'package:compiler/src/universe/call_structure.dart' show |
| 34 import 'package:compiler/src/util/util.dart' show Spannable; | 38 CallStructure; |
| 39 import 'package:compiler/src/universe/selector.dart' show | |
| 40 Selector; | |
| 41 import 'package:compiler/src/diagnostics/spannable.dart' show | |
| 42 Spannable; | |
| 35 import 'package:compiler/src/dart_types.dart'; | 43 import 'package:compiler/src/dart_types.dart'; |
| 36 | 44 |
| 37 import 'fletch_context.dart'; | 45 import 'fletch_context.dart'; |
| 38 | 46 |
| 39 import 'fletch_backend.dart'; | 47 import 'fletch_backend.dart'; |
| 40 | 48 |
| 41 import 'fletch_constants.dart' show | 49 import 'fletch_constants.dart' show |
| 42 FletchFunctionBuilderConstant, | |
| 43 FletchClassConstant, | 50 FletchClassConstant, |
| 44 FletchClassInstanceConstant; | 51 FletchClassInstanceConstant; |
| 45 | 52 |
| 46 import 'fletch_function_builder.dart' show | 53 import 'fletch_function_builder.dart' show |
| 47 FletchFunctionBuilder; | 54 FletchFunctionBuilder; |
| 48 | 55 |
| 49 import 'fletch_class_builder.dart' show | 56 import 'fletch_class_builder.dart' show |
| 50 FletchClassBuilder; | 57 FletchClassBuilder; |
| 51 | 58 |
| 52 import 'fletch_selector.dart'; | 59 import 'fletch_selector.dart'; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 BinaryBulkMixin, | 210 BinaryBulkMixin, |
| 204 PrefixBulkMixin, | 211 PrefixBulkMixin, |
| 205 PostfixBulkMixin, | 212 PostfixBulkMixin, |
| 206 NewBulkMixin, | 213 NewBulkMixin, |
| 207 VariableBulkMixin, | 214 VariableBulkMixin, |
| 208 ParameterBulkMixin, | 215 ParameterBulkMixin, |
| 209 FunctionBulkMixin, | 216 FunctionBulkMixin, |
| 210 ConstructorBulkMixin, | 217 ConstructorBulkMixin, |
| 211 InitializerBulkMixin, | 218 InitializerBulkMixin, |
| 212 BaseImplementationOfStaticsMixin, | 219 BaseImplementationOfStaticsMixin, |
| 213 BaseImplementationOfLocalsMixin | 220 BaseImplementationOfLocalsMixin, |
| 221 SetIfNullBulkMixin | |
| 214 implements SemanticSendVisitor, SemanticDeclarationVisitor { | 222 implements SemanticSendVisitor, SemanticDeclarationVisitor { |
| 215 // A literal int can have up to 31 bits of information (32 minus sign). | 223 // A literal int can have up to 31 bits of information (32 minus sign). |
| 216 static const int LITERAL_INT_MAX = 0x3FFFFFFF; | 224 static const int LITERAL_INT_MAX = 0x3FFFFFFF; |
| 217 static const int MAX_INT64 = (1 << 63) - 1; | 225 static const int MAX_INT64 = (1 << 63) - 1; |
| 218 static const int MIN_INT64 = -(1 << 63); | 226 static const int MIN_INT64 = -(1 << 63); |
| 219 | 227 |
| 220 final FletchContext context; | 228 final FletchContext context; |
| 221 | 229 |
| 222 final ClosureEnvironment closureEnvironment; | 230 final ClosureEnvironment closureEnvironment; |
| 223 | 231 |
| 224 final ExecutableElement element; | 232 final ExecutableElement element; |
| 225 | 233 |
| 226 final MemberElement member; | |
| 227 | |
| 228 final FletchFunctionBuilder functionBuilder; | 234 final FletchFunctionBuilder functionBuilder; |
| 229 | 235 |
| 230 final Map<Element, LocalValue> scope = <Element, LocalValue>{}; | 236 final Map<Element, LocalValue> scope = <Element, LocalValue>{}; |
| 231 | 237 |
| 232 final Map<Node, JumpInfo> jumpInfo = <Node, JumpInfo>{}; | 238 final Map<Node, JumpInfo> jumpInfo = <Node, JumpInfo>{}; |
| 233 | 239 |
| 234 // Stack of try blocks (inner-most first), in the lexical scope. | 240 // Stack of try blocks (inner-most first), in the lexical scope. |
| 235 Link<TryBlock> tryBlockStack = const Link<TryBlock>(); | 241 Link<TryBlock> tryBlockStack = const Link<TryBlock>(); |
| 236 | 242 |
| 237 VisitState visitState; | 243 VisitState visitState; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 } | 366 } |
| 361 | 367 |
| 362 void pushVariableDeclaration(LocalValue value) { | 368 void pushVariableDeclaration(LocalValue value) { |
| 363 scope[value.element] = value; | 369 scope[value.element] = value; |
| 364 } | 370 } |
| 365 | 371 |
| 366 void popVariableDeclaration(Element local) { | 372 void popVariableDeclaration(Element local) { |
| 367 scope.remove(local); | 373 scope.remove(local); |
| 368 } | 374 } |
| 369 | 375 |
| 370 void registerDynamicInvocation(Selector selector); | 376 void registerDynamicUse(Selector selector); |
| 371 | 377 |
| 372 void registerDynamicGetter(Selector selector); | 378 void registerStaticUse(StaticUse use); |
|
ahe
2015/12/01 10:12:12
StaticUse (like DynamicUse) is problematic to use
sigurdm
2015/12/03 14:48:09
Done.
| |
| 373 | |
| 374 void registerDynamicSetter(Selector selector); | |
| 375 | |
| 376 void registerStaticInvocation(FunctionElement function); | |
| 377 | 379 |
| 378 void registerInstantiatedClass(ClassElement klass); | 380 void registerInstantiatedClass(ClassElement klass); |
| 379 | 381 |
| 380 void registerIsCheck(DartType type); | 382 void registerIsCheck(DartType type); |
| 381 | 383 |
| 382 void registerLocalInvoke(LocalElement element, Selector selector); | 384 void registerLocalInvoke(LocalElement element, Selector selector); |
| 383 | 385 |
| 384 /// Register that [element] is a closure. This can happen for a tear-off, or | 386 /// Register that [element] is a closure. This can happen for a tear-off, or |
| 385 /// for local functions. See [ClosureKind] for more information about the | 387 /// for local functions. See [ClosureKind] for more information about the |
| 386 /// various kinds of implicit or explicit closurizations that can occur. | 388 /// various kinds of implicit or explicit closurizations that can occur. |
| 387 void registerClosurization(FunctionElement element, ClosureKind kind); | 389 void registerClosurization(FunctionElement element, ClosureKind kind); |
| 388 | 390 |
| 389 int compileLazyFieldInitializer(FieldElement field); | 391 int compileLazyFieldInitializer(FieldElement field); |
| 390 | 392 |
| 391 void invokeMethod(Node node, Selector selector) { | 393 void invokeMethod(Node node, Selector selector) { |
| 392 registerDynamicInvocation(selector); | 394 registerDynamicUse(selector); |
| 393 String symbol = context.getSymbolFromSelector(selector); | 395 String symbol = context.getSymbolFromSelector(selector); |
| 394 int id = context.getSymbolId(symbol); | 396 int id = context.getSymbolId(symbol); |
| 395 int arity = selector.argumentCount; | 397 int arity = selector.argumentCount; |
| 396 int fletchSelector = FletchSelector.encodeMethod(id, arity); | 398 int fletchSelector = FletchSelector.encodeMethod(id, arity); |
| 397 assembler.invokeMethod(fletchSelector, arity, selector.name); | 399 assembler.invokeMethod(fletchSelector, arity, selector.name); |
| 398 } | 400 } |
| 399 | 401 |
| 400 void invokeGetter(Node node, Selector selector) { | 402 void invokeGetter(Node node, Name name) { |
| 401 registerDynamicGetter(selector); | 403 registerDynamicUse(new Selector.getter(name)); |
|
ahe
2015/12/01 10:12:12
This shouldn't create new objects.
sigurdm
2015/12/03 14:48:09
Done.
| |
| 402 String symbol = context.getSymbolFromSelector(selector); | 404 String symbol = context.mangleName(name); |
| 403 int id = context.getSymbolId(symbol); | 405 int id = context.getSymbolId(symbol); |
| 404 int fletchSelector = FletchSelector.encodeGetter(id); | 406 int fletchSelector = FletchSelector.encodeGetter(id); |
| 405 assembler.invokeMethod(fletchSelector, 0); | 407 assembler.invokeMethod(fletchSelector, 0); |
| 406 } | 408 } |
| 407 | 409 |
| 408 void invokeSetter(Node node, Selector selector) { | 410 void invokeSetter(Node node, Name name) { |
| 409 registerDynamicSetter(selector); | 411 registerDynamicUse(new Selector.setter(name)); |
|
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
| 410 String symbol = context.getSymbolFromSelector(selector); | 412 String symbol = context.mangleName(name); |
| 411 int id = context.getSymbolId(symbol); | 413 int id = context.getSymbolId(symbol); |
| 412 int fletchSelector = FletchSelector.encodeSetter(id); | 414 int fletchSelector = FletchSelector.encodeSetter(id); |
| 413 assembler.invokeMethod(fletchSelector, 1); | 415 assembler.invokeMethod(fletchSelector, 1); |
| 414 } | 416 } |
| 415 | 417 |
| 416 void invokeFactory(Node node, int constId, int arity) { | 418 void invokeFactory(Node node, int constId, int arity) { |
| 417 assembler.invokeFactory(constId, arity); | 419 assembler.invokeFactory(constId, arity); |
| 418 } | 420 } |
| 419 | 421 |
| 420 void invokeStatic(Node node, int constId, int arity) { | 422 void invokeStatic(Node node, int constId, int arity) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 442 int constId = allocateConstantFromNode(caseMatch.expression); | 444 int constId = allocateConstantFromNode(caseMatch.expression); |
| 443 assembler.loadConst(constId); | 445 assembler.loadConst(constId); |
| 444 // For debugging, ignore the equality checks in connection | 446 // For debugging, ignore the equality checks in connection |
| 445 // with case matches by not associating the calls with | 447 // with case matches by not associating the calls with |
| 446 // any node. | 448 // any node. |
| 447 invokeMethod(null, new Selector.binaryOperator('==')); | 449 invokeMethod(null, new Selector.binaryOperator('==')); |
| 448 assembler.branchIfTrue(ifTrue); | 450 assembler.branchIfTrue(ifTrue); |
| 449 } | 451 } |
| 450 | 452 |
| 451 FletchFunctionBase requireFunction(FunctionElement element) { | 453 FletchFunctionBase requireFunction(FunctionElement element) { |
| 452 registerStaticInvocation(element); | 454 // TODO(johnniwinther): More precise use. |
| 455 registerStaticUse(new StaticUse.foreignUse(element)); | |
|
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
| 453 return context.backend.getFunctionForElement(element); | 456 return context.backend.getFunctionForElement(element); |
| 454 } | 457 } |
| 455 | 458 |
| 456 FletchFunctionBase requireConstructorInitializer( | 459 FletchFunctionBase requireConstructorInitializer( |
| 457 ConstructorElement constructor) { | 460 ConstructorElement constructor) { |
| 458 assert(constructor.isGenerativeConstructor); | 461 assert(constructor.isGenerativeConstructor); |
| 459 registerInstantiatedClass(constructor.enclosingClass); | 462 registerInstantiatedClass(constructor.enclosingClass); |
| 460 registerStaticInvocation(constructor); | 463 registerStaticUse(new StaticUse.foreignUse(constructor)); |
|
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
| 461 return context.backend.getConstructorInitializerFunction(constructor); | 464 return context.backend.getConstructorInitializerFunction(constructor); |
| 462 } | 465 } |
| 463 | 466 |
| 464 void doStaticFunctionInvoke( | 467 void doStaticFunctionInvoke( |
| 465 Node node, | 468 Node node, |
| 466 FletchFunctionBase function, | 469 FletchFunctionBase function, |
| 467 NodeList arguments, | 470 NodeList arguments, |
| 468 CallStructure callStructure, | 471 CallStructure callStructure, |
| 469 {bool factoryInvoke: false}) { | 472 {bool factoryInvoke: false}) { |
| 470 if (function.isInstanceMember) loadThis(); | 473 if (function.isInstanceMember) loadThis(); |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 902 assembler.loadLiteralTrue(); | 905 assembler.loadLiteralTrue(); |
| 903 return; | 906 return; |
| 904 } | 907 } |
| 905 | 908 |
| 906 if (type.isTypedef) { | 909 if (type.isTypedef) { |
| 907 // TODO(ajohnsen): This only matches with the number of arguments, not | 910 // TODO(ajohnsen): This only matches with the number of arguments, not |
| 908 // the actual argument types. | 911 // the actual argument types. |
| 909 TypedefType typedefType = type; | 912 TypedefType typedefType = type; |
| 910 int arity = typedefType.element.functionSignature.parameterCount; | 913 int arity = typedefType.element.functionSignature.parameterCount; |
| 911 int fletchSelector = context.toFletchIsSelector( | 914 int fletchSelector = context.toFletchIsSelector( |
| 912 context.backend.compiler.functionClass, arity); | 915 context.backend.compiler.coreClasses.functionClass, arity); |
| 913 assembler.invokeTest(fletchSelector, 0); | 916 assembler.invokeTest(fletchSelector, 0); |
| 914 return; | 917 return; |
| 915 } | 918 } |
| 916 | 919 |
| 917 if (!type.isInterfaceType) { | 920 if (!type.isInterfaceType) { |
| 918 assembler.pop(); | 921 assembler.pop(); |
| 919 generateUnimplementedError( | 922 generateUnimplementedError( |
| 920 diagnosticLocation, "Unhandled type test for $type."); | 923 diagnosticLocation, "Unhandled type test for $type."); |
| 921 return; | 924 return; |
| 922 } | 925 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 994 FletchClassBuilder classBuilder = | 997 FletchClassBuilder classBuilder = |
| 995 context.backend.createTearoffClass(target); | 998 context.backend.createTearoffClass(target); |
| 996 assert(classBuilder.fields == 0); | 999 assert(classBuilder.fields == 0); |
| 997 int constId = allocateConstantClassInstance(classBuilder.classId); | 1000 int constId = allocateConstantClassInstance(classBuilder.classId); |
| 998 assembler.loadConst(constId); | 1001 assembler.loadConst(constId); |
| 999 applyVisitState(); | 1002 applyVisitState(); |
| 1000 } | 1003 } |
| 1001 | 1004 |
| 1002 void doMainCall(Send node, NodeList arguments) { | 1005 void doMainCall(Send node, NodeList arguments) { |
| 1003 FunctionElement function = context.compiler.mainFunction; | 1006 FunctionElement function = context.compiler.mainFunction; |
| 1004 if (function.isErroneous) { | 1007 if (function.isMalformed) { |
| 1005 doCompileError(); | 1008 doCompileError(); |
| 1006 return; | 1009 return; |
| 1007 } | 1010 } |
| 1008 if (context.compiler.libraryLoader.libraries.any(checkCompileError)) return; | 1011 if (context.compiler.libraryLoader.libraries.any(checkCompileError)) return; |
| 1009 | 1012 |
| 1010 // Load up to 'parameterCount' arguments, padding with nulls. | 1013 // Load up to 'parameterCount' arguments, padding with nulls. |
| 1011 int parameterCount = function.functionSignature.parameterCount; | 1014 int parameterCount = function.functionSignature.parameterCount; |
| 1012 int argumentCount = 0; | 1015 int argumentCount = 0; |
| 1013 for (Node argument in arguments) { | 1016 for (Node argument in arguments) { |
| 1014 if (argumentCount == parameterCount) break; | 1017 if (argumentCount == parameterCount) break; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1068 Send node, | 1071 Send node, |
| 1069 MethodElement element, | 1072 MethodElement element, |
| 1070 NodeList arguments, | 1073 NodeList arguments, |
| 1071 CallStructure callStructure, | 1074 CallStructure callStructure, |
| 1072 _) { | 1075 _) { |
| 1073 doStaticallyBoundInvoke(node, element, arguments, callStructure); | 1076 doStaticallyBoundInvoke(node, element, arguments, callStructure); |
| 1074 applyVisitState(); | 1077 applyVisitState(); |
| 1075 } | 1078 } |
| 1076 | 1079 |
| 1077 void doSuperCall(Node node, FunctionElement function) { | 1080 void doSuperCall(Node node, FunctionElement function) { |
| 1078 registerStaticInvocation(function); | 1081 registerStaticUse(new StaticUse.foreignUse(function)); |
|
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
| 1079 int arity = function.functionSignature.parameterCount + 1; | 1082 int arity = function.functionSignature.parameterCount + 1; |
| 1080 FletchFunctionBase base = requireFunction(function); | 1083 FletchFunctionBase base = requireFunction(function); |
| 1081 int constId = functionBuilder.allocateConstantFromFunction(base.functionId); | 1084 int constId = functionBuilder.allocateConstantFromFunction(base.functionId); |
| 1082 invokeStatic(node, constId, arity); | 1085 invokeStatic(node, constId, arity); |
| 1083 } | 1086 } |
| 1084 | 1087 |
| 1085 void visitSuperGetterGet( | 1088 void visitSuperGetterGet( |
| 1086 Send node, | 1089 Send node, |
| 1087 FunctionElement getter, | 1090 FunctionElement getter, |
| 1088 _) { | 1091 _) { |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1285 invokeMethod(node, callStructure.callSelector); | 1288 invokeMethod(node, callStructure.callSelector); |
| 1286 applyVisitState(); | 1289 applyVisitState(); |
| 1287 } | 1290 } |
| 1288 | 1291 |
| 1289 void visitDynamicPropertyInvoke( | 1292 void visitDynamicPropertyInvoke( |
| 1290 Send node, | 1293 Send node, |
| 1291 Node receiver, | 1294 Node receiver, |
| 1292 NodeList arguments, | 1295 NodeList arguments, |
| 1293 Selector selector, | 1296 Selector selector, |
| 1294 _) { | 1297 _) { |
| 1295 if (selector == null) { | |
| 1296 // TODO(ajohnsen): Remove hack - dart2js has a problem with generating | |
| 1297 // selectors in initializer bodies. | |
| 1298 selector = new Selector.call( | |
| 1299 node.selector.asIdentifier().source, | |
| 1300 element.library, | |
| 1301 arguments.slowLength()); | |
| 1302 } | |
| 1303 visitForValue(receiver); | 1298 visitForValue(receiver); |
| 1304 for (Node argument in arguments) { | 1299 for (Node argument in arguments) { |
| 1305 visitForValue(argument); | 1300 visitForValue(argument); |
| 1306 } | 1301 } |
| 1307 invokeMethod(node, selector); | 1302 invokeMethod(node, selector); |
| 1308 applyVisitState(); | 1303 applyVisitState(); |
| 1309 } | 1304 } |
| 1310 | 1305 |
| 1306 void visitIfNull( | |
| 1307 Send node, | |
| 1308 Node left, | |
| 1309 Node right, | |
| 1310 _) { | |
| 1311 BytecodeLabel end = new BytecodeLabel(); | |
| 1312 visitForValue(left); | |
| 1313 assembler.dup(); | |
| 1314 assembler.loadLiteralNull(); | |
| 1315 assembler.identicalNonNumeric(); | |
| 1316 assembler.branchIfFalse(end); | |
| 1317 assembler.pop(); | |
| 1318 visitForValue(right); | |
| 1319 assembler.bind(end); | |
| 1320 applyVisitState(); | |
| 1321 } | |
| 1322 | |
| 1311 void doIfNotNull(Node receiver, void ifNotNull()) { | 1323 void doIfNotNull(Node receiver, void ifNotNull()) { |
| 1312 BytecodeLabel end = new BytecodeLabel(); | 1324 BytecodeLabel end = new BytecodeLabel(); |
| 1313 visitForValue(receiver); | 1325 visitForValue(receiver); |
| 1314 assembler.dup(); | 1326 assembler.dup(); |
| 1315 assembler.loadLiteralNull(); | 1327 assembler.loadLiteralNull(); |
| 1316 assembler.identicalNonNumeric(); | 1328 assembler.identicalNonNumeric(); |
| 1317 assembler.branchIfTrue(end); | 1329 assembler.branchIfTrue(end); |
| 1318 ifNotNull(); | 1330 ifNotNull(); |
| 1319 assembler.bind(end); | 1331 assembler.bind(end); |
| 1320 } | 1332 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1331 } | 1343 } |
| 1332 invokeMethod(node, selector); | 1344 invokeMethod(node, selector); |
| 1333 }); | 1345 }); |
| 1334 applyVisitState(); | 1346 applyVisitState(); |
| 1335 } | 1347 } |
| 1336 | 1348 |
| 1337 void visitExpressionInvoke( | 1349 void visitExpressionInvoke( |
| 1338 Send node, | 1350 Send node, |
| 1339 Expression receiver, | 1351 Expression receiver, |
| 1340 NodeList arguments, | 1352 NodeList arguments, |
| 1341 Selector selector, | 1353 CallStructure callStructure, |
| 1342 _) { | 1354 _) { |
| 1343 visitForValue(receiver); | 1355 visitForValue(receiver); |
| 1344 for (Node argument in arguments) { | 1356 for (Node argument in arguments) { |
| 1345 visitForValue(argument); | 1357 visitForValue(argument); |
| 1346 } | 1358 } |
| 1347 invokeMethod(node, selector); | 1359 invokeMethod(node, new Selector.call(Names.call, callStructure)); |
| 1348 applyVisitState(); | 1360 applyVisitState(); |
| 1349 } | 1361 } |
| 1350 | 1362 |
| 1351 void visitThisPropertyInvoke( | 1363 void visitThisPropertyInvoke( |
| 1352 Send node, | 1364 Send node, |
| 1353 NodeList arguments, | 1365 NodeList arguments, |
| 1354 Selector selector, | 1366 Selector selector, |
| 1355 _) { | 1367 _) { |
| 1356 loadThis(); | 1368 loadThis(); |
| 1357 | 1369 |
| 1358 // If the property is statically known to be a field, instead invoke the | 1370 // If the property is statically known to be a field, instead invoke the |
| 1359 // getter and then invoke 'call(...)' on the value. | 1371 // getter and then invoke 'call(...)' on the value. |
| 1360 // TODO(ajohnsen): This is a fix that only works when the field is | 1372 // TODO(ajohnsen): This is a fix that only works when the field is |
| 1361 // statically known - that is not always the case. Implement VM support? | 1373 // statically known - that is not always the case. Implement VM support? |
| 1362 Element target = elements[node]; | 1374 Element target = elements[node]; |
| 1363 if (target != null && target.isField) { | 1375 if (target != null && target.isField) { |
| 1364 invokeGetter(node, new Selector.getter(target.name, element.library)); | 1376 invokeGetter(node, new Name(target.name, element.library)); |
| 1365 selector = new Selector.callClosureFrom(selector); | 1377 selector = new Selector.callClosureFrom(selector); |
| 1366 } | 1378 } |
| 1367 for (Node argument in arguments) { | 1379 for (Node argument in arguments) { |
| 1368 visitForValue(argument); | 1380 visitForValue(argument); |
| 1369 } | 1381 } |
| 1370 invokeMethod(node, selector); | 1382 invokeMethod(node, selector); |
| 1371 applyVisitState(); | 1383 applyVisitState(); |
| 1372 } | 1384 } |
| 1373 | 1385 |
| 1374 void visitThisInvoke( | 1386 void visitThisInvoke( |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 1389 ConstantExpression constant, | 1401 ConstantExpression constant, |
| 1390 _) { | 1402 _) { |
| 1391 generateUnimplementedError( | 1403 generateUnimplementedError( |
| 1392 node, "[visitClassTypeLiteralGet] isn't implemented."); | 1404 node, "[visitClassTypeLiteralGet] isn't implemented."); |
| 1393 applyVisitState(); | 1405 applyVisitState(); |
| 1394 } | 1406 } |
| 1395 | 1407 |
| 1396 void visitDynamicPropertyGet( | 1408 void visitDynamicPropertyGet( |
| 1397 Send node, | 1409 Send node, |
| 1398 Node receiver, | 1410 Node receiver, |
| 1399 Selector selector, | 1411 Name name, |
| 1400 _) { | 1412 _) { |
| 1401 if (selector == null) { | 1413 if (name.text == "runtimeType") { |
| 1402 // TODO(ajohnsen): Remove hack - dart2js has a problem with generating | |
| 1403 // selectors in initializer bodies. | |
| 1404 selector = new Selector.getter( | |
| 1405 node.selector.asIdentifier().source, | |
| 1406 element.library); | |
| 1407 } | |
| 1408 if (selector.name == "runtimeType") { | |
| 1409 // TODO(ahe): Implement runtimeType. | 1414 // TODO(ahe): Implement runtimeType. |
| 1410 generateUnimplementedError( | 1415 generateUnimplementedError( |
| 1411 node, | 1416 node, |
| 1412 "'runtimeType' isn't supported in Fletch. See https://goo.gl/ELH6Zc"); | 1417 "'runtimeType' isn't supported in Fletch. See https://goo.gl/ELH6Zc"); |
| 1413 applyVisitState(); | 1418 applyVisitState(); |
| 1414 return; | 1419 return; |
| 1415 } | 1420 } |
| 1416 visitForValue(receiver); | 1421 visitForValue(receiver); |
| 1417 invokeGetter(node, selector); | 1422 invokeGetter(node, name); |
| 1418 applyVisitState(); | 1423 applyVisitState(); |
| 1419 } | 1424 } |
| 1420 | 1425 |
| 1421 void visitIfNotNullDynamicPropertyGet( | 1426 void visitIfNotNullDynamicPropertyGet( |
| 1422 Send node, | 1427 Send node, |
| 1423 Node receiver, | 1428 Node receiver, |
| 1424 Selector selector, | 1429 Name name, |
| 1425 _) { | 1430 _) { |
| 1426 doIfNotNull(receiver, () { | 1431 doIfNotNull(receiver, () { |
| 1427 invokeGetter(node, selector); | 1432 invokeGetter(node, name); |
| 1428 }); | 1433 }); |
| 1429 applyVisitState(); | 1434 applyVisitState(); |
| 1430 } | 1435 } |
| 1431 | 1436 |
| 1432 void visitThisPropertyGet( | 1437 void visitThisPropertyGet( |
| 1433 Send node, | 1438 Send node, |
| 1434 Selector selector, | 1439 Name name, |
| 1435 _) { | 1440 _) { |
| 1436 loadThis(); | 1441 loadThis(); |
| 1437 invokeGetter(node, selector); | 1442 invokeGetter(node, name); |
| 1438 applyVisitState(); | 1443 applyVisitState(); |
| 1439 } | 1444 } |
| 1440 | 1445 |
| 1441 void visitThisPropertySet( | 1446 void visitThisPropertySet( |
| 1442 Send node, | 1447 Send node, |
| 1443 Selector selector, | 1448 Name name, |
| 1444 Node rhs, | 1449 Node rhs, |
| 1445 _) { | 1450 _) { |
| 1446 loadThis(); | 1451 loadThis(); |
| 1447 visitForValue(rhs); | 1452 visitForValue(rhs); |
| 1448 invokeSetter(node, selector); | 1453 invokeSetter(node, name); |
| 1449 applyVisitState(); | 1454 applyVisitState(); |
| 1450 } | 1455 } |
| 1451 | 1456 |
| 1452 void doStaticFieldGet(FieldElement field) { | 1457 void doStaticFieldGet(FieldElement field) { |
| 1453 if (checkCompileError(field)) return; | 1458 if (checkCompileError(field)) return; |
| 1454 if (field.isConst) { | 1459 if (field.isConst) { |
| 1455 int constId = allocateConstantFromNode( | 1460 int constId = allocateConstantFromNode( |
| 1456 field.initializer, | 1461 field.initializer, |
| 1457 elements: field.resolvedAst.elements); | 1462 elements: field.resolvedAst.elements); |
| 1458 assembler.loadConst(constId); | 1463 assembler.loadConst(constId); |
| 1459 } else { | 1464 } else { |
| 1460 int index = compileLazyFieldInitializer(field); | 1465 int index = compileLazyFieldInitializer(field); |
| 1461 if (field.initializer != null) { | 1466 if (field.initializer != null) { |
| 1462 assembler.loadStaticInit(index); | 1467 assembler.loadStaticInit(index); |
| 1463 } else { | 1468 } else { |
| 1464 assembler.loadStatic(index); | 1469 assembler.loadStatic(index); |
| 1465 } | 1470 } |
| 1466 } | 1471 } |
| 1467 } | 1472 } |
| 1468 | 1473 |
| 1469 void handleStaticFieldGet( | 1474 void handleStaticFieldGet( |
| 1470 Send node, | 1475 Send node, |
| 1471 FieldElement field, | 1476 FieldElement field, |
| 1472 _) { | 1477 _) { |
| 1473 doStaticFieldGet(field); | 1478 doStaticFieldGet(field); |
| 1474 applyVisitState(); | 1479 applyVisitState(); |
| 1475 } | 1480 } |
| 1476 | 1481 |
| 1477 void visitAssert(Send node, Node expression, _) { | 1482 void visitAssert(Assert node) { |
| 1478 // TODO(ajohnsen): Emit assert in checked mode. | 1483 // TODO(ajohnsen): Emit assert in checked mode. |
| 1479 } | 1484 } |
| 1480 | 1485 |
| 1481 void visitDynamicPropertySet( | 1486 void visitDynamicPropertySet( |
| 1482 Send node, | 1487 Send node, |
| 1483 Node receiver, | 1488 Node receiver, |
| 1484 Selector selector, | 1489 Name name, |
| 1485 Node rhs, | 1490 Node rhs, |
| 1486 _) { | 1491 _) { |
| 1487 visitForValue(receiver); | 1492 visitForValue(receiver); |
| 1488 visitForValue(rhs); | 1493 visitForValue(rhs); |
| 1489 invokeSetter(node, selector); | 1494 invokeSetter(node, name); |
| 1490 applyVisitState(); | 1495 applyVisitState(); |
| 1491 } | 1496 } |
| 1492 | 1497 |
| 1493 void visitIfNotNullDynamicPropertySet( | 1498 void visitIfNotNullDynamicPropertySet( |
| 1494 SendSet node, | 1499 SendSet node, |
| 1495 Node receiver, | 1500 Node receiver, |
| 1496 Selector selector, | 1501 Name name, |
| 1497 Node rhs, | 1502 Node rhs, |
| 1498 _) { | 1503 _) { |
| 1499 doIfNotNull(receiver, () { | 1504 doIfNotNull(receiver, () { |
| 1500 visitForValue(rhs); | 1505 visitForValue(rhs); |
| 1501 invokeSetter(node, selector); | 1506 invokeSetter(node, name); |
| 1502 }); | 1507 }); |
| 1503 applyVisitState(); | 1508 applyVisitState(); |
| 1504 } | 1509 } |
| 1505 | 1510 |
| 1506 void doStaticFieldSet(FieldElement field) { | 1511 void doStaticFieldSet( |
|
ahe
2015/12/01 10:12:12
Why this change?
sigurdm
2015/12/03 14:48:09
Not sure - reverted.
| |
| 1512 FieldElement field) { | |
| 1507 int index = context.getStaticFieldIndex(field, element); | 1513 int index = context.getStaticFieldIndex(field, element); |
| 1508 assembler.storeStatic(index); | 1514 assembler.storeStatic(index); |
| 1509 } | 1515 } |
| 1510 | 1516 |
| 1511 void handleStaticFieldSet( | 1517 void handleStaticFieldSet( |
| 1512 SendSet node, | 1518 SendSet node, |
| 1513 FieldElement field, | 1519 FieldElement field, |
| 1514 Node rhs, | 1520 Node rhs, |
| 1515 _) { | 1521 _) { |
| 1516 visitForValue(rhs); | 1522 visitForValue(rhs); |
| 1517 doStaticFieldSet(field); | 1523 doStaticFieldSet(field); |
| 1518 applyVisitState(); | 1524 applyVisitState(); |
| 1519 } | 1525 } |
| 1520 | 1526 |
| 1521 void visitStringJuxtaposition(StringJuxtaposition node) { | 1527 void visitStringJuxtaposition(StringJuxtaposition node) { |
| 1522 // TODO(ajohnsen): This could probably be optimized to string constants in | 1528 // TODO(ajohnsen): This could probably be optimized to string constants in |
| 1523 // some cases. | 1529 // some cases. |
| 1524 visitForValue(node.first); | 1530 visitForValue(node.first); |
| 1525 visitForValue(node.second); | 1531 visitForValue(node.second); |
| 1526 // TODO(ajohnsen): Cache these in context/backend. | 1532 // TODO(ajohnsen): Cache these in context/backend. |
| 1527 Selector concat = new Selector.binaryOperator('+'); | 1533 Selector concat = new Selector.binaryOperator('+'); |
| 1528 invokeMethod(node, concat); | 1534 invokeMethod(node, concat); |
| 1529 applyVisitState(); | 1535 applyVisitState(); |
| 1530 } | 1536 } |
| 1531 | 1537 |
| 1532 void visitStringInterpolation(StringInterpolation node) { | 1538 void visitStringInterpolation(StringInterpolation node) { |
| 1533 // TODO(ajohnsen): Cache these in context/backend. | 1539 // TODO(ajohnsen): Cache this in context/backend. |
| 1534 Selector toString = new Selector.call('toString', null, 0); | |
| 1535 Selector concat = new Selector.binaryOperator('+'); | 1540 Selector concat = new Selector.binaryOperator('+'); |
| 1536 visitForValueNoDebugInfo(node.string); | 1541 visitForValueNoDebugInfo(node.string); |
| 1537 for (StringInterpolationPart part in node.parts) { | 1542 for (StringInterpolationPart part in node.parts) { |
| 1538 visitForValue(part.expression); | 1543 visitForValue(part.expression); |
| 1539 invokeMethod(part.expression, toString); | 1544 invokeMethod(part.expression, Selectors.toString_); |
| 1540 LiteralString string = part.string; | 1545 LiteralString string = part.string; |
| 1541 if (string.dartString.isNotEmpty) { | 1546 if (string.dartString.isNotEmpty) { |
| 1542 visitForValueNoDebugInfo(string); | 1547 visitForValueNoDebugInfo(string); |
| 1543 invokeMethod(null, concat); | 1548 invokeMethod(null, concat); |
| 1544 } | 1549 } |
| 1545 invokeMethod(null, concat); | 1550 invokeMethod(null, concat); |
| 1546 } | 1551 } |
| 1547 applyVisitState(); | 1552 applyVisitState(); |
| 1548 } | 1553 } |
| 1549 | 1554 |
| 1550 void visitLiteralNull(LiteralNull node) { | 1555 void visitLiteralNull(LiteralNull node) { |
| 1551 if (visitState == VisitState.Value) { | 1556 if (visitState == VisitState.Value) { |
| 1552 assembler.loadLiteralNull(); | 1557 assembler.loadLiteralNull(); |
| 1553 } else if (visitState == VisitState.Test) { | 1558 } else if (visitState == VisitState.Test) { |
| 1554 assembler.branch(falseLabel); | 1559 if (falseLabel != null) assembler.branch(falseLabel); |
| 1555 } | 1560 } |
| 1556 } | 1561 } |
| 1557 | 1562 |
| 1558 void visitLiteralSymbol(LiteralSymbol node) { | 1563 void visitLiteralSymbol(LiteralSymbol node) { |
| 1559 int constId = allocateConstantFromNode(node); | 1564 int constId = allocateConstantFromNode(node); |
| 1560 assembler.loadConst(constId); | 1565 assembler.loadConst(constId); |
| 1561 applyVisitState(); | 1566 applyVisitState(); |
| 1562 } | 1567 } |
| 1563 | 1568 |
| 1564 void visitLiteralBool(LiteralBool node) { | 1569 void visitLiteralBool(LiteralBool node) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1591 node, | 1596 node, |
| 1592 'Program compiled without support for big integers'); | 1597 'Program compiled without support for big integers'); |
| 1593 } else { | 1598 } else { |
| 1594 int constId = allocateConstantFromNode(node); | 1599 int constId = allocateConstantFromNode(node); |
| 1595 assembler.loadConst(constId); | 1600 assembler.loadConst(constId); |
| 1596 } | 1601 } |
| 1597 } else { | 1602 } else { |
| 1598 assembler.loadLiteral(value); | 1603 assembler.loadLiteral(value); |
| 1599 } | 1604 } |
| 1600 } else if (visitState == VisitState.Test) { | 1605 } else if (visitState == VisitState.Test) { |
| 1601 assembler.branch(falseLabel); | 1606 if (falseLabel != null) assembler.branch(falseLabel); |
| 1602 } | 1607 } |
| 1603 } | 1608 } |
| 1604 | 1609 |
| 1605 void visitLiteral(Literal node) { | 1610 void visitLiteral(Literal node) { |
| 1606 if (visitState == VisitState.Value) { | 1611 if (visitState == VisitState.Value) { |
| 1607 assembler.loadConst(allocateConstantFromNode(node)); | 1612 assembler.loadConst(allocateConstantFromNode(node)); |
| 1608 } else if (visitState == VisitState.Test) { | 1613 } else if (visitState == VisitState.Test) { |
| 1609 assembler.branch(falseLabel); | 1614 if (falseLabel != null) assembler.branch(falseLabel); |
| 1610 } | 1615 } |
| 1611 } | 1616 } |
| 1612 | 1617 |
| 1613 void visitLiteralList(LiteralList node) { | 1618 void visitLiteralList(LiteralList node) { |
| 1614 if (node.isConst) { | 1619 if (node.isConst) { |
| 1615 int constId = allocateConstantFromNode(node); | 1620 int constId = allocateConstantFromNode(node); |
| 1616 assembler.loadConst(constId); | 1621 assembler.loadConst(constId); |
| 1617 applyVisitState(); | 1622 applyVisitState(); |
| 1618 return; | 1623 return; |
| 1619 } | 1624 } |
| 1620 ClassElement literalClass = context.backend.growableListClass; | 1625 ClassElement literalClass = context.backend.growableListClass; |
| 1621 ConstructorElement constructor = literalClass.lookupDefaultConstructor(); | 1626 ConstructorElement constructor = literalClass.lookupDefaultConstructor(); |
| 1622 if (constructor == null) { | 1627 if (constructor == null) { |
| 1623 internalError(node, "Failed to lookup default list constructor"); | 1628 internalError(node, "Failed to lookup default list constructor"); |
| 1624 } | 1629 } |
| 1625 // Call with empty arguments, as we call the default constructor. | 1630 // Call with empty arguments, as we call the default constructor. |
| 1626 callConstructor( | 1631 callConstructor( |
| 1627 node, constructor, new NodeList.empty(), CallStructure.NO_ARGS); | 1632 node, constructor, new NodeList.empty(), CallStructure.NO_ARGS); |
| 1628 Selector add = new Selector.call('add', null, 1); | 1633 Selector add = new Selector.call(new Name('add', null), |
| 1634 CallStructure.ONE_ARG); | |
| 1629 for (Node element in node.elements) { | 1635 for (Node element in node.elements) { |
| 1630 assembler.dup(); | 1636 assembler.dup(); |
| 1631 visitForValue(element); | 1637 visitForValue(element); |
| 1632 invokeMethod(node, add); | 1638 invokeMethod(node, add); |
| 1633 assembler.pop(); | 1639 assembler.pop(); |
| 1634 } | 1640 } |
| 1635 applyVisitState(); | 1641 applyVisitState(); |
| 1636 } | 1642 } |
| 1637 | 1643 |
| 1638 void visitLiteralMap(LiteralMap node) { | 1644 void visitLiteralMap(LiteralMap node) { |
| 1639 if (node.isConst) { | 1645 if (node.isConst) { |
| 1640 int constId = allocateConstantFromNode(node); | 1646 int constId = allocateConstantFromNode(node); |
| 1641 assembler.loadConst(constId); | 1647 assembler.loadConst(constId); |
| 1642 applyVisitState(); | 1648 applyVisitState(); |
| 1643 return; | 1649 return; |
| 1644 } | 1650 } |
| 1645 ClassElement literalClass = context.backend.mapImplementation; | 1651 ClassElement literalClass = |
| 1646 ConstructorElement constructor = literalClass.lookupDefaultConstructor(); | 1652 context.backend.mapImplementation.implementation; |
| 1653 ConstructorElement constructor = literalClass.lookupConstructor(""); | |
| 1647 if (constructor == null) { | 1654 if (constructor == null) { |
| 1648 internalError(literalClass, "Failed to lookup default map constructor"); | 1655 internalError(literalClass, "Failed to lookup default map constructor"); |
| 1649 return; | 1656 return; |
| 1650 } | 1657 } |
| 1651 // The default constructor is a redirecting factory constructor. Follow it. | 1658 // The default constructor is a redirecting factory constructor. Follow it. |
| 1652 constructor = constructor.effectiveTarget; | 1659 constructor = constructor.effectiveTarget; |
| 1653 FletchFunctionBase function = requireFunction(constructor.declaration); | 1660 FletchFunctionBase function = requireFunction(constructor.declaration); |
| 1654 doStaticFunctionInvoke( | 1661 doStaticFunctionInvoke( |
| 1655 node, | 1662 node, |
| 1656 function, | 1663 function, |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1881 Send node, | 1888 Send node, |
| 1882 FieldElement field, | 1889 FieldElement field, |
| 1883 IncDecOperator operator, | 1890 IncDecOperator operator, |
| 1884 _) { | 1891 _) { |
| 1885 doStaticFieldPrefix(node, field, operator); | 1892 doStaticFieldPrefix(node, field, operator); |
| 1886 applyVisitState(); | 1893 applyVisitState(); |
| 1887 } | 1894 } |
| 1888 | 1895 |
| 1889 void doDynamicPropertyCompound( | 1896 void doDynamicPropertyCompound( |
| 1890 Node node, | 1897 Node node, |
| 1898 Name name, | |
| 1891 AssignmentOperator operator, | 1899 AssignmentOperator operator, |
| 1892 Node rhs, | 1900 Node rhs) { |
| 1893 Selector getterSelector, | |
| 1894 Selector setterSelector) { | |
| 1895 // Dup receiver for setter. | 1901 // Dup receiver for setter. |
| 1896 assembler.dup(); | 1902 assembler.dup(); |
| 1897 invokeGetter(node, getterSelector); | 1903 invokeGetter(node, name); |
| 1898 visitForValue(rhs); | 1904 visitForValue(rhs); |
| 1899 invokeMethod(node, getAssignmentSelector(operator)); | 1905 invokeMethod(node, getAssignmentSelector(operator)); |
| 1900 invokeSetter(node, setterSelector); | 1906 invokeSetter(node, name); |
| 1901 } | 1907 } |
| 1902 | 1908 |
| 1903 void visitDynamicPropertyCompound( | 1909 void visitDynamicPropertyCompound( |
| 1904 Send node, | 1910 Send node, |
| 1905 Node receiver, | 1911 Node receiver, |
| 1912 Name name, | |
| 1906 AssignmentOperator operator, | 1913 AssignmentOperator operator, |
| 1907 Node rhs, | 1914 Node rhs, |
| 1908 Selector getterSelector, | |
| 1909 Selector setterSelector, | |
| 1910 _) { | 1915 _) { |
| 1911 visitForValue(receiver); | 1916 visitForValue(receiver); |
| 1912 doDynamicPropertyCompound( | 1917 doDynamicPropertyCompound( |
| 1913 node, | 1918 node, |
| 1919 name, | |
| 1914 operator, | 1920 operator, |
| 1915 rhs, | 1921 rhs); |
| 1916 getterSelector, | |
| 1917 setterSelector); | |
| 1918 applyVisitState(); | 1922 applyVisitState(); |
| 1919 } | 1923 } |
| 1920 | 1924 |
| 1921 void visitIfNotNullDynamicPropertyCompound( | 1925 void visitIfNotNullDynamicPropertyCompound( |
| 1922 Send node, | 1926 Send node, |
| 1923 Node receiver, | 1927 Node receiver, |
| 1928 Name name, | |
| 1924 AssignmentOperator operator, | 1929 AssignmentOperator operator, |
| 1925 Node rhs, | 1930 Node rhs, |
| 1926 Selector getterSelector, | |
| 1927 Selector setterSelector, | |
| 1928 _) { | 1931 _) { |
| 1929 doIfNotNull(receiver, () { | 1932 doIfNotNull(receiver, () { |
| 1930 doDynamicPropertyCompound( | 1933 doDynamicPropertyCompound( |
| 1931 node, | 1934 node, |
| 1935 name, | |
| 1932 operator, | 1936 operator, |
| 1933 rhs, | 1937 rhs); |
| 1934 getterSelector, | |
| 1935 setterSelector); | |
| 1936 }); | 1938 }); |
| 1937 applyVisitState(); | 1939 applyVisitState(); |
| 1938 } | 1940 } |
| 1939 | 1941 |
| 1940 void visitThisPropertyCompound( | 1942 void visitThisPropertyCompound( |
| 1941 Send node, | 1943 Send node, |
| 1944 Name name, | |
| 1942 AssignmentOperator operator, | 1945 AssignmentOperator operator, |
| 1943 Node rhs, | 1946 Node rhs, |
| 1944 Selector getterSelector, | |
| 1945 Selector setterSelector, | |
| 1946 _) { | 1947 _) { |
| 1947 loadThis(); | 1948 loadThis(); |
| 1948 doDynamicPropertyCompound( | 1949 doDynamicPropertyCompound( |
| 1949 node, | 1950 node, |
| 1951 name, | |
| 1950 operator, | 1952 operator, |
| 1951 rhs, | 1953 rhs); |
| 1952 getterSelector, | |
| 1953 setterSelector); | |
| 1954 applyVisitState(); | 1954 applyVisitState(); |
| 1955 } | 1955 } |
| 1956 | 1956 |
| 1957 void doDynamicPrefix( | 1957 void doDynamicPrefix( |
| 1958 Node node, | 1958 Node node, |
| 1959 IncDecOperator operator, | 1959 Name name, |
| 1960 Selector getterSelector, | 1960 IncDecOperator operator) { |
| 1961 Selector setterSelector) { | |
| 1962 assembler.dup(); | 1961 assembler.dup(); |
| 1963 invokeGetter(node, getterSelector); | 1962 invokeGetter(node, name); |
| 1964 assembler.loadLiteral(1); | 1963 assembler.loadLiteral(1); |
| 1965 invokeMethod(node, getIncDecSelector(operator)); | 1964 invokeMethod(node, getIncDecSelector(operator)); |
| 1966 invokeSetter(node, setterSelector); | 1965 invokeSetter(node, name); |
| 1967 } | 1966 } |
| 1968 | 1967 |
| 1969 void doIndexPrefix( | 1968 void doIndexPrefix( |
| 1970 SendSet node, | 1969 SendSet node, |
| 1971 Node receiver, | 1970 Node receiver, |
| 1972 Node index, | 1971 Node index, |
| 1973 IncDecOperator operator) { | 1972 IncDecOperator operator) { |
| 1974 visitForValue(receiver); | 1973 visitForValue(receiver); |
| 1975 visitForValue(index); | 1974 visitForValue(index); |
| 1976 // Load already evaluated receiver and index for '[]' call. | 1975 // Load already evaluated receiver and index for '[]' call. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2037 invokeMethod(node, new Selector.index()); | 2036 invokeMethod(node, new Selector.index()); |
| 2038 visitForValue(rhs); | 2037 visitForValue(rhs); |
| 2039 invokeMethod(node, getAssignmentSelector(operator)); | 2038 invokeMethod(node, getAssignmentSelector(operator)); |
| 2040 // Use existing evaluated receiver and index for '[]=' call. | 2039 // Use existing evaluated receiver and index for '[]=' call. |
| 2041 invokeMethod(node, new Selector.indexSet()); | 2040 invokeMethod(node, new Selector.indexSet()); |
| 2042 applyVisitState(); | 2041 applyVisitState(); |
| 2043 } | 2042 } |
| 2044 | 2043 |
| 2045 void visitThisPropertyPrefix( | 2044 void visitThisPropertyPrefix( |
| 2046 Send node, | 2045 Send node, |
| 2046 Name name, | |
| 2047 IncDecOperator operator, | 2047 IncDecOperator operator, |
| 2048 Selector getterSelector, | |
| 2049 Selector setterSelector, | |
| 2050 _) { | 2048 _) { |
| 2051 loadThis(); | 2049 loadThis(); |
| 2052 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2050 doDynamicPrefix(node, name, operator); |
| 2053 applyVisitState(); | 2051 applyVisitState(); |
| 2054 } | 2052 } |
| 2055 | 2053 |
| 2056 void visitThisPropertyPostfix( | 2054 void visitThisPropertyPostfix( |
| 2057 Send node, | 2055 Send node, |
| 2056 Name name, | |
| 2058 IncDecOperator operator, | 2057 IncDecOperator operator, |
| 2059 Selector getterSelector, | |
| 2060 Selector setterSelector, | |
| 2061 _) { | 2058 _) { |
| 2062 // If visitState is for effect, we can ignore the return value, thus always | 2059 // If visitState is for effect, we can ignore the return value, thus always |
| 2063 // generate code for the simpler 'prefix' case. | 2060 // generate code for the simpler 'prefix' case. |
| 2064 if (visitState == VisitState.Effect) { | 2061 if (visitState == VisitState.Effect) { |
| 2065 loadThis(); | 2062 loadThis(); |
| 2066 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2063 doDynamicPrefix(node, name, operator); |
| 2067 applyVisitState(); | 2064 applyVisitState(); |
| 2068 return; | 2065 return; |
| 2069 } | 2066 } |
| 2070 | 2067 |
| 2071 loadThis(); | 2068 loadThis(); |
| 2072 invokeGetter(node, getterSelector); | 2069 invokeGetter(node, name); |
| 2073 // For postfix, keep local, unmodified version, to 'return' after store. | 2070 // For postfix, keep local, unmodified version, to 'return' after store. |
| 2074 assembler.dup(); | 2071 assembler.dup(); |
| 2075 assembler.loadLiteral(1); | 2072 assembler.loadLiteral(1); |
| 2076 invokeMethod(node, getIncDecSelector(operator)); | 2073 invokeMethod(node, getIncDecSelector(operator)); |
| 2077 loadThis(); | 2074 loadThis(); |
| 2078 assembler.loadLocal(1); | 2075 assembler.loadLocal(1); |
| 2079 invokeSetter(node, setterSelector); | 2076 invokeSetter(node, name); |
| 2080 assembler.popMany(2); | 2077 assembler.popMany(2); |
| 2081 applyVisitState(); | 2078 applyVisitState(); |
| 2082 } | 2079 } |
| 2083 | 2080 |
| 2084 void visitDynamicPropertyPrefix( | 2081 void visitDynamicPropertyPrefix( |
| 2085 Send node, | 2082 Send node, |
| 2086 Node receiver, | 2083 Node receiver, |
| 2084 Name name, | |
| 2087 IncDecOperator operator, | 2085 IncDecOperator operator, |
| 2088 Selector getterSelector, | |
| 2089 Selector setterSelector, | |
| 2090 _) { | 2086 _) { |
| 2091 visitForValue(receiver); | 2087 visitForValue(receiver); |
| 2092 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2088 doDynamicPrefix(node, name, operator); |
| 2093 applyVisitState(); | 2089 applyVisitState(); |
| 2094 } | 2090 } |
| 2095 | 2091 |
| 2096 void visitIfNotNullDynamicPropertyPrefix( | 2092 void visitIfNotNullDynamicPropertyPrefix( |
| 2097 Send node, | 2093 Send node, |
| 2098 Node receiver, | 2094 Node receiver, |
| 2095 Name name, | |
| 2099 IncDecOperator operator, | 2096 IncDecOperator operator, |
| 2100 Selector getterSelector, | |
| 2101 Selector setterSelector, | |
| 2102 _) { | 2097 _) { |
| 2103 doIfNotNull(receiver, () { | 2098 doIfNotNull(receiver, () { |
| 2104 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2099 doDynamicPrefix(node, name, operator); |
| 2105 }); | 2100 }); |
| 2106 applyVisitState(); | 2101 applyVisitState(); |
| 2107 } | 2102 } |
| 2108 | 2103 |
| 2109 void doDynamicPostfix( | 2104 void doDynamicPostfix( |
| 2110 Send node, | 2105 Send node, |
| 2111 Node receiver, | 2106 Node receiver, |
| 2112 IncDecOperator operator, | 2107 Name name, |
| 2113 Selector getterSelector, | 2108 IncDecOperator operator) { |
| 2114 Selector setterSelector) { | |
| 2115 int receiverSlot = assembler.stackSize - 1; | 2109 int receiverSlot = assembler.stackSize - 1; |
| 2116 assembler.loadSlot(receiverSlot); | 2110 assembler.loadSlot(receiverSlot); |
| 2117 invokeGetter(node, getterSelector); | 2111 invokeGetter(node, name); |
| 2118 // For postfix, keep local, unmodified version, to 'return' after store. | 2112 // For postfix, keep local, unmodified version, to 'return' after store. |
| 2119 assembler.dup(); | 2113 assembler.dup(); |
| 2120 assembler.loadLiteral(1); | 2114 assembler.loadLiteral(1); |
| 2121 invokeMethod(node, getIncDecSelector(operator)); | 2115 invokeMethod(node, getIncDecSelector(operator)); |
| 2122 assembler.loadSlot(receiverSlot); | 2116 assembler.loadSlot(receiverSlot); |
| 2123 assembler.loadLocal(1); | 2117 assembler.loadLocal(1); |
| 2124 invokeSetter(node, setterSelector); | 2118 invokeSetter(node, name); |
| 2125 assembler.popMany(2); | 2119 assembler.popMany(2); |
| 2126 assembler.storeLocal(1); | 2120 assembler.storeLocal(1); |
| 2127 // Pop receiver. | 2121 // Pop receiver. |
| 2128 assembler.pop(); | 2122 assembler.pop(); |
| 2129 } | 2123 } |
| 2130 | 2124 |
| 2131 void visitDynamicPropertyPostfix( | 2125 void visitDynamicPropertyPostfix( |
| 2132 Send node, | 2126 Send node, |
| 2133 Node receiver, | 2127 Node receiver, |
| 2128 Name name, | |
| 2134 IncDecOperator operator, | 2129 IncDecOperator operator, |
| 2135 Selector getterSelector, | |
| 2136 Selector setterSelector, | |
| 2137 _) { | 2130 _) { |
| 2138 // If visitState is for effect, we can ignore the return value, thus always | 2131 // If visitState is for effect, we can ignore the return value, thus always |
| 2139 // generate code for the simpler 'prefix' case. | 2132 // generate code for the simpler 'prefix' case. |
| 2140 if (visitState == VisitState.Effect) { | 2133 if (visitState == VisitState.Effect) { |
| 2141 visitForValue(receiver); | 2134 visitForValue(receiver); |
| 2142 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2135 doDynamicPrefix(node, name, operator); |
| 2143 applyVisitState(); | 2136 applyVisitState(); |
| 2144 return; | 2137 return; |
| 2145 } | 2138 } |
| 2146 | 2139 |
| 2147 visitForValue(receiver); | 2140 visitForValue(receiver); |
| 2148 doDynamicPostfix(node, receiver, operator, getterSelector, setterSelector); | 2141 doDynamicPostfix(node, receiver, name, operator); |
| 2149 applyVisitState(); | 2142 applyVisitState(); |
| 2150 } | 2143 } |
| 2151 | 2144 |
| 2152 void visitIfNotNullDynamicPropertyPostfix( | 2145 void visitIfNotNullDynamicPropertyPostfix( |
| 2153 Send node, | 2146 Send node, |
| 2154 Node receiver, | 2147 Node receiver, |
| 2148 Name name, | |
| 2155 IncDecOperator operator, | 2149 IncDecOperator operator, |
| 2156 Selector getterSelector, | |
| 2157 Selector setterSelector, | |
| 2158 _) { | 2150 _) { |
| 2159 doIfNotNull(receiver, () { | 2151 doIfNotNull(receiver, () { |
| 2160 doDynamicPostfix( | 2152 doDynamicPostfix( |
| 2161 node,receiver, operator, getterSelector, setterSelector); | 2153 node, receiver, name, operator); |
| 2162 }); | 2154 }); |
| 2163 applyVisitState(); | 2155 applyVisitState(); |
| 2164 } | 2156 } |
| 2165 | 2157 |
| 2166 void visitThrow(Throw node) { | 2158 void visitThrow(Throw node) { |
| 2167 visitForValue(node.expression); | 2159 visitForValue(node.expression); |
| 2168 assembler.emitThrow(); | 2160 assembler.emitThrow(); |
| 2169 // TODO(ahe): It seems suboptimal that each throw is followed by a pop. | 2161 // TODO(ahe): It seems suboptimal that each throw is followed by a pop. |
| 2170 applyVisitState(); | 2162 applyVisitState(); |
| 2171 } | 2163 } |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2747 void visitSyncForIn(SyncForIn node) { | 2739 void visitSyncForIn(SyncForIn node) { |
| 2748 visitForIn(node); | 2740 visitForIn(node); |
| 2749 } | 2741 } |
| 2750 | 2742 |
| 2751 void visitForIn(ForIn node) { | 2743 void visitForIn(ForIn node) { |
| 2752 BytecodeLabel start = new BytecodeLabel(); | 2744 BytecodeLabel start = new BytecodeLabel(); |
| 2753 BytecodeLabel end = new BytecodeLabel(); | 2745 BytecodeLabel end = new BytecodeLabel(); |
| 2754 | 2746 |
| 2755 // Evalutate expression and iterator. | 2747 // Evalutate expression and iterator. |
| 2756 visitForValue(node.expression); | 2748 visitForValue(node.expression); |
| 2757 invokeGetter(node.expression, new Selector.getter('iterator', null)); | 2749 invokeGetter(node.expression, Names.iterator); |
| 2758 | 2750 |
| 2759 jumpInfo[node] = new JumpInfo(assembler.stackSize, start, end); | 2751 jumpInfo[node] = new JumpInfo(assembler.stackSize, start, end); |
| 2760 | 2752 |
| 2761 assembler.bind(start); | 2753 assembler.bind(start); |
| 2762 | 2754 |
| 2763 assembler.dup(); | 2755 assembler.dup(); |
| 2764 invokeMethod(node, new Selector.call('moveNext', null, 0)); | 2756 invokeMethod(node, Selectors.moveNext); |
| 2765 assembler.branchIfFalse(end); | 2757 assembler.branchIfFalse(end); |
| 2766 | 2758 |
| 2767 bool isVariableDeclaration = node.declaredIdentifier.asSend() == null; | 2759 bool isVariableDeclaration = node.declaredIdentifier.asSend() == null; |
| 2768 Element element = elements[node]; | 2760 Element element = elements[node]; |
| 2769 if (isVariableDeclaration) { | 2761 if (isVariableDeclaration) { |
| 2770 // Create local value and load the current element to it. | 2762 // Create local value and load the current element to it. |
| 2771 LocalValue value = createLocalValueFor(element); | 2763 LocalValue value = createLocalValueFor(element); |
| 2772 assembler.dup(); | 2764 assembler.dup(); |
| 2773 invokeGetter(node, new Selector.getter('current', null)); | 2765 invokeGetter(node, Names.current); |
| 2774 value.initialize(assembler); | 2766 value.initialize(assembler); |
| 2775 pushVariableDeclaration(value); | 2767 pushVariableDeclaration(value); |
| 2776 } else { | 2768 } else { |
| 2777 if (element == null || element.isInstanceMember) { | 2769 if (element == null || element.isInstanceMember) { |
| 2778 loadThis(); | 2770 loadThis(); |
| 2779 assembler.loadLocal(1); | 2771 assembler.loadLocal(1); |
| 2780 invokeGetter(node, new Selector.getter('current', null)); | 2772 invokeGetter(node, Names.current); |
| 2781 Selector selector = elements.getSelector(node.declaredIdentifier); | 2773 Selector selector = elements.getSelector(node.declaredIdentifier); |
| 2782 invokeSetter(node, selector); | 2774 invokeSetter(node, selector.memberName); |
| 2783 } else { | 2775 } else { |
| 2784 assembler.dup(); | 2776 assembler.dup(); |
| 2785 invokeGetter(node, new Selector.getter('current', null)); | 2777 invokeGetter(node, Names.current); |
| 2786 if (element.isLocal) { | 2778 if (element.isLocal) { |
| 2787 scope[element].store(assembler); | 2779 scope[element].store(assembler); |
| 2788 } else if (element.isField) { | 2780 } else if (element.isField) { |
| 2789 doStaticFieldSet(element); | 2781 doStaticFieldSet(element); |
| 2790 } else if (element.isErroneous) { | 2782 } else if (element.isMalformed) { |
| 2791 doUnresolved(element.name); | 2783 doUnresolved(element.name); |
| 2792 assembler.pop(); | 2784 assembler.pop(); |
| 2793 } else { | 2785 } else { |
| 2794 internalError(node, "Unhandled store in for-in"); | 2786 internalError(node, "Unhandled store in for-in"); |
| 2795 } | 2787 } |
| 2796 } | 2788 } |
| 2797 assembler.pop(); | 2789 assembler.pop(); |
| 2798 } | 2790 } |
| 2799 | 2791 |
| 2800 doScopedStatement(node.body); | 2792 doScopedStatement(node.body); |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3092 NodeList arguments, | 3084 NodeList arguments, |
| 3093 CallStructure callStructure, | 3085 CallStructure callStructure, |
| 3094 _) { | 3086 _) { |
| 3095 if (!checkCompileError(function)) { | 3087 if (!checkCompileError(function)) { |
| 3096 doUnresolved(function.name); | 3088 doUnresolved(function.name); |
| 3097 } | 3089 } |
| 3098 applyVisitState(); | 3090 applyVisitState(); |
| 3099 } | 3091 } |
| 3100 | 3092 |
| 3101 void internalError(Spannable spannable, String reason) { | 3093 void internalError(Spannable spannable, String reason) { |
| 3102 context.compiler.internalError(spannable, reason); | 3094 context.compiler.reporter.internalError(spannable, reason); |
| 3103 } | 3095 } |
| 3104 | 3096 |
| 3105 void generateUnimplementedError(Spannable spannable, String reason) { | 3097 void generateUnimplementedError(Spannable spannable, String reason) { |
| 3106 context.backend.generateUnimplementedError( | 3098 context.backend.generateUnimplementedError( |
| 3107 spannable, | 3099 spannable, |
| 3108 reason, | 3100 reason, |
| 3109 functionBuilder); | 3101 functionBuilder); |
| 3110 } | 3102 } |
| 3111 | 3103 |
| 3112 String toString() => "FunctionCompiler(${element.name})"; | 3104 String toString() => "FunctionCompiler(${element.name})"; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3164 void handleStaticFunctionSet( | 3156 void handleStaticFunctionSet( |
| 3165 SendSet node, | 3157 SendSet node, |
| 3166 MethodElement function, | 3158 MethodElement function, |
| 3167 Node rhs, | 3159 Node rhs, |
| 3168 _) { | 3160 _) { |
| 3169 generateUnimplementedError( | 3161 generateUnimplementedError( |
| 3170 node, "[handleStaticFunctionSet] isn't implemented."); | 3162 node, "[handleStaticFunctionSet] isn't implemented."); |
| 3171 applyVisitState(); | 3163 applyVisitState(); |
| 3172 } | 3164 } |
| 3173 | 3165 |
| 3166 @override | |
| 3167 void bulkHandleSetIfNull(Node node, _) { | |
| 3168 generateUnimplementedError( | |
| 3169 node, "[bulkHandleSetIfNull] isn't implemented."); | |
| 3170 applyVisitState(); | |
| 3171 } | |
| 3172 | |
| 3174 void previsitDeferredAccess(Send node, PrefixElement prefix, _) { | 3173 void previsitDeferredAccess(Send node, PrefixElement prefix, _) { |
| 3175 // We don't support deferred access, so nothing to do for now. | 3174 // We don't support deferred access, so nothing to do for now. |
| 3176 } | 3175 } |
| 3177 | 3176 |
| 3178 void bulkHandleNode(Node node, String msg, _) { | 3177 void bulkHandleNode(Node node, String msg, _) { |
| 3179 generateUnimplementedError(node, msg.replaceAll('#', node.toString())); | 3178 generateUnimplementedError(node, msg.replaceAll('#', node.toString())); |
| 3180 applyVisitState(); | 3179 applyVisitState(); |
| 3181 } | 3180 } |
| 3182 | 3181 |
| 3183 void visitNode(Node node) { | 3182 void visitNode(Node node) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 3194 | 3193 |
| 3195 void applyParameters(NodeList parameters, _) { | 3194 void applyParameters(NodeList parameters, _) { |
| 3196 internalError(parameters, "[applyParameters] isn't implemented."); | 3195 internalError(parameters, "[applyParameters] isn't implemented."); |
| 3197 } | 3196 } |
| 3198 } | 3197 } |
| 3199 | 3198 |
| 3200 abstract class FletchRegistryMixin { | 3199 abstract class FletchRegistryMixin { |
| 3201 FletchRegistry get registry; | 3200 FletchRegistry get registry; |
| 3202 FletchContext get context; | 3201 FletchContext get context; |
| 3203 | 3202 |
| 3204 void registerDynamicInvocation(Selector selector) { | 3203 void registerDynamicUse(Selector selector) { |
| 3205 registry.registerDynamicInvocation(new UniverseSelector(selector, null)); | 3204 registry.registerDynamicUse(selector); |
| 3206 } | 3205 } |
| 3207 | 3206 |
| 3208 void registerDynamicGetter(Selector selector) { | 3207 void registerStaticUse(StaticUse staticUse) { |
| 3209 registry.registerDynamicGetter(new UniverseSelector(selector, null)); | 3208 registry.registerStaticUse(staticUse); |
| 3210 } | |
| 3211 | |
| 3212 void registerDynamicSetter(Selector selector) { | |
| 3213 registry.registerDynamicSetter(new UniverseSelector(selector, null)); | |
| 3214 } | |
| 3215 | |
| 3216 void registerStaticInvocation(FunctionElement function) { | |
| 3217 registry.registerStaticInvocation(function); | |
| 3218 } | 3209 } |
| 3219 | 3210 |
| 3220 void registerInstantiatedClass(ClassElement klass) { | 3211 void registerInstantiatedClass(ClassElement klass) { |
| 3221 registry.registerInstantiatedClass(klass); | 3212 registry.registerInstantiatedClass(klass); |
| 3222 } | 3213 } |
| 3223 | 3214 |
| 3224 void registerIsCheck(DartType type) { | 3215 void registerIsCheck(DartType type) { |
| 3225 registry.registerIsCheck(type); | 3216 registry.registerIsCheck(type); |
| 3226 } | 3217 } |
| 3227 | 3218 |
| 3228 void registerLocalInvoke(LocalElement element, Selector selector) { | 3219 void registerLocalInvoke(LocalElement element, Selector selector) { |
| 3229 registry.registerLocalInvoke(element, selector); | 3220 registry.registerLocalInvoke(element, selector); |
| 3230 } | 3221 } |
| 3231 | 3222 |
| 3232 void registerClosurization(FunctionElement element, ClosureKind kind) { | 3223 void registerClosurization(FunctionElement element, ClosureKind kind) { |
| 3233 if (kind == ClosureKind.localFunction) { | 3224 if (kind == ClosureKind.localFunction) { |
| 3234 // TODO(ahe): Get rid of the call to [registerStaticInvocation]. It is | 3225 // TODO(ahe): Get rid of the call to [registerStaticUse]. It is |
| 3235 // currently needed to ensure that local function expression closures are | 3226 // currently needed to ensure that local function expression closures are |
| 3236 // compiled correctly. For example, `[() {}].last()`, notice that `last` | 3227 // compiled correctly. For example, `[() {}].last()`, notice that `last` |
| 3237 // is a getter. This happens for both named and unnamed. | 3228 // is a getter. This happens for both named and unnamed. |
| 3238 registerStaticInvocation(element); | 3229 registerStaticUse(new StaticUse.foreignUse(element)); |
| 3239 } | 3230 } |
| 3240 registry.registerClosurization(element, kind); | 3231 registry.registerClosurization(element, kind); |
| 3241 } | 3232 } |
| 3242 | 3233 |
| 3243 int compileLazyFieldInitializer(FieldElement field) { | 3234 int compileLazyFieldInitializer(FieldElement field) { |
| 3244 return context.backend.compileLazyFieldInitializer(field, registry); | 3235 return context.backend.compileLazyFieldInitializer(field, registry); |
| 3245 } | 3236 } |
| 3246 } | 3237 } |
| OLD | NEW |