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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/closure.dart

Issue 13019003: Enable full type-checks in checked mode. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 7 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
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/js_backend/backend.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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 which has been analyzed before the method has been
437 // resolved and the result has been thrown away.
438 if (type != null && type.containsTypeVariables) {
439 registerNeedsThis();
440 }
441 }
442 node.visitChildren(this);
443 }
444
420 visitIdentifier(Identifier node) { 445 visitIdentifier(Identifier node) {
421 if (node.isThis()) { 446 if (node.isThis()) {
422 useLocal(closureData.thisElement); 447 registerNeedsThis();
423 } else { 448 } else {
424 Element element = elements[node]; 449 Element element = elements[node];
425 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) { 450 if (element != null && element.kind == ElementKind.TYPE_VARIABLE) {
426 useLocal(closureData.thisElement); 451 registerNeedsThis();
427 } 452 }
428 } 453 }
429 node.visitChildren(this); 454 node.visitChildren(this);
430 } 455 }
431 456
432 visitSend(Send node) { 457 visitSend(Send node) {
433 Element element = elements[node]; 458 Element element = elements[node];
434 if (Elements.isLocal(element)) { 459 if (Elements.isLocal(element)) {
435 useLocal(element); 460 useLocal(element);
436 } else if (node.receiver == null && 461 } else if (node.receiver == null &&
437 Elements.isInstanceSend(node, elements)) { 462 Elements.isInstanceSend(node, elements)) {
438 useLocal(closureData.thisElement); 463 registerNeedsThis();
439 } else if (node.isSuperCall) { 464 } else if (node.isSuperCall) {
440 useLocal(closureData.thisElement); 465 registerNeedsThis();
441 } else if (node.isParameterCheck) { 466 } else if (node.isParameterCheck) {
442 Element parameter = elements[node.receiver]; 467 Element parameter = elements[node.receiver];
443 FunctionElement enclosing = parameter.enclosingElement; 468 FunctionElement enclosing = parameter.enclosingElement;
444 FunctionExpression function = enclosing.parseNode(compiler); 469 FunctionExpression function = enclosing.parseNode(compiler);
445 ClosureClassMap cached = closureMappingCache[function]; 470 ClosureClassMap cached = closureMappingCache[function];
446 if (!cached.parametersWithSentinel.containsKey(parameter)) { 471 if (!cached.parametersWithSentinel.containsKey(parameter)) {
447 SourceString parameterName = parameter.name; 472 SourceString parameterName = parameter.name;
448 String name = '${parameterName.slowToString()}_check'; 473 String name = '${parameterName.slowToString()}_check';
449 Element newElement = new CheckVariableElement(new SourceString(name), 474 Element newElement = new CheckVariableElement(new SourceString(name),
450 parameter, 475 parameter,
451 enclosing); 476 enclosing);
452 useLocal(newElement); 477 useLocal(newElement);
453 cached.parametersWithSentinel[parameter] = newElement; 478 cached.parametersWithSentinel[parameter] = newElement;
454 } 479 }
455 } 480 }
456 node.visitChildren(this); 481 node.visitChildren(this);
457 } 482 }
458 483
459 visitSendSet(SendSet node) { 484 visitSendSet(SendSet node) {
460 Element element = elements[node]; 485 Element element = elements[node];
461 if (Elements.isLocal(element)) { 486 if (Elements.isLocal(element)) {
462 mutatedVariables.add(element); 487 mutatedVariables.add(element);
463 } 488 }
489 if (Elements.isLocal(element) &&
490 element.computeType(compiler).containsTypeVariables) {
491 registerNeedsThis();
492 }
464 super.visitSendSet(node); 493 super.visitSendSet(node);
465 } 494 }
466 495
467 visitNewExpression(NewExpression node) { 496 visitNewExpression(NewExpression node) {
468 DartType type = elements.getType(node); 497 DartType type = elements.getType(node);
469 498
470 bool hasTypeVariable(DartType type) { 499 bool hasTypeVariable(DartType type) {
471 if (type is TypeVariableType) { 500 if (type is TypeVariableType) {
472 return true; 501 return true;
473 } else if (type is InterfaceType) { 502 } else if (type is InterfaceType) {
(...skipping 16 matching lines...) Expand all
490 analyzeTypeVariables(argument); 519 analyzeTypeVariables(argument);
491 } 520 }
492 } 521 }
493 } 522 }
494 523
495 if (outermostElement.isMember() && 524 if (outermostElement.isMember() &&
496 compiler.backend.needsRti(outermostElement.getEnclosingClass())) { 525 compiler.backend.needsRti(outermostElement.getEnclosingClass())) {
497 if (outermostElement.isConstructor() || outermostElement.isField()) { 526 if (outermostElement.isConstructor() || outermostElement.isField()) {
498 analyzeTypeVariables(type); 527 analyzeTypeVariables(type);
499 } else if (outermostElement.isInstanceMember()) { 528 } else if (outermostElement.isInstanceMember()) {
500 if (hasTypeVariable(type)) useLocal(closureData.thisElement); 529 if (hasTypeVariable(type)) {
530 registerNeedsThis();
531 }
501 } 532 }
502 } 533 }
503 534
504 node.visitChildren(this); 535 node.visitChildren(this);
505 } 536 }
506 537
507 // If variables that are declared in the [node] scope are captured and need 538 // 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 539 // to be boxed create a box-element and update the [capturingScopes] in the
509 // current [closureData]. 540 // current [closureData].
510 // The boxed variables are updated in the [capturedVariableMapping]. 541 // The boxed variables are updated in the [capturedVariableMapping].
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 if (currentElement.isFactoryConstructor() && 693 if (currentElement.isFactoryConstructor() &&
663 compiler.backend.needsRti(currentElement.enclosingElement)) { 694 compiler.backend.needsRti(currentElement.enclosingElement)) {
664 // Declare the type parameters in the scope. Generative 695 // Declare the type parameters in the scope. Generative
665 // constructors just use 'this'. 696 // constructors just use 'this'.
666 ClassElement cls = currentElement.enclosingElement; 697 ClassElement cls = currentElement.enclosingElement;
667 cls.typeVariables.forEach((TypeVariableType typeVariable) { 698 cls.typeVariables.forEach((TypeVariableType typeVariable) {
668 declareLocal(typeVariable.element); 699 declareLocal(typeVariable.element);
669 }); 700 });
670 } 701 }
671 702
703 // Compute the function type and check for type variables in return or
704 // parameter types.
705 if (element.computeType(compiler).containsTypeVariables) {
706 registerNeedsThis();
707 }
708
672 visitChildren(); 709 visitChildren();
673 }); 710 });
674 711
675 712
676 ClosureClassMap savedClosureData = closureData; 713 ClosureClassMap savedClosureData = closureData;
677 bool savedInsideClosure = insideClosure; 714 bool savedInsideClosure = insideClosure;
678 715
679 // Restore old values. 716 // Restore old values.
680 insideClosure = oldInsideClosure; 717 insideClosure = oldInsideClosure;
681 closureData = oldClosureData; 718 closureData = oldClosureData;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 } 756 }
720 757
721 visitTryStatement(TryStatement node) { 758 visitTryStatement(TryStatement node) {
722 // TODO(ngeoffray): implement finer grain state. 759 // TODO(ngeoffray): implement finer grain state.
723 bool oldInTryStatement = inTryStatement; 760 bool oldInTryStatement = inTryStatement;
724 inTryStatement = true; 761 inTryStatement = true;
725 node.visitChildren(this); 762 node.visitChildren(this);
726 inTryStatement = oldInTryStatement; 763 inTryStatement = oldInTryStatement;
727 } 764 }
728 } 765 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/js_backend/backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698