OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of ssa; | 5 part of ssa; |
6 | 6 |
7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
11 | 11 |
12 SsaFunctionCompiler(JavaScriptBackend backend, bool generateSourceMap) | 12 SsaFunctionCompiler(JavaScriptBackend backend, 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) { | |
25 JavaScriptBackend backend = builder.backend; | |
26 AsyncRewriter rewriter = null; | |
27 if (element.asyncMarker == AsyncMarker.ASYNC) { | |
28 rewriter = new AsyncRewriter( | |
29 backend.compiler, | |
30 backend.compiler.currentElement, | |
31 thenHelper: | |
32 backend.emitter.staticFunctionAccess(backend.getThenHelper()), | |
33 newController: new js.New(backend.emitter.staticFunctionAccess( | |
34 backend.getCompleterConstructor()), []), | |
35 safeVariableName: backend.namer.safeVariableName); | |
36 } else if (element.asyncMarker == AsyncMarker.SYNC_STAR) { | |
37 rewriter = new AsyncRewriter( | |
38 backend.compiler, | |
39 backend.compiler.currentElement, | |
40 endOfIteration: backend.emitter.staticFunctionAccess( | |
41 backend.getEndOfIteration()), | |
42 newIterable: backend.emitter.staticFunctionAccess( | |
43 backend.getSyncStarIterableConstructor()), | |
44 yieldStarExpression: backend.emitter.staticFunctionAccess( | |
45 backend.getYieldStar()), | |
46 safeVariableName: backend.namer.safeVariableName); | |
47 } | |
48 else if (element.asyncMarker == AsyncMarker.ASYNC_STAR) { | |
49 rewriter = new AsyncRewriter( | |
50 backend.compiler, | |
51 backend.compiler.currentElement, | |
52 thenHelper: backend.emitter.staticFunctionAccess( | |
53 backend.getStreamHelper()), | |
54 newController: new js.Call(backend.emitter.staticFunctionAccess( | |
55 backend.getMakeController()), []), | |
56 safeVariableName: backend.namer.safeVariableName, | |
57 yieldExpression: backend.emitter.staticFunctionAccess( | |
58 backend.getYieldSingle()), | |
59 yieldStarExpression: backend.emitter.staticFunctionAccess( | |
60 backend.getYieldStar())); | |
61 } | |
62 if (rewriter != null) { | |
63 result = rewriter.rewrite(result); | |
64 } | |
65 } | |
66 return result; | |
23 } | 67 } |
24 | 68 |
25 Iterable<CompilerTask> get tasks { | 69 Iterable<CompilerTask> get tasks { |
26 return <CompilerTask>[builder, optimizer, generator]; | 70 return <CompilerTask>[builder, optimizer, generator]; |
27 } | 71 } |
28 } | 72 } |
29 | 73 |
30 /// A synthetic local variable only used with the SSA graph. | 74 /// A synthetic local variable only used with the SSA graph. |
31 /// | 75 /// |
32 /// For instance used for holding return value of function or the exception of a | 76 /// 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 Loading... | |
355 } | 399 } |
356 } | 400 } |
357 | 401 |
358 /** | 402 /** |
359 * Returns true if the local can be accessed directly. Boxed variables or | 403 * Returns true if the local can be accessed directly. Boxed variables or |
360 * captured variables that are stored in the closure-field return [:false:]. | 404 * captured variables that are stored in the closure-field return [:false:]. |
361 */ | 405 */ |
362 bool isAccessedDirectly(Local local) { | 406 bool isAccessedDirectly(Local local) { |
363 assert(local != null); | 407 assert(local != null); |
364 return !redirectionMapping.containsKey(local) | 408 return !redirectionMapping.containsKey(local) |
365 && !closureData.usedVariablesInTry.contains(local); | 409 && !closureData.variablesUsedInTryOrGenerator.contains(local); |
366 } | 410 } |
367 | 411 |
368 bool isStoredInClosureField(Local local) { | 412 bool isStoredInClosureField(Local local) { |
369 assert(local != null); | 413 assert(local != null); |
370 if (isAccessedDirectly(local)) return false; | 414 if (isAccessedDirectly(local)) return false; |
371 CapturedVariable redirectTarget = redirectionMapping[local]; | 415 CapturedVariable redirectTarget = redirectionMapping[local]; |
372 if (redirectTarget == null) return false; | 416 if (redirectTarget == null) return false; |
373 return redirectTarget is ClosureFieldElement; | 417 return redirectTarget is ClosureFieldElement; |
374 } | 418 } |
375 | 419 |
376 bool isBoxed(Local local) { | 420 bool isBoxed(Local local) { |
377 if (isAccessedDirectly(local)) return false; | 421 if (isAccessedDirectly(local)) return false; |
378 if (isStoredInClosureField(local)) return false; | 422 if (isStoredInClosureField(local)) return false; |
379 return redirectionMapping.containsKey(local); | 423 return redirectionMapping.containsKey(local); |
380 } | 424 } |
381 | 425 |
382 bool isUsedInTry(Local local) { | 426 bool isUsedInTryOrGenerator(Local local) { |
383 return closureData.usedVariablesInTry.contains(local); | 427 return closureData.variablesUsedInTryOrGenerator.contains(local); |
384 } | 428 } |
385 | 429 |
386 /** | 430 /** |
387 * Returns an [HInstruction] for the given element. If the element is | 431 * 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 | 432 * boxed or stored in a closure then the method generates code to retrieve |
389 * the value. | 433 * the value. |
390 */ | 434 */ |
391 HInstruction readLocal(Local local) { | 435 HInstruction readLocal(Local local) { |
392 if (isAccessedDirectly(local)) { | 436 if (isAccessedDirectly(local)) { |
393 if (directLocals[local] == null) { | 437 if (directLocals[local] == null) { |
(...skipping 21 matching lines...) Expand all Loading... | |
415 // accessed as direct local. Inside the nested closure the box is | 459 // accessed as direct local. Inside the nested closure the box is |
416 // accessed through a closure-field. | 460 // accessed through a closure-field. |
417 // Calling [readLocal] makes sure we generate the correct code to get | 461 // Calling [readLocal] makes sure we generate the correct code to get |
418 // the box. | 462 // the box. |
419 HInstruction box = readLocal(redirect.box); | 463 HInstruction box = readLocal(redirect.box); |
420 HInstruction lookup = new HFieldGet( | 464 HInstruction lookup = new HFieldGet( |
421 redirect, box, builder.getTypeOfCapturedVariable(redirect)); | 465 redirect, box, builder.getTypeOfCapturedVariable(redirect)); |
422 builder.add(lookup); | 466 builder.add(lookup); |
423 return lookup; | 467 return lookup; |
424 } else { | 468 } else { |
425 assert(isUsedInTry(local)); | 469 assert(isUsedInTryOrGenerator(local)); |
426 HLocalValue localValue = getLocal(local); | 470 HLocalValue localValue = getLocal(local); |
427 HInstruction instruction = new HLocalGet( | 471 HInstruction instruction = new HLocalGet( |
428 local, localValue, builder.backend.dynamicType); | 472 local, localValue, builder.backend.dynamicType); |
429 builder.add(instruction); | 473 builder.add(instruction); |
430 return instruction; | 474 return instruction; |
431 } | 475 } |
432 } | 476 } |
433 | 477 |
434 HInstruction readThis() { | 478 HInstruction readThis() { |
435 HInstruction res = readLocal(closureData.thisLocal); | 479 HInstruction res = readLocal(closureData.thisLocal); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 directLocals[local] = value; | 515 directLocals[local] = value; |
472 } else if (isBoxed(local)) { | 516 } else if (isBoxed(local)) { |
473 BoxFieldElement redirect = redirectionMapping[local]; | 517 BoxFieldElement redirect = redirectionMapping[local]; |
474 // The box itself could be captured, or be local. A local variable that | 518 // 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. | 519 // 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 | 520 // Inside the closure the box is stored in a closure-field and cannot |
477 // be accessed directly. | 521 // be accessed directly. |
478 HInstruction box = readLocal(redirect.box); | 522 HInstruction box = readLocal(redirect.box); |
479 builder.add(new HFieldSet(redirect, box, value)); | 523 builder.add(new HFieldSet(redirect, box, value)); |
480 } else { | 524 } else { |
481 assert(isUsedInTry(local)); | 525 assert(isUsedInTryOrGenerator(local)); |
482 HLocalValue localValue = getLocal(local); | 526 HLocalValue localValue = getLocal(local); |
483 builder.add(new HLocalSet(local, localValue, value)); | 527 builder.add(new HLocalSet(local, localValue, value)); |
484 } | 528 } |
485 } | 529 } |
486 | 530 |
487 /** | 531 /** |
488 * This function, startLoop, must be called before visiting any children of | 532 * This function, startLoop, must be called before visiting any children of |
489 * the loop. In particular it needs to be called before executing the | 533 * the loop. In particular it needs to be called before executing the |
490 * initializers. | 534 * initializers. |
491 * | 535 * |
(...skipping 4665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5157 visitThrow(ast.Throw node) { | 5201 visitThrow(ast.Throw node) { |
5158 visitThrowExpression(node.expression); | 5202 visitThrowExpression(node.expression); |
5159 if (isReachable) { | 5203 if (isReachable) { |
5160 handleInTryStatement(); | 5204 handleInTryStatement(); |
5161 push(new HThrowExpression(pop())); | 5205 push(new HThrowExpression(pop())); |
5162 isReachable = false; | 5206 isReachable = false; |
5163 } | 5207 } |
5164 } | 5208 } |
5165 | 5209 |
5166 visitYield(ast.Yield node) { | 5210 visitYield(ast.Yield node) { |
5167 // Dummy implementation. | |
5168 visit(node.expression); | 5211 visit(node.expression); |
5169 pop(); | 5212 HInstruction yielded = pop(); |
5213 add(new HYield(yielded, node.hasStar)); | |
5170 } | 5214 } |
5171 | 5215 |
5172 visitAwait(ast.Await node) { | 5216 visitAwait(ast.Await node) { |
5173 // Dummy implementation. | |
5174 visit(node.expression); | 5217 visit(node.expression); |
5218 HInstruction awaited = pop(); | |
5219 // TODO(herhut): Improve this type. | |
5220 push(new HAwait(awaited, new TypeMask.subclass(compiler.objectClass, | |
5221 compiler.world))); | |
5175 } | 5222 } |
5176 | 5223 |
5177 visitTypeAnnotation(ast.TypeAnnotation node) { | 5224 visitTypeAnnotation(ast.TypeAnnotation node) { |
5178 compiler.internalError(node, | 5225 compiler.internalError(node, |
5179 'Visiting type annotation in SSA builder.'); | 5226 'Visiting type annotation in SSA builder.'); |
5180 } | 5227 } |
5181 | 5228 |
5182 visitVariableDefinitions(ast.VariableDefinitions node) { | 5229 visitVariableDefinitions(ast.VariableDefinitions node) { |
5183 assert(isReachable); | 5230 assert(isReachable); |
5184 for (Link<ast.Node> link = node.definitions.nodes; | 5231 for (Link<ast.Node> link = node.definitions.nodes; |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5308 return new NullJumpHandler(compiler); | 5355 return new NullJumpHandler(compiler); |
5309 } | 5356 } |
5310 if (isLoopJump && node is ast.SwitchStatement) { | 5357 if (isLoopJump && node is ast.SwitchStatement) { |
5311 // Create a special jump handler for loops created for switch statements | 5358 // Create a special jump handler for loops created for switch statements |
5312 // with continue statements. | 5359 // with continue statements. |
5313 return new SwitchCaseJumpHandler(this, element, node); | 5360 return new SwitchCaseJumpHandler(this, element, node); |
5314 } | 5361 } |
5315 return new JumpHandler(this, element); | 5362 return new JumpHandler(this, element); |
5316 } | 5363 } |
5317 | 5364 |
5365 buildAsyncForIn(ast.ForIn node) { | |
5366 assert(node.isAsync); | |
5367 // The async-for is implemented with a StreamIterator. | |
5368 HInstruction streamIterator; | |
5369 | |
5370 visit(node.expression); | |
5371 HInstruction expression = pop(); | |
5372 pushInvokeStatic(node, | |
5373 backend.getStreamIteratorConstructor(), | |
5374 [expression, graph.addConstantNull(compiler)]); | |
5375 streamIterator = pop(); | |
5376 | |
5377 void buildInitializer() {} | |
5378 | |
5379 HInstruction buildCondition() { | |
5380 Selector selector = elements.getMoveNextSelector(node); | |
5381 pushInvokeDynamic(node, selector, [streamIterator]); | |
5382 HInstruction future = pop(); | |
5383 push(new HAwait(future, new TypeMask.subclass(compiler.objectClass, | |
5384 compiler.world))); | |
5385 return popBoolified(); | |
5386 } | |
5387 void buildBody() { | |
5388 Selector call = elements.getCurrentSelector(node); | |
5389 pushInvokeDynamic(node, call, [streamIterator]); | |
5390 | |
5391 ast.Node identifier = node.declaredIdentifier; | |
5392 Element variable = elements.getForInVariable(node); | |
5393 Selector selector = elements.getSelector(identifier); | |
5394 | |
5395 HInstruction value = pop(); | |
5396 if (identifier.asSend() != null | |
5397 && Elements.isInstanceSend(identifier, elements)) { | |
5398 HInstruction receiver = generateInstanceSendReceiver(identifier); | |
5399 assert(receiver != null); | |
5400 generateInstanceSetterWithCompiledReceiver( | |
5401 null, | |
5402 receiver, | |
5403 value, | |
5404 selector: selector, | |
5405 location: identifier); | |
5406 } else { | |
5407 generateNonInstanceSetter( | |
5408 null, variable, value, location: identifier); | |
5409 } | |
5410 pop(); // Pop the value pushed by the setter call. | |
5411 | |
5412 visit(node.body); | |
5413 } | |
5414 | |
5415 void buildUpdate() {}; | |
5416 | |
5417 buildProtectedByFinally(() { | |
5418 handleLoop(node, | |
5419 buildInitializer, | |
5420 buildCondition, | |
5421 buildUpdate, | |
5422 buildBody); | |
5423 }, () { | |
5424 pushInvokeDynamic(node, new Selector.call("cancel", null, 0), | |
5425 [streamIterator]); | |
5426 push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass, | |
5427 compiler.world))); | |
5428 pop(); | |
5429 }); | |
5430 } | |
5431 | |
5318 visitForIn(ast.ForIn node) { | 5432 visitForIn(ast.ForIn node) { |
5433 if (node.isAsync) { | |
5434 return buildAsyncForIn(node); | |
5435 } | |
5436 | |
5319 // Generate a structure equivalent to: | 5437 // Generate a structure equivalent to: |
5320 // Iterator<E> $iter = <iterable>.iterator; | 5438 // Iterator<E> $iter = <iterable>.iterator; |
5321 // while ($iter.moveNext()) { | 5439 // while ($iter.moveNext()) { |
5322 // E <declaredIdentifier> = $iter.current; | 5440 // E <declaredIdentifier> = $iter.current; |
5323 // <body> | 5441 // <body> |
5324 // } | 5442 // } |
5325 | 5443 |
5326 // The iterator is shared between initializer, condition and body. | 5444 // The iterator is shared between initializer, condition and body. |
5327 HInstruction iterator; | 5445 HInstruction iterator; |
5328 void buildInitializer() { | 5446 void buildInitializer() { |
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5844 } | 5962 } |
5845 | 5963 |
5846 visitSwitchCase(ast.SwitchCase node) { | 5964 visitSwitchCase(ast.SwitchCase node) { |
5847 compiler.internalError(node, 'SsaFromAstMixin.visitSwitchCase.'); | 5965 compiler.internalError(node, 'SsaFromAstMixin.visitSwitchCase.'); |
5848 } | 5966 } |
5849 | 5967 |
5850 visitCaseMatch(ast.CaseMatch node) { | 5968 visitCaseMatch(ast.CaseMatch node) { |
5851 compiler.internalError(node, 'SsaFromAstMixin.visitCaseMatch.'); | 5969 compiler.internalError(node, 'SsaFromAstMixin.visitCaseMatch.'); |
5852 } | 5970 } |
5853 | 5971 |
5972 /// Calls [buildTry] inside a synthetic try block with [buildFinally] in the | |
5973 /// finally block. | |
5974 void buildProtectedByFinally(void buildTry(), void buildFinally()) { | |
5975 // Save the current locals. The finally block must not reuse the existing | |
5976 // locals handler. None of the variables | |
5977 // that have been defined in the body-block will be used, but for | |
5978 // loops we will add (unnecessary) phis that will reference the body | |
5979 // variables. This makes it look as if the variables were used | |
5980 // in a non-dominated block. | |
5981 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | |
5982 HBasicBlock enterBlock = openNewBlock(); | |
5983 HTry tryInstruction = new HTry(); | |
5984 close(tryInstruction); | |
5985 bool oldInTryStatement = inTryStatement; | |
5986 inTryStatement = true; | |
5987 | |
5988 HBasicBlock startTryBlock; | |
5989 HBasicBlock endTryBlock; | |
5990 HBasicBlock startFinallyBlock; | |
5991 HBasicBlock endFinallyBlock; | |
5992 | |
5993 startTryBlock = graph.addNewBlock(); | |
5994 open(startTryBlock); | |
5995 buildTry(); | |
5996 // We use a [HExitTry] instead of a [HGoto] for the try block | |
5997 // because it will have two successors: the join block, and | |
5998 // the finally block. | |
5999 if (!isAborted()) endTryBlock = close(new HExitTry()); | |
6000 SubGraph bodyGraph = new SubGraph(startTryBlock, lastOpenedBlock); | |
6001 | |
6002 SubGraph finallyGraph = null; | |
6003 | |
6004 localsHandler = new LocalsHandler.from(savedLocals); | |
6005 startFinallyBlock = graph.addNewBlock(); | |
6006 open(startFinallyBlock); | |
6007 buildFinally(); | |
6008 if (!isAborted()) endFinallyBlock = close(new HGoto()); | |
6009 tryInstruction.finallyBlock = startFinallyBlock; | |
6010 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock); | |
6011 | |
6012 HBasicBlock exitBlock = graph.addNewBlock(); | |
6013 | |
6014 void addExitTrySuccessor(HBasicBlock successor) { | |
6015 // Iterate over all blocks created inside this try/catch, and | |
6016 // attach successor information to blocks that end with | |
6017 // [HExitTry]. | |
6018 for (int i = startTryBlock.id; i < successor.id; i++) { | |
6019 HBasicBlock block = graph.blocks[i]; | |
6020 var last = block.last; | |
6021 if (last is HExitTry) { | |
6022 block.addSuccessor(successor); | |
6023 } | |
6024 } | |
6025 } | |
6026 | |
6027 // Setup all successors. The entry block that contains the [HTry] | |
6028 // has 1) the body 2) the finally, and 4) the exit | |
6029 // blocks as successors. | |
6030 enterBlock.addSuccessor(startTryBlock); | |
6031 enterBlock.addSuccessor(startFinallyBlock); | |
6032 enterBlock.addSuccessor(exitBlock); | |
6033 | |
6034 // The body has the finally block as successor. | |
6035 if (endTryBlock != null) { | |
6036 endTryBlock.addSuccessor(startFinallyBlock); | |
6037 endTryBlock.addSuccessor(exitBlock); | |
6038 } | |
6039 | |
6040 // The finally block has the exit block as successor. | |
6041 endFinallyBlock.addSuccessor(exitBlock); | |
6042 | |
6043 // If a block inside try/catch aborts (eg with a return statement), | |
6044 // we explicitely mark this block a predecessor of the catch | |
6045 // block and the finally block. | |
6046 addExitTrySuccessor(startFinallyBlock); | |
6047 | |
6048 // Use the locals handler not altered by the catch and finally | |
6049 // blocks. | |
6050 localsHandler = savedLocals; | |
6051 open(exitBlock); | |
6052 enterBlock.setBlockFlow( | |
6053 new HTryBlockInformation( | |
6054 wrapStatementGraph(bodyGraph), | |
6055 null, | |
6056 null, // No catchGraph | |
6057 wrapStatementGraph(finallyGraph)), | |
6058 exitBlock); | |
6059 inTryStatement = oldInTryStatement; | |
6060 } | |
6061 | |
5854 visitTryStatement(ast.TryStatement node) { | 6062 visitTryStatement(ast.TryStatement node) { |
5855 // Save the current locals. The catch block and the finally block | 6063 // Save the current locals. The catch block and the finally block |
5856 // must not reuse the existing locals handler. None of the variables | 6064 // 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 | 6065 // 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 | 6066 // loops we will add (unnecessary) phis that will reference the body |
5859 // variables. This makes it look as if the variables were used | 6067 // variables. This makes it look as if the variables were used |
5860 // in a non-dominated block. | 6068 // in a non-dominated block. |
5861 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 6069 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
5862 HBasicBlock enterBlock = openNewBlock(); | 6070 HBasicBlock enterBlock = openNewBlock(); |
5863 HTry tryInstruction = new HTry(); | 6071 HTry tryInstruction = new HTry(); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6038 enterBlock.setBlockFlow( | 6246 enterBlock.setBlockFlow( |
6039 new HTryBlockInformation( | 6247 new HTryBlockInformation( |
6040 wrapStatementGraph(bodyGraph), | 6248 wrapStatementGraph(bodyGraph), |
6041 exception, | 6249 exception, |
6042 wrapStatementGraph(catchGraph), | 6250 wrapStatementGraph(catchGraph), |
6043 wrapStatementGraph(finallyGraph)), | 6251 wrapStatementGraph(finallyGraph)), |
6044 exitBlock); | 6252 exitBlock); |
6045 inTryStatement = oldInTryStatement; | 6253 inTryStatement = oldInTryStatement; |
6046 } | 6254 } |
6047 | 6255 |
6256 | |
6048 visitCatchBlock(ast.CatchBlock node) { | 6257 visitCatchBlock(ast.CatchBlock node) { |
6049 visit(node.block); | 6258 visit(node.block); |
6050 } | 6259 } |
6051 | 6260 |
6052 visitTypedef(ast.Typedef node) { | 6261 visitTypedef(ast.Typedef node) { |
6053 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.'); | 6262 compiler.unimplemented(node, 'SsaFromAstMixin.visitTypedef.'); |
6054 } | 6263 } |
6055 | 6264 |
6056 visitTypeVariable(ast.TypeVariable node) { | 6265 visitTypeVariable(ast.TypeVariable node) { |
6057 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); | 6266 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6213 InlineWeeder(this.maxInliningNodes, | 6422 InlineWeeder(this.maxInliningNodes, |
6214 this.useMaxInliningNodes, | 6423 this.useMaxInliningNodes, |
6215 this.allowLoops); | 6424 this.allowLoops); |
6216 | 6425 |
6217 static bool canBeInlined(ast.FunctionExpression functionExpression, | 6426 static bool canBeInlined(ast.FunctionExpression functionExpression, |
6218 int maxInliningNodes, | 6427 int maxInliningNodes, |
6219 bool useMaxInliningNodes, | 6428 bool useMaxInliningNodes, |
6220 {bool allowLoops: false}) { | 6429 {bool allowLoops: false}) { |
6221 InlineWeeder weeder = | 6430 InlineWeeder weeder = |
6222 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); | 6431 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); |
6432 if (functionExpression.asyncModifier != null) return false; | |
herhut
2015/02/04 09:42:49
Nit: Why not move one line up?
I would prefer to
sigurdm
2015/02/04 10:11:44
Done.
| |
6223 weeder.visit(functionExpression.initializers); | 6433 weeder.visit(functionExpression.initializers); |
6224 weeder.visit(functionExpression.body); | 6434 weeder.visit(functionExpression.body); |
6225 return !weeder.tooDifficult; | 6435 return !weeder.tooDifficult; |
6226 } | 6436 } |
6227 | 6437 |
6228 bool registerNode() { | 6438 bool registerNode() { |
6229 if (!useMaxInliningNodes) return true; | 6439 if (!useMaxInliningNodes) return true; |
6230 if (nodeCount++ > maxInliningNodes) { | 6440 if (nodeCount++ > maxInliningNodes) { |
6231 tooDifficult = true; | 6441 tooDifficult = true; |
6232 return false; | 6442 return false; |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6670 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6880 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
6671 unaliased.accept(this, builder); | 6881 unaliased.accept(this, builder); |
6672 } | 6882 } |
6673 | 6883 |
6674 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6884 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
6675 JavaScriptBackend backend = builder.compiler.backend; | 6885 JavaScriptBackend backend = builder.compiler.backend; |
6676 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6886 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
6677 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 6887 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
6678 } | 6888 } |
6679 } | 6889 } |
OLD | NEW |