Mercurial > hg > truffle
view agent/src/share/classes/sun/jvm/hotspot/oops/Method.java @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | cbfe859bd244 |
children |
line wrap: on
line source
/* * Copyright (c) 2000, 2013, 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.PrintStream; import java.util.Observable; import java.util.Observer; import sun.jvm.hotspot.code.NMethod; import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.interpreter.OopMapCacheEntry; import sun.jvm.hotspot.runtime.SignatureConverter; import sun.jvm.hotspot.runtime.VM; import sun.jvm.hotspot.runtime.VMObjectFactory; import sun.jvm.hotspot.types.AddressField; import sun.jvm.hotspot.types.Type; import sun.jvm.hotspot.types.TypeDataBase; import sun.jvm.hotspot.types.WrongTypeException; import sun.jvm.hotspot.utilities.Assert; // A Method represents a Java method public class Method extends Metadata { 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("Method"); constMethod = type.getAddressField("_constMethod"); methodData = type.getAddressField("_method_data"); methodCounters = type.getAddressField("_method_counters"); methodSize = new CIntField(type.getCIntegerField("_method_size"), 0); accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0); code = type.getAddressField("_code"); vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0); bytecodeOffset = type.getSize(); /* interpreterEntry = type.getAddressField("_interpreter_entry"); fromCompiledCodeEntryPoint = type.getAddressField("_from_compiled_code_entry_point"); */ objectInitializerName = null; classInitializerName = null; } public Method(Address addr) { super(addr); } public boolean isMethod() { return true; } // Fields private static AddressField constMethod; private static AddressField methodData; private static AddressField methodCounters; private static CIntField methodSize; private static CIntField accessFlags; private static CIntField vtableIndex; private static long bytecodeOffset; private static AddressField code; // constant method names - <init>, <clinit> // Initialized lazily to avoid initialization ordering dependencies between Method and SymbolTable private static Symbol objectInitializerName; private static Symbol classInitializerName; private static Symbol objectInitializerName() { if (objectInitializerName == null) { objectInitializerName = VM.getVM().getSymbolTable().probe("<init>"); } return objectInitializerName; } private static Symbol classInitializerName() { if (classInitializerName == null) { classInitializerName = VM.getVM().getSymbolTable().probe("<clinit>"); } return classInitializerName; } /* private static AddressCField interpreterEntry; private static AddressCField fromCompiledCodeEntryPoint; */ // Accessors for declared fields public ConstMethod getConstMethod() { Address addr = constMethod.getValue(getAddress()); return (ConstMethod) VMObjectFactory.newObject(ConstMethod.class, addr); } public ConstantPool getConstants() { return getConstMethod().getConstants(); } public MethodData getMethodData() { Address addr = methodData.getValue(getAddress()); return (MethodData) VMObjectFactory.newObject(MethodData.class, addr); } public MethodCounters getMethodCounters() { Address addr = methodCounters.getValue(getAddress()); return (MethodCounters) VMObjectFactory.newObject(MethodCounters.class, addr); } /** WARNING: this is in words, not useful in this system; use getObjectSize() instead */ public long getMethodSize() { return methodSize.getValue(this); } public long getMaxStack() { return getConstMethod().getMaxStack(); } public long getMaxLocals() { return getConstMethod().getMaxLocals(); } public long getSizeOfParameters() { return getConstMethod().getSizeOfParameters(); } public long getNameIndex() { return getConstMethod().getNameIndex(); } public long getSignatureIndex() { return getConstMethod().getSignatureIndex(); } public long getGenericSignatureIndex() { return getConstMethod().getGenericSignatureIndex(); } public long getAccessFlags() { return accessFlags.getValue(this); } public long getCodeSize() { return getConstMethod().getCodeSize(); } public long getVtableIndex() { return vtableIndex.getValue(this); } public long getInvocationCount() { MethodCounters mc = getMethodCounters(); return mc == null ? 0 : mc.getInvocationCounter(); } public long getBackedgeCount() { MethodCounters mc = getMethodCounters(); return mc == null ? 0 : mc.getBackedgeCounter(); } // get associated compiled native method, if available, else return null. public NMethod getNativeMethod() { Address addr = code.getValue(getAddress()); return (NMethod) VMObjectFactory.newObject(NMethod.class, addr); } // Convenience routine public AccessFlags getAccessFlagsObj() { return new AccessFlags(getAccessFlags()); } /** Get a bytecode or breakpoint at the given bci */ public int getBytecodeOrBPAt(int bci) { return getConstMethod().getBytecodeOrBPAt(bci); } /** Fetch the original non-breakpoint bytecode at the specified bci. It is required that there is currently a bytecode at this bci. */ public int getOrigBytecodeAt(int bci) { BreakpointInfo bp = getMethodHolder().getBreakpoints(); for (; bp != null; bp = bp.getNext()) { if (bp.match(this, bci)) { return bp.getOrigBytecode(); } } System.err.println("Requested bci " + bci); for (; bp != null; bp = bp.getNext()) { System.err.println("Breakpoint at bci " + bp.getBCI() + ", bytecode " + bp.getOrigBytecode()); } Assert.that(false, "Should not reach here"); return -1; // not reached } public byte getBytecodeByteArg(int bci) { return getConstMethod().getBytecodeByteArg(bci); } /** Fetches a 16-bit big-endian ("Java ordered") value from the bytecode stream */ public short getBytecodeShortArg(int bci) { return getConstMethod().getBytecodeShortArg(bci); } /** Fetches a 16-bit native ordered value from the bytecode stream */ public short getNativeShortArg(int bci) { return getConstMethod().getNativeShortArg(bci); } /** Fetches a 32-bit big-endian ("Java ordered") value from the bytecode stream */ public int getBytecodeIntArg(int bci) { return getConstMethod().getBytecodeIntArg(bci); } /** Fetches a 32-bit native ordered value from the bytecode stream */ public int getNativeIntArg(int bci) { return getConstMethod().getNativeIntArg(bci); } public byte[] getByteCode() { return getConstMethod().getByteCode(); } /* public Address getCode() { return codeField.getValue(this); } public Address getInterpreterEntry() { return interpreterEntryField.getValue(this); } public Address getFromCompiledCodeEntryPoint() { return fromCompiledCodeEntryPointField.getValue(this); } */ // Accessors public Symbol getName() { return getConstants().getSymbolAt(getNameIndex()); } public Symbol getSignature() { return getConstants().getSymbolAt(getSignatureIndex()); } public Symbol getGenericSignature() { long index = getGenericSignatureIndex(); return (index != 0L) ? getConstants().getSymbolAt(index) : null; } // Method holder (the Klass holding this method) public InstanceKlass getMethodHolder() { return getConstants().getPoolHolder(); } // Access flags public boolean isPublic() { return getAccessFlagsObj().isPublic(); } public boolean isPrivate() { return getAccessFlagsObj().isPrivate(); } public boolean isProtected() { return getAccessFlagsObj().isProtected(); } public boolean isPackagePrivate() { AccessFlags af = getAccessFlagsObj(); return (!af.isPublic() && !af.isPrivate() && !af.isProtected()); } public boolean isStatic() { return getAccessFlagsObj().isStatic(); } public boolean isFinal() { return getAccessFlagsObj().isFinal(); } public boolean isSynchronized() { return getAccessFlagsObj().isSynchronized(); } public boolean isBridge() { return getAccessFlagsObj().isBridge(); } public boolean isVarArgs() { return getAccessFlagsObj().isVarArgs(); } public boolean isNative() { return getAccessFlagsObj().isNative(); } public boolean isAbstract() { return getAccessFlagsObj().isAbstract(); } public boolean isStrict() { return getAccessFlagsObj().isStrict(); } public boolean isSynthetic() { return getAccessFlagsObj().isSynthetic(); } public boolean isConstructor() { return (!isStatic()) && getName().equals(objectInitializerName()); } public boolean isStaticInitializer() { return isStatic() && getName().equals(classInitializerName()); } public boolean isObsolete() { return getAccessFlagsObj().isObsolete(); } public OopMapCacheEntry getMaskFor(int bci) { OopMapCacheEntry entry = new OopMapCacheEntry(); entry.fill(this, bci); return entry; } public long getSize() { return getMethodSize(); } public void printValueOn(PrintStream tty) { tty.print("Method " + getName().asString() + getSignature().asString() + "@" + getAddress()); } public void iterateFields(MetadataVisitor visitor) { visitor.doCInt(methodSize, true); visitor.doCInt(accessFlags, true); } public boolean hasLineNumberTable() { return getConstMethod().hasLineNumberTable(); } public int getLineNumberFromBCI(int bci) { return getConstMethod().getLineNumberFromBCI(bci); } public LineNumberTableElement[] getLineNumberTable() { return getConstMethod().getLineNumberTable(); } public boolean hasLocalVariableTable() { return getConstMethod().hasLocalVariableTable(); } /** Should only be called if table is present */ public LocalVariableTableElement[] getLocalVariableTable() { return getConstMethod().getLocalVariableTable(); } public Symbol getLocalVariableName(int bci, int slot) { if (! hasLocalVariableTable()) { return null; } LocalVariableTableElement[] locals = getLocalVariableTable(); for (int l = 0; l < locals.length; l++) { LocalVariableTableElement local = locals[l]; if ((bci >= local.getStartBCI()) && (bci < (local.getStartBCI() + local.getLength())) && slot == local.getSlot()) { return getConstants().getSymbolAt(local.getNameCPIndex()); } } return null; } public boolean hasExceptionTable() { return getConstMethod().hasExceptionTable(); } public ExceptionTableElement[] getExceptionTable() { return getConstMethod().getExceptionTable(); } public boolean hasCheckedExceptions() { return getConstMethod().hasCheckedExceptions(); } /** Should only be called if table is present */ public CheckedExceptionElement[] getCheckedExceptions() { return getConstMethod().getCheckedExceptions(); } /** Returns name and signature in external form for debugging purposes */ public String externalNameAndSignature() { final StringBuffer buf = new StringBuffer(); buf.append(getMethodHolder().getName().asString()); buf.append("."); buf.append(getName().asString()); buf.append("("); new SignatureConverter(getSignature(), buf).iterateParameters(); buf.append(")"); return buf.toString().replace('/', '.'); } public void dumpReplayData(PrintStream out) { NMethod nm = getNativeMethod(); int code_size = 0; if (nm != null) { code_size = (int)nm.codeEnd().minus(nm.getVerifiedEntryPoint()); } Klass holder = getMethodHolder(); out.println("ciMethod " + holder.getName().asString() + " " + OopUtilities.escapeString(getName().asString()) + " " + getSignature().asString() + " " + getInvocationCount() + " " + getBackedgeCount() + " " + interpreterInvocationCount() + " " + interpreterThrowoutCount() + " " + code_size); } public int interpreterThrowoutCount() { return getMethodCounters().interpreterThrowoutCount(); } public int interpreterInvocationCount() { return getMethodCounters().interpreterInvocationCount(); } }