/*
* 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 static com.sun.max.vm.MaxineVM.*;
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 ClassMethodRefConstant extends PoolConstant<ClassMethodRefConstant>, MethodRefConstant<ClassMethodRefConstant> {
public interface ClassMethodRefKey extends PoolConstantKey<ClassMethodRefConstant> {
TypeDescriptor holder();
Utf8Constant name();
SignatureDescriptor signature();
public static final class Util {
private Util() {
}
public static boolean equals(ClassMethodRefKey key, Object other) {
if (other instanceof ClassMethodRefKey) {
final ClassMethodRefKey otherKey = (ClassMethodRefKey) other;
return key.holder().equals(otherKey.holder()) && key.name().equals(otherKey.name()) && key.signature().equals(otherKey.signature());
}
return false;
}
public static int hashCode(ClassMethodRefKey key) {
return key.holder().hashCode() ^ key.name().hashCode() ^ key.signature().hashCode();
}
}
}
StaticMethodActor resolveStatic(ConstantPool pool, int index);
VirtualMethodActor resolveVirtual(ConstantPool pool, int index);
ClassMethodRefKey key(final ConstantPool pool);
static final class Resolved extends ResolvedMethodRefConstant<ClassMethodRefConstant> implements ClassMethodRefConstant, ClassMethodRefKey {
public Resolved(MethodActor methodActor) {
super(methodActor);
}
@Override
public ClassMethodRefKey key(final ConstantPool pool) {
return this;
}
@Override
public Tag tag() {
return Tag.METHOD_REF;
}
@Override
public boolean equals(Object object) {
return ClassMethodRefKey.Util.equals(this, object);
}
@Override
public int hashCode() {
return ClassMethodRefKey.Util.hashCode(this);
}
public StaticMethodActor resolveStatic(ConstantPool pool, int index) {
return verifyIsStatic(methodActor(), pool);
}
public VirtualMethodActor resolveVirtual(ConstantPool pool, int index) {
return verifyIsVirtual(methodActor(), pool);
}
}
static final class Unresolved extends UnresolvedRef<ClassMethodRefConstant> implements ClassMethodRefConstant, ClassMethodRefKey {
public Unresolved(ClassActor holder, Utf8Constant name, SignatureDescriptor signature) {
super(holder, name, signature);
}
@Override
public Tag tag() {
return Tag.METHOD_REF;
}
@Override
public ClassMethodRefKey key(final ConstantPool pool) {
return this;
}
static MethodActor resolve(ConstantPool pool, int index, ClassActor classActor, Utf8Constant name, SignatureDescriptor signature) {
if (classActor.isInterface() && name != SymbolTable.CLINIT) {
throw new IncompatibleClassChangeError();
}
// According to the JVM specification, we would have to look for interface methods,
// but we do not need to do this here,
// because we created Miranda methods for the TupleClassActor.
// If we did not come across any of those above,
// then there isn't any matching interface method either.
MethodActor methodActor = classActor.findClassMethodActor(name, signature);
if (methodActor != null) {
if (methodActor.isAbstract() && !classActor.isAbstract()) {
throw new AbstractMethodError();
}
methodActor.checkAccessBy(pool.holder());
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 (isHosted()) {
final Class<?> javaClass = classActor.toJava();
final Class[] parameterTypes = signature.resolveParameterTypes(javaClass.getClassLoader());
final Class returnType = signature.resolveReturnType(javaClass.getClassLoader());
final AccessibleObject member = name.equals(SymbolTable.INIT) ?
Classes.getDeclaredConstructor(javaClass, parameterTypes) :
Classes.resolveMethod(javaClass, returnType, name.string, parameterTypes);
if (MaxineVM.isHostedOnly(member)) {
throw new HostOnlyMethodError(errorMessage);
}
}
throw new NoSuchMethodError(errorMessage);
}
public MethodActor resolve(ConstantPool pool, int index) {
return resolve(pool, index, holder, name, signature());
}
public StaticMethodActor resolveStatic(ConstantPool pool, int index) {
return Resolved.verifyIsStatic(resolve(pool, index), pool);
}
public VirtualMethodActor resolveVirtual(ConstantPool pool, int index) {
return Resolved.verifyIsVirtual(resolve(pool, index), pool);
}
@Override
public boolean equals(Object object) {
return ClassMethodRefKey.Util.equals(this, object);
}
@Override
public int hashCode() {
return ClassMethodRefKey.Util.hashCode(this);
}
@Override
boolean isFieldConstant() {
return false;
}
}
static final class UnresolvedIndices extends UnresolvedRefIndices<ClassMethodRefConstant> implements ClassMethodRefConstant {
UnresolvedIndices(int classIndex, int nameAndTypeIndex, Tag[] tags) {
super(classIndex, nameAndTypeIndex, tags);
}
@Override
public Tag tag() {
return Tag.METHOD_REF;
}
@Override
public ClassMethodRefKey key(final ConstantPool pool) {
class Key extends RefKey implements ClassMethodRefKey {
Key() {
super(pool, UnresolvedIndices.this);
}
public final SignatureDescriptor signature() {
return UnresolvedIndices.this.signature(pool);
}
@Override
public boolean equals(Object object) {
return ClassMethodRefKey.Util.equals(this, object);
}
@Override
public int hashCode() {
return ClassMethodRefKey.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));
}
public StaticMethodActor resolveStatic(ConstantPool pool, int index) {
return Resolved.verifyIsStatic(resolve(pool, index), pool);
}
public VirtualMethodActor resolveVirtual(ConstantPool pool, int index) {
return Resolved.verifyIsVirtual(resolve(pool, index), pool);
}
@Override
boolean isFieldConstant() {
return false;
}
}
}