6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
Disable escape analysis when jvmti/debugger is used. Add support for EA ibto SA. Reviewed-by: never
This commit is contained in:
parent
0429abd38a
commit
7b9d6a79ac
@ -24,23 +24,64 @@
|
||||
|
||||
package sun.jvm.hotspot.code;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.runtime.VM;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class DebugInfoReadStream extends CompressedReadStream {
|
||||
private NMethod code;
|
||||
private int InvocationEntryBCI;
|
||||
private List objectPool; // ArrayList<ObjectValue>
|
||||
|
||||
public DebugInfoReadStream(NMethod code, int offset) {
|
||||
super(code.scopesDataBegin(), offset);
|
||||
InvocationEntryBCI = VM.getVM().getInvocationEntryBCI();
|
||||
this.code = code;
|
||||
this.objectPool = null;
|
||||
}
|
||||
|
||||
public DebugInfoReadStream(NMethod code, int offset, List objectPool) {
|
||||
super(code.scopesDataBegin(), offset);
|
||||
InvocationEntryBCI = VM.getVM().getInvocationEntryBCI();
|
||||
this.code = code;
|
||||
this.objectPool = objectPool;
|
||||
}
|
||||
|
||||
public OopHandle readOopHandle() {
|
||||
return code.getOopAt(readInt());
|
||||
}
|
||||
|
||||
ScopeValue readObjectValue() {
|
||||
int id = readInt();
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(objectPool != null, "object pool does not exist");
|
||||
for (Iterator itr = objectPool.iterator(); itr.hasNext();) {
|
||||
ObjectValue ov = (ObjectValue) itr.next();
|
||||
Assert.that(ov.id() != id, "should not be read twice");
|
||||
}
|
||||
}
|
||||
ObjectValue result = new ObjectValue(id);
|
||||
// Cache the object since an object field could reference it.
|
||||
objectPool.add(result);
|
||||
result.readObject(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
ScopeValue getCachedObject() {
|
||||
int id = readInt();
|
||||
Assert.that(objectPool != null, "object pool does not exist");
|
||||
for (Iterator itr = objectPool.iterator(); itr.hasNext();) {
|
||||
ObjectValue ov = (ObjectValue) itr.next();
|
||||
if (ov.id() == id) {
|
||||
return ov;
|
||||
}
|
||||
}
|
||||
Assert.that(false, "should not reach here");
|
||||
return null;
|
||||
}
|
||||
|
||||
public int readBCI() {
|
||||
return readInt() + InvocationEntryBCI;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import java.io.*;
|
||||
public class MonitorValue {
|
||||
private ScopeValue owner;
|
||||
private Location basicLock;
|
||||
private boolean eliminated;
|
||||
|
||||
// FIXME: not useful yet
|
||||
// MonitorValue(ScopeValue* owner, Location basic_lock);
|
||||
@ -36,10 +37,12 @@ public class MonitorValue {
|
||||
public MonitorValue(DebugInfoReadStream stream) {
|
||||
basicLock = new Location(stream);
|
||||
owner = ScopeValue.readFrom(stream);
|
||||
eliminated= stream.readBoolean();
|
||||
}
|
||||
|
||||
public ScopeValue owner() { return owner; }
|
||||
public Location basicLock() { return basicLock; }
|
||||
public boolean eliminated() { return eliminated; }
|
||||
|
||||
// FIXME: not yet implementable
|
||||
// void write_on(DebugInfoWriteStream* stream);
|
||||
@ -50,5 +53,8 @@ public class MonitorValue {
|
||||
tty.print(",");
|
||||
basicLock().printOn(tty);
|
||||
tty.print("}");
|
||||
if (eliminated) {
|
||||
tty.print(" (eliminated)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package sun.jvm.hotspot.code;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
/** An ObjectValue describes an object eliminated by escape analysis. */
|
||||
|
||||
public class ObjectValue extends ScopeValue {
|
||||
private int id;
|
||||
private ScopeValue klass;
|
||||
private List fieldsValue; // ArrayList<ScopeValue>
|
||||
|
||||
// Field "boolean visited" is not implemented here since
|
||||
// it is used only a during debug info creation.
|
||||
|
||||
public ObjectValue(int id) {
|
||||
this.id = id;
|
||||
klass = null;
|
||||
fieldsValue = new ArrayList();
|
||||
}
|
||||
|
||||
public boolean isObject() { return true; }
|
||||
public int id() { return id; }
|
||||
public ScopeValue getKlass() { return klass; }
|
||||
public List getFieldsValue() { return fieldsValue; }
|
||||
public ScopeValue getFieldAt(int i) { return (ScopeValue)fieldsValue.get(i); }
|
||||
public int fieldsSize() { return fieldsValue.size(); }
|
||||
|
||||
// Field "value" is always NULL here since it is used
|
||||
// only during deoptimization of a compiled frame
|
||||
// pointing to reallocated object.
|
||||
public OopHandle getValue() { return null; }
|
||||
|
||||
/** Serialization of debugging information */
|
||||
|
||||
void readObject(DebugInfoReadStream stream) {
|
||||
klass = readFrom(stream);
|
||||
Assert.that(klass.isConstantOop(), "should be constant klass oop");
|
||||
int length = stream.readInt();
|
||||
for (int i = 0; i < length; i++) {
|
||||
ScopeValue val = readFrom(stream);
|
||||
fieldsValue.add(val);
|
||||
}
|
||||
}
|
||||
|
||||
// Printing
|
||||
|
||||
public void print() {
|
||||
printOn(System.out);
|
||||
}
|
||||
|
||||
public void printOn(PrintStream tty) {
|
||||
tty.print("scalarObj[" + id + "]");
|
||||
}
|
||||
|
||||
void printFieldsOn(PrintStream tty) {
|
||||
if (fieldsValue.size() > 0) {
|
||||
((ScopeValue)fieldsValue.get(0)).printOn(tty);
|
||||
}
|
||||
for (int i = 1; i < fieldsValue.size(); i++) {
|
||||
tty.print(", ");
|
||||
((ScopeValue)fieldsValue.get(i)).printOn(tty);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
@ -27,8 +27,10 @@ package sun.jvm.hotspot.code;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.oops.*;
|
||||
import sun.jvm.hotspot.runtime.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
/** ScopeDescs contain the information that makes source-level
|
||||
debugging of nmethods possible; each scopeDesc describes a method
|
||||
@ -45,10 +47,31 @@ public class ScopeDesc {
|
||||
private int localsDecodeOffset;
|
||||
private int expressionsDecodeOffset;
|
||||
private int monitorsDecodeOffset;
|
||||
/** Scalar replaced bjects pool */
|
||||
private List objects; // ArrayList<ScopeValue>
|
||||
|
||||
|
||||
public ScopeDesc(NMethod code, int decodeOffset) {
|
||||
this.code = code;
|
||||
this.decodeOffset = decodeOffset;
|
||||
this.objects = decodeObjectValues(DebugInformationRecorder.SERIALIZED_NULL);
|
||||
|
||||
// Decode header
|
||||
DebugInfoReadStream stream = streamAt(decodeOffset);
|
||||
|
||||
senderDecodeOffset = stream.readInt();
|
||||
method = (Method) VM.getVM().getObjectHeap().newOop(stream.readOopHandle());
|
||||
bci = stream.readBCI();
|
||||
// Decode offsets for body and sender
|
||||
localsDecodeOffset = stream.readInt();
|
||||
expressionsDecodeOffset = stream.readInt();
|
||||
monitorsDecodeOffset = stream.readInt();
|
||||
}
|
||||
|
||||
public ScopeDesc(NMethod code, int decodeOffset, int objectDecodeOffset) {
|
||||
this.code = code;
|
||||
this.decodeOffset = decodeOffset;
|
||||
this.objects = decodeObjectValues(objectDecodeOffset);
|
||||
|
||||
// Decode header
|
||||
DebugInfoReadStream stream = streamAt(decodeOffset);
|
||||
@ -81,6 +104,11 @@ public class ScopeDesc {
|
||||
return decodeMonitorValues(monitorsDecodeOffset);
|
||||
}
|
||||
|
||||
/** Returns a List<MonitorValue> */
|
||||
public List getObjects() {
|
||||
return objects;
|
||||
}
|
||||
|
||||
/** Stack walking. Returns null if this is the outermost scope. */
|
||||
public ScopeDesc sender() {
|
||||
if (isTop()) {
|
||||
@ -131,7 +159,7 @@ public class ScopeDesc {
|
||||
//
|
||||
|
||||
private DebugInfoReadStream streamAt(int decodeOffset) {
|
||||
return new DebugInfoReadStream(code, decodeOffset);
|
||||
return new DebugInfoReadStream(code, decodeOffset, objects);
|
||||
}
|
||||
|
||||
/** Returns a List<ScopeValue> or null if no values were present */
|
||||
@ -161,4 +189,22 @@ public class ScopeDesc {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Returns a List<ObjectValue> or null if no values were present */
|
||||
private List decodeObjectValues(int decodeOffset) {
|
||||
if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) {
|
||||
return null;
|
||||
}
|
||||
List res = new ArrayList();
|
||||
DebugInfoReadStream stream = new DebugInfoReadStream(code, decodeOffset, res);
|
||||
int length = stream.readInt();
|
||||
for (int i = 0; i < length; i++) {
|
||||
// Objects values are pushed to 'res' array during read so that
|
||||
// object's fields could reference it (OBJECT_ID_CODE).
|
||||
ScopeValue.readFrom(stream);
|
||||
// res.add(ScopeValue.readFrom(stream));
|
||||
}
|
||||
Assert.that(res.size() == length, "inconsistent debug information");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -49,12 +49,15 @@ public abstract class ScopeValue {
|
||||
static final int CONSTANT_OOP_CODE = 2;
|
||||
static final int CONSTANT_LONG_CODE = 3;
|
||||
static final int CONSTANT_DOUBLE_CODE = 4;
|
||||
static final int CONSTANT_OBJECT_CODE = 5;
|
||||
static final int CONSTANT_OBJECT_ID_CODE = 6;
|
||||
|
||||
public boolean isLocation() { return false; }
|
||||
public boolean isConstantInt() { return false; }
|
||||
public boolean isConstantDouble() { return false; }
|
||||
public boolean isConstantLong() { return false; }
|
||||
public boolean isConstantOop() { return false; }
|
||||
public boolean isObject() { return false; }
|
||||
|
||||
public static ScopeValue readFrom(DebugInfoReadStream stream) {
|
||||
switch (stream.readInt()) {
|
||||
@ -68,6 +71,10 @@ public abstract class ScopeValue {
|
||||
return new ConstantLongValue(stream);
|
||||
case CONSTANT_DOUBLE_CODE:
|
||||
return new ConstantDoubleValue(stream);
|
||||
case CONSTANT_OBJECT_CODE:
|
||||
return stream.readObjectValue();
|
||||
case CONSTANT_OBJECT_ID_CODE:
|
||||
return stream.getCachedObject();
|
||||
default:
|
||||
Assert.that(false, "should not reach here");
|
||||
return null;
|
||||
|
@ -249,6 +249,7 @@ public class ObjectReferenceImpl extends ValueImpl implements ObjectReference {
|
||||
OopHandle givenHandle = obj.getHandle();
|
||||
for (Iterator itr = monitors.iterator(); itr.hasNext();) {
|
||||
MonitorInfo mi = (MonitorInfo) itr.next();
|
||||
if (mi.eliminated() && frame.isCompiledFrame()) continue; // skip eliminated monitor
|
||||
if (givenHandle.equals(mi.owner())) {
|
||||
res++;
|
||||
}
|
||||
|
@ -301,6 +301,9 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
|
||||
List frameMonitors = frame.getMonitors(); // List<MonitorInfo>
|
||||
for (Iterator miItr = frameMonitors.iterator(); miItr.hasNext(); ) {
|
||||
sun.jvm.hotspot.runtime.MonitorInfo mi = (sun.jvm.hotspot.runtime.MonitorInfo) miItr.next();
|
||||
if (mi.eliminated() && frame.isCompiledFrame()) {
|
||||
continue; // skip eliminated monitor
|
||||
}
|
||||
OopHandle obj = mi.owner();
|
||||
if (obj == null) {
|
||||
// this monitor doesn't have an owning object so skip it
|
||||
|
@ -131,8 +131,18 @@ public class CompiledVFrame extends JavaVFrame {
|
||||
List result = new ArrayList(monitors.size());
|
||||
for (int i = 0; i < monitors.size(); i++) {
|
||||
MonitorValue mv = (MonitorValue) monitors.get(i);
|
||||
StackValue ownerSV = createStackValue(mv.owner()); // it is an oop
|
||||
result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock())));
|
||||
ScopeValue ov = mv.owner();
|
||||
StackValue ownerSV = createStackValue(ov); // it is an oop
|
||||
if (ov.isObject()) { // The owner object was scalar replaced
|
||||
Assert.that(mv.eliminated() && ownerSV.objIsScalarReplaced(), "monitor should be eliminated for scalar replaced object");
|
||||
// Put klass for scalar replaced object.
|
||||
ScopeValue kv = ((ObjectValue)ov).getKlass();
|
||||
Assert.that(kv.isConstantOop(), "klass should be oop constant for scalar replaced object");
|
||||
OopHandle k = ((ConstantOopReadValue)kv).getValue();
|
||||
result.add(new MonitorInfo(k, resolveMonitorLock(mv.basicLock()), mv.eliminated(), true));
|
||||
} else {
|
||||
result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock()), mv.eliminated(), false));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -212,12 +222,12 @@ public class CompiledVFrame extends JavaVFrame {
|
||||
// long or is unused. He always saves a long. Here we know
|
||||
// a long was saved, but we only want an narrow oop back. Narrow the
|
||||
// saved long to the narrow oop that the JVM wants.
|
||||
return new StackValue(valueAddr.getCompOopHandleAt(VM.getVM().getIntSize()));
|
||||
return new StackValue(valueAddr.getCompOopHandleAt(VM.getVM().getIntSize()), 0);
|
||||
} else {
|
||||
return new StackValue(valueAddr.getCompOopHandleAt(0));
|
||||
return new StackValue(valueAddr.getCompOopHandleAt(0), 0);
|
||||
}
|
||||
} else if( loc.holdsOop() ) { // Holds an oop?
|
||||
return new StackValue(valueAddr.getOopHandleAt(0));
|
||||
return new StackValue(valueAddr.getOopHandleAt(0), 0);
|
||||
} else if( loc.holdsDouble() ) {
|
||||
// Double value in a single stack slot
|
||||
return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF);
|
||||
@ -277,7 +287,7 @@ public class CompiledVFrame extends JavaVFrame {
|
||||
return new StackValue(((ConstantIntValue) sv).getValue() & 0xFFFFFFFF);
|
||||
} else if (sv.isConstantOop()) {
|
||||
// constant oop
|
||||
return new StackValue(((ConstantOopReadValue) sv).getValue());
|
||||
return new StackValue(((ConstantOopReadValue) sv).getValue(), 0);
|
||||
} else if (sv.isConstantDouble()) {
|
||||
// Constant double in a single stack slot
|
||||
double d = ((ConstantDoubleValue) sv).getValue();
|
||||
@ -285,6 +295,9 @@ public class CompiledVFrame extends JavaVFrame {
|
||||
} else if (VM.getVM().isLP64() && sv.isConstantLong()) {
|
||||
// Constant long in a single stack slot
|
||||
return new StackValue(((ConstantLongValue) sv).getValue() & 0xFFFFFFFF);
|
||||
} else if (sv.isObject()) {
|
||||
// Scalar replaced object in compiled frame
|
||||
return new StackValue(((ObjectValue)sv).getValue(), 1);
|
||||
}
|
||||
|
||||
// Unknown ScopeValue type
|
||||
|
@ -61,7 +61,7 @@ public class InterpretedVFrame extends JavaVFrame {
|
||||
StackValue sv;
|
||||
if (oopMask.isOop(i)) {
|
||||
// oop value
|
||||
sv = new StackValue(addr.getOopHandleAt(0));
|
||||
sv = new StackValue(addr.getOopHandleAt(0), 0);
|
||||
} else {
|
||||
// integer
|
||||
// Fetch a signed integer the size of a stack slot
|
||||
@ -95,7 +95,7 @@ public class InterpretedVFrame extends JavaVFrame {
|
||||
StackValue sv;
|
||||
if (oopMask.isOop(i + nofLocals)) {
|
||||
// oop value
|
||||
sv = new StackValue(addr.getOopHandleAt(0));
|
||||
sv = new StackValue(addr.getOopHandleAt(0), 0);
|
||||
} else {
|
||||
// integer
|
||||
// Fetch a signed integer the size of a stack slot
|
||||
@ -113,7 +113,7 @@ public class InterpretedVFrame extends JavaVFrame {
|
||||
for (BasicObjectLock current = getFrame().interpreterFrameMonitorEnd();
|
||||
current.address().lessThan(getFrame().interpreterFrameMonitorBegin().address());
|
||||
current = getFrame().nextMonitorInInterpreterFrame(current)) {
|
||||
result.add(new MonitorInfo(current.obj(), current.lock()));
|
||||
result.add(new MonitorInfo(current.obj(), current.lock(), false, false));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -25,16 +25,39 @@
|
||||
package sun.jvm.hotspot.runtime;
|
||||
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
import sun.jvm.hotspot.utilities.*;
|
||||
|
||||
public class MonitorInfo {
|
||||
private OopHandle owner;
|
||||
private BasicLock lock;
|
||||
private OopHandle ownerKlass;
|
||||
private boolean eliminated;
|
||||
private boolean ownerIsScalarReplaced;
|
||||
|
||||
public MonitorInfo(OopHandle owner, BasicLock lock) {
|
||||
this.owner = owner;
|
||||
this.lock = lock;
|
||||
public MonitorInfo(OopHandle owner, BasicLock lock, boolean eliminated, boolean ownerIsScalarReplaced) {
|
||||
if (!ownerIsScalarReplaced) {
|
||||
this.owner = owner;
|
||||
this.ownerKlass = null;
|
||||
} else {
|
||||
Assert.that(eliminated, "monitor should be eliminated for scalar replaced object");
|
||||
this.owner = null;
|
||||
this.ownerKlass = owner;
|
||||
}
|
||||
this.eliminated = eliminated;
|
||||
this.ownerIsScalarReplaced = ownerIsScalarReplaced;
|
||||
}
|
||||
|
||||
public OopHandle owner() {
|
||||
Assert.that(!ownerIsScalarReplaced, "should not be called for scalar replaced object");
|
||||
return owner;
|
||||
}
|
||||
|
||||
public OopHandle ownerKlass() {
|
||||
Assert.that(ownerIsScalarReplaced, "should not be called for not scalar replaced object");
|
||||
return ownerKlass;
|
||||
}
|
||||
|
||||
public OopHandle owner() { return owner; }
|
||||
public BasicLock lock() { return lock; }
|
||||
public boolean eliminated() { return eliminated; }
|
||||
public boolean ownerIsScalarReplaced() { return ownerIsScalarReplaced; }
|
||||
}
|
||||
|
@ -37,9 +37,11 @@ public class StackValue {
|
||||
type = BasicType.getTConflict();
|
||||
}
|
||||
|
||||
public StackValue(OopHandle h) {
|
||||
public StackValue(OopHandle h, long scalar_replaced) {
|
||||
handleValue = h;
|
||||
type = BasicType.getTObject();
|
||||
integerValue = scalar_replaced;
|
||||
Assert.that(integerValue == 0 || handleValue == null, "not null object should not be marked as scalar replaced");
|
||||
}
|
||||
|
||||
public StackValue(long i) {
|
||||
@ -59,6 +61,13 @@ public class StackValue {
|
||||
return handleValue;
|
||||
}
|
||||
|
||||
boolean objIsScalarReplaced() {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(type == BasicType.getTObject(), "type check");
|
||||
}
|
||||
return integerValue != 0;
|
||||
}
|
||||
|
||||
public long getInteger() {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(type == BasicType.getTInt(), "type check");
|
||||
|
@ -135,6 +135,10 @@ public class JSJavaThread extends JSJavaInstance {
|
||||
List frameMonitors = frame.getMonitors(); // List<MonitorInfo>
|
||||
for (Iterator miItr = frameMonitors.iterator(); miItr.hasNext(); ) {
|
||||
MonitorInfo mi = (MonitorInfo) miItr.next();
|
||||
|
||||
if (mi.eliminated() && frame.isCompiledFrame()) {
|
||||
continue; // skip eliminated monitor
|
||||
}
|
||||
OopHandle obj = mi.owner();
|
||||
if (obj == null) {
|
||||
// this monitor doesn't have an owning object so skip it
|
||||
|
@ -104,7 +104,9 @@ void C2Compiler::compile_method(ciEnv* env,
|
||||
initialize();
|
||||
}
|
||||
bool subsume_loads = true;
|
||||
bool do_escape_analysis = DoEscapeAnalysis;
|
||||
bool do_escape_analysis = DoEscapeAnalysis &&
|
||||
!(env->jvmti_can_hotswap_or_post_breakpoint() ||
|
||||
env->jvmti_can_examine_or_deopt_anywhere());
|
||||
while (!env->failing()) {
|
||||
// Attempt to compile while subsuming loads into machine instructions.
|
||||
Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis);
|
||||
|
@ -606,6 +606,7 @@ JvmtiEnvBase::count_locked_objects(JavaThread *java_thread, Handle hobj) {
|
||||
if (!mons->is_empty()) {
|
||||
for (int i = 0; i < mons->length(); i++) {
|
||||
MonitorInfo *mi = mons->at(i);
|
||||
if (mi->owner_is_scalar_replaced()) continue;
|
||||
|
||||
// see if owner of the monitor is our object
|
||||
if (mi->owner() != NULL && mi->owner() == hobj()) {
|
||||
@ -726,6 +727,8 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread
|
||||
for (int i = 0; i < mons->length(); i++) {
|
||||
MonitorInfo *mi = mons->at(i);
|
||||
|
||||
if (mi->owner_is_scalar_replaced()) continue;
|
||||
|
||||
oop obj = mi->owner();
|
||||
if (obj == NULL) {
|
||||
// this monitor doesn't have an owning object so skip it
|
||||
|
@ -121,6 +121,7 @@ static GrowableArray<MonitorInfo*>* get_or_compute_monitor_info(JavaThread* thre
|
||||
// Walk monitors youngest to oldest
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
MonitorInfo* mon_info = monitors->at(i);
|
||||
if (mon_info->owner_is_scalar_replaced()) continue;
|
||||
oop owner = mon_info->owner();
|
||||
if (owner != NULL) {
|
||||
info->append(mon_info);
|
||||
@ -694,6 +695,7 @@ void BiasedLocking::preserve_marks() {
|
||||
// Walk monitors youngest to oldest
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
MonitorInfo* mon_info = monitors->at(i);
|
||||
if (mon_info->owner_is_scalar_replaced()) continue;
|
||||
oop owner = mon_info->owner();
|
||||
if (owner != NULL) {
|
||||
markOop mark = owner->mark();
|
||||
|
@ -933,7 +933,7 @@ static void collect_monitors(compiledVFrame* cvf, GrowableArray<Handle>* objects
|
||||
GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
|
||||
for (int i = 0; i < monitors->length(); i++) {
|
||||
MonitorInfo* mon_info = monitors->at(i);
|
||||
if (mon_info->owner() != NULL && !mon_info->eliminated()) {
|
||||
if (!mon_info->eliminated() && mon_info->owner() != NULL) {
|
||||
objects_to_revoke->append(Handle(mon_info->owner()));
|
||||
}
|
||||
}
|
||||
|
@ -146,8 +146,9 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r
|
||||
value.jl = ((ConstantLongValue *)sv)->value();
|
||||
return new StackValue(value.p);
|
||||
#endif
|
||||
} else if (sv->is_object()) {
|
||||
return new StackValue(((ObjectValue *)sv)->value());
|
||||
} else if (sv->is_object()) { // Scalar replaced object in compiled frame
|
||||
Handle ov = ((ObjectValue *)sv)->value();
|
||||
return new StackValue(ov, (ov.is_null()) ? 1 : 0);
|
||||
}
|
||||
|
||||
// Unknown ScopeValue type
|
||||
|
@ -34,9 +34,11 @@ class StackValue : public ResourceObj {
|
||||
_i = value;
|
||||
}
|
||||
|
||||
StackValue(Handle value) {
|
||||
StackValue(Handle value, intptr_t scalar_replaced = 0) {
|
||||
_type = T_OBJECT;
|
||||
_i = scalar_replaced;
|
||||
_o = value;
|
||||
assert(_i == 0 || _o.is_null(), "not null object should not be marked as scalar replaced");
|
||||
}
|
||||
|
||||
StackValue() {
|
||||
@ -56,6 +58,11 @@ class StackValue : public ResourceObj {
|
||||
return _o;
|
||||
}
|
||||
|
||||
bool obj_is_scalar_replaced() const {
|
||||
assert(type() == T_OBJECT, "type check");
|
||||
return _i != 0;
|
||||
}
|
||||
|
||||
void set_obj(Handle value) {
|
||||
assert(type() == T_OBJECT, "type check");
|
||||
_o = value;
|
||||
|
@ -106,6 +106,7 @@ GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() {
|
||||
|
||||
for (int index = (mons->length()-1); index >= 0; index--) {
|
||||
MonitorInfo* monitor = mons->at(index);
|
||||
if (monitor->eliminated() && is_compiled_frame()) continue; // skip eliminated monitor
|
||||
oop obj = monitor->owner();
|
||||
if (obj == NULL) continue; // skip unowned monitor
|
||||
//
|
||||
@ -162,6 +163,18 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
|
||||
bool found_first_monitor = false;
|
||||
for (int index = (mons->length()-1); index >= 0; index--) {
|
||||
MonitorInfo* monitor = mons->at(index);
|
||||
if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code
|
||||
if (monitor->owner_is_scalar_replaced()) {
|
||||
Klass* k = Klass::cast(monitor->owner_klass());
|
||||
st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name());
|
||||
} else {
|
||||
oop obj = monitor->owner();
|
||||
if (obj != NULL) {
|
||||
print_locked_object_class_name(st, obj, "eliminated");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (monitor->owner() != NULL) {
|
||||
|
||||
// First, assume we have the monitor locked. If we haven't found an
|
||||
@ -171,11 +184,11 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
|
||||
|
||||
const char *lock_state = "locked"; // assume we have the monitor locked
|
||||
if (!found_first_monitor && frame_count == 0) {
|
||||
markOop mark = monitor->owner()->mark();
|
||||
if (mark->has_monitor() &&
|
||||
mark->monitor() == thread()->current_pending_monitor()) {
|
||||
markOop mark = monitor->owner()->mark();
|
||||
if (mark->has_monitor() &&
|
||||
mark->monitor() == thread()->current_pending_monitor()) {
|
||||
lock_state = "waiting to lock";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
found_first_monitor = true;
|
||||
@ -206,7 +219,7 @@ GrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const {
|
||||
for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin()));
|
||||
current >= fr().interpreter_frame_monitor_end();
|
||||
current = fr().previous_monitor_in_interpreter_frame(current)) {
|
||||
result->push(new MonitorInfo(current->obj(), current->lock(), false));
|
||||
result->push(new MonitorInfo(current->obj(), current->lock(), false, false));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -531,8 +544,18 @@ void javaVFrame::print() {
|
||||
tty->print_cr("\tmonitor list:");
|
||||
for (int index = (list->length()-1); index >= 0; index--) {
|
||||
MonitorInfo* monitor = list->at(index);
|
||||
tty->print("\t obj\t"); monitor->owner()->print_value();
|
||||
tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner());
|
||||
tty->print("\t obj\t");
|
||||
if (monitor->owner_is_scalar_replaced()) {
|
||||
Klass* k = Klass::cast(monitor->owner_klass());
|
||||
tty->print("( is scalar replaced %s)", k->external_name());
|
||||
} else if (monitor->owner() == NULL) {
|
||||
tty->print("( null )");
|
||||
} else {
|
||||
monitor->owner()->print_value();
|
||||
tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner());
|
||||
}
|
||||
if (monitor->eliminated() && is_compiled_frame())
|
||||
tty->print(" ( lock is eliminated )");
|
||||
tty->cr();
|
||||
tty->print("\t ");
|
||||
monitor->lock()->print_on(tty);
|
||||
|
@ -230,18 +230,36 @@ class MonitorInfo : public ResourceObj {
|
||||
private:
|
||||
oop _owner; // the object owning the monitor
|
||||
BasicLock* _lock;
|
||||
oop _owner_klass; // klass if owner was scalar replaced
|
||||
bool _eliminated;
|
||||
bool _owner_is_scalar_replaced;
|
||||
public:
|
||||
// Constructor
|
||||
MonitorInfo(oop owner, BasicLock* lock, bool eliminated) {
|
||||
_owner = owner;
|
||||
MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced) {
|
||||
if (!owner_is_scalar_replaced) {
|
||||
_owner = owner;
|
||||
_owner_klass = NULL;
|
||||
} else {
|
||||
assert(eliminated, "monitor should be eliminated for scalar replaced object");
|
||||
_owner = NULL;
|
||||
_owner_klass = owner;
|
||||
}
|
||||
_lock = lock;
|
||||
_eliminated = eliminated;
|
||||
_owner_is_scalar_replaced = owner_is_scalar_replaced;
|
||||
}
|
||||
// Accessors
|
||||
oop owner() const { return _owner; }
|
||||
oop owner() const {
|
||||
assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object");
|
||||
return _owner;
|
||||
}
|
||||
klassOop owner_klass() const {
|
||||
assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object");
|
||||
return (klassOop)_owner_klass;
|
||||
}
|
||||
BasicLock* lock() const { return _lock; }
|
||||
bool eliminated() const { return _eliminated; }
|
||||
bool owner_is_scalar_replaced() const { return _owner_is_scalar_replaced; }
|
||||
};
|
||||
|
||||
class vframeStreamCommon : StackObj {
|
||||
|
@ -61,6 +61,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
// Migrate the BasicLocks from the stack to the monitor chunk
|
||||
for (index = 0; index < list->length(); index++) {
|
||||
MonitorInfo* monitor = list->at(index);
|
||||
assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already");
|
||||
assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
|
||||
BasicObjectLock* dest = _monitors->at(index);
|
||||
dest->set_obj(monitor->owner());
|
||||
@ -89,6 +90,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
StackValue* value = locs->at(index);
|
||||
switch(value->type()) {
|
||||
case T_OBJECT:
|
||||
assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
|
||||
// preserve object type
|
||||
_locals->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
|
||||
break;
|
||||
@ -113,6 +115,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
StackValue* value = exprs->at(index);
|
||||
switch(value->type()) {
|
||||
case T_OBJECT:
|
||||
assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
|
||||
// preserve object type
|
||||
_expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT ));
|
||||
break;
|
||||
|
@ -190,7 +190,7 @@ GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const {
|
||||
// Casting away const
|
||||
frame& fr = (frame&) _fr;
|
||||
MonitorInfo* info = new MonitorInfo(fr.compiled_synchronized_native_monitor_owner(nm),
|
||||
fr.compiled_synchronized_native_monitor(nm), false);
|
||||
fr.compiled_synchronized_native_monitor(nm), false, false);
|
||||
monitors->push(info);
|
||||
return monitors;
|
||||
}
|
||||
@ -201,8 +201,20 @@ GrowableArray<MonitorInfo*>* compiledVFrame::monitors() const {
|
||||
GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(monitors->length());
|
||||
for (int index = 0; index < monitors->length(); index++) {
|
||||
MonitorValue* mv = monitors->at(index);
|
||||
StackValue *owner_sv = create_stack_value(mv->owner()); // it is an oop
|
||||
result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()), mv->eliminated()));
|
||||
ScopeValue* ov = mv->owner();
|
||||
StackValue *owner_sv = create_stack_value(ov); // it is an oop
|
||||
if (ov->is_object() && owner_sv->obj_is_scalar_replaced()) { // The owner object was scalar replaced
|
||||
assert(mv->eliminated(), "monitor should be eliminated for scalar replaced object");
|
||||
// Put klass for scalar replaced object.
|
||||
ScopeValue* kv = ((ObjectValue *)ov)->klass();
|
||||
assert(kv->is_constant_oop(), "klass should be oop constant for scalar replaced object");
|
||||
KlassHandle k(((ConstantOopReadValue*)kv)->value()());
|
||||
result->push(new MonitorInfo(k->as_klassOop(), resolve_monitor_lock(mv->basic_lock()),
|
||||
mv->eliminated(), true));
|
||||
} else {
|
||||
result->push(new MonitorInfo(owner_sv->get_obj()(), resolve_monitor_lock(mv->basic_lock()),
|
||||
mv->eliminated(), false));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user