| 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 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| 11 | 11 |
| 12 SsaFunctionCompiler(JavaScriptBackend backend, bool generateSourceMap) | 12 SsaFunctionCompiler(JavaScriptBackend backend, |
| 13 : generator = new SsaCodeGeneratorTask(backend), | 13 SourceInformationFactory sourceInformationFactory) |
| 14 builder = new SsaBuilderTask(backend, generateSourceMap), | 14 : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory), |
| 15 builder = new SsaBuilderTask(backend, sourceInformationFactory), |
| 15 optimizer = new SsaOptimizerTask(backend); | 16 optimizer = new SsaOptimizerTask(backend); |
| 16 | 17 |
| 17 /// Generates JavaScript code for `work.element`. | 18 /// Generates JavaScript code for `work.element`. |
| 18 /// Using the ssa builder, optimizer and codegenerator. | 19 /// Using the ssa builder, optimizer and codegenerator. |
| 19 js.Fun compile(CodegenWorkItem work) { | 20 js.Fun compile(CodegenWorkItem work) { |
| 20 HGraph graph = builder.build(work); | 21 HGraph graph = builder.build(work); |
| 21 optimizer.optimize(work, graph); | 22 optimizer.optimize(work, graph); |
| 22 Element element = work.element; | 23 Element element = work.element; |
| 23 js.Expression result = generator.generateCode(work, graph); | 24 js.Expression result = generator.generateCode(work, graph); |
| 24 if (element is FunctionElement) { | 25 if (element is FunctionElement) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 final ExecutableElement executableContext; | 90 final ExecutableElement executableContext; |
| 90 | 91 |
| 91 SyntheticLocal(this.name, this.executableContext); | 92 SyntheticLocal(this.name, this.executableContext); |
| 92 | 93 |
| 93 toString() => 'SyntheticLocal($name)'; | 94 toString() => 'SyntheticLocal($name)'; |
| 94 } | 95 } |
| 95 | 96 |
| 96 class SsaBuilderTask extends CompilerTask { | 97 class SsaBuilderTask extends CompilerTask { |
| 97 final CodeEmitterTask emitter; | 98 final CodeEmitterTask emitter; |
| 98 final JavaScriptBackend backend; | 99 final JavaScriptBackend backend; |
| 99 final bool generateSourceMap; | 100 final SourceInformationFactory sourceInformationFactory; |
| 100 | 101 |
| 101 String get name => 'SSA builder'; | 102 String get name => 'SSA builder'; |
| 102 | 103 |
| 103 SsaBuilderTask(JavaScriptBackend backend, this.generateSourceMap) | 104 SsaBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) |
| 104 : emitter = backend.emitter, | 105 : emitter = backend.emitter, |
| 105 backend = backend, | 106 backend = backend, |
| 106 super(backend.compiler); | 107 super(backend.compiler); |
| 107 | 108 |
| 108 HGraph build(CodegenWorkItem work) { | 109 HGraph build(CodegenWorkItem work) { |
| 109 return measure(() { | 110 return measure(() { |
| 110 Element element = work.element.implementation; | 111 Element element = work.element.implementation; |
| 111 return compiler.withCurrentElement(element, () { | 112 return compiler.withCurrentElement(element, () { |
| 112 HInstruction.idCounter = 0; | 113 HInstruction.idCounter = 0; |
| 113 SsaBuilder builder = | 114 SsaBuilder builder = |
| 114 new SsaBuilder( | 115 new SsaBuilder( |
| 115 backend, work, emitter.nativeEmitter, generateSourceMap); | 116 backend, work, emitter.nativeEmitter, |
| 117 sourceInformationFactory); |
| 116 HGraph graph; | 118 HGraph graph; |
| 117 ElementKind kind = element.kind; | 119 ElementKind kind = element.kind; |
| 118 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 120 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 119 graph = compileConstructor(builder, work); | 121 graph = compileConstructor(builder, work); |
| 120 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 122 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 121 kind == ElementKind.FUNCTION || | 123 kind == ElementKind.FUNCTION || |
| 122 kind == ElementKind.GETTER || | 124 kind == ElementKind.GETTER || |
| 123 kind == ElementKind.SETTER) { | 125 kind == ElementKind.SETTER) { |
| 124 graph = builder.buildMethod(element); | 126 graph = builder.buildMethod(element); |
| 125 } else if (kind == ElementKind.FIELD) { | 127 } else if (kind == ElementKind.FIELD) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 SsaBuilder builder; | 194 SsaBuilder builder; |
| 193 ClosureClassMap closureData; | 195 ClosureClassMap closureData; |
| 194 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals = | 196 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals = |
| 195 new Map<TypeVariableType, TypeVariableLocal>(); | 197 new Map<TypeVariableType, TypeVariableLocal>(); |
| 196 final ExecutableElement executableContext; | 198 final ExecutableElement executableContext; |
| 197 | 199 |
| 198 /// The class that defines the current type environment or null if no type | 200 /// The class that defines the current type environment or null if no type |
| 199 /// variables are in scope. | 201 /// variables are in scope. |
| 200 ClassElement get contextClass => executableContext.contextClass; | 202 ClassElement get contextClass => executableContext.contextClass; |
| 201 | 203 |
| 204 SourceInformationBuilder get sourceInformationBuilder { |
| 205 return builder.sourceInformationBuilder; |
| 206 } |
| 207 |
| 202 LocalsHandler(this.builder, this.executableContext); | 208 LocalsHandler(this.builder, this.executableContext); |
| 203 | 209 |
| 204 /// Substituted type variables occurring in [type] into the context of | 210 /// Substituted type variables occurring in [type] into the context of |
| 205 /// [contextClass]. | 211 /// [contextClass]. |
| 206 DartType substInContext(DartType type) { | 212 DartType substInContext(DartType type) { |
| 207 if (contextClass != null) { | 213 if (contextClass != null) { |
| 208 ClassElement typeContext = Types.getClassContext(type); | 214 ClassElement typeContext = Types.getClassContext(type); |
| 209 if (typeContext != null) { | 215 if (typeContext != null) { |
| 210 type = type.substByContext( | 216 type = type.substByContext( |
| 211 contextClass.asInstanceOf(typeContext)); | 217 contextClass.asInstanceOf(typeContext)); |
| (...skipping 774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 986 | 992 |
| 987 /** | 993 /** |
| 988 * This class builds SSA nodes for functions represented in AST. | 994 * This class builds SSA nodes for functions represented in AST. |
| 989 */ | 995 */ |
| 990 class SsaBuilder extends NewResolvedVisitor { | 996 class SsaBuilder extends NewResolvedVisitor { |
| 991 final Compiler compiler; | 997 final Compiler compiler; |
| 992 final JavaScriptBackend backend; | 998 final JavaScriptBackend backend; |
| 993 final ConstantSystem constantSystem; | 999 final ConstantSystem constantSystem; |
| 994 final CodegenWorkItem work; | 1000 final CodegenWorkItem work; |
| 995 final RuntimeTypes rti; | 1001 final RuntimeTypes rti; |
| 996 final bool generateSourceMap; | 1002 SourceInformationBuilder sourceInformationBuilder; |
| 997 bool inLazyInitializerExpression = false; | 1003 bool inLazyInitializerExpression = false; |
| 998 | 1004 |
| 999 /* This field is used by the native handler. */ | 1005 /* This field is used by the native handler. */ |
| 1000 final NativeEmitter nativeEmitter; | 1006 final NativeEmitter nativeEmitter; |
| 1001 | 1007 |
| 1002 final HGraph graph = new HGraph(); | 1008 final HGraph graph = new HGraph(); |
| 1003 | 1009 |
| 1004 /** | 1010 /** |
| 1005 * The current block to add instructions to. Might be null, if we are | 1011 * The current block to add instructions to. Might be null, if we are |
| 1006 * visiting dead code, but see [isReachable]. | 1012 * visiting dead code, but see [isReachable]. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 /// Returns `true` if the current element is an `async` function. | 1080 /// Returns `true` if the current element is an `async` function. |
| 1075 bool get isBuildingAsyncFunction { | 1081 bool get isBuildingAsyncFunction { |
| 1076 Element element = sourceElement; | 1082 Element element = sourceElement; |
| 1077 return (element is FunctionElement && | 1083 return (element is FunctionElement && |
| 1078 element.asyncMarker == AsyncMarker.ASYNC); | 1084 element.asyncMarker == AsyncMarker.ASYNC); |
| 1079 } | 1085 } |
| 1080 | 1086 |
| 1081 SsaBuilder(JavaScriptBackend backend, | 1087 SsaBuilder(JavaScriptBackend backend, |
| 1082 CodegenWorkItem work, | 1088 CodegenWorkItem work, |
| 1083 this.nativeEmitter, | 1089 this.nativeEmitter, |
| 1084 this.generateSourceMap) | 1090 SourceInformationFactory sourceInformationFactory) |
| 1085 : this.compiler = backend.compiler, | 1091 : this.compiler = backend.compiler, |
| 1086 this.backend = backend, | 1092 this.backend = backend, |
| 1087 this.constantSystem = backend.constantSystem, | 1093 this.constantSystem = backend.constantSystem, |
| 1088 this.work = work, | 1094 this.work = work, |
| 1089 this.rti = backend.rti, | 1095 this.rti = backend.rti, |
| 1090 super(work.resolutionTree) { | 1096 super(work.resolutionTree) { |
| 1091 localsHandler = new LocalsHandler(this, work.element); | 1097 localsHandler = new LocalsHandler(this, work.element); |
| 1092 sourceElementStack.add(work.element); | 1098 sourceElementStack.add(work.element); |
| 1099 sourceInformationBuilder = |
| 1100 sourceInformationFactory.forContext(work.element.implementation); |
| 1093 } | 1101 } |
| 1094 | 1102 |
| 1095 CodegenRegistry get registry => work.registry; | 1103 CodegenRegistry get registry => work.registry; |
| 1096 | 1104 |
| 1097 /// Returns the current source element. | 1105 /// Returns the current source element. |
| 1098 /// | 1106 /// |
| 1099 /// The returned element is a declaration element. | 1107 /// The returned element is a declaration element. |
| 1100 // TODO(johnniwinther): Check that all usages of sourceElement agree on | 1108 // TODO(johnniwinther): Check that all usages of sourceElement agree on |
| 1101 // implementation/declaration distinction. | 1109 // implementation/declaration distinction. |
| 1102 Element get sourceElement => sourceElementStack.last; | 1110 Element get sourceElement => sourceElementStack.last; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 } | 1161 } |
| 1154 | 1162 |
| 1155 void add(HInstruction instruction) { | 1163 void add(HInstruction instruction) { |
| 1156 current.add(instruction); | 1164 current.add(instruction); |
| 1157 } | 1165 } |
| 1158 | 1166 |
| 1159 void addWithPosition(HInstruction instruction, ast.Node node) { | 1167 void addWithPosition(HInstruction instruction, ast.Node node) { |
| 1160 add(attachPosition(instruction, node)); | 1168 add(attachPosition(instruction, node)); |
| 1161 } | 1169 } |
| 1162 | 1170 |
| 1163 SourceFile currentSourceFile() { | |
| 1164 return sourceElement.implementation.compilationUnit.script.file; | |
| 1165 } | |
| 1166 | |
| 1167 void checkValidSourceFileLocation( | |
| 1168 SourceLocation location, SourceFile sourceFile, int offset) { | |
| 1169 if (!location.isValid) { | |
| 1170 throw MessageKind.INVALID_SOURCE_FILE_LOCATION.message( | |
| 1171 {'offset': offset, | |
| 1172 'fileName': sourceFile.filename, | |
| 1173 'length': sourceFile.length}); | |
| 1174 } | |
| 1175 } | |
| 1176 | |
| 1177 /** | 1171 /** |
| 1178 * Returns a complete argument list for a call of [function]. | 1172 * Returns a complete argument list for a call of [function]. |
| 1179 */ | 1173 */ |
| 1180 List<HInstruction> completeSendArgumentsList( | 1174 List<HInstruction> completeSendArgumentsList( |
| 1181 FunctionElement function, | 1175 FunctionElement function, |
| 1182 Selector selector, | 1176 Selector selector, |
| 1183 List<HInstruction> providedArguments, | 1177 List<HInstruction> providedArguments, |
| 1184 ast.Node currentNode) { | 1178 ast.Node currentNode) { |
| 1185 assert(invariant(function, function.isImplementation)); | 1179 assert(invariant(function, function.isImplementation)); |
| 1186 assert(providedArguments != null); | 1180 assert(providedArguments != null); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1453 bool isCalledOnce(Element element) { | 1447 bool isCalledOnce(Element element) { |
| 1454 if (!allInlinedFunctionsCalledOnce) return false; | 1448 if (!allInlinedFunctionsCalledOnce) return false; |
| 1455 TypesInferrer inferrer = compiler.typesTask.typesInferrer; | 1449 TypesInferrer inferrer = compiler.typesTask.typesInferrer; |
| 1456 return inferrer.isCalledOnce(element); | 1450 return inferrer.isCalledOnce(element); |
| 1457 } | 1451 } |
| 1458 | 1452 |
| 1459 inlinedFrom(Element element, f()) { | 1453 inlinedFrom(Element element, f()) { |
| 1460 assert(element is FunctionElement || element is VariableElement); | 1454 assert(element is FunctionElement || element is VariableElement); |
| 1461 return compiler.withCurrentElement(element, () { | 1455 return compiler.withCurrentElement(element, () { |
| 1462 // The [sourceElementStack] contains declaration elements. | 1456 // The [sourceElementStack] contains declaration elements. |
| 1457 SourceInformationBuilder oldSourceInformationBuilder = |
| 1458 sourceInformationBuilder; |
| 1459 sourceInformationBuilder = |
| 1460 sourceInformationBuilder.forContext(element.implementation); |
| 1463 sourceElementStack.add(element.declaration); | 1461 sourceElementStack.add(element.declaration); |
| 1464 var result = f(); | 1462 var result = f(); |
| 1463 sourceInformationBuilder = oldSourceInformationBuilder; |
| 1465 sourceElementStack.removeLast(); | 1464 sourceElementStack.removeLast(); |
| 1466 return result; | 1465 return result; |
| 1467 }); | 1466 }); |
| 1468 } | 1467 } |
| 1469 | 1468 |
| 1470 HInstruction handleConstantForOptionalParameter(Element parameter) { | 1469 HInstruction handleConstantForOptionalParameter(Element parameter) { |
| 1471 ConstantExpression constant = | 1470 ConstantExpression constant = |
| 1472 backend.constants.getConstantForVariable(parameter); | 1471 backend.constants.getConstantForVariable(parameter); |
| 1473 assert(invariant(parameter, constant != null, | 1472 assert(invariant(parameter, constant != null, |
| 1474 message: 'No constant computed for $parameter')); | 1473 message: 'No constant computed for $parameter')); |
| (...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2506 value, | 2505 value, |
| 2507 compiler.boolClass.rawType, | 2506 compiler.boolClass.rawType, |
| 2508 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 2507 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
| 2509 } | 2508 } |
| 2510 HInstruction result = new HBoolify(value, backend.boolType); | 2509 HInstruction result = new HBoolify(value, backend.boolType); |
| 2511 add(result); | 2510 add(result); |
| 2512 return result; | 2511 return result; |
| 2513 } | 2512 } |
| 2514 | 2513 |
| 2515 HInstruction attachPosition(HInstruction target, ast.Node node) { | 2514 HInstruction attachPosition(HInstruction target, ast.Node node) { |
| 2516 if (generateSourceMap && node != null) { | 2515 if (node != null) { |
| 2517 target.sourceInformation = sourceInformationForBeginToken(node); | 2516 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); |
| 2518 } | 2517 } |
| 2519 return target; | 2518 return target; |
| 2520 } | 2519 } |
| 2521 | 2520 |
| 2522 SourceInformation sourceInformationForBeginToken(ast.Node node) { | |
| 2523 return new StartEndSourceInformation(sourceFileLocationForBeginToken(node)); | |
| 2524 } | |
| 2525 | |
| 2526 SourceInformation sourceInformationForBeginEndToken(ast.Node node) { | |
| 2527 return new StartEndSourceInformation( | |
| 2528 sourceFileLocationForBeginToken(node), | |
| 2529 sourceFileLocationForEndToken(node)); | |
| 2530 } | |
| 2531 | |
| 2532 SourceLocation sourceFileLocationForBeginToken(ast.Node node) => | |
| 2533 sourceFileLocationForToken(node, node.getBeginToken()); | |
| 2534 | |
| 2535 SourceLocation sourceFileLocationForEndToken(ast.Node node) => | |
| 2536 sourceFileLocationForToken(node, node.getEndToken()); | |
| 2537 | |
| 2538 SourceLocation sourceFileLocationForToken(ast.Node node, Token token) { | |
| 2539 SourceFile sourceFile = currentSourceFile(); | |
| 2540 SourceLocation location = | |
| 2541 new TokenSourceLocation(sourceFile, token, sourceElement.name); | |
| 2542 checkValidSourceFileLocation(location, sourceFile, token.charOffset); | |
| 2543 return location; | |
| 2544 } | |
| 2545 | |
| 2546 void visit(ast.Node node) { | 2521 void visit(ast.Node node) { |
| 2547 if (node != null) node.accept(this); | 2522 if (node != null) node.accept(this); |
| 2548 } | 2523 } |
| 2549 | 2524 |
| 2550 visitBlock(ast.Block node) { | 2525 visitBlock(ast.Block node) { |
| 2551 assert(!isAborted()); | 2526 assert(!isAborted()); |
| 2552 if (!isReachable) return; // This can only happen when inlining. | 2527 if (!isReachable) return; // This can only happen when inlining. |
| 2553 for (Link<ast.Node> link = node.statements.nodes; | 2528 for (Link<ast.Node> link = node.statements.nodes; |
| 2554 !link.isEmpty; | 2529 !link.isEmpty; |
| 2555 link = link.tail) { | 2530 link = link.tail) { |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2805 conditionBlock.postProcessLoopHeader(); | 2780 conditionBlock.postProcessLoopHeader(); |
| 2806 HLoopBlockInformation info = | 2781 HLoopBlockInformation info = |
| 2807 new HLoopBlockInformation( | 2782 new HLoopBlockInformation( |
| 2808 HLoopBlockInformation.loopType(loop), | 2783 HLoopBlockInformation.loopType(loop), |
| 2809 wrapExpressionGraph(initializerGraph), | 2784 wrapExpressionGraph(initializerGraph), |
| 2810 wrapExpressionGraph(conditionExpression), | 2785 wrapExpressionGraph(conditionExpression), |
| 2811 wrapStatementGraph(bodyGraph), | 2786 wrapStatementGraph(bodyGraph), |
| 2812 wrapExpressionGraph(updateGraph), | 2787 wrapExpressionGraph(updateGraph), |
| 2813 conditionBlock.loopInformation.target, | 2788 conditionBlock.loopInformation.target, |
| 2814 conditionBlock.loopInformation.labels, | 2789 conditionBlock.loopInformation.labels, |
| 2815 sourceInformationForBeginEndToken(loop)); | 2790 sourceInformationBuilder.buildLoop(loop)); |
| 2816 | 2791 |
| 2817 startBlock.setBlockFlow(info, current); | 2792 startBlock.setBlockFlow(info, current); |
| 2818 loopInfo.loopBlockInformation = info; | 2793 loopInfo.loopBlockInformation = info; |
| 2819 } else { | 2794 } else { |
| 2820 // The body of the for/while loop always aborts, so there is no back edge. | 2795 // The body of the for/while loop always aborts, so there is no back edge. |
| 2821 // We turn the code into: | 2796 // We turn the code into: |
| 2822 // if (condition) { | 2797 // if (condition) { |
| 2823 // body; | 2798 // body; |
| 2824 // } else { | 2799 // } else { |
| 2825 // // We always create an empty else block to avoid critical edges. | 2800 // // We always create an empty else block to avoid critical edges. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3022 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); | 2997 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); |
| 3023 HLoopBlockInformation loopBlockInfo = | 2998 HLoopBlockInformation loopBlockInfo = |
| 3024 new HLoopBlockInformation( | 2999 new HLoopBlockInformation( |
| 3025 HLoopBlockInformation.DO_WHILE_LOOP, | 3000 HLoopBlockInformation.DO_WHILE_LOOP, |
| 3026 null, | 3001 null, |
| 3027 wrapExpressionGraph(conditionExpression), | 3002 wrapExpressionGraph(conditionExpression), |
| 3028 wrapStatementGraph(bodyGraph), | 3003 wrapStatementGraph(bodyGraph), |
| 3029 null, | 3004 null, |
| 3030 loopEntryBlock.loopInformation.target, | 3005 loopEntryBlock.loopInformation.target, |
| 3031 loopEntryBlock.loopInformation.labels, | 3006 loopEntryBlock.loopInformation.labels, |
| 3032 sourceInformationForBeginEndToken(node)); | 3007 sourceInformationBuilder.buildLoop(node)); |
| 3033 loopEntryBlock.setBlockFlow(loopBlockInfo, current); | 3008 loopEntryBlock.setBlockFlow(loopBlockInfo, current); |
| 3034 loopInfo.loopBlockInformation = loopBlockInfo; | 3009 loopInfo.loopBlockInformation = loopBlockInfo; |
| 3035 } else { | 3010 } else { |
| 3036 // Since the loop has no back edge, we remove the loop information on the | 3011 // Since the loop has no back edge, we remove the loop information on the |
| 3037 // header. | 3012 // header. |
| 3038 loopEntryBlock.loopInformation = null; | 3013 loopEntryBlock.loopInformation = null; |
| 3039 | 3014 |
| 3040 if (jumpHandler.hasAnyBreak()) { | 3015 if (jumpHandler.hasAnyBreak()) { |
| 3041 // Null branchBlock because the body of the do-while loop always aborts, | 3016 // Null branchBlock because the body of the do-while loop always aborts, |
| 3042 // so we never get to the condition. | 3017 // so we never get to the condition. |
| (...skipping 4090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7133 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7108 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 7134 unaliased.accept(this, builder); | 7109 unaliased.accept(this, builder); |
| 7135 } | 7110 } |
| 7136 | 7111 |
| 7137 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7112 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 7138 JavaScriptBackend backend = builder.compiler.backend; | 7113 JavaScriptBackend backend = builder.compiler.backend; |
| 7139 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7114 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 7140 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7115 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 7141 } | 7116 } |
| 7142 } | 7117 } |
| OLD | NEW |