1 /* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.nashorn.internal.ir; 27 28 import jdk.nashorn.internal.ir.annotations.Immutable; 29 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 30 31 /** 32 * IR representation for THROW statements. 33 */ 34 @Immutable 35 public final class ThrowNode extends Statement implements JoinPredecessor { 36 private static final long serialVersionUID = 1L; 37 38 /** Exception expression. */ 39 private final Expression expression; 40 41 private final LocalVariableConversion conversion; 42 43 private final boolean isSyntheticRethrow; 44 45 /** 46 * Constructor 47 * 48 * @param lineNumber line number 49 * @param token token 50 * @param finish finish 51 * @param expression expression to throw 52 * @param isSyntheticRethrow true if this throw node is part of a synthetic rethrow. 53 */ ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final boolean isSyntheticRethrow)54 public ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final boolean isSyntheticRethrow) { 55 super(lineNumber, token, finish); 56 this.expression = expression; 57 this.isSyntheticRethrow = isSyntheticRethrow; 58 this.conversion = null; 59 } 60 ThrowNode(final ThrowNode node, final Expression expression, final boolean isSyntheticRethrow, final LocalVariableConversion conversion)61 private ThrowNode(final ThrowNode node, final Expression expression, final boolean isSyntheticRethrow, 62 final LocalVariableConversion conversion) { 63 super(node); 64 this.expression = expression; 65 this.isSyntheticRethrow = isSyntheticRethrow; 66 this.conversion = conversion; 67 } 68 69 @Override isTerminal()70 public boolean isTerminal() { 71 return true; 72 } 73 74 /** 75 * Assist in IR navigation. 76 * @param visitor IR navigating visitor. 77 */ 78 @Override accept(final NodeVisitor<? extends LexicalContext> visitor)79 public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { 80 if (visitor.enterThrowNode(this)) { 81 return visitor.leaveThrowNode(setExpression((Expression)expression.accept(visitor))); 82 } 83 84 return this; 85 } 86 87 @Override toString(final StringBuilder sb, final boolean printType)88 public void toString(final StringBuilder sb, final boolean printType) { 89 sb.append("throw "); 90 91 if (expression != null) { 92 expression.toString(sb, printType); 93 } 94 if (conversion != null) { 95 conversion.toString(sb); 96 } 97 } 98 99 /** 100 * Get the expression that is being thrown by this node 101 * @return expression 102 */ getExpression()103 public Expression getExpression() { 104 return expression; 105 } 106 107 /** 108 * Reset the expression being thrown by this node 109 * @param expression new expression 110 * @return new or same thrownode 111 */ setExpression(final Expression expression)112 public ThrowNode setExpression(final Expression expression) { 113 if (this.expression == expression) { 114 return this; 115 } 116 return new ThrowNode(this, expression, isSyntheticRethrow, conversion); 117 } 118 119 /** 120 * Is this a throw a synthetic rethrow in a synthetic catch-all block 121 * created when inlining finally statements? In that case we never 122 * wrap whatever is thrown into an ECMAException, just rethrow it. 123 * @return true if synthetic throw node 124 */ isSyntheticRethrow()125 public boolean isSyntheticRethrow() { 126 return isSyntheticRethrow; 127 } 128 129 @Override setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion)130 public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) { 131 if(this.conversion == conversion) { 132 return this; 133 } 134 return new ThrowNode(this, expression, isSyntheticRethrow, conversion); 135 } 136 137 @Override getLocalVariableConversion()138 public LocalVariableConversion getLocalVariableConversion() { 139 return conversion; 140 } 141 142 } 143