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

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: Go back to generating return of wrapped errors when possible. 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 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
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
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
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
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
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
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,
floitsch 2015/02/04 12:31:28 add comment what this is.
sigurdm 2015/02/05 14:06:04 Done.
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 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
6213 InlineWeeder(this.maxInliningNodes, 6421 InlineWeeder(this.maxInliningNodes,
6214 this.useMaxInliningNodes, 6422 this.useMaxInliningNodes,
6215 this.allowLoops); 6423 this.allowLoops);
6216 6424
6217 static bool canBeInlined(ast.FunctionExpression functionExpression, 6425 static bool canBeInlined(ast.FunctionExpression functionExpression,
6218 int maxInliningNodes, 6426 int maxInliningNodes,
6219 bool useMaxInliningNodes, 6427 bool useMaxInliningNodes,
6220 {bool allowLoops: false}) { 6428 {bool allowLoops: false}) {
6221 InlineWeeder weeder = 6429 InlineWeeder weeder =
6222 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops); 6430 new InlineWeeder(maxInliningNodes, useMaxInliningNodes, allowLoops);
6431 if (functionExpression.asyncModifier != null) return false;
6223 weeder.visit(functionExpression.initializers); 6432 weeder.visit(functionExpression.initializers);
6224 weeder.visit(functionExpression.body); 6433 weeder.visit(functionExpression.body);
6225 return !weeder.tooDifficult; 6434 return !weeder.tooDifficult;
6226 } 6435 }
6227 6436
6228 bool registerNode() { 6437 bool registerNode() {
6229 if (!useMaxInliningNodes) return true; 6438 if (!useMaxInliningNodes) return true;
6230 if (nodeCount++ > maxInliningNodes) { 6439 if (nodeCount++ > maxInliningNodes) {
6231 tooDifficult = true; 6440 tooDifficult = true;
6232 return false; 6441 return false;
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
6670 if (unaliased is TypedefType) throw 'unable to unalias $type'; 6879 if (unaliased is TypedefType) throw 'unable to unalias $type';
6671 unaliased.accept(this, builder); 6880 unaliased.accept(this, builder);
6672 } 6881 }
6673 6882
6674 void visitDynamicType(DynamicType type, SsaBuilder builder) { 6883 void visitDynamicType(DynamicType type, SsaBuilder builder) {
6675 JavaScriptBackend backend = builder.compiler.backend; 6884 JavaScriptBackend backend = builder.compiler.backend;
6676 ClassElement cls = backend.findHelper('DynamicRuntimeType'); 6885 ClassElement cls = backend.findHelper('DynamicRuntimeType');
6677 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 6886 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
6678 } 6887 }
6679 } 6888 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698