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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/codegen.dart

Issue 11275189: Clean up the codegen by not re-computing parameter names. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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
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 SsaCodeGeneratorTask extends CompilerTask { 7 class SsaCodeGeneratorTask extends CompilerTask {
8 8
9 final JavaScriptBackend backend; 9 final JavaScriptBackend backend;
10 10
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 if (work.element.isField()) { 47 if (work.element.isField()) {
48 return generateLazyInitializer(work, graph); 48 return generateLazyInitializer(work, graph);
49 } else { 49 } else {
50 return generateMethod(work, graph); 50 return generateMethod(work, graph);
51 } 51 }
52 } 52 }
53 53
54 CodeBuffer generateLazyInitializer(work, graph) { 54 CodeBuffer generateLazyInitializer(work, graph) {
55 return measure(() { 55 return measure(() {
56 compiler.tracer.traceGraph("codegen", graph); 56 compiler.tracer.traceGraph("codegen", graph);
57 List<js.Parameter> parameters = <js.Parameter>[]; 57 SsaOptimizedCodeGenerator codegen =
58 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( 58 new SsaOptimizedCodeGenerator(backend, work);
59 backend, work, parameters, new Map<Element, String>());
60 codegen.visitGraph(graph); 59 codegen.visitGraph(graph);
61 js.Block body = codegen.body; 60 js.Block body = codegen.body;
62 js.Fun fun = new js.Fun(parameters, body); 61 js.Fun fun = new js.Fun(codegen.parameters, body);
63 return prettyPrint(fun); 62 return prettyPrint(fun);
64 }); 63 });
65 } 64 }
66 65
67 CodeBuffer generateMethod(WorkItem work, HGraph graph) { 66 CodeBuffer generateMethod(WorkItem work, HGraph graph) {
68 return measure(() { 67 return measure(() {
69 JavaScriptItemCompilationContext context = work.compilationContext; 68 JavaScriptItemCompilationContext context = work.compilationContext;
70 HTypeMap types = context.types; 69 HTypeMap types = context.types;
71 graph.exit.predecessors.forEach((block) { 70 graph.exit.predecessors.forEach((block) {
72 assert(block.last is HGoto || block.last is HReturn); 71 assert(block.last is HGoto || block.last is HReturn);
73 if (block.last is HReturn) { 72 if (block.last is HReturn) {
74 backend.registerReturnType(work.element, types[block.last.inputs[0]]); 73 backend.registerReturnType(work.element, types[block.last.inputs[0]]);
75 } else { 74 } else {
76 backend.registerReturnType(work.element, HType.NULL); 75 backend.registerReturnType(work.element, HType.NULL);
77 } 76 }
78 }); 77 });
79 compiler.tracer.traceGraph("codegen", graph); 78 compiler.tracer.traceGraph("codegen", graph);
80 Map<Element, String> parameterNames = getParameterNames(work); 79 SsaOptimizedCodeGenerator codegen =
81 // Use [work.element] to ensure that the parameter element come from 80 new SsaOptimizedCodeGenerator(backend, work);
82 // the declaration.
83 FunctionElement function = work.element;
84 function.computeSignature(compiler).forEachParameter((element) {
85 compiler.enqueuer.codegen.addToWorkList(element, work.resolutionTree);
86 });
87 List<js.Parameter> parameters = <js.Parameter>[];
88 parameterNames.forEach((element, name) {
89 parameters.add(new js.Parameter(name));
90 });
91 addBackendParameters(work.element, parameters, parameterNames);
92 String parametersString = Strings.join(parameterNames.values, ", ");
93 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator(
94 backend, work, parameters, parameterNames);
95 codegen.visitGraph(graph); 81 codegen.visitGraph(graph);
96 82
97 FunctionElement element = work.element; 83 FunctionElement element = work.element;
98 js.Block body; 84 js.Block body;
99 ClassElement enclosingClass = element.getEnclosingClass(); 85 ClassElement enclosingClass = element.getEnclosingClass();
100 bool allowVariableMinification; 86 bool allowVariableMinification;
101 if (element.isInstanceMember() 87 if (element.isInstanceMember()
102 && enclosingClass.isNative() 88 && enclosingClass.isNative()
103 && native.isOverriddenMethod( 89 && native.isOverriddenMethod(
104 element, enclosingClass, nativeEmitter)) { 90 element, enclosingClass, nativeEmitter)) {
105 // Record that this method is overridden. In case of optional 91 // Record that this method is overridden. In case of optional
106 // arguments, the emitter will generate stubs to handle them, 92 // arguments, the emitter will generate stubs to handle them,
107 // and needs to know if the method is overridden. 93 // and needs to know if the method is overridden.
108 nativeEmitter.overriddenMethods.add(element); 94 nativeEmitter.overriddenMethods.add(element);
109 StringBuffer buffer = new StringBuffer(); 95 StringBuffer buffer = new StringBuffer();
110 String codeString = prettyPrint(codegen.body).toString(); 96 String codeString = prettyPrint(codegen.body).toString();
97 String parametersString = Strings.join(codegen.parameterNames.values, ", ");
floitsch 2012/11/07 14:44:37 80chars.
ngeoffray 2012/11/07 14:47:48 Done.
111 native.generateMethodWithPrototypeCheckForElement( 98 native.generateMethodWithPrototypeCheckForElement(
112 compiler, buffer, element, codeString, parametersString); 99 compiler, buffer, element, codeString, parametersString);
113 js.Node nativeCode = new js.LiteralStatement(buffer.toString()); 100 js.Node nativeCode = new js.LiteralStatement(buffer.toString());
114 body = new js.Block(<js.Statement>[nativeCode]); 101 body = new js.Block(<js.Statement>[nativeCode]);
115 allowVariableMinification = false; 102 allowVariableMinification = false;
116 } else { 103 } else {
117 body = codegen.body; 104 body = codegen.body;
118 allowVariableMinification = !codegen.visitedForeignCode; 105 allowVariableMinification = !codegen.visitedForeignCode;
119 } 106 }
120 js.Fun fun = buildJavaScriptFunction(element, parameters, body); 107 js.Fun fun = buildJavaScriptFunction(element, codegen.parameters, body);
121 return prettyPrint(fun, 108 return prettyPrint(fun,
122 allowVariableMinification: allowVariableMinification); 109 allowVariableMinification: allowVariableMinification);
123 }); 110 });
124 } 111 }
125 112
126 void addBackendParameter(Element element,
127 List<js.Parameter> parameters,
128 Map<Element, String> parameterNames) {
129 String name = element.name.slowToString();
130 String prefix = '';
131 // Avoid collisions with real parameters of the method.
132 do {
133 name = JsNames.getValid('$prefix$name');
134 prefix = '\$$prefix';
135 } while (parameterNames.containsValue(name));
136 parameterNames[element] = name;
137 parameters.add(new js.Parameter(name));
138 }
139
140 void addBackendParameters(Element element,
141 List<js.Parameter> parameters,
142 Map<Element, String> parameterNames) {
143 // TODO(ngeoffray): We should infer this information from the
144 // graph, instead of recomputing what the builder did.
145 if (element.isConstructor()) {
146 // Put the type parameters.
147 ClassElement cls = element.enclosingElement;
148 if (!compiler.world.needsRti(cls)) return;
149 cls.typeVariables.forEach((TypeVariableType typeVariable) {
150 addBackendParameter(typeVariable.element, parameters, parameterNames);
151 });
152 } else if (element.isGenerativeConstructorBody()) {
153 // Put the parameter checks parameters.
154 Node node = element.implementation.parseNode(compiler);
155 ClosureClassMap closureData =
156 compiler.closureToClassMapper.getMappingForNestedFunction(node);
157 FunctionElement functionElement = element;
158 FunctionSignature params = functionElement.computeSignature(compiler);
159 TreeElements elements =
160 compiler.enqueuer.resolution.getCachedElements(element);
161 params.orderedForEachParameter((Element element) {
162 if (elements.isParameterChecked(element)) {
163 Element checkResultElement =
164 closureData.parametersWithSentinel[element];
165 addBackendParameter(checkResultElement, parameters, parameterNames);
166 }
167 });
168 // Put the box parameter.
169 ClosureScope scopeData = closureData.capturingScopes[node];
170 if (scopeData != null) {
171 addBackendParameter(scopeData.boxElement, parameters, parameterNames);
172 }
173 }
174 }
175
176 CodeBuffer generateBailoutMethod(WorkItem work, HGraph graph) { 113 CodeBuffer generateBailoutMethod(WorkItem work, HGraph graph) {
177 return measure(() { 114 return measure(() {
178 compiler.tracer.traceGraph("codegen-bailout", graph); 115 compiler.tracer.traceGraph("codegen-bailout", graph);
179 116
180 Map<Element, String> parameterNames = getParameterNames(work); 117 SsaUnoptimizedCodeGenerator codegen =
181 List<js.Parameter> parameters = <js.Parameter>[]; 118 new SsaUnoptimizedCodeGenerator(backend, work);
182 parameterNames.forEach((element, name) {
183 parameters.add(new js.Parameter(name));
184 });
185 addBackendParameters(work.element, parameters, parameterNames);
186
187 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator(
188 backend, work, parameters, parameterNames);
189 codegen.visitGraph(graph); 119 codegen.visitGraph(graph);
190 120
191 js.Block body = new js.Block(<js.Statement>[]); 121 js.Block body = new js.Block(<js.Statement>[]);
192 if (codegen.setup != null) body.statements.add(codegen.setup); 122 if (codegen.setup != null) body.statements.add(codegen.setup);
193 body.statements.add(codegen.body); 123 body.statements.add(codegen.body);
194 js.Fun fun = 124 js.Fun fun =
195 buildJavaScriptFunction(work.element, codegen.newParameters, body); 125 buildJavaScriptFunction(work.element, codegen.newParameters, body);
196 return prettyPrint(fun); 126 return prettyPrint(fun);
197 }); 127 });
198 } 128 }
199
200 Map<Element, String> getParameterNames(WorkItem work) {
201 // Make sure the map preserves insertion order, so that fetching
202 // the values will keep the order of parameters.
203 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>();
204 FunctionElement function = work.element.implementation;
205
206 // The dom/html libraries have inline JS code that reference
207 // parameter names directly. Long-term such code will be rejected.
208 // Now, just don't mangle the parameter name.
209 FunctionSignature signature = function.computeSignature(compiler);
210 signature.orderedForEachParameter((Element element) {
211 parameterNames[element] = function.isNative()
212 ? element.name.slowToString()
213 : JsNames.getValid('${element.name.slowToString()}');
214 });
215 return parameterNames;
216 }
217 } 129 }
218 130
219 // Stop-gap until the core classes have such a class. 131 // Stop-gap until the core classes have such a class.
220 class OrderedSet<T> { 132 class OrderedSet<T> {
221 final LinkedHashMap<T, bool> map = new LinkedHashMap<T, bool>(); 133 final LinkedHashMap<T, bool> map = new LinkedHashMap<T, bool>();
222 134
223 void add(T x) { 135 void add(T x) {
224 if (!map.containsKey(x)) { 136 if (!map.containsKey(x)) {
225 map[x] = true; 137 map[x] = true;
226 } 138 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 180
269 final JavaScriptBackend backend; 181 final JavaScriptBackend backend;
270 final WorkItem work; 182 final WorkItem work;
271 final HTypeMap types; 183 final HTypeMap types;
272 184
273 final Set<HInstruction> generateAtUseSite; 185 final Set<HInstruction> generateAtUseSite;
274 final Set<HInstruction> controlFlowOperators; 186 final Set<HInstruction> controlFlowOperators;
275 final Map<Element, ElementAction> breakAction; 187 final Map<Element, ElementAction> breakAction;
276 final Map<Element, ElementAction> continueAction; 188 final Map<Element, ElementAction> continueAction;
277 final Map<Element, String> parameterNames; 189 final Map<Element, String> parameterNames;
190 final List<js.Parameter> parameters;
278 191
279 js.Block currentContainer; 192 js.Block currentContainer;
280 js.Block get body => currentContainer; 193 js.Block get body => currentContainer;
281 List<js.Expression> expressionStack; 194 List<js.Expression> expressionStack;
282 List<js.Block> oldContainerStack; 195 List<js.Block> oldContainerStack;
283 196
284 /** 197 /**
285 * Contains the names of the instructions, as well as the parallel 198 * Contains the names of the instructions, as well as the parallel
286 * copies to perform on block transitioning. 199 * copies to perform on block transitioning.
287 */ 200 */
(...skipping 19 matching lines...) Expand all
307 HGraph currentGraph; 220 HGraph currentGraph;
308 HBasicBlock currentBlock; 221 HBasicBlock currentBlock;
309 222
310 // Records a block-information that is being handled specially. 223 // Records a block-information that is being handled specially.
311 // Used to break bad recursion. 224 // Used to break bad recursion.
312 HBlockInformation currentBlockInformation; 225 HBlockInformation currentBlockInformation;
313 // The subgraph is used to delimit traversal for some constructions, e.g., 226 // The subgraph is used to delimit traversal for some constructions, e.g.,
314 // if branches. 227 // if branches.
315 SubGraph subGraph; 228 SubGraph subGraph;
316 229
317 SsaCodeGenerator(this.backend, 230 SsaCodeGenerator(this.backend, WorkItem work)
318 WorkItem work,
319 this.parameterNames)
320 : this.work = work, 231 : this.work = work,
321 this.types = 232 this.types =
322 (work.compilationContext as JavaScriptItemCompilationContext).types, 233 (work.compilationContext as JavaScriptItemCompilationContext).types,
234 parameterNames = new LinkedHashMap<Element, String>(),
323 declaredLocals = new Set<String>(), 235 declaredLocals = new Set<String>(),
324 collectedVariableDeclarations = new OrderedSet<String>(), 236 collectedVariableDeclarations = new OrderedSet<String>(),
325 currentContainer = new js.Block.empty(), 237 currentContainer = new js.Block.empty(),
238 parameters = <js.Parameter>[],
326 expressionStack = <js.Expression>[], 239 expressionStack = <js.Expression>[],
327 oldContainerStack = <js.Block>[], 240 oldContainerStack = <js.Block>[],
328 generateAtUseSite = new Set<HInstruction>(), 241 generateAtUseSite = new Set<HInstruction>(),
329 controlFlowOperators = new Set<HInstruction>(), 242 controlFlowOperators = new Set<HInstruction>(),
330 breakAction = new Map<Element, ElementAction>(), 243 breakAction = new Map<Element, ElementAction>(),
331 continueAction = new Map<Element, ElementAction>(); 244 continueAction = new Map<Element, ElementAction>();
332 245
333 LibraryElement get currentLibrary => work.element.getLibrary(); 246 LibraryElement get currentLibrary => work.element.getLibrary();
334 Compiler get compiler => backend.compiler; 247 Compiler get compiler => backend.compiler;
335 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; 248 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
(...skipping 2282 matching lines...) Expand 10 before | Expand all | Expand 10 after
2618 } 2531 }
2619 String helperName = backend.namer.isolateAccess(helperElement); 2532 String helperName = backend.namer.isolateAccess(helperElement);
2620 push(new js.Call(new js.VariableUse(helperName), arguments)); 2533 push(new js.Call(new js.VariableUse(helperName), arguments));
2621 } else { 2534 } else {
2622 use(node.checkedInput); 2535 use(node.checkedInput);
2623 } 2536 }
2624 } 2537 }
2625 } 2538 }
2626 2539
2627 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { 2540 class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
2628 SsaOptimizedCodeGenerator(backend, work, parameters, parameterNames) 2541 SsaOptimizedCodeGenerator(backend, work) : super(backend, work);
2629 : super(backend, work, parameterNames) { 2542
2543 int maxBailoutParameters;
2544
2545 HBasicBlock beginGraph(HGraph graph) {
2630 // Declare the parameter names only for the optimized version. The 2546 // Declare the parameter names only for the optimized version. The
2631 // unoptimized version has different parameters. 2547 // unoptimized version has different parameters.
2632 parameterNames.forEach((Element element, String name) { 2548 parameterNames.forEach((Element element, String name) {
2549 parameters.add(new js.Parameter(name));
2633 declaredLocals.add(name); 2550 declaredLocals.add(name);
2634 }); 2551 });
2552 return graph.entry;
2635 } 2553 }
2636 2554
2637 int maxBailoutParameters;
2638
2639 HBasicBlock beginGraph(HGraph graph) => graph.entry;
2640 void endGraph(HGraph graph) {} 2555 void endGraph(HGraph graph) {}
2641 2556
2642 js.Statement bailout(HTypeGuard guard, String reason) { 2557 js.Statement bailout(HTypeGuard guard, String reason) {
2643 if (maxBailoutParameters == null) { 2558 if (maxBailoutParameters == null) {
2644 maxBailoutParameters = 0; 2559 maxBailoutParameters = 0;
2645 work.guards.forEach((HTypeGuard workGuard) { 2560 work.guards.forEach((HTypeGuard workGuard) {
2646 HBailoutTarget target = workGuard.bailoutTarget; 2561 HBailoutTarget target = workGuard.bailoutTarget;
2647 int inputLength = target.inputs.length; 2562 int inputLength = target.inputs.length;
2648 if (inputLength > maxBailoutParameters) { 2563 if (inputLength > maxBailoutParameters) {
2649 maxBailoutParameters = inputLength; 2564 maxBailoutParameters = inputLength;
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
2815 /** 2730 /**
2816 * Keeps track if a bailout switch already used its [:default::] clause. New 2731 * Keeps track if a bailout switch already used its [:default::] clause. New
2817 * bailout-switches just push [:false:] on the stack and replace it when 2732 * bailout-switches just push [:false:] on the stack and replace it when
2818 * they used the [:default::] clause. 2733 * they used the [:default::] clause.
2819 */ 2734 */
2820 final List<bool> defaultClauseUsedInBailoutStack; 2735 final List<bool> defaultClauseUsedInBailoutStack;
2821 2736
2822 SsaBailoutPropagator propagator; 2737 SsaBailoutPropagator propagator;
2823 HInstruction savedFirstInstruction; 2738 HInstruction savedFirstInstruction;
2824 2739
2825 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames) 2740 SsaUnoptimizedCodeGenerator(backend, work)
2826 : super(backend, work, parameterNames), 2741 : super(backend, work),
2827 oldBailoutSwitches = <js.Switch>[], 2742 oldBailoutSwitches = <js.Switch>[],
2828 newParameters = <js.Parameter>[], 2743 newParameters = <js.Parameter>[],
2829 labels = <String>[], 2744 labels = <String>[],
2830 defaultClauseUsedInBailoutStack = <bool>[]; 2745 defaultClauseUsedInBailoutStack = <bool>[];
2831 2746
2832 String pushLabel() { 2747 String pushLabel() {
2833 String label = 'L${labelId++}'; 2748 String label = 'L${labelId++}';
2834 labels.addLast(label); 2749 labels.addLast(label);
2835 return label; 2750 return label;
2836 } 2751 }
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
3144 if (leftType.canBeNull() && rightType.canBeNull()) { 3059 if (leftType.canBeNull() && rightType.canBeNull()) {
3145 if (left.isConstantNull() || right.isConstantNull() || 3060 if (left.isConstantNull() || right.isConstantNull() ||
3146 (leftType.isPrimitive() && leftType == rightType)) { 3061 (leftType.isPrimitive() && leftType == rightType)) {
3147 return '=='; 3062 return '==';
3148 } 3063 }
3149 return null; 3064 return null;
3150 } else { 3065 } else {
3151 return '==='; 3066 return '===';
3152 } 3067 }
3153 } 3068 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698