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

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

Issue 1100723002: Add SourceInformationFactory. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 5 years, 8 months 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 | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/js_backend/js_backend.dart ('k') | pkg/compiler/lib/src/ssa/codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/js_backend.dart ('k') | pkg/compiler/lib/src/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698