1 /* 2 * Copyright (c) 1994, 2003, 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 sun.tools.tree; 27 28 import sun.tools.java.*; 29 import sun.tools.asm.Assembler; 30 import sun.tools.asm.Label; 31 import java.io.PrintStream; 32 import java.util.Hashtable; 33 34 /** 35 * WARNING: The contents of this source file are not part of any 36 * supported API. Code that depends on them does so at its own risk: 37 * they are subject to change or removal without notice. 38 */ 39 public 40 class ConditionalExpression extends BinaryExpression { 41 Expression cond; 42 43 /** 44 * Constructor 45 */ ConditionalExpression(long where, Expression cond, Expression left, Expression right)46 public ConditionalExpression(long where, Expression cond, Expression left, Expression right) { 47 super(COND, where, Type.tError, left, right); 48 this.cond = cond; 49 } 50 51 /** 52 * Order the expression based on precedence 53 */ order()54 public Expression order() { 55 if (precedence() > cond.precedence()) { 56 UnaryExpression e = (UnaryExpression)cond; 57 cond = e.right; 58 e.right = order(); 59 return e; 60 } 61 return this; 62 } 63 64 /** 65 * Check the expression 66 */ checkValue(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp)67 public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp) { 68 ConditionVars cvars = cond.checkCondition(env, ctx, vset, exp); 69 vset = left.checkValue(env, ctx, cvars.vsTrue, exp).join( 70 right.checkValue(env, ctx, cvars.vsFalse, exp) ); 71 cond = convert(env, ctx, Type.tBoolean, cond); 72 73 int tm = left.type.getTypeMask() | right.type.getTypeMask(); 74 if ((tm & TM_ERROR) != 0) { 75 type = Type.tError; 76 return vset; 77 } 78 if (left.type.equals(right.type)) { 79 type = left.type; 80 } else if ((tm & TM_DOUBLE) != 0) { 81 type = Type.tDouble; 82 } else if ((tm & TM_FLOAT) != 0) { 83 type = Type.tFloat; 84 } else if ((tm & TM_LONG) != 0) { 85 type = Type.tLong; 86 } else if ((tm & TM_REFERENCE) != 0) { 87 try { 88 // This is wrong. We should be using their most common 89 // ancestor, instead. 90 type = env.implicitCast(right.type, left.type) 91 ? left.type : right.type; 92 } catch (ClassNotFound e) { 93 type = Type.tError; 94 } 95 } else if (((tm & TM_CHAR) != 0) && left.fitsType(env, ctx, Type.tChar) && right.fitsType(env, ctx, Type.tChar)) { 96 type = Type.tChar; 97 } else if (((tm & TM_SHORT) != 0) && left.fitsType(env, ctx, Type.tShort) && right.fitsType(env, ctx, Type.tShort)) { 98 type = Type.tShort; 99 } else if (((tm & TM_BYTE) != 0) && left.fitsType(env, ctx, Type.tByte) && right.fitsType(env, ctx, Type.tByte)) { 100 type = Type.tByte; 101 } else { 102 type = Type.tInt; 103 } 104 105 left = convert(env, ctx, type, left); 106 right = convert(env, ctx, type, right); 107 return vset; 108 } 109 check(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp)110 public Vset check(Environment env, Context ctx, Vset vset, Hashtable<Object, Object> exp) { 111 vset = cond.checkValue(env, ctx, vset, exp); 112 cond = convert(env, ctx, Type.tBoolean, cond); 113 return left.check(env, ctx, vset.copy(), exp).join(right.check(env, ctx, vset, exp)); 114 } 115 116 /** 117 * Check if constant 118 */ isConstant()119 public boolean isConstant() { 120 return cond.isConstant() && left.isConstant() && right.isConstant(); 121 } 122 123 /** 124 * Simplify 125 */ simplify()126 Expression simplify() { 127 if (cond.equals(true)) { 128 return left; 129 } 130 if (cond.equals(false)) { 131 return right; 132 } 133 return this; 134 } 135 136 /** 137 * Inline 138 */ inline(Environment env, Context ctx)139 public Expression inline(Environment env, Context ctx) { 140 left = left.inline(env, ctx); 141 right = right.inline(env, ctx); 142 if ((left == null) && (right == null)) { 143 return cond.inline(env, ctx); 144 } 145 if (left == null) { 146 left = right; 147 right = null; 148 cond = new NotExpression(where, cond); 149 } 150 cond = cond.inlineValue(env, ctx); 151 return simplify(); 152 } 153 inlineValue(Environment env, Context ctx)154 public Expression inlineValue(Environment env, Context ctx) { 155 cond = cond.inlineValue(env, ctx); 156 left = left.inlineValue(env, ctx); 157 right = right.inlineValue(env, ctx); 158 return simplify(); 159 } 160 161 /** 162 * The cost of inlining this expression 163 */ costInline(int thresh, Environment env, Context ctx)164 public int costInline(int thresh, Environment env, Context ctx) { 165 // We need to check if right is null in case costInline() 166 // is called after this expression has been inlined. 167 // This call can happen, for example, in MemberDefinition#cleanup(). 168 // (Fix for 4069861). 169 return 1 + 170 cond.costInline(thresh, env, ctx) + 171 left.costInline(thresh, env, ctx) + 172 ((right == null) ? 0 : right.costInline(thresh, env, ctx)); 173 } 174 175 /** 176 * Create a copy of the expression for method inlining 177 */ copyInline(Context ctx)178 public Expression copyInline(Context ctx) { 179 ConditionalExpression e = (ConditionalExpression)clone(); 180 e.cond = cond.copyInline(ctx); 181 e.left = left.copyInline(ctx); 182 183 // If copyInline() is called after inlining is complete, 184 // right could be null. 185 e.right = (right == null) ? null : right.copyInline(ctx); 186 187 return e; 188 } 189 190 /** 191 * Code 192 */ codeValue(Environment env, Context ctx, Assembler asm)193 public void codeValue(Environment env, Context ctx, Assembler asm) { 194 Label l1 = new Label(); 195 Label l2 = new Label(); 196 197 cond.codeBranch(env, ctx, asm, l1, false); 198 left.codeValue(env, ctx, asm); 199 asm.add(where, opc_goto, l2); 200 asm.add(l1); 201 right.codeValue(env, ctx, asm); 202 asm.add(l2); 203 } code(Environment env, Context ctx, Assembler asm)204 public void code(Environment env, Context ctx, Assembler asm) { 205 Label l1 = new Label(); 206 cond.codeBranch(env, ctx, asm, l1, false); 207 left.code(env, ctx, asm); 208 if (right != null) { 209 Label l2 = new Label(); 210 asm.add(where, opc_goto, l2); 211 asm.add(l1); 212 right.code(env, ctx, asm); 213 asm.add(l2); 214 } else { 215 asm.add(l1); 216 } 217 } 218 219 /** 220 * Print 221 */ print(PrintStream out)222 public void print(PrintStream out) { 223 out.print("(" + opNames[op] + " "); 224 cond.print(out); 225 out.print(" "); 226 left.print(out); 227 out.print(" "); 228 if (right != null) { 229 right.print(out); 230 } else { 231 out.print("<null>"); 232 } 233 out.print(")"); 234 } 235 } 236