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

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

Issue 839323003: Implementation of async-await transformation on js ast. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Implement new ssa-nodes in ssa-tracer. Created 5 years, 10 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
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, bool generateSourceMap)
13 : generator = new SsaCodeGeneratorTask(backend), 13 : generator = new SsaCodeGeneratorTask(backend),
14 builder = new SsaBuilderTask(backend, generateSourceMap), 14 builder = new SsaBuilderTask(backend, generateSourceMap),
15 optimizer = new SsaOptimizerTask(backend); 15 optimizer = new SsaOptimizerTask(backend);
16 16
17 /// Generates JavaScript code for `work.element`. 17 /// Generates JavaScript code for `work.element`.
18 /// Using the ssa builder, optimizer and codegenerator. 18 /// Using the ssa builder, optimizer and codegenerator.
19 js.Fun compile(CodegenWorkItem work) { 19 js.Fun compile(CodegenWorkItem work) {
20 HGraph graph = builder.build(work); 20 HGraph graph = builder.build(work);
21 optimizer.optimize(work, graph); 21 optimizer.optimize(work, graph);
22 return generator.generateCode(work, graph); 22 Element element = work.element;
23 js.Expression result = generator.generateCode(work, graph);
24 if (element is FunctionElement) {
floitsch 2015/02/02 22:00:10 For another CL: the FunctionCompiler should *not*
sigurdm 2015/02/03 16:59:31 Acknowledged.
25 JavaScriptBackend backend = builder.backend;
26 if (element.asyncMarker == AsyncMarker.ASYNC) {
27 result = new AsyncRewriter(
28 thenHelper:
29 backend.emitter.staticFunctionAccess(backend.getThenHelper()),
30 newController: new js.New(backend.emitter.staticFunctionAccess(
31 backend.getCompleterConstructor()), []),
32 safeVariableName: backend.namer.safeVariableName)
33 .rewrite(result);
floitsch 2015/02/02 22:00:11 The "rewrite" drowns in the whole expression. Crea
sigurdm 2015/02/03 16:59:31 Done.
34 } else if (element.asyncMarker == AsyncMarker.SYNC_STAR) {
35 result = new AsyncRewriter(
36 endOfIteration: backend.emitter.staticFunctionAccess(
37 backend.getEndOfIteration()),
38 newIterable: backend.emitter.staticFunctionAccess(
39 backend.getSyncStarIterableConstructor()),
40 yieldStarExpression: backend.emitter.staticFunctionAccess(
41 backend.getSyncStarYieldStar()),
42 safeVariableName: backend.namer.safeVariableName)
43 .rewrite(result);
44 }
45 else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) {
46 result = new AsyncRewriter(
47 thenHelper: backend.emitter.staticFunctionAccess(
48 backend.getStreamHelper()),
49 newController: new js.Call(backend.emitter.staticFunctionAccess(
50 backend.getMakeController()), []),
51 safeVariableName: backend.namer.safeVariableName,
52 yieldExpression: backend.emitter.staticFunctionAccess(
53 backend.getYieldSingle()))
54 .rewrite(result);
55 }
56 }
57 return result;
23 } 58 }
24 59
25 Iterable<CompilerTask> get tasks { 60 Iterable<CompilerTask> get tasks {
26 return <CompilerTask>[builder, optimizer, generator]; 61 return <CompilerTask>[builder, optimizer, generator];
27 } 62 }
28 } 63 }
29 64
30 /// A synthetic local variable only used with the SSA graph. 65 /// A synthetic local variable only used with the SSA graph.
31 /// 66 ///
32 /// For instance used for holding return value of function or the exception of a 67 /// For instance used for holding return value of function or the exception of a
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 390 }
356 } 391 }
357 392
358 /** 393 /**
359 * Returns true if the local can be accessed directly. Boxed variables or 394 * Returns true if the local can be accessed directly. Boxed variables or
360 * captured variables that are stored in the closure-field return [:false:]. 395 * captured variables that are stored in the closure-field return [:false:].
361 */ 396 */
362 bool isAccessedDirectly(Local local) { 397 bool isAccessedDirectly(Local local) {
363 assert(local != null); 398 assert(local != null);
364 return !redirectionMapping.containsKey(local) 399 return !redirectionMapping.containsKey(local)
365 && !closureData.usedVariablesInTry.contains(local); 400 && !closureData.variablesUsedInTryOrGenerator.contains(local);
366 } 401 }
367 402
368 bool isStoredInClosureField(Local local) { 403 bool isStoredInClosureField(Local local) {
369 assert(local != null); 404 assert(local != null);
370 if (isAccessedDirectly(local)) return false; 405 if (isAccessedDirectly(local)) return false;
371 CapturedVariable redirectTarget = redirectionMapping[local]; 406 CapturedVariable redirectTarget = redirectionMapping[local];
372 if (redirectTarget == null) return false; 407 if (redirectTarget == null) return false;
373 return redirectTarget is ClosureFieldElement; 408 return redirectTarget is ClosureFieldElement;
374 } 409 }
375 410
376 bool isBoxed(Local local) { 411 bool isBoxed(Local local) {
377 if (isAccessedDirectly(local)) return false; 412 if (isAccessedDirectly(local)) return false;
378 if (isStoredInClosureField(local)) return false; 413 if (isStoredInClosureField(local)) return false;
379 return redirectionMapping.containsKey(local); 414 return redirectionMapping.containsKey(local);
380 } 415 }
381 416
382 bool isUsedInTry(Local local) { 417 bool isUsedInTryOrGenerator(Local local) {
383 return closureData.usedVariablesInTry.contains(local); 418 return closureData.variablesUsedInTryOrGenerator.contains(local);
384 } 419 }
385 420
386 /** 421 /**
387 * Returns an [HInstruction] for the given element. If the element is 422 * Returns an [HInstruction] for the given element. If the element is
388 * boxed or stored in a closure then the method generates code to retrieve 423 * boxed or stored in a closure then the method generates code to retrieve
389 * the value. 424 * the value.
390 */ 425 */
391 HInstruction readLocal(Local local) { 426 HInstruction readLocal(Local local) {
392 if (isAccessedDirectly(local)) { 427 if (isAccessedDirectly(local)) {
393 if (directLocals[local] == null) { 428 if (directLocals[local] == null) {
(...skipping 21 matching lines...) Expand all
415 // accessed as direct local. Inside the nested closure the box is 450 // accessed as direct local. Inside the nested closure the box is
416 // accessed through a closure-field. 451 // accessed through a closure-field.
417 // Calling [readLocal] makes sure we generate the correct code to get 452 // Calling [readLocal] makes sure we generate the correct code to get
418 // the box. 453 // the box.
419 HInstruction box = readLocal(redirect.box); 454 HInstruction box = readLocal(redirect.box);
420 HInstruction lookup = new HFieldGet( 455 HInstruction lookup = new HFieldGet(
421 redirect, box, builder.getTypeOfCapturedVariable(redirect)); 456 redirect, box, builder.getTypeOfCapturedVariable(redirect));
422 builder.add(lookup); 457 builder.add(lookup);
423 return lookup; 458 return lookup;
424 } else { 459 } else {
425 assert(isUsedInTry(local)); 460 assert(isUsedInTryOrGenerator(local));
426 HLocalValue localValue = getLocal(local); 461 HLocalValue localValue = getLocal(local);
427 HInstruction instruction = new HLocalGet( 462 HInstruction instruction = new HLocalGet(
428 local, localValue, builder.backend.dynamicType); 463 local, localValue, builder.backend.dynamicType);
429 builder.add(instruction); 464 builder.add(instruction);
430 return instruction; 465 return instruction;
431 } 466 }
432 } 467 }
433 468
434 HInstruction readThis() { 469 HInstruction readThis() {
435 HInstruction res = readLocal(closureData.thisLocal); 470 HInstruction res = readLocal(closureData.thisLocal);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 directLocals[local] = value; 506 directLocals[local] = value;
472 } else if (isBoxed(local)) { 507 } else if (isBoxed(local)) {
473 BoxFieldElement redirect = redirectionMapping[local]; 508 BoxFieldElement redirect = redirectionMapping[local];
474 // The box itself could be captured, or be local. A local variable that 509 // The box itself could be captured, or be local. A local variable that
475 // is captured will be boxed, but the box itself will be a local. 510 // is captured will be boxed, but the box itself will be a local.
476 // Inside the closure the box is stored in a closure-field and cannot 511 // Inside the closure the box is stored in a closure-field and cannot
477 // be accessed directly. 512 // be accessed directly.
478 HInstruction box = readLocal(redirect.box); 513 HInstruction box = readLocal(redirect.box);
479 builder.add(new HFieldSet(redirect, box, value)); 514 builder.add(new HFieldSet(redirect, box, value));
480 } else { 515 } else {
481 assert(isUsedInTry(local)); 516 assert(isUsedInTryOrGenerator(local));
482 HLocalValue localValue = getLocal(local); 517 HLocalValue localValue = getLocal(local);
483 builder.add(new HLocalSet(local, localValue, value)); 518 builder.add(new HLocalSet(local, localValue, value));
484 } 519 }
485 } 520 }
486 521
487 /** 522 /**
488 * This function, startLoop, must be called before visiting any children of 523 * This function, startLoop, must be called before visiting any children of
489 * the loop. In particular it needs to be called before executing the 524 * the loop. In particular it needs to be called before executing the
490 * initializers. 525 * initializers.
491 * 526 *
(...skipping 4665 matching lines...) Expand 10 before | Expand all | Expand 10 after
5157 visitThrow(ast.Throw node) { 5192 visitThrow(ast.Throw node) {
5158 visitThrowExpression(node.expression); 5193 visitThrowExpression(node.expression);
5159 if (isReachable) { 5194 if (isReachable) {
5160 handleInTryStatement(); 5195 handleInTryStatement();
5161 push(new HThrowExpression(pop())); 5196 push(new HThrowExpression(pop()));
5162 isReachable = false; 5197 isReachable = false;
5163 } 5198 }
5164 } 5199 }
5165 5200
5166 visitYield(ast.Yield node) { 5201 visitYield(ast.Yield node) {
5167 // Dummy implementation.
5168 visit(node.expression); 5202 visit(node.expression);
5203 HInstruction yielded = pop();
5204 push(new HYield(yielded, node.hasStar));
floitsch 2015/02/02 22:00:10 I think there is a function that does this. Maybe
sigurdm 2015/02/03 16:59:31 Right, add does it.
5169 pop(); 5205 pop();
5170 } 5206 }
5171 5207
5172 visitAwait(ast.Await node) { 5208 visitAwait(ast.Await node) {
5173 // Dummy implementation.
5174 visit(node.expression); 5209 visit(node.expression);
5210 HInstruction awaited = pop();
5211 // TODO(herhut): Improve this type.
5212 push(new HAwait(awaited, new TypeMask.subclass(compiler.objectClass,
5213 compiler.world)));
5175 } 5214 }
5176 5215
5177 visitTypeAnnotation(ast.TypeAnnotation node) { 5216 visitTypeAnnotation(ast.TypeAnnotation node) {
5178 compiler.internalError(node, 5217 compiler.internalError(node,
5179 'Visiting type annotation in SSA builder.'); 5218 'Visiting type annotation in SSA builder.');
5180 } 5219 }
5181 5220
5182 visitVariableDefinitions(ast.VariableDefinitions node) { 5221 visitVariableDefinitions(ast.VariableDefinitions node) {
5183 assert(isReachable); 5222 assert(isReachable);
5184 for (Link<ast.Node> link = node.definitions.nodes; 5223 for (Link<ast.Node> link = node.definitions.nodes;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
5308 return new NullJumpHandler(compiler); 5347 return new NullJumpHandler(compiler);
5309 } 5348 }
5310 if (isLoopJump && node is ast.SwitchStatement) { 5349 if (isLoopJump && node is ast.SwitchStatement) {
5311 // Create a special jump handler for loops created for switch statements 5350 // Create a special jump handler for loops created for switch statements
5312 // with continue statements. 5351 // with continue statements.
5313 return new SwitchCaseJumpHandler(this, element, node); 5352 return new SwitchCaseJumpHandler(this, element, node);
5314 } 5353 }
5315 return new JumpHandler(this, element); 5354 return new JumpHandler(this, element);
5316 } 5355 }
5317 5356
5357
floitsch 2015/02/02 22:00:10 no need for the new line.
sigurdm 2015/02/03 16:59:31 Done.
5318 visitForIn(ast.ForIn node) { 5358 visitForIn(ast.ForIn node) {
5359 if (node.isAsync) {
floitsch 2015/02/02 22:00:10 Move the code into a separate function.
sigurdm 2015/02/03 16:59:32 Done.
5360 // The async for is implemented with a StreamIterator.
floitsch 2015/02/02 22:00:10 async-for
sigurdm 2015/02/03 16:59:31 Done.
5361 HInstruction streamIterator;
5362
5363 visit(node.expression);
5364 HInstruction expression = pop();
5365 pushInvokeStatic(node,
5366 backend.getStreamIteratorConstructor(),
5367 [expression, graph.addConstantNull(compiler)]);
5368 streamIterator = pop();
5369 void buildInitializer() {
floitsch 2015/02/02 22:00:11 nested functions should have a new line before and
sigurdm 2015/02/03 16:59:31 Done.
5370 }
5371 HInstruction buildCondition() {
5372 Selector selector = elements.getMoveNextSelector(node);
5373 pushInvokeDynamic(node, selector, [streamIterator]);
5374 HInstruction future = pop();
5375 push(new HAwait(future, new TypeMask.subclass(compiler.objectClass,
5376 compiler.world)));
5377 return popBoolified();
5378 }
5379 void buildBody() {
5380 Selector call = elements.getCurrentSelector(node);
5381 pushInvokeDynamic(node, call, [streamIterator]);
5382
5383 ast.Node identifier = node.declaredIdentifier;
5384 Element variable = elements.getForInVariable(node);
5385 Selector selector = elements.getSelector(identifier);
5386
5387 HInstruction value = pop();
5388 if (identifier.asSend() != null
5389 && Elements.isInstanceSend(identifier, elements)) {
5390 HInstruction receiver = generateInstanceSendReceiver(identifier);
5391 assert(receiver != null);
5392 generateInstanceSetterWithCompiledReceiver(
5393 null,
5394 receiver,
5395 value,
5396 selector: selector,
5397 location: identifier);
5398 } else {
5399 generateNonInstanceSetter(
5400 null, variable, value, location: identifier);
5401 }
5402 pop(); // Pop the value pushed by the setter call.
5403
5404 visit(node.body);
5405 }
5406 buildProtected(() {
5407 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody);
floitsch 2015/02/02 22:00:10 Since you already give a name to the buildInitiali
sigurdm 2015/02/03 16:59:31 Done.
5408 }, () {
5409 pushInvokeDynamic(node, new Selector.call("cancel", null, 0),
5410 [streamIterator]);
5411 push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass,
5412 compiler.world)));
5413 pop();
5414 });
5415 return;
5416 }
5417
5319 // Generate a structure equivalent to: 5418 // Generate a structure equivalent to:
5320 // Iterator<E> $iter = <iterable>.iterator; 5419 // Iterator<E> $iter = <iterable>.iterator;
5321 // while ($iter.moveNext()) { 5420 // while ($iter.moveNext()) {
5322 // E <declaredIdentifier> = $iter.current; 5421 // E <declaredIdentifier> = $iter.current;
5323 // <body> 5422 // <body>
5324 // } 5423 // }
5325 5424
5326 // The iterator is shared between initializer, condition and body. 5425 // The iterator is shared between initializer, condition and body.
5327 HInstruction iterator; 5426 HInstruction iterator;
5328 void buildInitializer() { 5427 void buildInitializer() {
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
5844 } 5943 }
5845 5944
5846 visitSwitchCase(ast.SwitchCase node) { 5945 visitSwitchCase(ast.SwitchCase node) {
5847 compiler.internalError(node, 'SsaFromAstMixin.visitSwitchCase.'); 5946 compiler.internalError(node, 'SsaFromAstMixin.visitSwitchCase.');
5848 } 5947 }
5849 5948
5850 visitCaseMatch(ast.CaseMatch node) { 5949 visitCaseMatch(ast.CaseMatch node) {
5851 compiler.internalError(node, 'SsaFromAstMixin.visitCaseMatch.'); 5950 compiler.internalError(node, 'SsaFromAstMixin.visitCaseMatch.');
5852 } 5951 }
5853 5952
5953 buildProtected(void buildTry(), void buildFinally()) {
floitsch 2015/02/02 22:00:11 return type. Change name, since it's not a genera
sigurdm 2015/02/03 16:59:32 Done.
floitsch 2015/02/04 12:31:27 That's not what I meant. If the buildProtected wor
5954 // Save the current locals. The catch block and the finally block
5955 // must not reuse the existing locals handler. None of the variables
5956 // that have been defined in the body-block will be used, but for
5957 // loops we will add (unnecessary) phis that will reference the body
5958 // variables. This makes it look as if the variables were used
5959 // in a non-dominated block.
floitsch 2015/02/02 22:00:11 Does this comment apply for us? Do we really need
sigurdm 2015/02/03 16:59:32 Not sure - I will ask
sigurdm 2015/02/04 11:43:39 I discussed with Karl, and you are right - it is o
floitsch 2015/02/04 12:31:27 I would say no, since the only variable that is us
5960 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
5961 HBasicBlock enterBlock = openNewBlock();
5962 HTry tryInstruction = new HTry();
5963 close(tryInstruction);
5964 bool oldInTryStatement = inTryStatement;
5965 inTryStatement = true;
5966
5967 HBasicBlock startTryBlock;
5968 HBasicBlock endTryBlock;
5969 HBasicBlock startFinallyBlock;
5970 HBasicBlock endFinallyBlock;
5971
5972 startTryBlock = graph.addNewBlock();
5973 open(startTryBlock);
5974 buildTry();
5975 // We use a [HExitTry] instead of a [HGoto] for the try block
5976 // because it will have multiple successors: the join block, and
5977 // the catch or finally block.
floitsch 2015/02/02 22:00:10 It won't have any catch block.
sigurdm 2015/02/03 16:59:31 Done.
5978 if (!isAborted()) endTryBlock = close(new HExitTry());
5979 SubGraph bodyGraph = new SubGraph(startTryBlock, lastOpenedBlock);
5980 SubGraph catchGraph = null;
floitsch 2015/02/02 22:00:11 Remove variable.
sigurdm 2015/02/03 16:59:31 Done.
5981 HLocalValue exception = null;
floitsch 2015/02/02 22:00:11 Remove (and inline) ?
sigurdm 2015/02/03 16:59:32 Done.
5982
5983 SubGraph finallyGraph = null;
5984
5985 localsHandler = new LocalsHandler.from(savedLocals);
5986 startFinallyBlock = graph.addNewBlock();
5987 open(startFinallyBlock);
5988 buildFinally();
5989 if (!isAborted()) endFinallyBlock = close(new HGoto());
5990 tryInstruction.finallyBlock = startFinallyBlock;
5991 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock);
5992
5993 HBasicBlock exitBlock = graph.addNewBlock();
5994
5995 addExitTrySuccessor(successor) {
floitsch 2015/02/02 22:00:10 add return type. (especially for nested functions)
sigurdm 2015/02/03 16:59:31 Done.
5996 if (successor == null) return;
floitsch 2015/02/02 22:00:10 Check should be unnecessary.
sigurdm 2015/02/03 16:59:31 Done.
5997 // Iterate over all blocks created inside this try/catch, and
5998 // attach successor information to blocks that end with
5999 // [HExitTry].
6000 for (int i = startTryBlock.id; i < successor.id; i++) {
6001 HBasicBlock block = graph.blocks[i];
6002 var last = block.last;
6003 if (last is HExitTry) {
6004 block.addSuccessor(successor);
6005 }
6006 }
6007 }
6008
6009 // Setup all successors. The entry block that contains the [HTry]
6010 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit
floitsch 2015/02/02 22:00:11 no catch.
sigurdm 2015/02/03 16:59:31 Done.
6011 // blocks as successors.
6012 enterBlock.addSuccessor(startTryBlock);
6013 enterBlock.addSuccessor(startFinallyBlock);
6014 enterBlock.addSuccessor(exitBlock);
6015
6016 // The body has either the catch or the finally block as successor.
floitsch 2015/02/02 22:00:10 no catch.
sigurdm 2015/02/03 16:59:31 Done.
6017 if (endTryBlock != null) {
6018 endTryBlock.addSuccessor(startFinallyBlock);
6019 endTryBlock.addSuccessor(exitBlock);
6020 }
6021
6022 // The finally block has the exit block as successor.
6023 endFinallyBlock.addSuccessor(exitBlock);
6024
6025 // If a block inside try/catch aborts (eg with a return statement),
6026 // we explicitely mark this block a predecessor of the catch
6027 // block and the finally block.
6028 addExitTrySuccessor(startFinallyBlock);
6029
6030 // Use the locals handler not altered by the catch and finally
6031 // blocks.
6032 localsHandler = savedLocals;
6033 open(exitBlock);
6034 enterBlock.setBlockFlow(
6035 new HTryBlockInformation(
6036 wrapStatementGraph(bodyGraph),
6037 exception,
6038 null, // No catchGraph
6039 wrapStatementGraph(finallyGraph)),
6040 exitBlock);
6041 inTryStatement = oldInTryStatement;
6042 }
6043
5854 visitTryStatement(ast.TryStatement node) { 6044 visitTryStatement(ast.TryStatement node) {
5855 // Save the current locals. The catch block and the finally block 6045 // Save the current locals. The catch block and the finally block
5856 // must not reuse the existing locals handler. None of the variables 6046 // must not reuse the existing locals handler. None of the variables
5857 // that have been defined in the body-block will be used, but for 6047 // that have been defined in the body-block will be used, but for
5858 // loops we will add (unnecessary) phis that will reference the body 6048 // loops we will add (unnecessary) phis that will reference the body
5859 // variables. This makes it look as if the variables were used 6049 // variables. This makes it look as if the variables were used
5860 // in a non-dominated block. 6050 // in a non-dominated block.
5861 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 6051 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
5862 HBasicBlock enterBlock = openNewBlock(); 6052 HBasicBlock enterBlock = openNewBlock();
5863 HTry tryInstruction = new HTry(); 6053 HTry tryInstruction = new HTry();
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
6038 enterBlock.setBlockFlow( 6228 enterBlock.setBlockFlow(
6039 new HTryBlockInformation( 6229 new HTryBlockInformation(
6040 wrapStatementGraph(bodyGraph), 6230 wrapStatementGraph(bodyGraph),
6041 exception, 6231 exception,
6042 wrapStatementGraph(catchGraph), 6232 wrapStatementGraph(catchGraph),
6043 wrapStatementGraph(finallyGraph)), 6233 wrapStatementGraph(finallyGraph)),
6044 exitBlock); 6234 exitBlock);
6045 inTryStatement = oldInTryStatement; 6235 inTryStatement = oldInTryStatement;
6046 } 6236 }
6047 6237
6238
6048 visitCatchBlock(ast.CatchBlock node) { 6239 visitCatchBlock(ast.CatchBlock node) {
6049 visit(node.block); 6240 visit(node.block);
6050 } 6241 }
6051 6242
6052 visitTypedef(ast.Typedef node) { 6243 visitTypedef(ast.Typedef node) {
6053 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.'); 6244 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.');
6054 } 6245 }
6055 6246
6056 visitTypeVariable(ast.TypeVariable node) { 6247 visitTypeVariable(ast.TypeVariable node) {
6057 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); 6248 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable.');
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
6213 InlineWeeder(this.maxInliningNodes, 6404 InlineWeeder(this.maxInliningNodes,
6214 this.useMaxInliningNodes, 6405 this.useMaxInliningNodes,
6215 this.allowLoops); 6406 this.allowLoops);
6216 6407
6217 static bool canBeInlined(ast.FunctionExpression functionExpression, 6408 static bool canBeInlined(ast.FunctionExpression functionExpression,
6218 int maxInliningNodes, 6409 int maxInliningNodes,
6219 bool useMaxInliningNodes, 6410 bool useMaxInliningNodes,
6220 {bool allowLoops: false}) { 6411 {bool allowLoops: false}) {
6221 InlineWeeder weeder = 6412 InlineWeeder weeder =
6222 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); 6413 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops);
6414 if (functionExpression.asyncModifier != null) return false;
6223 weeder.visit(functionExpression.initializers); 6415 weeder.visit(functionExpression.initializers);
6224 weeder.visit(functionExpression.body); 6416 weeder.visit(functionExpression.body);
6225 return !weeder.tooDifficult; 6417 return !weeder.tooDifficult;
6226 } 6418 }
6227 6419
6228 bool registerNode() { 6420 bool registerNode() {
6229 if (!useMaxInliningNodes) return true; 6421 if (!useMaxInliningNodes) return true;
6230 if (nodeCount++ > maxInliningNodes) { 6422 if (nodeCount++ > maxInliningNodes) {
6231 tooDifficult = true; 6423 tooDifficult = true;
6232 return false; 6424 return false;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
6299 void visitThrow(ast.Throw node) { 6491 void visitThrow(ast.Throw node) {
6300 if (!registerNode()) return; 6492 if (!registerNode()) return;
6301 // For now, we don't want to handle throw after a return even if 6493 // For now, we don't want to handle throw after a return even if
6302 // it is in an "if". 6494 // it is in an "if".
6303 if (seenReturn) { 6495 if (seenReturn) {
6304 tooDifficult = true; 6496 tooDifficult = true;
6305 } else { 6497 } else {
6306 node.visitChildren(this); 6498 node.visitChildren(this);
6307 } 6499 }
6308 } 6500 }
6501
6502 void visitAwait(ast.Await node) {
6503 if (!registerNode()) return;
6504 tooDifficult = true;
floitsch 2015/02/02 22:00:10 How can this happen, when we already return if the
sigurdm 2015/02/03 16:59:32 Right - I added this one first, then realized that
6505 }
6309 } 6506 }
6310 6507
6311 abstract class InliningState { 6508 abstract class InliningState {
6312 /** 6509 /**
6313 * Invariant: [function] must be an implementation element. 6510 * Invariant: [function] must be an implementation element.
6314 */ 6511 */
6315 final FunctionElement function; 6512 final FunctionElement function;
6316 6513
6317 InliningState(this.function) { 6514 InliningState(this.function) {
6318 assert(function.isImplementation); 6515 assert(function.isImplementation);
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
6670 if (unaliased is TypedefType) throw 'unable to unalias $type'; 6867 if (unaliased is TypedefType) throw 'unable to unalias $type';
6671 unaliased.accept(this, builder); 6868 unaliased.accept(this, builder);
6672 } 6869 }
6673 6870
6674 void visitDynamicType(DynamicType type, SsaBuilder builder) { 6871 void visitDynamicType(DynamicType type, SsaBuilder builder) {
6675 JavaScriptBackend backend = builder.compiler.backend; 6872 JavaScriptBackend backend = builder.compiler.backend;
6676 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 6873 ClassElement cls = backend.findHelper('DynamicRuntimeType');
6677 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 6874 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
6678 } 6875 }
6679 } 6876 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698