src/jdk/nashorn/internal/codegen/FinalizeTypes.java

changeset 290
6fc7b51e83d6
parent 287
f7eb4436410e
child 415
edca88d3a03e
equal deleted inserted replaced
289:8af550dee961 290:6fc7b51e83d6
29 import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE; 29 import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
30 30
31 import java.util.ArrayList; 31 import java.util.ArrayList;
32 import java.util.HashSet; 32 import java.util.HashSet;
33 import java.util.List; 33 import java.util.List;
34
34 import jdk.nashorn.internal.codegen.types.Type; 35 import jdk.nashorn.internal.codegen.types.Type;
35 import jdk.nashorn.internal.ir.AccessNode; 36 import jdk.nashorn.internal.ir.AccessNode;
36 import jdk.nashorn.internal.ir.Assignment; 37 import jdk.nashorn.internal.ir.Assignment;
37 import jdk.nashorn.internal.ir.BinaryNode; 38 import jdk.nashorn.internal.ir.BinaryNode;
38 import jdk.nashorn.internal.ir.Block; 39 import jdk.nashorn.internal.ir.Block;
82 * For any op that we process in FinalizeTypes it is an absolute guarantee 83 * For any op that we process in FinalizeTypes it is an absolute guarantee
83 * that scope and slot information is correct. This enables e.g. AccessSpecialization 84 * that scope and slot information is correct. This enables e.g. AccessSpecialization
84 * and frame optimizations 85 * and frame optimizations
85 */ 86 */
86 87
87 final class FinalizeTypes extends NodeOperatorVisitor { 88 final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
88 89
89 private static final DebugLogger LOG = new DebugLogger("finalize"); 90 private static final DebugLogger LOG = new DebugLogger("finalize");
90 91
91 private final TemporarySymbols temporarySymbols; 92 private final TemporarySymbols temporarySymbols;
92 93
93 FinalizeTypes(final TemporarySymbols temporarySymbols) { 94 FinalizeTypes(final TemporarySymbols temporarySymbols) {
95 super(new LexicalContext());
94 this.temporarySymbols = temporarySymbols; 96 this.temporarySymbols = temporarySymbols;
95 } 97 }
96 98
97 @Override 99 @Override
98 public Node leaveCallNode(final CallNode callNode) { 100 public Node leaveCallNode(final CallNode callNode) {
231 return leaveASSIGN(binaryNode); 233 return leaveASSIGN(binaryNode);
232 } 234 }
233 235
234 private boolean symbolIsInteger(Node node) { 236 private boolean symbolIsInteger(Node node) {
235 final Symbol symbol = node.getSymbol(); 237 final Symbol symbol = node.getSymbol();
236 assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + getLexicalContext().getCurrentFunction().getSource(); 238 assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + lc.getCurrentFunction().getSource();
237 return true; 239 return true;
238 } 240 }
239 241
240 @Override 242 @Override
241 public Node leaveBIT_AND(final BinaryNode binaryNode) { 243 public Node leaveBIT_AND(final BinaryNode binaryNode) {
380 public Node leaveForNode(final ForNode forNode) { 382 public Node leaveForNode(final ForNode forNode) {
381 final Node init = forNode.getInit(); 383 final Node init = forNode.getInit();
382 final Node test = forNode.getTest(); 384 final Node test = forNode.getTest();
383 final Node modify = forNode.getModify(); 385 final Node modify = forNode.getModify();
384 386
385 final LexicalContext lc = getLexicalContext();
386
387 if (forNode.isForIn()) { 387 if (forNode.isForIn()) {
388 return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400 388 return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400
389 } 389 }
390 assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + getLexicalContext().getCurrentFunction(); 390 assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction();
391 391
392 return forNode. 392 return forNode.
393 setInit(lc, init == null ? null : discard(init)). 393 setInit(lc, init == null ? null : discard(init)).
394 setTest(lc, test == null ? null : convert(test, Type.BOOLEAN)). 394 setTest(lc, test == null ? null : convert(test, Type.BOOLEAN)).
395 setModify(lc, modify == null ? null : discard(modify)); 395 setModify(lc, modify == null ? null : discard(modify));
417 return true; 417 return true;
418 } 418 }
419 419
420 @Override 420 @Override
421 public Node leaveFunctionNode(final FunctionNode functionNode) { 421 public Node leaveFunctionNode(final FunctionNode functionNode) {
422 return functionNode.setState(getLexicalContext(), CompilationState.FINALIZED); 422 return functionNode.setState(lc, CompilationState.FINALIZED);
423 } 423 }
424 424
425 @Override 425 @Override
426 public Node leaveIfNode(final IfNode ifNode) { 426 public Node leaveIfNode(final IfNode ifNode) {
427 return ifNode.setTest(convert(ifNode.getTest(), Type.BOOLEAN)); 427 return ifNode.setTest(convert(ifNode.getTest(), Type.BOOLEAN));
448 448
449 @Override 449 @Override
450 public Node leaveReturnNode(final ReturnNode returnNode) { 450 public Node leaveReturnNode(final ReturnNode returnNode) {
451 final Node expr = returnNode.getExpression(); 451 final Node expr = returnNode.getExpression();
452 if (expr != null) { 452 if (expr != null) {
453 return returnNode.setExpression(convert(expr, getLexicalContext().getCurrentFunction().getReturnType())); 453 return returnNode.setExpression(convert(expr, lc.getCurrentFunction().getReturnType()));
454 } 454 }
455 return returnNode; 455 return returnNode;
456 } 456 }
457 457
458 @Override 458 @Override
480 final Node test = caseNode.getTest(); 480 final Node test = caseNode.getTest();
481 newCases.add(test != null ? caseNode.setTest(convert(test, Type.OBJECT)) : caseNode); 481 newCases.add(test != null ? caseNode.setTest(convert(test, Type.OBJECT)) : caseNode);
482 } 482 }
483 483
484 return switchNode. 484 return switchNode.
485 setExpression(getLexicalContext(), convert(expression, Type.OBJECT)). 485 setExpression(lc, convert(expression, Type.OBJECT)).
486 setCases(getLexicalContext(), newCases); 486 setCases(lc, newCases);
487 } 487 }
488 488
489 @Override 489 @Override
490 public Node leaveTernaryNode(final TernaryNode ternaryNode) { 490 public Node leaveTernaryNode(final TernaryNode ternaryNode) {
491 return ternaryNode.setLHS(convert(ternaryNode.lhs(), Type.BOOLEAN)); 491 return ternaryNode.setLHS(convert(ternaryNode.lhs(), Type.BOOLEAN));
517 517
518 @Override 518 @Override
519 public Node leaveWhileNode(final WhileNode whileNode) { 519 public Node leaveWhileNode(final WhileNode whileNode) {
520 final Node test = whileNode.getTest(); 520 final Node test = whileNode.getTest();
521 if (test != null) { 521 if (test != null) {
522 return whileNode.setTest(getLexicalContext(), convert(test, Type.BOOLEAN)); 522 return whileNode.setTest(lc, convert(test, Type.BOOLEAN));
523 } 523 }
524 return whileNode; 524 return whileNode;
525 } 525 }
526 526
527 @Override 527 @Override
528 public Node leaveWithNode(final WithNode withNode) { 528 public Node leaveWithNode(final WithNode withNode) {
529 return withNode.setExpression(getLexicalContext(), convert(withNode.getExpression(), Type.OBJECT)); 529 return withNode.setExpression(lc, convert(withNode.getExpression(), Type.OBJECT));
530 } 530 }
531 531
532 private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) { 532 private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
533 if (LOG.isEnabled()) { 533 if (LOG.isEnabled()) {
534 if (!symbol.isScope()) { 534 if (!symbol.isScope()) {
548 private void updateSymbols(final Block block) { 548 private void updateSymbols(final Block block) {
549 if (!block.needsScope()) { 549 if (!block.needsScope()) {
550 return; // nothing to do 550 return; // nothing to do
551 } 551 }
552 552
553 final LexicalContext lc = getLexicalContext();
554 final FunctionNode functionNode = lc.getFunction(block); 553 final FunctionNode functionNode = lc.getFunction(block);
555 final boolean allVarsInScope = functionNode.allVarsInScope(); 554 final boolean allVarsInScope = functionNode.allVarsInScope();
556 final boolean isVarArg = functionNode.isVarArg(); 555 final boolean isVarArg = functionNode.isVarArg();
557 556
558 for (final Symbol symbol : block.getSymbols()) { 557 for (final Symbol symbol : block.getSymbols()) {
650 * @param to which primitive type to use for tagging 649 * @param to which primitive type to use for tagging
651 */ 650 */
652 private static void setCanBePrimitive(final Node node, final Type to) { 651 private static void setCanBePrimitive(final Node node, final Type to) {
653 final HashSet<Node> exclude = new HashSet<>(); 652 final HashSet<Node> exclude = new HashSet<>();
654 653
655 node.accept(new NodeVisitor() { 654 node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
656 private void setCanBePrimitive(final Symbol symbol) { 655 private void setCanBePrimitive(final Symbol symbol) {
657 LOG.info("*** can be primitive symbol ", symbol, " ", Debug.id(symbol)); 656 LOG.info("*** can be primitive symbol ", symbol, " ", Debug.id(symbol));
658 symbol.setCanBePrimitive(to); 657 symbol.setCanBePrimitive(to);
659 } 658 }
660 659
760 if (!to.isObject() && from.isObject()) { 759 if (!to.isObject() && from.isObject()) {
761 setCanBePrimitive(node, to); 760 setCanBePrimitive(node, to);
762 } 761 }
763 } 762 }
764 LOG.info("Type override for lhs in '", node, "' => ", to); 763 LOG.info("Type override for lhs in '", node, "' => ", to);
765 return ((TypeOverride<T>)node).setType(temporarySymbols, getLexicalContext(), to); 764 return ((TypeOverride<T>)node).setType(temporarySymbols, lc, to);
766 } 765 }
767 766
768 /** 767 /**
769 * Add an explicit conversion. This is needed when attribution has created types 768 * Add an explicit conversion. This is needed when attribution has created types
770 * that do not mesh into an op type, e.g. a = b, where b is object and a is double 769 * that do not mesh into an op type, e.g. a = b, where b is object and a is double
783 * @return conversion node 782 * @return conversion node
784 */ 783 */
785 private Node convert(final Node node, final Type to) { 784 private Node convert(final Node node, final Type to) {
786 assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass(); 785 assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass();
787 assert node != null : "node is null"; 786 assert node != null : "node is null";
788 assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + getLexicalContext().getCurrentFunction(); 787 assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + lc.getCurrentFunction();
789 assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + getLexicalContext().getCurrentFunction(); 788 assert node.tokenType() != TokenType.CONVERT : "assert convert in convert " + node + " in " + lc.getCurrentFunction();
790 789
791 final Type from = node.getType(); 790 final Type from = node.getType();
792 791
793 if (Type.areEquivalent(from, to)) { 792 if (Type.areEquivalent(from, to)) {
794 return node; 793 return node;
815 814
816 LOG.info("CONVERT('", node, "', ", to, ") => '", resultNode, "'"); 815 LOG.info("CONVERT('", node, "', ", to, ") => '", resultNode, "'");
817 816
818 assert !node.isTerminal(); 817 assert !node.isTerminal();
819 818
820 final LexicalContext lc = getLexicalContext();
821 //This is the only place in this file that can create new temporaries 819 //This is the only place in this file that can create new temporaries
822 //FinalizeTypes may not introduce ANY node that is not a conversion. 820 //FinalizeTypes may not introduce ANY node that is not a conversion.
823 return temporarySymbols.ensureSymbol(lc, to, resultNode); 821 return temporarySymbols.ensureSymbol(lc, to, resultNode);
824 } 822 }
825 823
852 Symbol symbol = node.getSymbol(); 850 Symbol symbol = node.getSymbol();
853 if (symbol.isTemp() && symbol.getSymbolType() != to) { 851 if (symbol.isTemp() && symbol.getSymbolType() != to) {
854 symbol = symbol.setTypeOverrideShared(to, temporarySymbols); 852 symbol = symbol.setTypeOverrideShared(to, temporarySymbols);
855 LOG.info("Type override for temporary in '", node, "' => ", to); 853 LOG.info("Type override for temporary in '", node, "' => ", to);
856 } 854 }
857 return node.setSymbol(getLexicalContext(), symbol); 855 return node.setSymbol(lc, symbol);
858 } 856 }
859 857
860 /** 858 /**
861 * Determine if the outcome of + operator is a string. 859 * Determine if the outcome of + operator is a string.
862 * 860 *
905 literalNode = LiteralNode.newInstance(token, finish, JSType.toNumber(value)); 903 literalNode = LiteralNode.newInstance(token, finish, JSType.toNumber(value));
906 } 904 }
907 905
908 if (literalNode != null) { 906 if (literalNode != null) {
909 //inherit literal symbol for attr. 907 //inherit literal symbol for attr.
910 literalNode = (LiteralNode<?>)literalNode.setSymbol(getLexicalContext(), parent.getSymbol()); 908 literalNode = (LiteralNode<?>)literalNode.setSymbol(lc, parent.getSymbol());
911 } 909 }
912 910
913 return literalNode; 911 return literalNode;
914 } 912 }
915 } 913 }

mercurial