Chromium Code Reviews| 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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 // TODO(ngeoffray): only do this if the variable is mutated. | 383 // TODO(ngeoffray): only do this if the variable is mutated. |
| 384 closureData.usedVariablesInTry.add(element); | 384 closureData.usedVariablesInTry.add(element); |
| 385 } | 385 } |
| 386 } | 386 } |
| 387 } | 387 } |
| 388 | 388 |
| 389 void declareLocal(Element element) { | 389 void declareLocal(Element element) { |
| 390 scopeVariables.add(element); | 390 scopeVariables.add(element); |
| 391 } | 391 } |
| 392 | 392 |
| 393 void registerNeedsThis() { | |
| 394 if (closureData.thisElement != null) { | |
| 395 useLocal(closureData.thisElement); | |
| 396 } | |
| 397 } | |
| 398 | |
| 393 visit(Node node) => node.accept(this); | 399 visit(Node node) => node.accept(this); |
| 394 | 400 |
| 395 visitNode(Node node) => node.visitChildren(this); | 401 visitNode(Node node) => node.visitChildren(this); |
| 396 | 402 |
| 397 visitVariableDefinitions(VariableDefinitions node) { | 403 visitVariableDefinitions(VariableDefinitions node) { |
| 404 if (node.type != null) { | |
| 405 visit(node.type); | |
| 406 } | |
| 398 for (Link<Node> link = node.definitions.nodes; | 407 for (Link<Node> link = node.definitions.nodes; |
| 399 !link.isEmpty; | 408 !link.isEmpty; |
| 400 link = link.tail) { | 409 link = link.tail) { |
| 401 Node definition = link.head; | 410 Node definition = link.head; |
| 402 Element element = elements[definition]; | 411 Element element = elements[definition]; |
| 403 assert(element != null); | 412 assert(element != null); |
| 404 declareLocal(element); | 413 declareLocal(element); |
| 405 // We still need to visit the right-hand sides of the init-assignments. | 414 // We still need to visit the right-hand sides of the init-assignments. |
| 406 // For SendSets don't visit the left again. Otherwise it would be marked | 415 // For SendSets don't visit the left again. Otherwise it would be marked |
| 407 // as mutated. | 416 // as mutated. |
| 408 if (definition is Send) { | 417 if (definition is Send) { |
| 409 Send assignment = definition; | 418 Send assignment = definition; |
| 410 Node arguments = assignment.argumentsNode; | 419 Node arguments = assignment.argumentsNode; |
| 411 if (arguments != null) { | 420 if (arguments != null) { |
| 412 visit(arguments); | 421 visit(arguments); |
| 413 } | 422 } |
| 414 } else { | 423 } else { |
| 415 visit(definition); | 424 visit(definition); |
| 416 } | 425 } |
| 417 } | 426 } |
| 418 } | 427 } |
| 419 | 428 |
| 429 visitTypeAnnotation(TypeAnnotation node) { | |
| 430 if (compiler.enableTypeAssertions && currentElement.isInstanceMember()) { | |
| 431 DartType type = elements.getType(node); | |
| 432 // In checked mode, using a type variable in a type annotation may lead | |
| 433 // to a runtime type check that needs to access the type argument and | |
| 434 // therefore the closure needs a this-element. | |
| 435 // TODO(karlklose,johnniwinther): if the type is null, the annotation is | |
| 436 // from a parameter; in checked mode, we need to resolve all types. | |
|
ngeoffray
2013/05/13 09:10:59
So for foo(T a), we don't resolve the "T" ?
karlklose
2013/05/14 13:49:41
I updated the comment to be more precise.
ngeoffray
2013/05/15 08:45:32
Thank you. I still find it a bit obscure: what is
| |
| 437 if (type != null && type.containsTypeVariables) { | |
| 438 registerNeedsThis(); | |
| 439 } | |
| 440 } | |
| 441 node.visitChildren(this); | |
| 442 } | |
| 443 | |
| 420 visitIdentifier(Identifier node) { | 444 visitIdentifier(Identifier node) { |
| 421 if (node.isThis()) { | 445 if (node.isThis()) { |
| 422 useLocal(closureData.thisElement); | 446 registerNeedsThis(); |
| 423 } else { | 447 } else { |
| 424 Element element = elements[node]; | 448 Element element = elements[node]; |
| 425 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { | 449 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { |
| 426 useLocal(closureData.thisElement); | 450 registerNeedsThis(); |
| 427 } | 451 } |
| 428 } | 452 } |
| 429 node.visitChildren(this); | 453 node.visitChildren(this); |
| 430 } | 454 } |
| 431 | 455 |
| 432 visitSend(Send node) { | 456 visitSend(Send node) { |
| 433 Element element = elements[node]; | 457 Element element = elements[node]; |
| 434 if (Elements.isLocal(element)) { | 458 if (Elements.isLocal(element)) { |
| 435 useLocal(element); | 459 useLocal(element); |
| 436 } else if (node.receiver == null && | 460 } else if (node.receiver == null && |
| 437 Elements.isInstanceSend(node, elements)) { | 461 Elements.isInstanceSend(node, elements)) { |
| 438 useLocal(closureData.thisElement); | 462 registerNeedsThis(); |
| 439 } else if (node.isSuperCall) { | 463 } else if (node.isSuperCall) { |
| 440 useLocal(closureData.thisElement); | 464 registerNeedsThis(); |
| 441 } else if (node.isParameterCheck) { | 465 } else if (node.isParameterCheck) { |
| 442 Element parameter = elements[node.receiver]; | 466 Element parameter = elements[node.receiver]; |
| 443 FunctionElement enclosing = parameter.enclosingElement; | 467 FunctionElement enclosing = parameter.enclosingElement; |
| 444 FunctionExpression function = enclosing.parseNode(compiler); | 468 FunctionExpression function = enclosing.parseNode(compiler); |
| 445 ClosureClassMap cached = closureMappingCache[function]; | 469 ClosureClassMap cached = closureMappingCache[function]; |
| 446 if (!cached.parametersWithSentinel.containsKey(parameter)) { | 470 if (!cached.parametersWithSentinel.containsKey(parameter)) { |
| 447 SourceString parameterName = parameter.name; | 471 SourceString parameterName = parameter.name; |
| 448 String name = '${parameterName.slowToString()}_check'; | 472 String name = '${parameterName.slowToString()}_check'; |
| 449 Element newElement = new CheckVariableElement(new SourceString(name), | 473 Element newElement = new CheckVariableElement(new SourceString(name), |
| 450 parameter, | 474 parameter, |
| 451 enclosing); | 475 enclosing); |
| 452 useLocal(newElement); | 476 useLocal(newElement); |
| 453 cached.parametersWithSentinel[parameter] = newElement; | 477 cached.parametersWithSentinel[parameter] = newElement; |
| 454 } | 478 } |
| 455 } | 479 } |
| 456 node.visitChildren(this); | 480 node.visitChildren(this); |
| 457 } | 481 } |
| 458 | 482 |
| 459 visitSendSet(SendSet node) { | 483 visitSendSet(SendSet node) { |
| 460 Element element = elements[node]; | 484 Element element = elements[node]; |
| 461 if (Elements.isLocal(element)) { | 485 if (Elements.isLocal(element)) { |
| 462 mutatedVariables.add(element); | 486 mutatedVariables.add(element); |
| 463 } | 487 } |
| 488 if (element != null && element is VariableElement) { | |
|
ngeoffray
2013/05/13 09:10:59
Should that be Elements.isLocal(element) ?
karlklose
2013/05/14 13:49:41
Done.
karlklose
2013/05/14 13:49:41
Done.
| |
| 489 VariableElement variable = element; | |
| 490 if (variable.variables.type.containsTypeVariables) { | |
|
ngeoffray
2013/05/13 09:10:59
Change to element.computeType(compiler).containsTy
karlklose
2013/05/14 13:49:41
Done.
| |
| 491 registerNeedsThis(); | |
| 492 } | |
| 493 } | |
| 464 super.visitSendSet(node); | 494 super.visitSendSet(node); |
| 465 } | 495 } |
| 466 | 496 |
| 467 visitNewExpression(NewExpression node) { | 497 visitNewExpression(NewExpression node) { |
| 468 DartType type = elements.getType(node); | 498 DartType type = elements.getType(node); |
| 469 | 499 |
| 470 bool hasTypeVariable(DartType type) { | 500 bool hasTypeVariable(DartType type) { |
| 471 if (type is TypeVariableType) { | 501 if (type is TypeVariableType) { |
| 472 return true; | 502 return true; |
| 473 } else if (type is InterfaceType) { | 503 } else if (type is InterfaceType) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 490 analyzeTypeVariables(argument); | 520 analyzeTypeVariables(argument); |
| 491 } | 521 } |
| 492 } | 522 } |
| 493 } | 523 } |
| 494 | 524 |
| 495 if (outermostElement.isMember() && | 525 if (outermostElement.isMember() && |
| 496 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { | 526 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { |
| 497 if (outermostElement.isConstructor() || outermostElement.isField()) { | 527 if (outermostElement.isConstructor() || outermostElement.isField()) { |
| 498 analyzeTypeVariables(type); | 528 analyzeTypeVariables(type); |
| 499 } else if (outermostElement.isInstanceMember()) { | 529 } else if (outermostElement.isInstanceMember()) { |
| 500 if (hasTypeVariable(type)) useLocal(closureData.thisElement); | 530 if (hasTypeVariable(type)) { |
| 531 registerNeedsThis(); | |
| 532 } | |
| 501 } | 533 } |
| 502 } | 534 } |
| 503 | 535 |
| 504 node.visitChildren(this); | 536 node.visitChildren(this); |
| 505 } | 537 } |
| 506 | 538 |
| 507 // If variables that are declared in the [node] scope are captured and need | 539 // If variables that are declared in the [node] scope are captured and need |
| 508 // to be boxed create a box-element and update the [capturingScopes] in the | 540 // to be boxed create a box-element and update the [capturingScopes] in the |
| 509 // current [closureData]. | 541 // current [closureData]. |
| 510 // The boxed variables are updated in the [capturedVariableMapping]. | 542 // The boxed variables are updated in the [capturedVariableMapping]. |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 659 if (currentElement.isFactoryConstructor() && | 691 if (currentElement.isFactoryConstructor() && |
| 660 compiler.backend.needsRti(currentElement.enclosingElement)) { | 692 compiler.backend.needsRti(currentElement.enclosingElement)) { |
| 661 // Declare the type parameters in the scope. Generative | 693 // Declare the type parameters in the scope. Generative |
| 662 // constructors just use 'this'. | 694 // constructors just use 'this'. |
| 663 ClassElement cls = currentElement.enclosingElement; | 695 ClassElement cls = currentElement.enclosingElement; |
| 664 cls.typeVariables.forEach((TypeVariableType typeVariable) { | 696 cls.typeVariables.forEach((TypeVariableType typeVariable) { |
| 665 declareLocal(typeVariable.element); | 697 declareLocal(typeVariable.element); |
| 666 }); | 698 }); |
| 667 } | 699 } |
| 668 | 700 |
| 701 // Compute the function type and check for type variables in return or | |
| 702 // parameter types. | |
| 703 if (element.computeType(compiler).containsTypeVariables) { | |
| 704 registerNeedsThis(); | |
| 705 } | |
| 706 | |
| 669 visitChildren(); | 707 visitChildren(); |
| 670 }); | 708 }); |
| 671 | 709 |
| 672 | 710 |
| 673 ClosureClassMap savedClosureData = closureData; | 711 ClosureClassMap savedClosureData = closureData; |
| 674 bool savedInsideClosure = insideClosure; | 712 bool savedInsideClosure = insideClosure; |
| 675 | 713 |
| 676 // Restore old values. | 714 // Restore old values. |
| 677 insideClosure = oldInsideClosure; | 715 insideClosure = oldInsideClosure; |
| 678 closureData = oldClosureData; | 716 closureData = oldClosureData; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 } | 754 } |
| 717 | 755 |
| 718 visitTryStatement(TryStatement node) { | 756 visitTryStatement(TryStatement node) { |
| 719 // TODO(ngeoffray): implement finer grain state. | 757 // TODO(ngeoffray): implement finer grain state. |
| 720 bool oldInTryStatement = inTryStatement; | 758 bool oldInTryStatement = inTryStatement; |
| 721 inTryStatement = true; | 759 inTryStatement = true; |
| 722 node.visitChildren(this); | 760 node.visitChildren(this); |
| 723 inTryStatement = oldInTryStatement; | 761 inTryStatement = oldInTryStatement; |
| 724 } | 762 } |
| 725 } | 763 } |
| OLD | NEW |