Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: pkg/compiler/lib/src/ssa/codegen.dart

Issue 2569733002: Even less reliance on Compiler.closedWorld (Closed)
Patch Set: Updated cf. comments. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 import 'dart:math' as math; 5 import 'dart:math' as math;
6 import '../common.dart'; 6 import '../common.dart';
7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
8 import '../common/tasks.dart' show CompilerTask; 8 import '../common/tasks.dart' show CompilerTask;
9 import '../compiler.dart' show Compiler; 9 import '../compiler.dart' show Compiler;
10 import '../constants/constant_system.dart'; 10 import '../constants/constant_system.dart';
11 import '../constants/values.dart'; 11 import '../constants/values.dart';
12 import '../core_types.dart' show CoreClasses; 12 import '../core_types.dart' show CommonElements;
13 import '../dart_types.dart'; 13 import '../dart_types.dart';
14 import '../elements/elements.dart'; 14 import '../elements/elements.dart';
15 import '../elements/entities.dart'; 15 import '../elements/entities.dart';
16 import '../io/source_information.dart'; 16 import '../io/source_information.dart';
17 import '../js/js.dart' as js; 17 import '../js/js.dart' as js;
18 import '../js_backend/backend_helpers.dart' show BackendHelpers; 18 import '../js_backend/backend_helpers.dart' show BackendHelpers;
19 import '../js_backend/js_backend.dart'; 19 import '../js_backend/js_backend.dart';
20 import '../js_emitter/js_emitter.dart' show NativeEmitter; 20 import '../js_emitter/js_emitter.dart' show NativeEmitter;
21 import '../native/native.dart' as native; 21 import '../native/native.dart' as native;
22 import '../types/types.dart'; 22 import '../types/types.dart';
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 CodegenRegistry get registry => work.registry; 186 CodegenRegistry get registry => work.registry;
187 187
188 BackendHelpers get helpers => backend.helpers; 188 BackendHelpers get helpers => backend.helpers;
189 189
190 native.NativeEnqueuer get nativeEnqueuer { 190 native.NativeEnqueuer get nativeEnqueuer {
191 return compiler.enqueuer.codegen.nativeEnqueuer; 191 return compiler.enqueuer.codegen.nativeEnqueuer;
192 } 192 }
193 193
194 DiagnosticReporter get reporter => compiler.reporter; 194 DiagnosticReporter get reporter => compiler.reporter;
195 195
196 CoreClasses get coreClasses => compiler.coreClasses; 196 CommonElements get commonElements => closedWorld.commonElements;
197 197
198 bool isGenerateAtUseSite(HInstruction instruction) { 198 bool isGenerateAtUseSite(HInstruction instruction) {
199 return generateAtUseSite.contains(instruction); 199 return generateAtUseSite.contains(instruction);
200 } 200 }
201 201
202 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { 202 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) {
203 for (HInstruction user in instruction.usedBy) { 203 for (HInstruction user in instruction.usedBy) {
204 if (user is HPhi) { 204 if (user is HPhi) {
205 if (!phiSet.contains(user)) { 205 if (!phiSet.contains(user)) {
206 phiSet.add(user); 206 phiSet.add(user);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 */ 300 */
301 push(js.Expression expression) { 301 push(js.Expression expression) {
302 expressionStack.add(expression); 302 expressionStack.add(expression);
303 } 303 }
304 304
305 js.Expression pop() { 305 js.Expression pop() {
306 return expressionStack.removeLast(); 306 return expressionStack.removeLast();
307 } 307 }
308 308
309 void preGenerateMethod(HGraph graph) { 309 void preGenerateMethod(HGraph graph) {
310 new SsaInstructionSelection(compiler).visitGraph(graph); 310 new SsaInstructionSelection(compiler, closedWorld).visitGraph(graph);
311 new SsaTypeKnownRemover().visitGraph(graph); 311 new SsaTypeKnownRemover().visitGraph(graph);
312 new SsaTrustedCheckRemover(compiler).visitGraph(graph); 312 new SsaTrustedCheckRemover(compiler).visitGraph(graph);
313 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph); 313 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph);
314 new SsaConditionMerger(generateAtUseSite, controlFlowOperators) 314 new SsaConditionMerger(generateAtUseSite, controlFlowOperators)
315 .visitGraph(graph); 315 .visitGraph(graph);
316 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder( 316 SsaLiveIntervalBuilder intervalBuilder = new SsaLiveIntervalBuilder(
317 compiler, generateAtUseSite, controlFlowOperators); 317 compiler, generateAtUseSite, controlFlowOperators);
318 intervalBuilder.visitGraph(graph); 318 intervalBuilder.visitGraph(graph);
319 SsaVariableAllocator allocator = new SsaVariableAllocator( 319 SsaVariableAllocator allocator = new SsaVariableAllocator(
320 compiler, 320 compiler,
(...skipping 1321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1642 // TODO(herhut): The namer should return the appropriate backendname here. 1642 // TODO(herhut): The namer should return the appropriate backendname here.
1643 if (target != null && !node.isInterceptedCall) { 1643 if (target != null && !node.isInterceptedCall) {
1644 if (target == helpers.jsArrayAdd) { 1644 if (target == helpers.jsArrayAdd) {
1645 methodName = 'push'; 1645 methodName = 'push';
1646 } else if (target == helpers.jsArrayRemoveLast) { 1646 } else if (target == helpers.jsArrayRemoveLast) {
1647 methodName = 'pop'; 1647 methodName = 'pop';
1648 } else if (target == helpers.jsStringSplit) { 1648 } else if (target == helpers.jsStringSplit) {
1649 methodName = 'split'; 1649 methodName = 'split';
1650 // Split returns a List, so we make sure the backend knows the 1650 // Split returns a List, so we make sure the backend knows the
1651 // list class is instantiated. 1651 // list class is instantiated.
1652 registry.registerInstantiatedClass(coreClasses.listClass); 1652 registry.registerInstantiatedClass(commonElements.listClass);
1653 } else if (backend.isNative(target) && 1653 } else if (backend.isNative(target) &&
1654 target.isFunction && 1654 target.isFunction &&
1655 !node.isInterceptedCall) { 1655 !node.isInterceptedCall) {
1656 // A direct (i.e. non-interceptor) native call is the result of 1656 // A direct (i.e. non-interceptor) native call is the result of
1657 // optimization. The optimization ensures any type checks or 1657 // optimization. The optimization ensures any type checks or
1658 // conversions have been satisified. 1658 // conversions have been satisified.
1659 methodName = backend.nativeData.getFixedBackendName(target); 1659 methodName = backend.nativeData.getFixedBackendName(target);
1660 } 1660 }
1661 } 1661 }
1662 1662
(...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after
2398 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG)); 2398 new StaticUse.staticInvoke(convertToString, CallStructure.ONE_ARG));
2399 js.Expression jsHelper = 2399 js.Expression jsHelper =
2400 backend.emitter.staticFunctionAccess(convertToString); 2400 backend.emitter.staticFunctionAccess(convertToString);
2401 use(input); 2401 use(input);
2402 push(new js.Call(jsHelper, <js.Expression>[pop()], 2402 push(new js.Call(jsHelper, <js.Expression>[pop()],
2403 sourceInformation: node.sourceInformation)); 2403 sourceInformation: node.sourceInformation));
2404 } 2404 }
2405 } 2405 }
2406 2406
2407 void visitLiteralList(HLiteralList node) { 2407 void visitLiteralList(HLiteralList node) {
2408 registry.registerInstantiatedClass(coreClasses.listClass); 2408 registry.registerInstantiatedClass(commonElements.listClass);
2409 generateArrayLiteral(node); 2409 generateArrayLiteral(node);
2410 } 2410 }
2411 2411
2412 void generateArrayLiteral(HLiteralList node) { 2412 void generateArrayLiteral(HLiteralList node) {
2413 List<js.Expression> elements = node.inputs.map((HInstruction input) { 2413 List<js.Expression> elements = node.inputs.map((HInstruction input) {
2414 use(input); 2414 use(input);
2415 return pop(); 2415 return pop();
2416 }).toList(); 2416 }).toList();
2417 push(new js.ArrayInitializer(elements) 2417 push(new js.ArrayInitializer(elements)
2418 .withSourceInformation(node.sourceInformation)); 2418 .withSourceInformation(node.sourceInformation));
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2627 } 2627 }
2628 registry.registerInstantiation(type); 2628 registry.registerInstantiation(type);
2629 } 2629 }
2630 2630
2631 void handleNumberOrStringSupertypeCheck( 2631 void handleNumberOrStringSupertypeCheck(
2632 HInstruction input, 2632 HInstruction input,
2633 HInstruction interceptor, 2633 HInstruction interceptor,
2634 DartType type, 2634 DartType type,
2635 SourceInformation sourceInformation, 2635 SourceInformation sourceInformation,
2636 {bool negative: false}) { 2636 {bool negative: false}) {
2637 assert(!identical(type.element, coreClasses.listClass) && 2637 assert(!identical(type.element, commonElements.listClass) &&
2638 !Elements.isListSupertype(type.element, compiler) && 2638 !Elements.isListSupertype(type.element, commonElements) &&
2639 !Elements.isStringOnlySupertype(type.element, compiler)); 2639 !Elements.isStringOnlySupertype(type.element, commonElements));
2640 String relation = negative ? '!==' : '==='; 2640 String relation = negative ? '!==' : '===';
2641 checkNum(input, relation, sourceInformation); 2641 checkNum(input, relation, sourceInformation);
2642 js.Expression numberTest = pop(); 2642 js.Expression numberTest = pop();
2643 checkString(input, relation, sourceInformation); 2643 checkString(input, relation, sourceInformation);
2644 js.Expression stringTest = pop(); 2644 js.Expression stringTest = pop();
2645 checkObject(input, relation, sourceInformation); 2645 checkObject(input, relation, sourceInformation);
2646 js.Expression objectTest = pop(); 2646 js.Expression objectTest = pop();
2647 checkType(input, interceptor, type, sourceInformation, negative: negative); 2647 checkType(input, interceptor, type, sourceInformation, negative: negative);
2648 String combiner = negative ? '&&' : '||'; 2648 String combiner = negative ? '&&' : '||';
2649 String combiner2 = negative ? '||' : '&&'; 2649 String combiner2 = negative ? '||' : '&&';
2650 push(new js.Binary( 2650 push(new js.Binary(
2651 combiner, 2651 combiner,
2652 new js.Binary(combiner, numberTest, stringTest) 2652 new js.Binary(combiner, numberTest, stringTest)
2653 .withSourceInformation(sourceInformation), 2653 .withSourceInformation(sourceInformation),
2654 new js.Binary(combiner2, objectTest, pop()) 2654 new js.Binary(combiner2, objectTest, pop())
2655 .withSourceInformation(sourceInformation)) 2655 .withSourceInformation(sourceInformation))
2656 .withSourceInformation(sourceInformation)); 2656 .withSourceInformation(sourceInformation));
2657 } 2657 }
2658 2658
2659 void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor, 2659 void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor,
2660 DartType type, SourceInformation sourceInformation, 2660 DartType type, SourceInformation sourceInformation,
2661 {bool negative: false}) { 2661 {bool negative: false}) {
2662 assert(!identical(type.element, coreClasses.listClass) && 2662 assert(!identical(type.element, commonElements.listClass) &&
2663 !Elements.isListSupertype(type.element, compiler) && 2663 !Elements.isListSupertype(type.element, commonElements) &&
2664 !Elements.isNumberOrStringSupertype(type.element, compiler)); 2664 !Elements.isNumberOrStringSupertype(type.element, commonElements));
2665 String relation = negative ? '!==' : '==='; 2665 String relation = negative ? '!==' : '===';
2666 checkString(input, relation, sourceInformation); 2666 checkString(input, relation, sourceInformation);
2667 js.Expression stringTest = pop(); 2667 js.Expression stringTest = pop();
2668 checkObject(input, relation, sourceInformation); 2668 checkObject(input, relation, sourceInformation);
2669 js.Expression objectTest = pop(); 2669 js.Expression objectTest = pop();
2670 checkType(input, interceptor, type, sourceInformation, negative: negative); 2670 checkType(input, interceptor, type, sourceInformation, negative: negative);
2671 String combiner = negative ? '||' : '&&'; 2671 String combiner = negative ? '||' : '&&';
2672 push(new js.Binary(negative ? '&&' : '||', stringTest, 2672 push(new js.Binary(negative ? '&&' : '||', stringTest,
2673 new js.Binary(combiner, objectTest, pop()))); 2673 new js.Binary(combiner, objectTest, pop())));
2674 } 2674 }
2675 2675
2676 void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor, 2676 void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor,
2677 DartType type, SourceInformation sourceInformation, 2677 DartType type, SourceInformation sourceInformation,
2678 {bool negative: false}) { 2678 {bool negative: false}) {
2679 assert(!identical(type.element, coreClasses.stringClass) && 2679 assert(!identical(type.element, commonElements.stringClass) &&
2680 !Elements.isStringOnlySupertype(type.element, compiler) && 2680 !Elements.isStringOnlySupertype(type.element, commonElements) &&
2681 !Elements.isNumberOrStringSupertype(type.element, compiler)); 2681 !Elements.isNumberOrStringSupertype(type.element, commonElements));
2682 String relation = negative ? '!==' : '==='; 2682 String relation = negative ? '!==' : '===';
2683 checkObject(input, relation, sourceInformation); 2683 checkObject(input, relation, sourceInformation);
2684 js.Expression objectTest = pop(); 2684 js.Expression objectTest = pop();
2685 checkArray(input, relation); 2685 checkArray(input, relation);
2686 js.Expression arrayTest = pop(); 2686 js.Expression arrayTest = pop();
2687 checkType(input, interceptor, type, sourceInformation, negative: negative); 2687 checkType(input, interceptor, type, sourceInformation, negative: negative);
2688 String combiner = negative ? '&&' : '||'; 2688 String combiner = negative ? '&&' : '||';
2689 push(new js.Binary(negative ? '||' : '&&', objectTest, 2689 push(new js.Binary(negative ? '||' : '&&', objectTest,
2690 new js.Binary(combiner, arrayTest, pop())) 2690 new js.Binary(combiner, arrayTest, pop()))
2691 .withSourceInformation(sourceInformation)); 2691 .withSourceInformation(sourceInformation));
(...skipping 16 matching lines...) Expand all
2708 // be changed to match. 2708 // be changed to match.
2709 assert(relation == '===' || relation == '!=='); 2709 assert(relation == '===' || relation == '!==');
2710 bool negative = relation == '!=='; 2710 bool negative = relation == '!==';
2711 2711
2712 if (node.isVariableCheck || node.isCompoundCheck) { 2712 if (node.isVariableCheck || node.isCompoundCheck) {
2713 use(node.checkCall); 2713 use(node.checkCall);
2714 if (negative) push(new js.Prefix('!', pop())); 2714 if (negative) push(new js.Prefix('!', pop()));
2715 } else { 2715 } else {
2716 assert(node.isRawCheck); 2716 assert(node.isRawCheck);
2717 HInstruction interceptor = node.interceptor; 2717 HInstruction interceptor = node.interceptor;
2718 ClassElement objectClass = coreClasses.objectClass; 2718 ClassElement objectClass = commonElements.objectClass;
2719 Element element = type.element; 2719 Element element = type.element;
2720 if (element == coreClasses.nullClass) { 2720 if (element == commonElements.nullClass) {
2721 if (negative) { 2721 if (negative) {
2722 checkNonNull(input); 2722 checkNonNull(input);
2723 } else { 2723 } else {
2724 checkNull(input); 2724 checkNull(input);
2725 } 2725 }
2726 } else if (identical(element, objectClass) || type.treatAsDynamic) { 2726 } else if (identical(element, objectClass) || type.treatAsDynamic) {
2727 // The constant folder also does this optimization, but we make 2727 // The constant folder also does this optimization, but we make
2728 // it safe by assuming it may have not run. 2728 // it safe by assuming it may have not run.
2729 push(newLiteralBool(!negative, sourceInformation)); 2729 push(newLiteralBool(!negative, sourceInformation));
2730 } else if (element == coreClasses.stringClass) { 2730 } else if (element == commonElements.stringClass) {
2731 checkString(input, relation, sourceInformation); 2731 checkString(input, relation, sourceInformation);
2732 } else if (element == coreClasses.doubleClass) { 2732 } else if (element == commonElements.doubleClass) {
2733 checkDouble(input, relation, sourceInformation); 2733 checkDouble(input, relation, sourceInformation);
2734 } else if (element == coreClasses.numClass) { 2734 } else if (element == commonElements.numClass) {
2735 checkNum(input, relation, sourceInformation); 2735 checkNum(input, relation, sourceInformation);
2736 } else if (element == coreClasses.boolClass) { 2736 } else if (element == commonElements.boolClass) {
2737 checkBool(input, relation, sourceInformation); 2737 checkBool(input, relation, sourceInformation);
2738 } else if (element == coreClasses.intClass) { 2738 } else if (element == commonElements.intClass) {
2739 // The is check in the code tells us that it might not be an 2739 // The is check in the code tells us that it might not be an
2740 // int. So we do a typeof first to avoid possible 2740 // int. So we do a typeof first to avoid possible
2741 // deoptimizations on the JS engine due to the Math.floor check. 2741 // deoptimizations on the JS engine due to the Math.floor check.
2742 checkNum(input, relation, sourceInformation); 2742 checkNum(input, relation, sourceInformation);
2743 js.Expression numTest = pop(); 2743 js.Expression numTest = pop();
2744 checkBigInt(input, relation, sourceInformation); 2744 checkBigInt(input, relation, sourceInformation);
2745 push(new js.Binary(negative ? '||' : '&&', numTest, pop()) 2745 push(new js.Binary(negative ? '||' : '&&', numTest, pop())
2746 .withSourceInformation(sourceInformation)); 2746 .withSourceInformation(sourceInformation));
2747 } else if (node.useInstanceOf) { 2747 } else if (node.useInstanceOf) {
2748 assert(interceptor == null); 2748 assert(interceptor == null);
2749 checkTypeViaInstanceof(input, type, sourceInformation, 2749 checkTypeViaInstanceof(input, type, sourceInformation,
2750 negative: negative); 2750 negative: negative);
2751 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { 2751 } else if (Elements.isNumberOrStringSupertype(element, commonElements)) {
2752 handleNumberOrStringSupertypeCheck( 2752 handleNumberOrStringSupertypeCheck(
2753 input, interceptor, type, sourceInformation, 2753 input, interceptor, type, sourceInformation,
2754 negative: negative); 2754 negative: negative);
2755 } else if (Elements.isStringOnlySupertype(element, compiler)) { 2755 } else if (Elements.isStringOnlySupertype(element, commonElements)) {
2756 handleStringSupertypeCheck(input, interceptor, type, sourceInformation, 2756 handleStringSupertypeCheck(input, interceptor, type, sourceInformation,
2757 negative: negative); 2757 negative: negative);
2758 } else if (identical(element, coreClasses.listClass) || 2758 } else if (identical(element, commonElements.listClass) ||
2759 Elements.isListSupertype(element, compiler)) { 2759 Elements.isListSupertype(element, commonElements)) {
2760 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation, 2760 handleListOrSupertypeCheck(input, interceptor, type, sourceInformation,
2761 negative: negative); 2761 negative: negative);
2762 } else if (type.isFunctionType) { 2762 } else if (type.isFunctionType) {
2763 checkType(input, interceptor, type, sourceInformation, 2763 checkType(input, interceptor, type, sourceInformation,
2764 negative: negative); 2764 negative: negative);
2765 } else if ((input.canBePrimitive(closedWorld) && 2765 } else if ((input.canBePrimitive(closedWorld) &&
2766 !input.canBePrimitiveArray(closedWorld)) || 2766 !input.canBePrimitiveArray(closedWorld)) ||
2767 input.canBeNull()) { 2767 input.canBeNull()) {
2768 checkObject(input, relation, node.sourceInformation); 2768 checkObject(input, relation, node.sourceInformation);
2769 js.Expression objectTest = pop(); 2769 js.Expression objectTest = pop();
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
2993 js.Expression result = backend.rtiEncoder.getTypeRepresentation( 2993 js.Expression result = backend.rtiEncoder.getTypeRepresentation(
2994 node.dartType, (TypeVariableType variable) => arguments[index++]); 2994 node.dartType, (TypeVariableType variable) => arguments[index++]);
2995 assert(index == node.inputs.length); 2995 assert(index == node.inputs.length);
2996 push(result); 2996 push(result);
2997 return; 2997 return;
2998 2998
2999 case TypeInfoExpressionKind.INSTANCE: 2999 case TypeInfoExpressionKind.INSTANCE:
3000 // We expect only flat types for the INSTANCE representation. 3000 // We expect only flat types for the INSTANCE representation.
3001 assert( 3001 assert(
3002 node.dartType == (node.dartType.element as ClassElement).thisType); 3002 node.dartType == (node.dartType.element as ClassElement).thisType);
3003 registry.registerInstantiatedClass(coreClasses.listClass); 3003 registry.registerInstantiatedClass(commonElements.listClass);
3004 push(new js.ArrayInitializer(arguments) 3004 push(new js.ArrayInitializer(arguments)
3005 .withSourceInformation(node.sourceInformation)); 3005 .withSourceInformation(node.sourceInformation));
3006 } 3006 }
3007 } 3007 }
3008 3008
3009 bool typeVariableAccessNeedsSubstitution( 3009 bool typeVariableAccessNeedsSubstitution(
3010 TypeVariableElement element, TypeMask receiverMask) { 3010 TypeVariableElement element, TypeMask receiverMask) {
3011 ClassElement cls = element.enclosingClass; 3011 ClassElement cls = element.enclosingClass;
3012 3012
3013 // See if the receiver type narrows the set of classes to ones that can be 3013 // See if the receiver type narrows the set of classes to ones that can be
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
3094 registry.registerStaticUse(new StaticUse.staticInvoke( 3094 registry.registerStaticUse(new StaticUse.staticInvoke(
3095 helper, new CallStructure.unnamed(argumentCount))); 3095 helper, new CallStructure.unnamed(argumentCount)));
3096 return backend.emitter.staticFunctionAccess(helper); 3096 return backend.emitter.staticFunctionAccess(helper);
3097 } 3097 }
3098 3098
3099 @override 3099 @override
3100 void visitRef(HRef node) { 3100 void visitRef(HRef node) {
3101 visit(node.value); 3101 visit(node.value);
3102 } 3102 }
3103 } 3103 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder_kernel.dart ('k') | pkg/compiler/lib/src/ssa/codegen_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698