001 /* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013 package org.jikesrvm.classloader; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.SizeConstants; 017 import org.jikesrvm.objectmodel.TIBLayoutConstants; 018 import org.jikesrvm.util.ImmutableEntryHashSetRVM; 019 import org.vmmagic.unboxed.Offset; 020 021 /** 022 * An interface method signature is a pair of atoms: 023 * interfaceMethodName + interfaceMethodDescriptor. 024 */ 025 public final class InterfaceMethodSignature implements TIBLayoutConstants, SizeConstants { 026 027 /** 028 * Used to canonicalize InterfaceMethodSignatures 029 */ 030 private static final ImmutableEntryHashSetRVM<InterfaceMethodSignature> dictionary = 031 new ImmutableEntryHashSetRVM<InterfaceMethodSignature>(); 032 033 /** 034 * Used to assign ids. Don't use id 0 to allow clients to use id 0 as a 'null'. 035 */ 036 private static int nextId = 1; 037 038 /** 039 * Name of the interface method 040 */ 041 private final Atom name; 042 043 /** 044 * Descriptor of the interface method 045 */ 046 private final Atom descriptor; 047 048 /** 049 * Id of this interface method signature (not used in hashCode or equals). 050 */ 051 private final int id; 052 053 private InterfaceMethodSignature(Atom name, Atom descriptor, int id) { 054 this.name = name; 055 this.descriptor = descriptor; 056 this.id = id; 057 } 058 059 /** 060 * Find or create an interface method signature for the given method reference. 061 * 062 * @param ref A reference to a supposed interface method 063 * @return the interface method signature 064 */ 065 public static synchronized InterfaceMethodSignature findOrCreate(MemberReference ref) { 066 InterfaceMethodSignature key = new InterfaceMethodSignature(ref.getName(), ref.getDescriptor(), nextId+1); 067 InterfaceMethodSignature val = dictionary.get(key); 068 if (val != null) return val; 069 nextId++; 070 dictionary.add(key); 071 return key; 072 } 073 074 /** 075 * @return name of the interface method 076 */ 077 public Atom getName() { 078 return name; 079 } 080 081 /** 082 * @return descriptor of hte interface method 083 */ 084 public Atom getDescriptor() { 085 return descriptor; 086 } 087 088 /** 089 * @return the id of thie interface method signature. 090 */ 091 public int getId() { return id; } 092 093 @Override 094 public String toString() { 095 return "{" + name + " " + descriptor + "}"; 096 } 097 098 @Override 099 public int hashCode() { 100 return name.hashCode() + descriptor.hashCode(); 101 } 102 103 @Override 104 public boolean equals(Object other) { 105 if (other instanceof InterfaceMethodSignature) { 106 InterfaceMethodSignature that = (InterfaceMethodSignature) other; 107 return name == that.name && descriptor == that.descriptor; 108 } else { 109 return false; 110 } 111 } 112 113 /** 114 * If using embedded IMTs, Get offset of interface method slot in TIB. 115 * If using indirect IMTs, Get offset of interface method slot in IMT. 116 * Note that all methods with same name & descriptor map to the same slot. 117 * <p> 118 * TODO!! replace this stupid offset assignment algorithm with something more reasonable. 119 * 120 * @return offset in TIB/IMT 121 */ 122 public Offset getIMTOffset() { 123 if (VM.VerifyAssertions) VM._assert(VM.BuildForIMTInterfaceInvocation); 124 int slot = id % IMT_METHOD_SLOTS; 125 return Offset.fromIntZeroExtend(slot << LOG_BYTES_IN_ADDRESS); 126 } 127 }