| /* |
| * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.tools.java; |
| |
| import sun.tools.tree.*; |
| import java.util.Vector; |
| import java.util.Hashtable; |
| import java.io.IOException; |
| import java.io.DataInputStream; |
| import java.io.ByteArrayInputStream; |
| |
| /** |
| * This class represents a binary member |
| * |
| * WARNING: The contents of this source file are not part of any |
| * supported API. Code that depends on them does so at its own risk: |
| * they are subject to change or removal without notice. |
| */ |
| public final |
| class BinaryMember extends MemberDefinition { |
| Expression value; |
| BinaryAttribute atts; |
| |
| /** |
| * Constructor |
| */ |
| public BinaryMember(ClassDefinition clazz, int modifiers, Type type, |
| Identifier name, BinaryAttribute atts) { |
| super(0, clazz, modifiers, type, name, null, null); |
| this.atts = atts; |
| |
| // Was it compiled as deprecated? |
| if (getAttribute(idDeprecated) != null) { |
| this.modifiers |= M_DEPRECATED; |
| } |
| |
| // Was it synthesized by the compiler? |
| if (getAttribute(idSynthetic) != null) { |
| this.modifiers |= M_SYNTHETIC; |
| } |
| } |
| |
| /** |
| * Constructor for an inner class. |
| */ |
| public BinaryMember(ClassDefinition innerClass) { |
| super(innerClass); |
| } |
| |
| /** |
| * Inline allowed (currently only allowed for the constructor of Object). |
| */ |
| public boolean isInlineable(Environment env, boolean fromFinal) { |
| // It is possible for 'getSuperClass()' to return null due to error |
| // recovery from cyclic inheritace. Can this cause a problem here? |
| return isConstructor() && (getClassDefinition().getSuperClass() == null); |
| } |
| |
| /** |
| * Get arguments |
| */ |
| public Vector<MemberDefinition> getArguments() { |
| if (isConstructor() && (getClassDefinition().getSuperClass() == null)) { |
| Vector<MemberDefinition> v = new Vector<>(); |
| v.addElement(new LocalMember(0, getClassDefinition(), 0, |
| getClassDefinition().getType(), idThis)); |
| return v; |
| } |
| return null; |
| } |
| |
| /** |
| * Get exceptions |
| */ |
| public ClassDeclaration[] getExceptions(Environment env) { |
| if ((!isMethod()) || (exp != null)) { |
| return exp; |
| } |
| byte data[] = getAttribute(idExceptions); |
| if (data == null) { |
| return new ClassDeclaration[0]; |
| } |
| |
| try { |
| BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants(); |
| DataInputStream in = new DataInputStream(new ByteArrayInputStream(data)); |
| // JVM 4.7.5 Exceptions_attribute.number_of_exceptions |
| int n = in.readUnsignedShort(); |
| exp = new ClassDeclaration[n]; |
| for (int i = 0 ; i < n ; i++) { |
| // JVM 4.7.5 Exceptions_attribute.exception_index_table[] |
| exp[i] = cpool.getDeclaration(env, in.readUnsignedShort()); |
| } |
| return exp; |
| } catch (IOException e) { |
| throw new CompilerError(e); |
| } |
| } |
| |
| /** |
| * Get documentation |
| */ |
| public String getDocumentation() { |
| if (documentation != null) { |
| return documentation; |
| } |
| byte data[] = getAttribute(idDocumentation); |
| if (data == null) { |
| return null; |
| } |
| try { |
| return documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF(); |
| } catch (IOException e) { |
| throw new CompilerError(e); |
| } |
| } |
| |
| /** |
| * Check if constant: Will it inline away to a constant? |
| * This override is needed to solve bug 4128266. It is also |
| * integral to the solution of 4119776. |
| */ |
| private boolean isConstantCache = false; |
| private boolean isConstantCached = false; |
| public boolean isConstant() { |
| if (!isConstantCached) { |
| isConstantCache = isFinal() |
| && isVariable() |
| && getAttribute(idConstantValue) != null; |
| isConstantCached = true; |
| } |
| return isConstantCache; |
| } |
| |
| /** |
| * Get the value |
| */ |
| public Node getValue(Environment env) { |
| if (isMethod()) { |
| return null; |
| } |
| if (!isFinal()) { |
| return null; |
| } |
| if (getValue() != null) { |
| return (Expression)getValue(); |
| } |
| byte data[] = getAttribute(idConstantValue); |
| if (data == null) { |
| return null; |
| } |
| |
| try { |
| BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants(); |
| // JVM 4.7.3 ConstantValue.constantvalue_index |
| Object obj = cpool.getValue(new DataInputStream(new ByteArrayInputStream(data)).readUnsignedShort()); |
| switch (getType().getTypeCode()) { |
| case TC_BOOLEAN: |
| setValue(new BooleanExpression(0, ((Number)obj).intValue() != 0)); |
| break; |
| case TC_BYTE: |
| case TC_SHORT: |
| case TC_CHAR: |
| case TC_INT: |
| setValue(new IntExpression(0, ((Number)obj).intValue())); |
| break; |
| case TC_LONG: |
| setValue(new LongExpression(0, ((Number)obj).longValue())); |
| break; |
| case TC_FLOAT: |
| setValue(new FloatExpression(0, ((Number)obj).floatValue())); |
| break; |
| case TC_DOUBLE: |
| setValue(new DoubleExpression(0, ((Number)obj).doubleValue())); |
| break; |
| case TC_CLASS: |
| setValue(new StringExpression(0, (String)cpool.getValue(((Number)obj).intValue()))); |
| break; |
| } |
| return (Expression)getValue(); |
| } catch (IOException e) { |
| throw new CompilerError(e); |
| } |
| } |
| |
| /** |
| * Get a field attribute |
| */ |
| public byte[] getAttribute(Identifier name) { |
| for (BinaryAttribute att = atts ; att != null ; att = att.next) { |
| if (att.name.equals(name)) { |
| return att.data; |
| } |
| } |
| return null; |
| } |
| |
| public boolean deleteAttribute(Identifier name) { |
| BinaryAttribute walker = null, next = null; |
| |
| boolean succeed = false; |
| |
| while (atts.name.equals(name)) { |
| atts = atts.next; |
| succeed = true; |
| } |
| for (walker = atts; walker != null; walker = next) { |
| next = walker.next; |
| if (next != null) { |
| if (next.name.equals(name)) { |
| walker.next = next.next; |
| next = next.next; |
| succeed = true; |
| } |
| } |
| } |
| for (walker = atts; walker != null; walker = walker.next) { |
| if (walker.name.equals(name)) { |
| throw new InternalError("Found attribute " + name); |
| } |
| } |
| |
| return succeed; |
| } |
| |
| |
| |
| /* |
| * Add an attribute to a field |
| */ |
| public void addAttribute(Identifier name, byte data[], Environment env) { |
| this.atts = new BinaryAttribute(name, data, this.atts); |
| // Make sure that the new attribute is in the constant pool |
| ((BinaryClass)(this.clazz)).cpool.indexString(name.toString(), env); |
| } |
| |
| } |