| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to implement [TypedElement.type] because our | 9 * methods. We need to implement [TypedElement.type] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 kind == ElementKind.SETTER) { | 47 kind == ElementKind.SETTER) { |
| 48 graph = builder.buildMethod(element); | 48 graph = builder.buildMethod(element); |
| 49 } else if (kind == ElementKind.FIELD) { | 49 } else if (kind == ElementKind.FIELD) { |
| 50 if (element.isInstanceMember()) { | 50 if (element.isInstanceMember()) { |
| 51 assert(compiler.enableTypeAssertions); | 51 assert(compiler.enableTypeAssertions); |
| 52 graph = builder.buildCheckedSetter(element); | 52 graph = builder.buildCheckedSetter(element); |
| 53 } else { | 53 } else { |
| 54 graph = builder.buildLazyInitializer(element); | 54 graph = builder.buildLazyInitializer(element); |
| 55 } | 55 } |
| 56 } else { | 56 } else { |
| 57 compiler.internalErrorOnElement(element, | 57 compiler.internalError(element, 'unexpected element kind $kind'); |
| 58 'unexpected element kind $kind'); | |
| 59 } | 58 } |
| 60 assert(graph.isValid()); | 59 assert(graph.isValid()); |
| 61 if (!identical(kind, ElementKind.FIELD)) { | 60 if (!identical(kind, ElementKind.FIELD)) { |
| 62 FunctionElement function = element; | 61 FunctionElement function = element; |
| 63 FunctionSignature signature = function.functionSignature; | 62 FunctionSignature signature = function.functionSignature; |
| 64 signature.forEachOptionalParameter((Element parameter) { | 63 signature.forEachOptionalParameter((Element parameter) { |
| 65 // This ensures the default value will be computed. | 64 // This ensures the default value will be computed. |
| 66 Constant constant = | 65 Constant constant = |
| 67 compiler.constantHandler.getConstantForVariable(parameter); | 66 compiler.constantHandler.getConstantForVariable(parameter); |
| 68 backend.registerCompileTimeConstant(constant, work.resolutionTree); | 67 backend.registerCompileTimeConstant(constant, work.resolutionTree); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 /** | 349 /** |
| 351 * Returns an [HInstruction] for the given element. If the element is | 350 * Returns an [HInstruction] for the given element. If the element is |
| 352 * boxed or stored in a closure then the method generates code to retrieve | 351 * boxed or stored in a closure then the method generates code to retrieve |
| 353 * the value. | 352 * the value. |
| 354 */ | 353 */ |
| 355 HInstruction readLocal(Element element) { | 354 HInstruction readLocal(Element element) { |
| 356 if (isAccessedDirectly(element)) { | 355 if (isAccessedDirectly(element)) { |
| 357 if (directLocals[element] == null) { | 356 if (directLocals[element] == null) { |
| 358 if (element.isTypeVariable()) { | 357 if (element.isTypeVariable()) { |
| 359 builder.compiler.internalError( | 358 builder.compiler.internalError( |
| 360 "Runtime type information not available for $element", | 359 builder.compiler.currentElement, |
| 361 element: builder.compiler.currentElement); | 360 "Runtime type information not available for $element"); |
| 362 } else { | 361 } else { |
| 363 builder.compiler.internalError( | 362 builder.compiler.internalError(element, "Cannot find value $element"); |
| 364 "Cannot find value $element", | |
| 365 element: element); | |
| 366 } | 363 } |
| 367 } | 364 } |
| 368 return directLocals[element]; | 365 return directLocals[element]; |
| 369 } else if (isStoredInClosureField(element)) { | 366 } else if (isStoredInClosureField(element)) { |
| 370 Element redirect = redirectionMapping[element]; | 367 Element redirect = redirectionMapping[element]; |
| 371 HInstruction receiver = readLocal(closureData.closureElement); | 368 HInstruction receiver = readLocal(closureData.closureElement); |
| 372 TypeMask type = (element.kind == ElementKind.VARIABLE_LIST) | 369 TypeMask type = (element.kind == ElementKind.VARIABLE_LIST) |
| 373 ? builder.backend.nonNullType | 370 ? builder.backend.nonNullType |
| 374 : builder.getTypeOfCapturedVariable(redirect); | 371 : builder.getTypeOfCapturedVariable(redirect); |
| 375 assert(element.kind != ElementKind.VARIABLE_LIST | 372 assert(element.kind != ElementKind.VARIABLE_LIST |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 | 686 |
| 690 // Insert break handler used to avoid null checks when a target isn't | 687 // Insert break handler used to avoid null checks when a target isn't |
| 691 // used as the target of a break, and therefore doesn't need a break | 688 // used as the target of a break, and therefore doesn't need a break |
| 692 // handler associated with it. | 689 // handler associated with it. |
| 693 class NullJumpHandler implements JumpHandler { | 690 class NullJumpHandler implements JumpHandler { |
| 694 final Compiler compiler; | 691 final Compiler compiler; |
| 695 | 692 |
| 696 NullJumpHandler(this.compiler); | 693 NullJumpHandler(this.compiler); |
| 697 | 694 |
| 698 void generateBreak([LabelElement label]) { | 695 void generateBreak([LabelElement label]) { |
| 699 compiler.internalError('generateBreak should not be called'); | 696 compiler.internalError(CURRENT_ELEMENT_SPANNABLE, |
| 697 'generateBreak should not be called'); |
| 700 } | 698 } |
| 701 | 699 |
| 702 void generateContinue([LabelElement label]) { | 700 void generateContinue([LabelElement label]) { |
| 703 compiler.internalError('generateContinue should not be called'); | 701 compiler.internalError(CURRENT_ELEMENT_SPANNABLE, |
| 702 'generateContinue should not be called'); |
| 704 } | 703 } |
| 705 | 704 |
| 706 void forEachBreak(Function ignored) { } | 705 void forEachBreak(Function ignored) { } |
| 707 void forEachContinue(Function ignored) { } | 706 void forEachContinue(Function ignored) { } |
| 708 void close() { } | 707 void close() { } |
| 709 bool hasAnyContinue() => false; | 708 bool hasAnyContinue() => false; |
| 710 bool hasAnyBreak() => false; | 709 bool hasAnyBreak() => false; |
| 711 | 710 |
| 712 List<LabelElement> labels() => const <LabelElement>[]; | 711 List<LabelElement> labels() => const <LabelElement>[]; |
| 713 TargetElement get target => null; | 712 TargetElement get target => null; |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1789 ClassElement enclosingClass = constructor.getEnclosingClass(); | 1788 ClassElement enclosingClass = constructor.getEnclosingClass(); |
| 1790 ClassElement superClass = enclosingClass.superclass; | 1789 ClassElement superClass = enclosingClass.superclass; |
| 1791 if (!enclosingClass.isObject(compiler)) { | 1790 if (!enclosingClass.isObject(compiler)) { |
| 1792 assert(superClass != null); | 1791 assert(superClass != null); |
| 1793 assert(superClass.resolutionState == STATE_DONE); | 1792 assert(superClass.resolutionState == STATE_DONE); |
| 1794 Selector selector = | 1793 Selector selector = |
| 1795 new Selector.callDefaultConstructor(enclosingClass.getLibrary()); | 1794 new Selector.callDefaultConstructor(enclosingClass.getLibrary()); |
| 1796 // TODO(johnniwinther): Should we find injected constructors as well? | 1795 // TODO(johnniwinther): Should we find injected constructors as well? |
| 1797 FunctionElement target = superClass.lookupConstructor(selector); | 1796 FunctionElement target = superClass.lookupConstructor(selector); |
| 1798 if (target == null) { | 1797 if (target == null) { |
| 1799 compiler.internalError("no default constructor available"); | 1798 compiler.internalError(superClass, |
| 1799 "no default constructor available"); |
| 1800 } | 1800 } |
| 1801 List<HInstruction> arguments = <HInstruction>[]; | 1801 List<HInstruction> arguments = <HInstruction>[]; |
| 1802 selector.addArgumentsToList(const Link<ast.Node>(), | 1802 selector.addArgumentsToList(const Link<ast.Node>(), |
| 1803 arguments, | 1803 arguments, |
| 1804 target.implementation, | 1804 target.implementation, |
| 1805 null, | 1805 null, |
| 1806 handleConstantForOptionalParameter, | 1806 handleConstantForOptionalParameter, |
| 1807 compiler); | 1807 compiler); |
| 1808 inlineSuperOrRedirect(target, | 1808 inlineSuperOrRedirect(target, |
| 1809 arguments, | 1809 arguments, |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2274 | 2274 |
| 2275 visitBlock(ast.Block node) { | 2275 visitBlock(ast.Block node) { |
| 2276 assert(!isAborted()); | 2276 assert(!isAborted()); |
| 2277 if (!isReachable) return; // This can only happen when inlining. | 2277 if (!isReachable) return; // This can only happen when inlining. |
| 2278 for (Link<ast.Node> link = node.statements.nodes; | 2278 for (Link<ast.Node> link = node.statements.nodes; |
| 2279 !link.isEmpty; | 2279 !link.isEmpty; |
| 2280 link = link.tail) { | 2280 link = link.tail) { |
| 2281 visit(link.head); | 2281 visit(link.head); |
| 2282 if (!isReachable) { | 2282 if (!isReachable) { |
| 2283 // The block has been aborted by a return or a throw. | 2283 // The block has been aborted by a return or a throw. |
| 2284 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); | 2284 if (!stack.isEmpty) { |
| 2285 compiler.internalError(node, 'non-empty instruction stack'); |
| 2286 } |
| 2285 return; | 2287 return; |
| 2286 } | 2288 } |
| 2287 } | 2289 } |
| 2288 assert(!current.isClosed()); | 2290 assert(!current.isClosed()); |
| 2289 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); | 2291 if (!stack.isEmpty) { |
| 2292 compiler.internalError(node, 'non-empty instruction stack'); |
| 2293 } |
| 2290 } | 2294 } |
| 2291 | 2295 |
| 2292 visitClassNode(ast.ClassNode node) { | 2296 visitClassNode(ast.ClassNode node) { |
| 2293 compiler.internalError('visitClassNode should not be called', node: node); | 2297 compiler.internalError(node, 'visitClassNode should not be called'); |
| 2294 } | 2298 } |
| 2295 | 2299 |
| 2296 visitThrowExpression(ast.Expression expression) { | 2300 visitThrowExpression(ast.Expression expression) { |
| 2297 bool old = inThrowExpression; | 2301 bool old = inThrowExpression; |
| 2298 try { | 2302 try { |
| 2299 inThrowExpression = true; | 2303 inThrowExpression = true; |
| 2300 visit(expression); | 2304 visit(expression); |
| 2301 } finally { | 2305 } finally { |
| 2302 inThrowExpression = old; | 2306 inThrowExpression = old; |
| 2303 } | 2307 } |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2810 visitFunctionDeclaration(ast.FunctionDeclaration node) { | 2814 visitFunctionDeclaration(ast.FunctionDeclaration node) { |
| 2811 assert(isReachable); | 2815 assert(isReachable); |
| 2812 visit(node.function); | 2816 visit(node.function); |
| 2813 localsHandler.updateLocal(elements[node], pop()); | 2817 localsHandler.updateLocal(elements[node], pop()); |
| 2814 } | 2818 } |
| 2815 | 2819 |
| 2816 visitIdentifier(ast.Identifier node) { | 2820 visitIdentifier(ast.Identifier node) { |
| 2817 if (node.isThis()) { | 2821 if (node.isThis()) { |
| 2818 stack.add(localsHandler.readThis()); | 2822 stack.add(localsHandler.readThis()); |
| 2819 } else { | 2823 } else { |
| 2820 compiler.internalError("SsaFromAstMixin.visitIdentifier on non-this", | 2824 compiler.internalError(node, |
| 2821 node: node); | 2825 "SsaFromAstMixin.visitIdentifier on non-this"); |
| 2822 } | 2826 } |
| 2823 } | 2827 } |
| 2824 | 2828 |
| 2825 visitIf(ast.If node) { | 2829 visitIf(ast.If node) { |
| 2826 assert(isReachable); | 2830 assert(isReachable); |
| 2827 handleIf(node, | 2831 handleIf(node, |
| 2828 () => visit(node.condition), | 2832 () => visit(node.condition), |
| 2829 () => visit(node.thenPart), | 2833 () => visit(node.thenPart), |
| 2830 node.elsePart != null ? () => visit(node.elsePart) : null); | 2834 node.elsePart != null ? () => visit(node.elsePart) : null); |
| 2831 } | 2835 } |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3291 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), | 3295 new HInvokeClosure(closureSelector, inputs, backend.dynamicType), |
| 3292 node); | 3296 node); |
| 3293 } | 3297 } |
| 3294 | 3298 |
| 3295 void handleForeignJs(ast.Send node) { | 3299 void handleForeignJs(ast.Send node) { |
| 3296 Link<ast.Node> link = node.arguments; | 3300 Link<ast.Node> link = node.arguments; |
| 3297 // If the invoke is on foreign code, don't visit the first | 3301 // If the invoke is on foreign code, don't visit the first |
| 3298 // argument, which is the type, and the second argument, | 3302 // argument, which is the type, and the second argument, |
| 3299 // which is the foreign code. | 3303 // which is the foreign code. |
| 3300 if (link.isEmpty || link.tail.isEmpty) { | 3304 if (link.isEmpty || link.tail.isEmpty) { |
| 3301 compiler.cancel('At least two arguments expected', | 3305 compiler.internalError(node.argumentsNode, |
| 3302 node: node.argumentsNode); | 3306 'At least two arguments expected'); |
| 3303 } | 3307 } |
| 3304 native.NativeBehavior nativeBehavior = | 3308 native.NativeBehavior nativeBehavior = |
| 3305 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); | 3309 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
| 3306 | 3310 |
| 3307 List<HInstruction> inputs = <HInstruction>[]; | 3311 List<HInstruction> inputs = <HInstruction>[]; |
| 3308 addGenericSendArgumentsToList(link.tail.tail, inputs); | 3312 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 3309 | 3313 |
| 3310 TypeMask ssaType = | 3314 TypeMask ssaType = |
| 3311 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); | 3315 TypeMaskFactory.fromNativeBehavior(nativeBehavior, compiler); |
| 3312 push(new HForeign(nativeBehavior.codeAst, ssaType, inputs, | 3316 push(new HForeign(nativeBehavior.codeAst, ssaType, inputs, |
| 3313 effects: nativeBehavior.sideEffects, | 3317 effects: nativeBehavior.sideEffects, |
| 3314 nativeBehavior: nativeBehavior)); | 3318 nativeBehavior: nativeBehavior)); |
| 3315 return; | 3319 return; |
| 3316 } | 3320 } |
| 3317 | 3321 |
| 3318 void handleForeignJsCurrentIsolateContext(ast.Send node) { | 3322 void handleForeignJsCurrentIsolateContext(ast.Send node) { |
| 3319 if (!node.arguments.isEmpty) { | 3323 if (!node.arguments.isEmpty) { |
| 3320 compiler.cancel( | 3324 compiler.internalError(node, |
| 3321 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT', node: node); | 3325 'Too many arguments to JS_CURRENT_ISOLATE_CONTEXT'); |
| 3322 } | 3326 } |
| 3323 | 3327 |
| 3324 if (!compiler.hasIsolateSupport()) { | 3328 if (!compiler.hasIsolateSupport()) { |
| 3325 // If the isolate library is not used, we just generate code | 3329 // If the isolate library is not used, we just generate code |
| 3326 // to fetch the current isolate. | 3330 // to fetch the current isolate. |
| 3327 String name = backend.namer.currentIsolate; | 3331 String name = backend.namer.currentIsolate; |
| 3328 push(new HForeign(new js.LiteralString(name), | 3332 push(new HForeign(new js.LiteralString(name), |
| 3329 backend.dynamicType, | 3333 backend.dynamicType, |
| 3330 <HInstruction>[])); | 3334 <HInstruction>[])); |
| 3331 } else { | 3335 } else { |
| 3332 // Call a helper method from the isolate library. The isolate | 3336 // Call a helper method from the isolate library. The isolate |
| 3333 // library uses its own isolate structure, that encapsulates | 3337 // library uses its own isolate structure, that encapsulates |
| 3334 // Leg's isolate. | 3338 // Leg's isolate. |
| 3335 Element element = compiler.isolateHelperLibrary.find('_currentIsolate'); | 3339 Element element = compiler.isolateHelperLibrary.find('_currentIsolate'); |
| 3336 if (element == null) { | 3340 if (element == null) { |
| 3337 compiler.cancel( | 3341 compiler.internalError(node, |
| 3338 'Isolate library and compiler mismatch', node: node); | 3342 'Isolate library and compiler mismatch'); |
| 3339 } | 3343 } |
| 3340 pushInvokeStatic(null, element, [], backend.dynamicType); | 3344 pushInvokeStatic(null, element, [], backend.dynamicType); |
| 3341 } | 3345 } |
| 3342 } | 3346 } |
| 3343 | 3347 |
| 3344 void handleForeignJsGetName(ast.Send node) { | 3348 void handleForeignJsGetName(ast.Send node) { |
| 3345 List<ast.Node> arguments = node.arguments.toList(); | 3349 List<ast.Node> arguments = node.arguments.toList(); |
| 3346 ast.Node argument; | 3350 ast.Node argument; |
| 3347 switch (arguments.length) { | 3351 switch (arguments.length) { |
| 3348 case 0: | 3352 case 0: |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3403 // closure. | 3407 // closure. |
| 3404 visit(link.tail.head); | 3408 visit(link.tail.head); |
| 3405 Selector selector = new Selector.callClosure(0); | 3409 Selector selector = new Selector.callClosure(0); |
| 3406 push(new HInvokeClosure(selector, | 3410 push(new HInvokeClosure(selector, |
| 3407 <HInstruction>[pop()], | 3411 <HInstruction>[pop()], |
| 3408 backend.dynamicType)); | 3412 backend.dynamicType)); |
| 3409 } else { | 3413 } else { |
| 3410 // Call a helper method from the isolate library. | 3414 // Call a helper method from the isolate library. |
| 3411 Element element = compiler.isolateHelperLibrary.find('_callInIsolate'); | 3415 Element element = compiler.isolateHelperLibrary.find('_callInIsolate'); |
| 3412 if (element == null) { | 3416 if (element == null) { |
| 3413 compiler.cancel( | 3417 compiler.internalError(node, |
| 3414 'Isolate library and compiler mismatch', node: node); | 3418 'Isolate library and compiler mismatch'); |
| 3415 } | 3419 } |
| 3416 List<HInstruction> inputs = <HInstruction>[]; | 3420 List<HInstruction> inputs = <HInstruction>[]; |
| 3417 addGenericSendArgumentsToList(link, inputs); | 3421 addGenericSendArgumentsToList(link, inputs); |
| 3418 pushInvokeStatic(node, element, inputs, backend.dynamicType); | 3422 pushInvokeStatic(node, element, inputs, backend.dynamicType); |
| 3419 } | 3423 } |
| 3420 } | 3424 } |
| 3421 | 3425 |
| 3422 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { | 3426 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { |
| 3423 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 3427 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
| 3424 compiler.cancel('"$name" requires exactly one argument', | 3428 compiler.internalError(node.argumentsNode, |
| 3425 node: node.argumentsNode); | 3429 '"$name" requires exactly one argument'); |
| 3426 } | 3430 } |
| 3427 ast.Node closure = node.arguments.head; | 3431 ast.Node closure = node.arguments.head; |
| 3428 Element element = elements[closure]; | 3432 Element element = elements[closure]; |
| 3429 if (!Elements.isStaticOrTopLevelFunction(element)) { | 3433 if (!Elements.isStaticOrTopLevelFunction(element)) { |
| 3430 compiler.cancel( | 3434 compiler.internalError(closure, |
| 3431 '"$name" requires a static or top-level method', | 3435 '"$name" requires a static or top-level method'); |
| 3432 node: closure); | |
| 3433 } | 3436 } |
| 3434 FunctionElement function = element; | 3437 FunctionElement function = element; |
| 3435 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration | 3438 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration |
| 3436 // and implementation signatures. Currently it is need because the | 3439 // and implementation signatures. Currently it is need because the |
| 3437 // signatures have different elements for parameters. | 3440 // signatures have different elements for parameters. |
| 3438 FunctionElement implementation = function.implementation; | 3441 FunctionElement implementation = function.implementation; |
| 3439 FunctionSignature params = implementation.functionSignature; | 3442 FunctionSignature params = implementation.functionSignature; |
| 3440 if (params.optionalParameterCount != 0) { | 3443 if (params.optionalParameterCount != 0) { |
| 3441 compiler.cancel( | 3444 compiler.internalError(closure, |
| 3442 '"$name" does not handle closure with optional parameters', | 3445 '"$name" does not handle closure with optional parameters'); |
| 3443 node: closure); | |
| 3444 } | 3446 } |
| 3445 | 3447 |
| 3446 compiler.enqueuer.codegen.registerStaticUse(element); | 3448 compiler.enqueuer.codegen.registerStaticUse(element); |
| 3447 push(new HForeign(backend.namer.elementAccess(element), | 3449 push(new HForeign(backend.namer.elementAccess(element), |
| 3448 backend.dynamicType, | 3450 backend.dynamicType, |
| 3449 <HInstruction>[])); | 3451 <HInstruction>[])); |
| 3450 return params; | 3452 return params; |
| 3451 } | 3453 } |
| 3452 | 3454 |
| 3453 void handleForeignDartClosureToJs(ast.Send node, String name) { | 3455 void handleForeignDartClosureToJs(ast.Send node, String name) { |
| 3454 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take | 3456 // TODO(ahe): This implements DART_CLOSURE_TO_JS and should probably take |
| 3455 // care to wrap the closure in another closure that saves the current | 3457 // care to wrap the closure in another closure that saves the current |
| 3456 // isolate. | 3458 // isolate. |
| 3457 handleForeignRawFunctionRef(node, name); | 3459 handleForeignRawFunctionRef(node, name); |
| 3458 } | 3460 } |
| 3459 | 3461 |
| 3460 void handleForeignSetCurrentIsolate(ast.Send node) { | 3462 void handleForeignSetCurrentIsolate(ast.Send node) { |
| 3461 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 3463 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
| 3462 compiler.cancel('Exactly one argument required', | 3464 compiler.internalError(node.argumentsNode, |
| 3463 node: node.argumentsNode); | 3465 'Exactly one argument required'); |
| 3464 } | 3466 } |
| 3465 visit(node.arguments.head); | 3467 visit(node.arguments.head); |
| 3466 String isolateName = backend.namer.currentIsolate; | 3468 String isolateName = backend.namer.currentIsolate; |
| 3467 SideEffects sideEffects = new SideEffects.empty(); | 3469 SideEffects sideEffects = new SideEffects.empty(); |
| 3468 sideEffects.setAllSideEffects(); | 3470 sideEffects.setAllSideEffects(); |
| 3469 push(new HForeign(js.js("$isolateName = #"), | 3471 push(new HForeign(js.js("$isolateName = #"), |
| 3470 backend.dynamicType, | 3472 backend.dynamicType, |
| 3471 <HInstruction>[pop()], | 3473 <HInstruction>[pop()], |
| 3472 effects: sideEffects)); | 3474 effects: sideEffects)); |
| 3473 } | 3475 } |
| 3474 | 3476 |
| 3475 void handleForeignCreateIsolate(ast.Send node) { | 3477 void handleForeignCreateIsolate(ast.Send node) { |
| 3476 if (!node.arguments.isEmpty) { | 3478 if (!node.arguments.isEmpty) { |
| 3477 compiler.cancel('Too many arguments', | 3479 compiler.internalError(node.argumentsNode, 'Too many arguments'); |
| 3478 node: node.argumentsNode); | |
| 3479 } | 3480 } |
| 3480 String constructorName = backend.namer.isolateName; | 3481 String constructorName = backend.namer.isolateName; |
| 3481 push(new HForeign(js.js("new $constructorName()"), | 3482 push(new HForeign(js.js("new $constructorName()"), |
| 3482 backend.dynamicType, | 3483 backend.dynamicType, |
| 3483 <HInstruction>[])); | 3484 <HInstruction>[])); |
| 3484 } | 3485 } |
| 3485 | 3486 |
| 3486 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { | 3487 void handleForeignDartObjectJsConstructorFunction(ast.Send node) { |
| 3487 if (!node.arguments.isEmpty) { | 3488 if (!node.arguments.isEmpty) { |
| 3488 compiler.cancel('Too many arguments', node: node.argumentsNode); | 3489 compiler.internalError(node.argumentsNode, 'Too many arguments'); |
| 3489 } | 3490 } |
| 3490 String jsClassReference = backend.namer.isolateAccess(compiler.objectClass); | 3491 String jsClassReference = backend.namer.isolateAccess(compiler.objectClass); |
| 3491 push(new HForeign(new js.LiteralString(jsClassReference), | 3492 push(new HForeign(new js.LiteralString(jsClassReference), |
| 3492 backend.dynamicType, | 3493 backend.dynamicType, |
| 3493 <HInstruction>[])); | 3494 <HInstruction>[])); |
| 3494 } | 3495 } |
| 3495 | 3496 |
| 3496 void handleForeignJsCurrentIsolate(ast.Send node) { | 3497 void handleForeignJsCurrentIsolate(ast.Send node) { |
| 3497 if (!node.arguments.isEmpty) { | 3498 if (!node.arguments.isEmpty) { |
| 3498 compiler.cancel('Too many arguments', node: node.argumentsNode); | 3499 compiler.internalError(node.argumentsNode, 'Too many arguments'); |
| 3499 } | 3500 } |
| 3500 push(new HForeign(new js.LiteralString(backend.namer.currentIsolate), | 3501 push(new HForeign(new js.LiteralString(backend.namer.currentIsolate), |
| 3501 backend.dynamicType, | 3502 backend.dynamicType, |
| 3502 <HInstruction>[])); | 3503 <HInstruction>[])); |
| 3503 } | 3504 } |
| 3504 | 3505 |
| 3505 visitForeignSend(ast.Send node) { | 3506 visitForeignSend(ast.Send node) { |
| 3506 Selector selector = elements.getSelector(node); | 3507 Selector selector = elements.getSelector(node); |
| 3507 String name = selector.name; | 3508 String name = selector.name; |
| 3508 if (name == 'JS') { | 3509 if (name == 'JS') { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3755 (member.isField() && !isBuildingFor(member))) { | 3756 (member.isField() && !isBuildingFor(member))) { |
| 3756 // The type variable is stored in a parameter of the method. | 3757 // The type variable is stored in a parameter of the method. |
| 3757 return localsHandler.readLocal(type.element); | 3758 return localsHandler.readLocal(type.element); |
| 3758 } else if (member.isInstanceMember()) { | 3759 } else if (member.isInstanceMember()) { |
| 3759 // The type variable is stored on the object. | 3760 // The type variable is stored on the object. |
| 3760 return readTypeVariable(member.getEnclosingClass(), | 3761 return readTypeVariable(member.getEnclosingClass(), |
| 3761 type.element); | 3762 type.element); |
| 3762 } else { | 3763 } else { |
| 3763 // TODO(ngeoffray): Match the VM behavior and throw an | 3764 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3764 // exception at runtime. | 3765 // exception at runtime. |
| 3765 compiler.cancel('Unimplemented unresolved type variable', | 3766 compiler.internalError(type.element, |
| 3766 element: type.element); | 3767 'Unimplemented unresolved type variable'); |
| 3767 return null; | 3768 return null; |
| 3768 } | 3769 } |
| 3769 } | 3770 } |
| 3770 | 3771 |
| 3771 HInstruction analyzeTypeArgument(DartType argument) { | 3772 HInstruction analyzeTypeArgument(DartType argument) { |
| 3772 if (argument.treatAsDynamic) { | 3773 if (argument.treatAsDynamic) { |
| 3773 // Represent [dynamic] as [null]. | 3774 // Represent [dynamic] as [null]. |
| 3774 return graph.addConstantNull(compiler); | 3775 return graph.addConstantNull(compiler); |
| 3775 } | 3776 } |
| 3776 | 3777 |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4163 push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType)); | 4164 push(new HInvokeClosure(closureSelector, inputs, backend.dynamicType)); |
| 4164 } | 4165 } |
| 4165 } | 4166 } |
| 4166 | 4167 |
| 4167 visitGetterSend(ast.Send node) { | 4168 visitGetterSend(ast.Send node) { |
| 4168 generateGetter(node, elements[node]); | 4169 generateGetter(node, elements[node]); |
| 4169 } | 4170 } |
| 4170 | 4171 |
| 4171 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. | 4172 // TODO(antonm): migrate rest of SsaFromAstMixin to internalError. |
| 4172 internalError(String reason, {ast.Node node}) { | 4173 internalError(String reason, {ast.Node node}) { |
| 4173 compiler.internalError(reason, node: node); | 4174 compiler.internalError(node, reason); |
| 4174 } | 4175 } |
| 4175 | 4176 |
| 4176 void generateError(ast.Node node, String message, Element helper) { | 4177 void generateError(ast.Node node, String message, Element helper) { |
| 4177 HInstruction errorMessage = addConstantString(message); | 4178 HInstruction errorMessage = addConstantString(message); |
| 4178 pushInvokeStatic(node, helper, [errorMessage]); | 4179 pushInvokeStatic(node, helper, [errorMessage]); |
| 4179 } | 4180 } |
| 4180 | 4181 |
| 4181 void generateRuntimeError(ast.Node node, String message) { | 4182 void generateRuntimeError(ast.Node node, String message) { |
| 4182 generateError(node, message, backend.getThrowRuntimeError()); | 4183 generateError(node, message, backend.getThrowRuntimeError()); |
| 4183 } | 4184 } |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4533 assert(!link.isEmpty && link.tail.isEmpty); | 4534 assert(!link.isEmpty && link.tail.isEmpty); |
| 4534 if (Elements.isInstanceSend(node, elements)) { | 4535 if (Elements.isInstanceSend(node, elements)) { |
| 4535 HInstruction receiver = generateInstanceSendReceiver(node); | 4536 HInstruction receiver = generateInstanceSendReceiver(node); |
| 4536 visit(link.head); | 4537 visit(link.head); |
| 4537 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); | 4538 generateInstanceSetterWithCompiledReceiver(node, receiver, pop()); |
| 4538 } else { | 4539 } else { |
| 4539 visit(link.head); | 4540 visit(link.head); |
| 4540 generateNonInstanceSetter(node, element, pop()); | 4541 generateNonInstanceSetter(node, element, pop()); |
| 4541 } | 4542 } |
| 4542 } else if (identical(op.source, "is")) { | 4543 } else if (identical(op.source, "is")) { |
| 4543 compiler.internalError("is-operator as SendSet", node: op); | 4544 compiler.internalError(op, "is-operator as SendSet"); |
| 4544 } else { | 4545 } else { |
| 4545 assert("++" == op.source || "--" == op.source || | 4546 assert("++" == op.source || "--" == op.source || |
| 4546 node.assignmentOperator.source.endsWith("=")); | 4547 node.assignmentOperator.source.endsWith("=")); |
| 4547 | 4548 |
| 4548 // [receiver] is only used if the node is an instance send. | 4549 // [receiver] is only used if the node is an instance send. |
| 4549 HInstruction receiver = null; | 4550 HInstruction receiver = null; |
| 4550 Element getter = elements[node.selector]; | 4551 Element getter = elements[node.selector]; |
| 4551 | 4552 |
| 4552 if (!Elements.isUnresolved(getter) && getter.impliesType()) { | 4553 if (!Elements.isUnresolved(getter) && getter.impliesType()) { |
| 4553 ast.Identifier selector = node.selector; | 4554 ast.Identifier selector = node.selector; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4626 } | 4627 } |
| 4627 } | 4628 } |
| 4628 } | 4629 } |
| 4629 | 4630 |
| 4630 void visitParenthesizedExpression(ast.ParenthesizedExpression node) { | 4631 void visitParenthesizedExpression(ast.ParenthesizedExpression node) { |
| 4631 visit(node.expression); | 4632 visit(node.expression); |
| 4632 } | 4633 } |
| 4633 | 4634 |
| 4634 visitOperator(ast.Operator node) { | 4635 visitOperator(ast.Operator node) { |
| 4635 // Operators are intercepted in their surrounding Send nodes. | 4636 // Operators are intercepted in their surrounding Send nodes. |
| 4636 compiler.internalError('visitOperator should not be called', node: node); | 4637 compiler.internalError(node, 'visitOperator should not be called'); |
| 4637 } | 4638 } |
| 4638 | 4639 |
| 4639 visitCascade(ast.Cascade node) { | 4640 visitCascade(ast.Cascade node) { |
| 4640 visit(node.expression); | 4641 visit(node.expression); |
| 4641 // Remove the result and reveal the duplicated receiver on the stack. | 4642 // Remove the result and reveal the duplicated receiver on the stack. |
| 4642 pop(); | 4643 pop(); |
| 4643 } | 4644 } |
| 4644 | 4645 |
| 4645 visitCascadeReceiver(ast.CascadeReceiver node) { | 4646 visitCascadeReceiver(ast.CascadeReceiver node) { |
| 4646 visit(node.expression); | 4647 visit(node.expression); |
| 4647 dup(); | 4648 dup(); |
| 4648 } | 4649 } |
| 4649 | 4650 |
| 4650 void handleInTryStatement() { | 4651 void handleInTryStatement() { |
| 4651 if (!inTryStatement) return; | 4652 if (!inTryStatement) return; |
| 4652 HBasicBlock block = close(new HExitTry()); | 4653 HBasicBlock block = close(new HExitTry()); |
| 4653 HBasicBlock newBlock = graph.addNewBlock(); | 4654 HBasicBlock newBlock = graph.addNewBlock(); |
| 4654 block.addSuccessor(newBlock); | 4655 block.addSuccessor(newBlock); |
| 4655 open(newBlock); | 4656 open(newBlock); |
| 4656 } | 4657 } |
| 4657 | 4658 |
| 4658 visitRethrow(ast.Rethrow node) { | 4659 visitRethrow(ast.Rethrow node) { |
| 4659 HInstruction exception = rethrowableException; | 4660 HInstruction exception = rethrowableException; |
| 4660 if (exception == null) { | 4661 if (exception == null) { |
| 4661 exception = graph.addConstantNull(compiler); | 4662 exception = graph.addConstantNull(compiler); |
| 4662 compiler.internalError( | 4663 compiler.internalError(node, |
| 4663 'rethrowableException should not be null', node: node); | 4664 'rethrowableException should not be null'); |
| 4664 } | 4665 } |
| 4665 handleInTryStatement(); | 4666 handleInTryStatement(); |
| 4666 closeAndGotoExit(new HThrow(exception, isRethrow: true)); | 4667 closeAndGotoExit(new HThrow(exception, isRethrow: true)); |
| 4667 } | 4668 } |
| 4668 | 4669 |
| 4669 visitReturn(ast.Return node) { | 4670 visitReturn(ast.Return node) { |
| 4670 if (identical(node.getBeginToken().stringValue, 'native')) { | 4671 if (identical(node.getBeginToken().stringValue, 'native')) { |
| 4671 native.handleSsaNative(this, node.expression); | 4672 native.handleSsaNative(this, node.expression); |
| 4672 return; | 4673 return; |
| 4673 } | 4674 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4720 visitThrow(ast.Throw node) { | 4721 visitThrow(ast.Throw node) { |
| 4721 visitThrowExpression(node.expression); | 4722 visitThrowExpression(node.expression); |
| 4722 if (isReachable) { | 4723 if (isReachable) { |
| 4723 handleInTryStatement(); | 4724 handleInTryStatement(); |
| 4724 push(new HThrowExpression(pop())); | 4725 push(new HThrowExpression(pop())); |
| 4725 isReachable = false; | 4726 isReachable = false; |
| 4726 } | 4727 } |
| 4727 } | 4728 } |
| 4728 | 4729 |
| 4729 visitTypeAnnotation(ast.TypeAnnotation node) { | 4730 visitTypeAnnotation(ast.TypeAnnotation node) { |
| 4730 compiler.internalError('visiting type annotation in SSA builder', | 4731 compiler.internalError(node, 'visiting type annotation in SSA builder'); |
| 4731 node: node); | |
| 4732 } | 4732 } |
| 4733 | 4733 |
| 4734 visitVariableDefinitions(ast.VariableDefinitions node) { | 4734 visitVariableDefinitions(ast.VariableDefinitions node) { |
| 4735 assert(isReachable); | 4735 assert(isReachable); |
| 4736 for (Link<ast.Node> link = node.definitions.nodes; | 4736 for (Link<ast.Node> link = node.definitions.nodes; |
| 4737 !link.isEmpty; | 4737 !link.isEmpty; |
| 4738 link = link.tail) { | 4738 link = link.tail) { |
| 4739 ast.Node definition = link.head; | 4739 ast.Node definition = link.head; |
| 4740 if (definition is ast.Identifier) { | 4740 if (definition is ast.Identifier) { |
| 4741 HInstruction initialValue = graph.addConstantNull(compiler); | 4741 HInstruction initialValue = graph.addConstantNull(compiler); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4794 } | 4794 } |
| 4795 | 4795 |
| 4796 visitStringInterpolation(ast.StringInterpolation node) { | 4796 visitStringInterpolation(ast.StringInterpolation node) { |
| 4797 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); | 4797 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this, node); |
| 4798 stringBuilder.visit(node); | 4798 stringBuilder.visit(node); |
| 4799 stack.add(stringBuilder.result); | 4799 stack.add(stringBuilder.result); |
| 4800 } | 4800 } |
| 4801 | 4801 |
| 4802 visitStringInterpolationPart(ast.StringInterpolationPart node) { | 4802 visitStringInterpolationPart(ast.StringInterpolationPart node) { |
| 4803 // The parts are iterated in visitStringInterpolation. | 4803 // The parts are iterated in visitStringInterpolation. |
| 4804 compiler.internalError('visitStringInterpolation should not be called', | 4804 compiler.internalError(node, |
| 4805 node: node); | 4805 'visitStringInterpolation should not be called'); |
| 4806 } | 4806 } |
| 4807 | 4807 |
| 4808 visitEmptyStatement(ast.EmptyStatement node) { | 4808 visitEmptyStatement(ast.EmptyStatement node) { |
| 4809 // Do nothing, empty statement. | 4809 // Do nothing, empty statement. |
| 4810 } | 4810 } |
| 4811 | 4811 |
| 4812 visitModifiers(ast.Modifiers node) { | 4812 visitModifiers(ast.Modifiers node) { |
| 4813 compiler.unimplemented('SsaFromAstMixin.visitModifiers', node: node); | 4813 compiler.unimplemented(node, 'SsaFromAstMixin.visitModifiers'); |
| 4814 } | 4814 } |
| 4815 | 4815 |
| 4816 visitBreakStatement(ast.BreakStatement node) { | 4816 visitBreakStatement(ast.BreakStatement node) { |
| 4817 assert(!isAborted()); | 4817 assert(!isAborted()); |
| 4818 handleInTryStatement(); | 4818 handleInTryStatement(); |
| 4819 TargetElement target = elements[node]; | 4819 TargetElement target = elements[node]; |
| 4820 assert(target != null); | 4820 assert(target != null); |
| 4821 JumpHandler handler = jumpTargets[target]; | 4821 JumpHandler handler = jumpTargets[target]; |
| 4822 assert(handler != null); | 4822 assert(handler != null); |
| 4823 if (node.target == null) { | 4823 if (node.target == null) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4911 generateNonInstanceSetter(null, variable, value, location: identifier); | 4911 generateNonInstanceSetter(null, variable, value, location: identifier); |
| 4912 } | 4912 } |
| 4913 pop(); // Pop the value pushed by the setter call. | 4913 pop(); // Pop the value pushed by the setter call. |
| 4914 | 4914 |
| 4915 visit(node.body); | 4915 visit(node.body); |
| 4916 } | 4916 } |
| 4917 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); | 4917 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); |
| 4918 } | 4918 } |
| 4919 | 4919 |
| 4920 visitLabel(ast.Label node) { | 4920 visitLabel(ast.Label node) { |
| 4921 compiler.internalError('SsaFromAstMixin.visitLabel', node: node); | 4921 compiler.internalError(node, 'SsaFromAstMixin.visitLabel'); |
| 4922 } | 4922 } |
| 4923 | 4923 |
| 4924 visitLabeledStatement(ast.LabeledStatement node) { | 4924 visitLabeledStatement(ast.LabeledStatement node) { |
| 4925 ast.Statement body = node.statement; | 4925 ast.Statement body = node.statement; |
| 4926 if (body is ast.Loop | 4926 if (body is ast.Loop |
| 4927 || body is ast.SwitchStatement | 4927 || body is ast.SwitchStatement |
| 4928 || Elements.isUnusedLabel(node, elements)) { | 4928 || Elements.isUnusedLabel(node, elements)) { |
| 4929 // Loops and switches handle their own labels. | 4929 // Loops and switches handle their own labels. |
| 4930 visit(body); | 4930 visit(body); |
| 4931 return; | 4931 return; |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5341 new HSwitchBlockInformation(expressionInfo, | 5341 new HSwitchBlockInformation(expressionInfo, |
| 5342 statements, | 5342 statements, |
| 5343 jumpHandler.target, | 5343 jumpHandler.target, |
| 5344 jumpHandler.labels()), | 5344 jumpHandler.labels()), |
| 5345 joinBlock); | 5345 joinBlock); |
| 5346 | 5346 |
| 5347 jumpHandler.close(); | 5347 jumpHandler.close(); |
| 5348 } | 5348 } |
| 5349 | 5349 |
| 5350 visitSwitchCase(ast.SwitchCase node) { | 5350 visitSwitchCase(ast.SwitchCase node) { |
| 5351 compiler.internalError('SsaFromAstMixin.visitSwitchCase'); | 5351 compiler.internalError(node, 'SsaFromAstMixin.visitSwitchCase'); |
| 5352 } | 5352 } |
| 5353 | 5353 |
| 5354 visitCaseMatch(ast.CaseMatch node) { | 5354 visitCaseMatch(ast.CaseMatch node) { |
| 5355 compiler.internalError('SsaFromAstMixin.visitCaseMatch'); | 5355 compiler.internalError(node, 'SsaFromAstMixin.visitCaseMatch'); |
| 5356 } | 5356 } |
| 5357 | 5357 |
| 5358 visitTryStatement(ast.TryStatement node) { | 5358 visitTryStatement(ast.TryStatement node) { |
| 5359 // Save the current locals. The catch block and the finally block | 5359 // Save the current locals. The catch block and the finally block |
| 5360 // must not reuse the existing locals handler. None of the variables | 5360 // must not reuse the existing locals handler. None of the variables |
| 5361 // that have been defined in the body-block will be used, but for | 5361 // that have been defined in the body-block will be used, but for |
| 5362 // loops we will add (unnecessary) phis that will reference the body | 5362 // loops we will add (unnecessary) phis that will reference the body |
| 5363 // variables. This makes it look as if the variables were used | 5363 // variables. This makes it look as if the variables were used |
| 5364 // in a non-dominated block. | 5364 // in a non-dominated block. |
| 5365 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 5365 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5402 | 5402 |
| 5403 pushInvokeStatic(node, backend.getExceptionUnwrapper(), [exception]); | 5403 pushInvokeStatic(node, backend.getExceptionUnwrapper(), [exception]); |
| 5404 HInvokeStatic unwrappedException = pop(); | 5404 HInvokeStatic unwrappedException = pop(); |
| 5405 tryInstruction.exception = exception; | 5405 tryInstruction.exception = exception; |
| 5406 Link<ast.Node> link = node.catchBlocks.nodes; | 5406 Link<ast.Node> link = node.catchBlocks.nodes; |
| 5407 | 5407 |
| 5408 void pushCondition(ast.CatchBlock catchBlock) { | 5408 void pushCondition(ast.CatchBlock catchBlock) { |
| 5409 if (catchBlock.onKeyword != null) { | 5409 if (catchBlock.onKeyword != null) { |
| 5410 DartType type = elements.getType(catchBlock.type); | 5410 DartType type = elements.getType(catchBlock.type); |
| 5411 if (type == null) { | 5411 if (type == null) { |
| 5412 compiler.internalError('On with no type', node: catchBlock.type); | 5412 compiler.internalError(catchBlock.type, 'On with no type'); |
| 5413 } | 5413 } |
| 5414 HInstruction condition = | 5414 HInstruction condition = |
| 5415 buildIsNode(catchBlock.type, type, unwrappedException); | 5415 buildIsNode(catchBlock.type, type, unwrappedException); |
| 5416 push(condition); | 5416 push(condition); |
| 5417 } else { | 5417 } else { |
| 5418 ast.VariableDefinitions declaration = catchBlock.formals.nodes.head; | 5418 ast.VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 5419 HInstruction condition = null; | 5419 HInstruction condition = null; |
| 5420 if (declaration.type == null) { | 5420 if (declaration.type == null) { |
| 5421 condition = graph.addConstantBool(true, compiler); | 5421 condition = graph.addConstantBool(true, compiler); |
| 5422 stack.add(condition); | 5422 stack.add(condition); |
| 5423 } else { | 5423 } else { |
| 5424 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 5424 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
| 5425 // "if" condition above and this "else" branch should be deleted as | 5425 // "if" condition above and this "else" branch should be deleted as |
| 5426 // type of declared variable won't matter for the catch | 5426 // type of declared variable won't matter for the catch |
| 5427 // condition. | 5427 // condition. |
| 5428 DartType type = elements.getType(declaration.type); | 5428 DartType type = elements.getType(declaration.type); |
| 5429 if (type == null) { | 5429 if (type == null) { |
| 5430 compiler.cancel('Catch with unresolved type', node: catchBlock); | 5430 compiler.internalError(catchBlock, 'Catch with unresolved type'); |
| 5431 } | 5431 } |
| 5432 condition = buildIsNode(declaration.type, type, unwrappedException); | 5432 condition = buildIsNode(declaration.type, type, unwrappedException); |
| 5433 push(condition); | 5433 push(condition); |
| 5434 } | 5434 } |
| 5435 } | 5435 } |
| 5436 } | 5436 } |
| 5437 | 5437 |
| 5438 void visitThen() { | 5438 void visitThen() { |
| 5439 ast.CatchBlock catchBlock = link.head; | 5439 ast.CatchBlock catchBlock = link.head; |
| 5440 link = link.tail; | 5440 link = link.tail; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5545 wrapStatementGraph(finallyGraph)), | 5545 wrapStatementGraph(finallyGraph)), |
| 5546 exitBlock); | 5546 exitBlock); |
| 5547 inTryStatement = oldInTryStatement; | 5547 inTryStatement = oldInTryStatement; |
| 5548 } | 5548 } |
| 5549 | 5549 |
| 5550 visitCatchBlock(ast.CatchBlock node) { | 5550 visitCatchBlock(ast.CatchBlock node) { |
| 5551 visit(node.block); | 5551 visit(node.block); |
| 5552 } | 5552 } |
| 5553 | 5553 |
| 5554 visitTypedef(ast.Typedef node) { | 5554 visitTypedef(ast.Typedef node) { |
| 5555 compiler.unimplemented('SsaFromAstMixin.visitTypedef', node: node); | 5555 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef'); |
| 5556 } | 5556 } |
| 5557 | 5557 |
| 5558 visitTypeVariable(ast.TypeVariable node) { | 5558 visitTypeVariable(ast.TypeVariable node) { |
| 5559 compiler.internalError('SsaFromAstMixin.visitTypeVariable'); | 5559 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable'); |
| 5560 } | 5560 } |
| 5561 | 5561 |
| 5562 /** | 5562 /** |
| 5563 * This method is invoked before inlining the body of [function] into this | 5563 * This method is invoked before inlining the body of [function] into this |
| 5564 * [SsaBuilder]. | 5564 * [SsaBuilder]. |
| 5565 */ | 5565 */ |
| 5566 void enterInlinedMethod(FunctionElement function, | 5566 void enterInlinedMethod(FunctionElement function, |
| 5567 ast.Node _, | 5567 ast.Node _, |
| 5568 List<HInstruction> compiledArguments) { | 5568 List<HInstruction> compiledArguments) { |
| 5569 AstInliningState state = new AstInliningState( | 5569 AstInliningState state = new AstInliningState( |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5613 */ | 5613 */ |
| 5614 HInstruction result = null; | 5614 HInstruction result = null; |
| 5615 | 5615 |
| 5616 StringBuilderVisitor(this.builder, this.diagnosticNode); | 5616 StringBuilderVisitor(this.builder, this.diagnosticNode); |
| 5617 | 5617 |
| 5618 void visit(ast.Node node) { | 5618 void visit(ast.Node node) { |
| 5619 node.accept(this); | 5619 node.accept(this); |
| 5620 } | 5620 } |
| 5621 | 5621 |
| 5622 visitNode(ast.Node node) { | 5622 visitNode(ast.Node node) { |
| 5623 builder.compiler.internalError('unexpected node', node: node); | 5623 builder.compiler.internalError(node, 'unexpected node'); |
| 5624 } | 5624 } |
| 5625 | 5625 |
| 5626 void visitExpression(ast.Node node) { | 5626 void visitExpression(ast.Node node) { |
| 5627 node.accept(builder); | 5627 node.accept(builder); |
| 5628 HInstruction expression = builder.pop(); | 5628 HInstruction expression = builder.pop(); |
| 5629 if (!expression.isConstantString()) { | 5629 if (!expression.isConstantString()) { |
| 5630 expression = new HStringify(expression, node, builder.backend.stringType); | 5630 expression = new HStringify(expression, node, builder.backend.stringType); |
| 5631 builder.add(expression); | 5631 builder.add(expression); |
| 5632 } | 5632 } |
| 5633 result = (result == null) ? expression : concat(result, expression); | 5633 result = (result == null) ? expression : concat(result, expression); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5803 class SsaBranchBuilder { | 5803 class SsaBranchBuilder { |
| 5804 final SsaBuilder builder; | 5804 final SsaBuilder builder; |
| 5805 final ast.Node diagnosticNode; | 5805 final ast.Node diagnosticNode; |
| 5806 | 5806 |
| 5807 SsaBranchBuilder(this.builder, [this.diagnosticNode]); | 5807 SsaBranchBuilder(this.builder, [this.diagnosticNode]); |
| 5808 | 5808 |
| 5809 Compiler get compiler => builder.compiler; | 5809 Compiler get compiler => builder.compiler; |
| 5810 | 5810 |
| 5811 void checkNotAborted() { | 5811 void checkNotAborted() { |
| 5812 if (builder.isAborted()) { | 5812 if (builder.isAborted()) { |
| 5813 compiler.unimplemented("aborted control flow", node: diagnosticNode); | 5813 compiler.unimplemented(diagnosticNode, "aborted control flow"); |
| 5814 } | 5814 } |
| 5815 } | 5815 } |
| 5816 | 5816 |
| 5817 void buildCondition(void visitCondition(), | 5817 void buildCondition(void visitCondition(), |
| 5818 SsaBranch conditionBranch, | 5818 SsaBranch conditionBranch, |
| 5819 SsaBranch thenBranch, | 5819 SsaBranch thenBranch, |
| 5820 SsaBranch elseBranch) { | 5820 SsaBranch elseBranch) { |
| 5821 startBranch(conditionBranch); | 5821 startBranch(conditionBranch); |
| 5822 visitCondition(); | 5822 visitCondition(); |
| 5823 checkNotAborted(); | 5823 checkNotAborted(); |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6114 DartType unaliased = type.unalias(builder.compiler); | 6114 DartType unaliased = type.unalias(builder.compiler); |
| 6115 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6115 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6116 unaliased.accept(this, builder); | 6116 unaliased.accept(this, builder); |
| 6117 } | 6117 } |
| 6118 | 6118 |
| 6119 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6119 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6120 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); | 6120 ClassElement cls = builder.compiler.findHelper('DynamicRuntimeType'); |
| 6121 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); | 6121 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 6122 } | 6122 } |
| 6123 } | 6123 } |
| OLD | NEW |