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

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

Powered by Google App Engine
This is Rietveld 408576698