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 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 // TODO(ngeoffray): only do this if the variable is mutated. | 368 // TODO(ngeoffray): only do this if the variable is mutated. |
| 369 closureData.usedVariablesInTry.add(element); | 369 closureData.usedVariablesInTry.add(element); |
| 370 } | 370 } |
| 371 } | 371 } |
| 372 } | 372 } |
| 373 | 373 |
| 374 void declareLocal(Element element) { | 374 void declareLocal(Element element) { |
| 375 scopeVariables.add(element); | 375 scopeVariables.add(element); |
| 376 } | 376 } |
| 377 | 377 |
| 378 void registerNeedsThis() { | |
| 379 if (closureData.thisElement != null) { | |
| 380 useLocal(closureData.thisElement); | |
| 381 } | |
| 382 } | |
| 383 | |
| 378 visit(Node node) => node.accept(this); | 384 visit(Node node) => node.accept(this); |
| 379 | 385 |
| 380 visitNode(Node node) => node.visitChildren(this); | 386 visitNode(Node node) => node.visitChildren(this); |
| 381 | 387 |
| 382 visitVariableDefinitions(VariableDefinitions node) { | 388 visitVariableDefinitions(VariableDefinitions node) { |
| 389 if (node.type != null) { | |
| 390 visit(node.type); | |
| 391 } | |
| 383 for (Link<Node> link = node.definitions.nodes; | 392 for (Link<Node> link = node.definitions.nodes; |
| 384 !link.isEmpty; | 393 !link.isEmpty; |
| 385 link = link.tail) { | 394 link = link.tail) { |
| 386 Node definition = link.head; | 395 Node definition = link.head; |
| 387 Element element = elements[definition]; | 396 Element element = elements[definition]; |
| 388 assert(element != null); | 397 assert(element != null); |
| 389 declareLocal(element); | 398 declareLocal(element); |
| 390 // We still need to visit the right-hand sides of the init-assignments. | 399 // We still need to visit the right-hand sides of the init-assignments. |
| 391 // For SendSets don't visit the left again. Otherwise it would be marked | 400 // For SendSets don't visit the left again. Otherwise it would be marked |
| 392 // as mutated. | 401 // as mutated. |
| 393 if (definition is Send) { | 402 if (definition is Send) { |
| 394 Send assignment = definition; | 403 Send assignment = definition; |
| 395 Node arguments = assignment.argumentsNode; | 404 Node arguments = assignment.argumentsNode; |
| 396 if (arguments != null) { | 405 if (arguments != null) { |
| 397 visit(arguments); | 406 visit(arguments); |
| 398 } | 407 } |
| 399 } else { | 408 } else { |
| 400 visit(definition); | 409 visit(definition); |
| 401 } | 410 } |
| 402 } | 411 } |
| 403 } | 412 } |
| 404 | 413 |
| 414 visitTypeAnnotation(TypeAnnotation node) { | |
| 415 if (compiler.enableTypeAssertions && currentElement.isInstanceMember()) { | |
| 416 DartType type = elements.getType(node); | |
| 417 // In checked mode, using a type variable in a type annotation may lead | |
| 418 // to a runtime type check that needs to access the type argument and | |
| 419 // therefor the closure needs a this-element. | |
|
ngeoffray
2013/04/15 10:59:14
therefore
karlklose
2013/05/02 15:04:54
Done.
| |
| 420 // TODO(karlklose,johnniwinther): if the type is null, the annotation is | |
| 421 // from a parameter; in checked mode, we need to resolve all types. | |
|
ngeoffray
2013/04/15 10:59:14
I don't understand this TODO. How can it be null?
karlklose
2013/05/02 15:04:54
Maybe we do not store the result in the TreeElemen
| |
| 422 if (type != null && type.containsTypeVariables) { | |
| 423 registerNeedsThis(); | |
| 424 } | |
| 425 } | |
| 426 node.visitChildren(this); | |
| 427 } | |
| 428 | |
| 405 visitIdentifier(Identifier node) { | 429 visitIdentifier(Identifier node) { |
| 406 if (node.isThis()) { | 430 if (node.isThis()) { |
| 407 useLocal(closureData.thisElement); | 431 registerNeedsThis(); |
| 408 } else { | 432 } else { |
| 409 Element element = elements[node]; | 433 Element element = elements[node]; |
| 410 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { | 434 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { |
| 411 useLocal(closureData.thisElement); | 435 registerNeedsThis(); |
| 412 } | 436 } |
| 413 } | 437 } |
| 414 node.visitChildren(this); | 438 node.visitChildren(this); |
| 415 } | 439 } |
| 416 | 440 |
| 417 visitSend(Send node) { | 441 visitSend(Send node) { |
| 418 Element element = elements[node]; | 442 Element element = elements[node]; |
| 419 if (Elements.isLocal(element)) { | 443 if (Elements.isLocal(element)) { |
| 420 useLocal(element); | 444 useLocal(element); |
| 421 } else if (node.receiver == null && | 445 } else if (node.receiver == null && |
| 422 Elements.isInstanceSend(node, elements)) { | 446 Elements.isInstanceSend(node, elements)) { |
| 423 useLocal(closureData.thisElement); | 447 registerNeedsThis(); |
| 424 } else if (node.isSuperCall) { | 448 } else if (node.isSuperCall) { |
| 425 useLocal(closureData.thisElement); | 449 registerNeedsThis(); |
| 426 } else if (node.isParameterCheck) { | 450 } else if (node.isParameterCheck) { |
| 427 Element parameter = elements[node.receiver]; | 451 Element parameter = elements[node.receiver]; |
| 428 FunctionElement enclosing = parameter.enclosingElement; | 452 FunctionElement enclosing = parameter.enclosingElement; |
| 429 FunctionExpression function = enclosing.parseNode(compiler); | 453 FunctionExpression function = enclosing.parseNode(compiler); |
| 430 ClosureClassMap cached = closureMappingCache[function]; | 454 ClosureClassMap cached = closureMappingCache[function]; |
| 431 if (!cached.parametersWithSentinel.containsKey(parameter)) { | 455 if (!cached.parametersWithSentinel.containsKey(parameter)) { |
| 432 SourceString parameterName = parameter.name; | 456 SourceString parameterName = parameter.name; |
| 433 String name = '${parameterName.slowToString()}_check'; | 457 String name = '${parameterName.slowToString()}_check'; |
| 434 Element newElement = new CheckVariableElement(new SourceString(name), | 458 Element newElement = new CheckVariableElement(new SourceString(name), |
| 435 parameter, | 459 parameter, |
| 436 enclosing); | 460 enclosing); |
| 437 useLocal(newElement); | 461 useLocal(newElement); |
| 438 cached.parametersWithSentinel[parameter] = newElement; | 462 cached.parametersWithSentinel[parameter] = newElement; |
| 439 } | 463 } |
| 440 } | 464 } |
| 441 node.visitChildren(this); | 465 node.visitChildren(this); |
| 442 } | 466 } |
| 443 | 467 |
| 444 visitSendSet(SendSet node) { | 468 visitSendSet(SendSet node) { |
| 445 Element element = elements[node]; | 469 Element element = elements[node]; |
| 446 if (Elements.isLocal(element)) { | 470 if (Elements.isLocal(element)) { |
| 447 mutatedVariables.add(element); | 471 mutatedVariables.add(element); |
| 448 } | 472 } |
| 473 if (element != null && element is VariableElement) { | |
| 474 VariableElement variable = element; | |
| 475 if (variable.variables.type.containsTypeVariables) { | |
| 476 registerNeedsThis(); | |
|
ngeoffray
2013/04/15 10:59:14
Not sure you need this:
- If element is a field, t
karlklose
2013/05/02 15:04:54
It is needed.
| |
| 477 } | |
| 478 } | |
| 449 super.visitSendSet(node); | 479 super.visitSendSet(node); |
| 450 } | 480 } |
| 451 | 481 |
| 452 visitNewExpression(NewExpression node) { | 482 visitNewExpression(NewExpression node) { |
| 453 DartType type = elements.getType(node); | 483 DartType type = elements.getType(node); |
| 454 | 484 |
| 455 bool hasTypeVariable(DartType type) { | 485 bool hasTypeVariable(DartType type) { |
| 456 if (type is TypeVariableType) { | 486 if (type is TypeVariableType) { |
| 457 return true; | 487 return true; |
| 458 } else if (type is InterfaceType) { | 488 } else if (type is InterfaceType) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 475 analyzeTypeVariables(argument); | 505 analyzeTypeVariables(argument); |
| 476 } | 506 } |
| 477 } | 507 } |
| 478 } | 508 } |
| 479 | 509 |
| 480 if (outermostElement.isMember() && | 510 if (outermostElement.isMember() && |
| 481 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { | 511 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { |
| 482 if (outermostElement.isConstructor() || outermostElement.isField()) { | 512 if (outermostElement.isConstructor() || outermostElement.isField()) { |
| 483 analyzeTypeVariables(type); | 513 analyzeTypeVariables(type); |
| 484 } else if (outermostElement.isInstanceMember()) { | 514 } else if (outermostElement.isInstanceMember()) { |
| 485 if (hasTypeVariable(type)) useLocal(closureData.thisElement); | 515 if (hasTypeVariable(type)) { |
| 516 registerNeedsThis(); | |
| 517 } | |
| 486 } | 518 } |
| 487 } | 519 } |
| 488 | 520 |
| 489 node.visitChildren(this); | 521 node.visitChildren(this); |
| 490 } | 522 } |
| 491 | 523 |
| 492 // If variables that are declared in the [node] scope are captured and need | 524 // If variables that are declared in the [node] scope are captured and need |
| 493 // to be boxed create a box-element and update the [capturingScopes] in the | 525 // to be boxed create a box-element and update the [capturingScopes] in the |
| 494 // current [closureData]. | 526 // current [closureData]. |
| 495 // The boxed variables are updated in the [capturedVariableMapping]. | 527 // The boxed variables are updated in the [capturedVariableMapping]. |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 644 if (currentElement.isFactoryConstructor() && | 676 if (currentElement.isFactoryConstructor() && |
| 645 compiler.backend.needsRti(currentElement.enclosingElement)) { | 677 compiler.backend.needsRti(currentElement.enclosingElement)) { |
| 646 // Declare the type parameters in the scope. Generative | 678 // Declare the type parameters in the scope. Generative |
| 647 // constructors just use 'this'. | 679 // constructors just use 'this'. |
| 648 ClassElement cls = currentElement.enclosingElement; | 680 ClassElement cls = currentElement.enclosingElement; |
| 649 cls.typeVariables.forEach((TypeVariableType typeVariable) { | 681 cls.typeVariables.forEach((TypeVariableType typeVariable) { |
| 650 declareLocal(typeVariable.element); | 682 declareLocal(typeVariable.element); |
| 651 }); | 683 }); |
| 652 } | 684 } |
| 653 | 685 |
| 686 if (element.computeType(compiler).containsTypeVariables) { | |
|
ngeoffray
2013/04/15 10:59:14
So that's the function type if the element? It mat
karlklose
2013/05/02 15:04:54
Done.
| |
| 687 registerNeedsThis(); | |
| 688 } | |
| 689 | |
| 654 visitChildren(); | 690 visitChildren(); |
| 655 }); | 691 }); |
| 656 | 692 |
| 657 | 693 |
| 658 ClosureClassMap savedClosureData = closureData; | 694 ClosureClassMap savedClosureData = closureData; |
| 659 bool savedInsideClosure = insideClosure; | 695 bool savedInsideClosure = insideClosure; |
| 660 | 696 |
| 661 // Restore old values. | 697 // Restore old values. |
| 662 insideClosure = oldInsideClosure; | 698 insideClosure = oldInsideClosure; |
| 663 closureData = oldClosureData; | 699 closureData = oldClosureData; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 } | 737 } |
| 702 | 738 |
| 703 visitTryStatement(TryStatement node) { | 739 visitTryStatement(TryStatement node) { |
| 704 // TODO(ngeoffray): implement finer grain state. | 740 // TODO(ngeoffray): implement finer grain state. |
| 705 bool oldInTryStatement = inTryStatement; | 741 bool oldInTryStatement = inTryStatement; |
| 706 inTryStatement = true; | 742 inTryStatement = true; |
| 707 node.visitChildren(this); | 743 node.visitChildren(this); |
| 708 inTryStatement = oldInTryStatement; | 744 inTryStatement = oldInTryStatement; |
| 709 } | 745 } |
| 710 } | 746 } |
| OLD | NEW |