/* * 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 InterfaceMethodRefConstant extends PoolConstant<InterfaceMethodRefConstant>, MethodRefConstant<InterfaceMethodRefConstant> { public interface InterfaceMethodRefKey extends PoolConstantKey<InterfaceMethodRefConstant> { TypeDescriptor holder(); Utf8Constant name(); SignatureDescriptor signature(); public static final class Util { private Util() { } public static boolean equals(InterfaceMethodRefKey key, Object other) { if (other instanceof InterfaceMethodRefKey) { final InterfaceMethodRefKey otherKey = (InterfaceMethodRefKey) other; return key.holder().equals(otherKey.holder()) && key.name().equals(otherKey.name()) && key.signature().equals(otherKey.signature()); } return false; } public static int hashCode(InterfaceMethodRefKey key) { return key.holder().hashCode() ^ key.name().hashCode() ^ key.signature().hashCode(); } } } InterfaceMethodRefKey key(final ConstantPool pool); static final class Resolved extends ResolvedMethodRefConstant<InterfaceMethodRefConstant> implements InterfaceMethodRefConstant, InterfaceMethodRefKey { public Resolved(MethodActor methodActor) { super(methodActor); } @Override public InterfaceMethodRefKey key(final ConstantPool pool) { return this; } @Override public Tag tag() { return Tag.INTERFACE_METHOD_REF; } @Override public boolean equals(Object object) { return InterfaceMethodRefKey.Util.equals(this, object); } @Override public int hashCode() { return InterfaceMethodRefKey.Util.hashCode(this); } } static final class Unresolved extends UnresolvedRef<InterfaceMethodRefConstant> implements InterfaceMethodRefConstant, InterfaceMethodRefKey { public Unresolved(ClassActor holder, Utf8Constant name, SignatureDescriptor signature) { super(holder, name, signature); } @Override public Tag tag() { return Tag.INTERFACE_METHOD_REF; } @Override public InterfaceMethodRefKey key(final ConstantPool pool) { return this; } /** * Part of #5.4.3.4. */ static MethodActor findInterfaceMethodActor(InterfaceActor interfaceActor, Utf8Constant name, SignatureDescriptor descriptor) { MethodActor result = interfaceActor.findLocalInterfaceMethodActor(name, descriptor); if (result != null) { return result; } for (InterfaceActor i : interfaceActor.localInterfaceActors()) { result = findInterfaceMethodActor(i, name, descriptor); if (result != null) { return result; } } result = ClassRegistry.OBJECT.findLocalVirtualMethodActor(name, descriptor); if (result != null) { return result; } return null; } static MethodActor resolve(ConstantPool pool, int index, ClassActor classActor, Utf8Constant name, SignatureDescriptor signature) { if (!classActor.isInterface()) { throw new IncompatibleClassChangeError(); } final InterfaceActor interfaceActor = (InterfaceActor) classActor; MethodActor methodActor = findInterfaceMethodActor(interfaceActor, name, signature); if (methodActor != null) { MethodActor aliasedMethodActor = ALIAS.Static.aliasedMethod(methodActor); if (aliasedMethodActor == null) { // Only update constant pool if no aliasing occurred. // Otherwise, subsequent verification of bytecode // referencing the alias method will fail. pool.updateAt(index, new Resolved(methodActor)); } else { methodActor = aliasedMethodActor; } return methodActor; } final String errorMessage = classActor.javaSignature(true) + "." + name + signature; if (MaxineVM.isHosted()) { final Class<?> javaClass = classActor.toJava(); final Class[] parameterTypes = signature.resolveParameterTypes(javaClass.getClassLoader()); final Class returnType = signature.resolveReturnType(javaClass.getClassLoader()); final Method method = Classes.resolveMethod(javaClass, returnType, name.string, parameterTypes); if (MaxineVM.isHostedOnly(method)) { throw new HostOnlyMethodError(errorMessage); } } throw new NoSuchMethodError(errorMessage); } public MethodActor resolve(ConstantPool pool, int index) { return resolve(pool, index, holder, name, signature()); } @Override public boolean equals(Object object) { return InterfaceMethodRefKey.Util.equals(this, object); } @Override public int hashCode() { return InterfaceMethodRefKey.Util.hashCode(this); } @Override boolean isFieldConstant() { return false; } } static final class UnresolvedIndices extends UnresolvedRefIndices<InterfaceMethodRefConstant> implements InterfaceMethodRefConstant { UnresolvedIndices(int classIndex, int nameAndTypeIndex, Tag[] tags) { super(classIndex, nameAndTypeIndex, tags); } @Override public Tag tag() { return Tag.INTERFACE_METHOD_REF; } @Override public InterfaceMethodRefKey key(final ConstantPool pool) { class Key extends RefKey implements InterfaceMethodRefKey { Key() { super(pool, UnresolvedIndices.this); } public final SignatureDescriptor signature() { return UnresolvedIndices.this.signature(pool); } @Override public boolean equals(Object object) { return InterfaceMethodRefKey.Util.equals(this, object); } @Override public int hashCode() { return InterfaceMethodRefKey.Util.hashCode(this); } } return new Key(); } public MethodActor resolve(ConstantPool pool, int index) { final ClassActor classActor = pool.classAt(classIndex).resolve(pool, classIndex); return Unresolved.resolve(pool, index, classActor, name(pool), signature(pool)); } @Override boolean isFieldConstant() { return false; } } }