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 library closureToClassMapper; | 5 library closureToClassMapper; |
6 | 6 |
7 import "elements/elements.dart"; | 7 import "elements/elements.dart"; |
8 import "dart2jslib.dart"; | 8 import "dart2jslib.dart"; |
9 import "dart_types.dart"; | 9 import "dart_types.dart"; |
10 import "scanner/scannerlib.dart" show Token; | 10 import "scanner/scannerlib.dart" show Token; |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 ClosureClassMap cached = closureMappingCache[function]; | 425 ClosureClassMap cached = closureMappingCache[function]; |
426 if (!cached.parametersWithSentinel.containsKey(parameter)) { | 426 if (!cached.parametersWithSentinel.containsKey(parameter)) { |
427 SourceString parameterName = parameter.name; | 427 SourceString parameterName = parameter.name; |
428 String name = '${parameterName.slowToString()}_check'; | 428 String name = '${parameterName.slowToString()}_check'; |
429 Element newElement = new CheckVariableElement(new SourceString(name), | 429 Element newElement = new CheckVariableElement(new SourceString(name), |
430 parameter, | 430 parameter, |
431 enclosing); | 431 enclosing); |
432 useLocal(newElement); | 432 useLocal(newElement); |
433 cached.parametersWithSentinel[parameter] = newElement; | 433 cached.parametersWithSentinel[parameter] = newElement; |
434 } | 434 } |
435 } else if (node.isOperator) { | |
436 String operatorString = node.selector.asOperator().source.stringValue; | |
437 if (operatorString == 'is' || operatorString == 'as') { | |
karlklose
2013/03/22 13:17:46
I would really like to encapsulate this pattern. I
Johnni Winther
2013/06/12 14:39:10
I looked. They are all slightly different.
| |
438 DartType type = elements.getType(node.arguments.head); | |
439 analyzeType(type); | |
440 } | |
435 } | 441 } |
436 node.visitChildren(this); | 442 node.visitChildren(this); |
437 } | 443 } |
438 | 444 |
439 visitSendSet(SendSet node) { | 445 visitSendSet(SendSet node) { |
440 Element element = elements[node]; | 446 Element element = elements[node]; |
441 if (Elements.isLocal(element)) { | 447 if (Elements.isLocal(element)) { |
442 mutatedVariables.add(element); | 448 mutatedVariables.add(element); |
443 } | 449 } |
444 super.visitSendSet(node); | 450 super.visitSendSet(node); |
445 } | 451 } |
446 | 452 |
447 visitNewExpression(NewExpression node) { | 453 visitNewExpression(NewExpression node) { |
448 DartType type = elements.getType(node); | 454 DartType type = elements.getType(node); |
455 analyzeType(type); | |
456 node.visitChildren(this); | |
457 } | |
449 | 458 |
450 bool hasTypeVariable(DartType type) { | 459 void analyzeTypeVariables(DartType type) { |
451 if (type is TypeVariableType) { | 460 if (type is TypeVariableType) { |
452 return true; | 461 useLocal(type.element); |
453 } else if (type is InterfaceType) { | 462 } else if (type is InterfaceType) { |
454 InterfaceType ifcType = type; | 463 InterfaceType ifcType = type; |
455 for (DartType argument in ifcType.typeArguments) { | 464 for (DartType argument in ifcType.typeArguments) { |
456 if (hasTypeVariable(argument)) { | 465 analyzeTypeVariables(argument); |
457 return true; | |
458 } | |
459 } | |
460 } | 466 } |
461 return false; | |
462 } | 467 } |
468 } | |
463 | 469 |
464 void analyzeTypeVariables(DartType type) { | 470 void analyzeType(DartType type) { |
465 if (type is TypeVariableType) { | 471 if (type == null) return; |
karlklose
2013/03/22 13:17:46
How can this happen?
Johnni Winther
2013/06/21 12:19:14
Bad handling of is!
Now fixed.
| |
466 useLocal(type.element); | 472 if (outermostElement.isMember() && |
467 } else if (type is InterfaceType) { | 473 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { |
468 InterfaceType ifcType = type; | 474 if (outermostElement.isConstructor() || |
469 for (DartType argument in ifcType.typeArguments) { | 475 outermostElement.isField()) { |
470 analyzeTypeVariables(argument); | 476 analyzeTypeVariables(type); |
477 } else if (outermostElement.isInstanceMember()) { | |
478 if (type.containsTypeVariables) { | |
479 useLocal(closureData.thisElement); | |
471 } | 480 } |
472 } | 481 } |
473 } | 482 } |
474 | |
475 if (outermostElement.isMember() && | |
476 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { | |
477 if (outermostElement.isConstructor() || outermostElement.isField()) { | |
478 analyzeTypeVariables(type); | |
479 } else if (outermostElement.isInstanceMember()) { | |
480 if (hasTypeVariable(type)) useLocal(closureData.thisElement); | |
481 } | |
482 } | |
483 | |
484 node.visitChildren(this); | |
485 } | 483 } |
486 | 484 |
487 // If variables that are declared in the [node] scope are captured and need | 485 // If variables that are declared in the [node] scope are captured and need |
488 // to be boxed create a box-element and update the [capturingScopes] in the | 486 // to be boxed create a box-element and update the [capturingScopes] in the |
489 // current [closureData]. | 487 // current [closureData]. |
490 // The boxed variables are updated in the [capturedVariableMapping]. | 488 // The boxed variables are updated in the [capturedVariableMapping]. |
491 void attachCapturedScopeVariables(Node node) { | 489 void attachCapturedScopeVariables(Node node) { |
492 Element box = null; | 490 Element box = null; |
493 Map<Element, Element> scopeMapping = new Map<Element, Element>(); | 491 Map<Element, Element> scopeMapping = new Map<Element, Element>(); |
494 for (Element element in scopeVariables) { | 492 for (Element element in scopeVariables) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
639 if (currentElement.isFactoryConstructor() && | 637 if (currentElement.isFactoryConstructor() && |
640 compiler.backend.needsRti(currentElement.enclosingElement)) { | 638 compiler.backend.needsRti(currentElement.enclosingElement)) { |
641 // Declare the type parameters in the scope. Generative | 639 // Declare the type parameters in the scope. Generative |
642 // constructors just use 'this'. | 640 // constructors just use 'this'. |
643 ClassElement cls = currentElement.enclosingElement; | 641 ClassElement cls = currentElement.enclosingElement; |
644 cls.typeVariables.forEach((TypeVariableType typeVariable) { | 642 cls.typeVariables.forEach((TypeVariableType typeVariable) { |
645 declareLocal(typeVariable.element); | 643 declareLocal(typeVariable.element); |
646 }); | 644 }); |
647 } | 645 } |
648 | 646 |
647 // Ensure that closure that need runtime type information has access to | |
648 // this of the enclosing class. | |
649 if (closureData.thisElement != null && | |
650 compiler.backend.methodNeedsRti(element)) { | |
651 useLocal(closureData.thisElement); | |
652 } | |
653 | |
649 visitChildren(); | 654 visitChildren(); |
650 }); | 655 }); |
651 | 656 |
652 | 657 |
653 ClosureClassMap savedClosureData = closureData; | 658 ClosureClassMap savedClosureData = closureData; |
654 bool savedInsideClosure = insideClosure; | 659 bool savedInsideClosure = insideClosure; |
655 | 660 |
656 // Restore old values. | 661 // Restore old values. |
657 insideClosure = oldInsideClosure; | 662 insideClosure = oldInsideClosure; |
658 closureData = oldClosureData; | 663 closureData = oldClosureData; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
696 } | 701 } |
697 | 702 |
698 visitTryStatement(TryStatement node) { | 703 visitTryStatement(TryStatement node) { |
699 // TODO(ngeoffray): implement finer grain state. | 704 // TODO(ngeoffray): implement finer grain state. |
700 bool oldInTryStatement = inTryStatement; | 705 bool oldInTryStatement = inTryStatement; |
701 inTryStatement = true; | 706 inTryStatement = true; |
702 node.visitChildren(this); | 707 node.visitChildren(this); |
703 inTryStatement = oldInTryStatement; | 708 inTryStatement = oldInTryStatement; |
704 } | 709 } |
705 } | 710 } |
OLD | NEW |