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.java; 27 28 import sun.tools.tree.*; 29 import java.util.Vector; 30 import java.util.Hashtable; 31 import java.io.IOException; 32 import java.io.DataInputStream; 33 import java.io.ByteArrayInputStream; 34 35 /** 36 * This class represents a binary member 37 * 38 * WARNING: The contents of this source file are not part of any 39 * supported API. Code that depends on them does so at its own risk: 40 * they are subject to change or removal without notice. 41 */ 42 public final 43 class BinaryMember extends MemberDefinition { 44 Expression value; 45 BinaryAttribute atts; 46 47 /** 48 * Constructor 49 */ BinaryMember(ClassDefinition clazz, int modifiers, Type type, Identifier name, BinaryAttribute atts)50 public BinaryMember(ClassDefinition clazz, int modifiers, Type type, 51 Identifier name, BinaryAttribute atts) { 52 super(0, clazz, modifiers, type, name, null, null); 53 this.atts = atts; 54 55 // Was it compiled as deprecated? 56 if (getAttribute(idDeprecated) != null) { 57 this.modifiers |= M_DEPRECATED; 58 } 59 60 // Was it synthesized by the compiler? 61 if (getAttribute(idSynthetic) != null) { 62 this.modifiers |= M_SYNTHETIC; 63 } 64 } 65 66 /** 67 * Constructor for an inner class. 68 */ BinaryMember(ClassDefinition innerClass)69 public BinaryMember(ClassDefinition innerClass) { 70 super(innerClass); 71 } 72 73 /** 74 * Inline allowed (currently only allowed for the constructor of Object). 75 */ isInlineable(Environment env, boolean fromFinal)76 public boolean isInlineable(Environment env, boolean fromFinal) { 77 // It is possible for 'getSuperClass()' to return null due to error 78 // recovery from cyclic inheritace. Can this cause a problem here? 79 return isConstructor() && (getClassDefinition().getSuperClass() == null); 80 } 81 82 /** 83 * Get arguments 84 */ getArguments()85 public Vector getArguments() { 86 if (isConstructor() && (getClassDefinition().getSuperClass() == null)) { 87 Vector v = new Vector(); 88 v.addElement(new LocalMember(0, getClassDefinition(), 0, 89 getClassDefinition().getType(), idThis)); 90 return v; 91 } 92 return null; 93 } 94 95 /** 96 * Get exceptions 97 */ getExceptions(Environment env)98 public ClassDeclaration[] getExceptions(Environment env) { 99 if ((!isMethod()) || (exp != null)) { 100 return exp; 101 } 102 byte data[] = getAttribute(idExceptions); 103 if (data == null) { 104 return new ClassDeclaration[0]; 105 } 106 107 try { 108 BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants(); 109 DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); 110 // JVM 4.7.5 Exceptions_attribute.number_of_exceptions 111 int n = in.readUnsignedShort(); 112 exp = new ClassDeclaration[n]; 113 for (int i = 0 ; i < n ; i++) { 114 // JVM 4.7.5 Exceptions_attribute.exception_index_table[] 115 exp[i] = cpool.getDeclaration(env, in.readUnsignedShort()); 116 } 117 return exp; 118 } catch (IOException e) { 119 throw new CompilerError(e); 120 } 121 } 122 123 /** 124 * Get documentation 125 */ getDocumentation()126 public String getDocumentation() { 127 if (documentation != null) { 128 return documentation; 129 } 130 byte data[] = getAttribute(idDocumentation); 131 if (data == null) { 132 return null; 133 } 134 try { 135 return documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF(); 136 } catch (IOException e) { 137 throw new CompilerError(e); 138 } 139 } 140 141 /** 142 * Check if constant: Will it inline away to a constant? 143 * This override is needed to solve bug 4128266. It is also 144 * integral to the solution of 4119776. 145 */ 146 private boolean isConstantCache = false; 147 private boolean isConstantCached = false; isConstant()148 public boolean isConstant() { 149 if (!isConstantCached) { 150 isConstantCache = isFinal() 151 && isVariable() 152 && getAttribute(idConstantValue) != null; 153 isConstantCached = true; 154 } 155 return isConstantCache; 156 } 157 158 /** 159 * Get the value 160 */ getValue(Environment env)161 public Node getValue(Environment env) { 162 if (isMethod()) { 163 return null; 164 } 165 if (!isFinal()) { 166 return null; 167 } 168 if (getValue() != null) { 169 return (Expression)getValue(); 170 } 171 byte data[] = getAttribute(idConstantValue); 172 if (data == null) { 173 return null; 174 } 175 176 try { 177 BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants(); 178 // JVM 4.7.3 ConstantValue.constantvalue_index 179 Object obj = cpool.getValue(new DataInputStream(new ByteArrayInputStream(data)).readUnsignedShort()); 180 switch (getType().getTypeCode()) { 181 case TC_BOOLEAN: 182 setValue(new BooleanExpression(0, ((Number)obj).intValue() != 0)); 183 break; 184 case TC_BYTE: 185 case TC_SHORT: 186 case TC_CHAR: 187 case TC_INT: 188 setValue(new IntExpression(0, ((Number)obj).intValue())); 189 break; 190 case TC_LONG: 191 setValue(new LongExpression(0, ((Number)obj).longValue())); 192 break; 193 case TC_FLOAT: 194 setValue(new FloatExpression(0, ((Number)obj).floatValue())); 195 break; 196 case TC_DOUBLE: 197 setValue(new DoubleExpression(0, ((Number)obj).doubleValue())); 198 break; 199 case TC_CLASS: 200 setValue(new StringExpression(0, (String)cpool.getValue(((Number)obj).intValue()))); 201 break; 202 } 203 return (Expression)getValue(); 204 } catch (IOException e) { 205 throw new CompilerError(e); 206 } 207 } 208 209 /** 210 * Get a field attribute 211 */ getAttribute(Identifier name)212 public byte[] getAttribute(Identifier name) { 213 for (BinaryAttribute att = atts ; att != null ; att = att.next) { 214 if (att.name.equals(name)) { 215 return att.data; 216 } 217 } 218 return null; 219 } 220 deleteAttribute(Identifier name)221 public boolean deleteAttribute(Identifier name) { 222 BinaryAttribute walker = null, next = null; 223 224 boolean succeed = false; 225 226 while (atts.name.equals(name)) { 227 atts = atts.next; 228 succeed = true; 229 } 230 for (walker = atts; walker != null; walker = next) { 231 next = walker.next; 232 if (next != null) { 233 if (next.name.equals(name)) { 234 walker.next = next.next; 235 next = next.next; 236 succeed = true; 237 } 238 } 239 } 240 for (walker = atts; walker != null; walker = walker.next) { 241 if (walker.name.equals(name)) { 242 throw new InternalError("Found attribute " + name); 243 } 244 } 245 246 return succeed; 247 } 248 249 250 251 /* 252 * Add an attribute to a field 253 */ addAttribute(Identifier name, byte data[], Environment env)254 public void addAttribute(Identifier name, byte data[], Environment env) { 255 this.atts = new BinaryAttribute(name, data, this.atts); 256 // Make sure that the new attribute is in the constant pool 257 ((BinaryClass)(this.clazz)).cpool.indexString(name.toString(), env); 258 } 259 260 } 261