/* * Copyright (c) 2007, 2011, 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. * * 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 com.sun.max.vm.classfile.constant; import java.lang.reflect.*; import com.sun.max.annotate.*; import com.sun.max.lang.*; import com.sun.max.vm.*; import com.sun.max.vm.actor.holder.*; import com.sun.max.vm.actor.member.*; import com.sun.max.vm.classfile.constant.ConstantPool.Tag; import com.sun.max.vm.type.*; /** * #4.4.2. */ public interface FieldRefConstant extends PoolConstant<FieldRefConstant>, MemberRefConstant<FieldRefConstant> { public interface FieldRefKey extends PoolConstantKey<FieldRefConstant> { TypeDescriptor holder(); Utf8Constant name(); TypeDescriptor type(); public static final class Util { private Util() { } public static boolean equals(FieldRefKey key, Object other) { if (other instanceof FieldRefKey) { final FieldRefKey otherKey = (FieldRefKey) other; return key.holder().equals(otherKey.holder()) && key.name().equals(otherKey.name()) && key.type().equals(otherKey.type()); } return false; } public static int hashCode(FieldRefKey key) { return key.holder().hashCode() ^ key.name().hashCode() ^ key.type().hashCode(); } } } TypeDescriptor type(ConstantPool pool); FieldActor resolve(ConstantPool pool, int index); FieldRefKey key(final ConstantPool pool); public static final class Resolved extends AbstractMemberRefConstant<FieldRefConstant> implements FieldRefConstant, FieldRefKey { @INSPECTED private final FieldActor fieldActor; public FieldActor fieldActor() { return fieldActor; } public Resolved(FieldActor fieldActor) { this.fieldActor = fieldActor; } @Override public Tag tag() { return Tag.FIELD_REF; } public boolean isResolvableWithoutClassLoading(ConstantPool pool) { return true; } public boolean isResolved() { return true; } public FieldActor resolve(ConstantPool pool, int index) { return fieldActor; } public TypeDescriptor holder() { return fieldActor.holder().typeDescriptor; } public Utf8Constant name() { return fieldActor.name; } public TypeDescriptor type() { return fieldActor.descriptor(); } public Utf8Constant name(ConstantPool pool) { return name(); } public TypeDescriptor holder(ConstantPool pool) { return holder(); } public Descriptor descriptor(ConstantPool pool) { return type(); } public TypeDescriptor type(ConstantPool pool) { return type(); } @Override public boolean equals(Object object) { return FieldRefKey.Util.equals(this, object); } @Override public int hashCode() { return FieldRefKey.Util.hashCode(this); } @Override public FieldRefKey key(ConstantPool pool) { return this; } public String valueString(ConstantPool pool) { return fieldActor.format("%H.%n:%t"); } } static final class Unresolved extends UnresolvedRef<FieldRefConstant> implements FieldRefConstant, FieldRefKey { Unresolved(ClassActor holder, Utf8Constant name, Descriptor descriptor) { super(holder, name, descriptor); } @Override public Tag tag() { return Tag.FIELD_REF; } static FieldActor resolve(ConstantPool pool, int index, ClassActor holder, Utf8Constant name, TypeDescriptor type) { FieldActor fieldActor = holder.findFieldActor(name, type); if (fieldActor != null) { fieldActor.checkAccessBy(pool.holder()); FieldActor aliasedFieldActor = ALIAS.Static.aliasedField(fieldActor); if (aliasedFieldActor == null) { // Only update constant pool if no aliasing occurred. // Otherwise, subsequent verification of bytecode // referencing the alias field will fail. pool.updateAt(index, new Resolved(fieldActor)); } else { fieldActor = aliasedFieldActor; } return fieldActor; } final String errorMessage = type + " " + holder.javaSignature(true) + "." + name; if (MaxineVM.isHosted()) { final Class<?> javaClass = holder.toJava(); final Class fieldType = type.resolveType(javaClass.getClassLoader()); final Field field = Classes.resolveField(javaClass, fieldType, name.string); if (MaxineVM.isHostedOnly(field)) { throw new HostOnlyFieldError(errorMessage); } } throw new NoSuchFieldError(errorMessage); } public FieldActor resolve(ConstantPool pool, int index) { return resolve(pool, index, holder, name, type()); } @Override public FieldRefKey key(ConstantPool pool) { return this; } @Override public boolean equals(Object object) { return FieldRefKey.Util.equals(this, object); } @Override public int hashCode() { return FieldRefKey.Util.hashCode(this); } @Override boolean isFieldConstant() { return true; } } static final class UnresolvedIndices extends UnresolvedRefIndices<FieldRefConstant> implements FieldRefConstant { UnresolvedIndices(int classIndex, int nameAndTypeIndex, Tag[] tags) { super(classIndex, nameAndTypeIndex, tags); } @Override public Tag tag() { return Tag.FIELD_REF; } @Override public FieldRefKey key(final ConstantPool pool) { class Key extends RefKey implements FieldRefKey { Key() { super(pool, UnresolvedIndices.this); } public final TypeDescriptor type() { return UnresolvedIndices.this.type(pool); } @Override public boolean equals(Object object) { return FieldRefKey.Util.equals(this, object); } @Override public int hashCode() { return FieldRefKey.Util.hashCode(this); } } return new Key(); } public FieldActor resolve(ConstantPool pool, int index) { final ClassActor classActor = pool.classAt(classIndex).resolve(pool, classIndex); return Unresolved.resolve(pool, index, classActor, name(pool), type(pool)); } @Override boolean isFieldConstant() { return true; } } }