mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00

Use cmpxchg for non permanent symbol refcounting, and pack refcount and length into an int. Reviewed-by: gziemski, kbarrett, iklam
158 lines
4.8 KiB
Java
158 lines
4.8 KiB
Java
/*
|
|
* Copyright (c) 2000, 2018, 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 sun.jvm.hotspot.oops;
|
|
|
|
import java.io.*;
|
|
import java.util.*;
|
|
import sun.jvm.hotspot.debugger.*;
|
|
import sun.jvm.hotspot.runtime.*;
|
|
import sun.jvm.hotspot.types.*;
|
|
import sun.jvm.hotspot.utilities.*;
|
|
|
|
// A Symbol is a canonicalized string.
|
|
// All Symbols reside in global symbolTable.
|
|
|
|
public class Symbol extends VMObject {
|
|
static {
|
|
VM.registerVMInitializedObserver(new Observer() {
|
|
public void update(Observable o, Object data) {
|
|
initialize(VM.getVM().getTypeDataBase());
|
|
}
|
|
});
|
|
}
|
|
|
|
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
|
Type type = db.lookupType("Symbol");
|
|
lengthAndRefcount = type.getCIntegerField("_length_and_refcount");
|
|
baseOffset = type.getField("_body").getOffset();
|
|
idHash = type.getCIntegerField("_identity_hash");
|
|
}
|
|
|
|
public static Symbol create(Address addr) {
|
|
if (addr == null) {
|
|
return null;
|
|
}
|
|
return new Symbol(addr);
|
|
}
|
|
|
|
Symbol(Address addr) {
|
|
super(addr);
|
|
}
|
|
|
|
public boolean isSymbol() { return true; }
|
|
|
|
private static long baseOffset; // tells where the array part starts
|
|
|
|
// Fields
|
|
private static CIntegerField lengthAndRefcount;
|
|
|
|
// Accessors for declared fields
|
|
public long getLength() {
|
|
long i = lengthAndRefcount.getValue(this.addr);
|
|
return (i >> 16) & 0xffff;
|
|
}
|
|
|
|
public byte getByteAt(long index) {
|
|
return addr.getJByteAt(baseOffset + index);
|
|
}
|
|
// _identity_hash is a short
|
|
private static CIntegerField idHash;
|
|
|
|
public int identityHash() {
|
|
long addr_value = getAddress().asLongValue();
|
|
int addr_bits = (int)(addr_value >> (VM.getVM().getLogMinObjAlignmentInBytes() + 3));
|
|
int length = (int)getLength();
|
|
int byte0 = getByteAt(0);
|
|
int byte1 = getByteAt(1);
|
|
int id_hash = (int)(0xffff & idHash.getValue(this.addr));
|
|
return id_hash |
|
|
((addr_bits ^ (length << 8) ^ ((byte0 << 8) | byte1)) << 16);
|
|
}
|
|
|
|
public boolean equals(byte[] modUTF8Chars) {
|
|
int l = (int) getLength();
|
|
if (l != modUTF8Chars.length) return false;
|
|
while (l-- > 0) {
|
|
if (modUTF8Chars[l] != getByteAt(l)) return false;
|
|
}
|
|
if (Assert.ASSERTS_ENABLED) {
|
|
Assert.that(l == -1, "we should be at the beginning");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public boolean equals(String string) {
|
|
return asString().equals(string);
|
|
}
|
|
|
|
public byte[] asByteArray() {
|
|
int length = (int) getLength();
|
|
byte [] result = new byte [length];
|
|
for (int index = 0; index < length; index++) {
|
|
result[index] = getByteAt(index);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public String asString() {
|
|
// Decode the byte array and return the string.
|
|
try {
|
|
return readModifiedUTF8(asByteArray());
|
|
} catch(Exception e) {
|
|
System.err.println(addr);
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public boolean startsWith(String str) {
|
|
return asString().startsWith(str);
|
|
}
|
|
|
|
public void printValueOn(PrintStream tty) {
|
|
tty.print("#" + asString());
|
|
}
|
|
|
|
/** Note: this comparison is used for vtable sorting only; it
|
|
doesn't matter what order it defines, as long as it is a total,
|
|
time-invariant order Since Symbol* are in C_HEAP, their
|
|
relative order in memory never changes, so use address
|
|
comparison for speed. */
|
|
public long fastCompare(Symbol other) {
|
|
return addr.minus(other.addr);
|
|
}
|
|
|
|
private static String readModifiedUTF8(byte[] buf) throws IOException {
|
|
final int len = buf.length;
|
|
byte[] tmp = new byte[len + 2];
|
|
// write modified UTF-8 length as short in big endian
|
|
tmp[0] = (byte) ((len >>> 8) & 0xFF);
|
|
tmp[1] = (byte) ((len >>> 0) & 0xFF);
|
|
// copy the data
|
|
System.arraycopy(buf, 0, tmp, 2, len);
|
|
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(tmp));
|
|
return dis.readUTF();
|
|
}
|
|
}
|