# HG changeset patch # User kvn # Date 1244589550 25200 # Node ID aa289b22b5772e5e1813952126d07a470fab5a07 # Parent c2974244a4967b20d88bc1e897c11f7f06dea7d2 6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14 Summary: Disable escape analysis when jvmti/debugger is used. Add support for EA ibto SA. Reviewed-by: never diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java Tue Jun 09 16:19:10 2009 -0700 @@ -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 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; } diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MonitorValue.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MonitorValue.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/MonitorValue.java Tue Jun 09 16:19:10 2009 -0700 @@ -29,6 +29,7 @@ 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 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 @@ tty.print(","); basicLock().printOn(tty); tty.print("}"); + if (eliminated) { + tty.print(" (eliminated)"); + } } } diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ObjectValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ObjectValue.java Tue Jun 09 16:19:10 2009 -0700 @@ -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 + + // 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); + } + } + +}; diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java Tue Jun 09 16:19:10 2009 -0700 @@ -27,8 +27,10 @@ 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 @@ private int localsDecodeOffset; private int expressionsDecodeOffset; private int monitorsDecodeOffset; + /** Scalar replaced bjects pool */ + private List objects; // ArrayList + 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 @@ 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 @@ // 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 @@ } 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; + } } diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeValue.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeValue.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeValue.java Tue Jun 09 16:19:10 2009 -0700 @@ -49,12 +49,15 @@ 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 @@ 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; diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java Tue Jun 09 16:19:10 2009 -0700 @@ -249,6 +249,7 @@ 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++; } diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ThreadReferenceImpl.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ThreadReferenceImpl.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ThreadReferenceImpl.java Tue Jun 09 16:19:10 2009 -0700 @@ -301,6 +301,9 @@ List frameMonitors = frame.getMonitors(); // List 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 diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Tue Jun 09 16:19:10 2009 -0700 @@ -131,8 +131,18 @@ 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 @@ // 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 @@ 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 @@ } 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 diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/InterpretedVFrame.java Tue Jun 09 16:19:10 2009 -0700 @@ -61,7 +61,7 @@ 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 @@ 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 @@ 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; } diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/MonitorInfo.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/MonitorInfo.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/MonitorInfo.java Tue Jun 09 16:19:10 2009 -0700 @@ -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() { return owner; } + 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 BasicLock lock() { return lock; } + public boolean eliminated() { return eliminated; } + public boolean ownerIsScalarReplaced() { return ownerIsScalarReplaced; } } diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/StackValue.java Tue Jun 09 16:19:10 2009 -0700 @@ -37,9 +37,11 @@ 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 @@ 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"); diff -r c2974244a496 -r aa289b22b577 hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaThread.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaThread.java Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaThread.java Tue Jun 09 16:19:10 2009 -0700 @@ -135,6 +135,10 @@ List frameMonitors = frame.getMonitors(); // List 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 diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/opto/c2compiler.cpp --- a/hotspot/src/share/vm/opto/c2compiler.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/opto/c2compiler.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -104,7 +104,9 @@ 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); diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/prims/jvmtiEnvBase.cpp --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -606,6 +606,7 @@ 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 @@ 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 diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/biasedLocking.cpp --- a/hotspot/src/share/vm/runtime/biasedLocking.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -121,6 +121,7 @@ // 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 @@ // 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(); diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/deoptimization.cpp --- a/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -933,7 +933,7 @@ GrowableArray* 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())); } } diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/stackValue.cpp --- a/hotspot/src/share/vm/runtime/stackValue.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/stackValue.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -146,8 +146,9 @@ 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 diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/stackValue.hpp --- a/hotspot/src/share/vm/runtime/stackValue.hpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/stackValue.hpp Tue Jun 09 16:19:10 2009 -0700 @@ -34,9 +34,11 @@ _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 @@ 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; diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/vframe.cpp --- a/hotspot/src/share/vm/runtime/vframe.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/vframe.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -106,6 +106,7 @@ 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 @@ 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 (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 @@ 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 @@ 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 @@ 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); diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/vframe.hpp --- a/hotspot/src/share/vm/runtime/vframe.hpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/vframe.hpp Tue Jun 09 16:19:10 2009 -0700 @@ -230,18 +230,36 @@ 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 { diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/vframeArray.cpp --- a/hotspot/src/share/vm/runtime/vframeArray.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -61,6 +61,7 @@ // 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 @@ 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 @@ 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; diff -r c2974244a496 -r aa289b22b577 hotspot/src/share/vm/runtime/vframe_hp.cpp --- a/hotspot/src/share/vm/runtime/vframe_hp.cpp Fri Jun 05 10:25:39 2009 -0700 +++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp Tue Jun 09 16:19:10 2009 -0700 @@ -190,7 +190,7 @@ // 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* result = new GrowableArray(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; }