--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/DebugInfoReadStream.java Tue Aug 25 13:08:40 2009 -0700
@@ -81,4 +81,8 @@
Assert.that(false, "should not reach here");
return null;
}
+
+ public int readBCI() {
+ return readInt() + InvocationEntryBCI;
+ }
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-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
@@ -259,7 +259,7 @@
if (Assert.ASSERTS_ENABLED) {
Assert.that(pd != null, "scope must be present");
}
- return new ScopeDesc(this, pd.getScopeDecodeOffset());
+ return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute());
}
/** This is only for use by the debugging system, and is only
@@ -291,7 +291,7 @@
public ScopeDesc getScopeDescNearDbg(Address pc) {
PCDesc pd = getPCDescNearDbg(pc);
if (pd == null) return null;
- return new ScopeDesc(this, pd.getScopeDecodeOffset());
+ return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getReexecute());
}
public Map/*<Address, PcDesc>*/ getSafepoints() {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/PCDesc.java Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-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
@@ -36,6 +36,7 @@
public class PCDesc extends VMObject {
private static CIntegerField pcOffsetField;
private static CIntegerField scopeDecodeOffsetField;
+ private static CIntegerField pcFlagsField;
static {
VM.registerVMInitializedObserver(new Observer() {
@@ -50,6 +51,7 @@
pcOffsetField = type.getCIntegerField("_pc_offset");
scopeDecodeOffsetField = type.getCIntegerField("_scope_decode_offset");
+ pcFlagsField = type.getCIntegerField("_flags");
}
public PCDesc(Address addr) {
@@ -70,6 +72,12 @@
return code.instructionsBegin().addOffsetTo(getPCOffset());
}
+
+ public boolean getReexecute() {
+ int flags = (int)pcFlagsField.getValue(addr);
+ return ((flags & 0x1)== 1); //first is the reexecute bit
+ }
+
public void print(NMethod code) {
printOn(System.out, code);
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/ScopeDesc.java Tue Aug 25 13:08:40 2009 -0700
@@ -52,44 +52,46 @@
private List objects; // ArrayList<ScopeValue>
- public ScopeDesc(NMethod code, int decodeOffset) {
+ public ScopeDesc(NMethod code, int decodeOffset, boolean reexecute) {
this.code = code;
this.decodeOffset = decodeOffset;
this.objects = decodeObjectValues(DebugInformationRecorder.SERIALIZED_NULL);
+ this.reexecute = reexecute;
// Decode header
DebugInfoReadStream stream = streamAt(decodeOffset);
senderDecodeOffset = stream.readInt();
method = (Method) VM.getVM().getObjectHeap().newOop(stream.readOopHandle());
- setBCIAndReexecute(stream.readInt());
+ 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) {
+ public ScopeDesc(NMethod code, int decodeOffset, int objectDecodeOffset, boolean reexecute) {
this.code = code;
this.decodeOffset = decodeOffset;
this.objects = decodeObjectValues(objectDecodeOffset);
+ this.reexecute = reexecute;
// Decode header
DebugInfoReadStream stream = streamAt(decodeOffset);
senderDecodeOffset = stream.readInt();
method = (Method) VM.getVM().getObjectHeap().newOop(stream.readOopHandle());
- setBCIAndReexecute(stream.readInt());
+ bci = stream.readBCI();
// Decode offsets for body and sender
localsDecodeOffset = stream.readInt();
expressionsDecodeOffset = stream.readInt();
monitorsDecodeOffset = stream.readInt();
}
- public NMethod getNMethod() { return code; }
- public Method getMethod() { return method; }
- public int getBCI() { return bci; }
- public boolean getReexecute() {return reexecute;}
+ public NMethod getNMethod() { return code; }
+ public Method getMethod() { return method; }
+ public int getBCI() { return bci; }
+ public boolean getReexecute() { return reexecute;}
/** Returns a List<ScopeValue> */
public List getLocals() {
@@ -117,7 +119,7 @@
return null;
}
- return new ScopeDesc(code, senderDecodeOffset);
+ return new ScopeDesc(code, senderDecodeOffset, false);
}
/** Returns where the scope was decoded */
@@ -151,8 +153,8 @@
public void printValueOn(PrintStream tty) {
tty.print("ScopeDesc for ");
method.printValueOn(tty);
- tty.println(" @bci " + bci);
- tty.println(" reexecute: " + reexecute);
+ tty.print(" @bci " + bci);
+ tty.println(" reexecute=" + reexecute);
}
// FIXME: add more accessors
@@ -160,12 +162,6 @@
//--------------------------------------------------------------------------------
// Internals only below this point
//
- private void setBCIAndReexecute(int combination) {
- int InvocationEntryBci = VM.getVM().getInvocationEntryBCI();
- bci = (combination >> 1) + InvocationEntryBci;
- reexecute = (combination & 1)==1 ? true : false;
- }
-
private DebugInfoReadStream streamAt(int decodeOffset) {
return new DebugInfoReadStream(code, decodeOffset, objects);
}
--- a/hotspot/src/cpu/sparc/vm/c1_Defs_sparc.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_Defs_sparc.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-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
@@ -38,7 +38,7 @@
// registers
enum {
pd_nof_cpu_regs_frame_map = 32, // number of registers used during code emission
- pd_nof_caller_save_cpu_regs_frame_map = 6, // number of cpu registers killed by calls
+ pd_nof_caller_save_cpu_regs_frame_map = 10, // number of cpu registers killed by calls
pd_nof_cpu_regs_reg_alloc = 20, // number of registers that are visible to register allocator
pd_nof_cpu_regs_linearscan = 32,// number of registers visible linear scan
pd_first_cpu_reg = 0,
--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -320,6 +320,10 @@
_caller_save_cpu_regs[3] = FrameMap::O3_opr;
_caller_save_cpu_regs[4] = FrameMap::O4_opr;
_caller_save_cpu_regs[5] = FrameMap::O5_opr;
+ _caller_save_cpu_regs[6] = FrameMap::G1_opr;
+ _caller_save_cpu_regs[7] = FrameMap::G3_opr;
+ _caller_save_cpu_regs[8] = FrameMap::G4_opr;
+ _caller_save_cpu_regs[9] = FrameMap::G5_opr;
for (int i = 0; i < nof_caller_save_fpu_regs; i++) {
_caller_save_fpu_regs[i] = LIR_OprFact::single_fpu(i);
}
--- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -749,6 +749,10 @@
void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
assert(x->number_of_arguments() == 5, "wrong type");
+
+ // Make all state_for calls early since they can emit code
+ CodeEmitInfo* info = state_for(x, x->state());
+
// Note: spill caller save before setting the item
LIRItem src (x->argument_at(0), this);
LIRItem src_pos (x->argument_at(1), this);
@@ -767,7 +771,6 @@
ciArrayKlass* expected_type;
arraycopy_helper(x, &flags, &expected_type);
- CodeEmitInfo* info = state_for(x, x->state());
__ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(),
length.result(), rlock_callee_saved(T_INT),
expected_type, flags, info);
@@ -878,6 +881,9 @@
void LIRGenerator::do_NewTypeArray(NewTypeArray* x) {
+ // Evaluate state_for early since it may emit code
+ CodeEmitInfo* info = state_for(x, x->state());
+
LIRItem length(x->length(), this);
length.load_item();
@@ -892,7 +898,6 @@
__ oop2reg(ciTypeArrayKlass::make(elem_type)->encoding(), klass_reg);
- CodeEmitInfo* info = state_for(x, x->state());
CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info);
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
@@ -902,7 +907,8 @@
void LIRGenerator::do_NewObjectArray(NewObjectArray* x) {
- LIRItem length(x->length(), this);
+ // Evaluate state_for early since it may emit code.
+ CodeEmitInfo* info = state_for(x, x->state());
// in case of patching (i.e., object class is not yet loaded), we need to reexecute the instruction
// and therefore provide the state before the parameters have been consumed
CodeEmitInfo* patching_info = NULL;
@@ -910,6 +916,7 @@
patching_info = state_for(x, x->state_before());
}
+ LIRItem length(x->length(), this);
length.load_item();
const LIR_Opr reg = result_register_for(x->type());
@@ -919,7 +926,6 @@
LIR_Opr tmp4 = FrameMap::O1_oop_opr;
LIR_Opr klass_reg = FrameMap::G5_oop_opr;
LIR_Opr len = length.result();
- CodeEmitInfo* info = state_for(x, x->state());
CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciObject* obj = (ciObject*) ciObjArrayKlass::make(x->klass());
@@ -943,25 +949,22 @@
items->at_put(i, size);
}
- // need to get the info before, as the items may become invalid through item_free
+ // Evaluate state_for early since it may emit code.
CodeEmitInfo* patching_info = NULL;
if (!x->klass()->is_loaded() || PatchALot) {
patching_info = state_for(x, x->state_before());
// cannot re-use same xhandlers for multiple CodeEmitInfos, so
- // clone all handlers
+ // clone all handlers. This is handled transparently in other
+ // places by the CodeEmitInfo cloning logic but is handled
+ // specially here because a stub isn't being used.
x->set_exception_handlers(new XHandlers(x->exception_handlers()));
}
+ CodeEmitInfo* info = state_for(x, x->state());
i = dims->length();
while (i-- > 0) {
LIRItem* size = items->at(i);
- // if a patching_info was generated above then debug information for the state before
- // the call is going to be emitted. The LIRGenerator calls above may have left some values
- // in registers and that's been recorded in the CodeEmitInfo. In that case the items
- // for those values can't simply be freed if they are registers because the values
- // might be destroyed by store_stack_parameter. So in the case of patching, delay the
- // freeing of the items that already were in registers
size->load_item();
store_stack_parameter (size->result(),
in_ByteSize(STACK_BIAS +
@@ -972,8 +975,6 @@
// This instruction can be deoptimized in the slow path : use
// O0 as result register.
const LIR_Opr reg = result_register_for(x->type());
- CodeEmitInfo* info = state_for(x, x->state());
-
jobject2reg_with_patching(reg, x->klass(), patching_info);
LIR_Opr rank = FrameMap::O1_opr;
__ move(LIR_OprFact::intConst(x->rank()), rank);
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1047,16 +1047,17 @@
items->at_put(i, size);
}
- // need to get the info before, as the items may become invalid through item_free
+ // Evaluate state_for early since it may emit code.
CodeEmitInfo* patching_info = NULL;
if (!x->klass()->is_loaded() || PatchALot) {
patching_info = state_for(x, x->state_before());
// cannot re-use same xhandlers for multiple CodeEmitInfos, so
- // clone all handlers.
+ // clone all handlers. This is handled transparently in other
+ // places by the CodeEmitInfo cloning logic but is handled
+ // specially here because a stub isn't being used.
x->set_exception_handlers(new XHandlers(x->exception_handlers()));
}
-
CodeEmitInfo* info = state_for(x, x->state());
i = dims->length();
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -2381,7 +2381,7 @@
// Save everything in sight.
- map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words);
+ map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false);
// Normal deoptimization
__ push(Deoptimization::Unpack_deopt);
__ jmp(cont);
@@ -2392,7 +2392,7 @@
// return address is the pc describes what bci to do re-execute at
// No need to update map as each call to save_live_registers will produce identical oopmap
- (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words);
+ (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false);
__ push(Deoptimization::Unpack_reexecute);
__ jmp(cont);
@@ -2428,7 +2428,7 @@
// Save everything in sight.
// No need to update map as each call to save_live_registers will produce identical oopmap
- (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words);
+ (void) RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false);
// Now it is safe to overwrite any register
@@ -2515,6 +2515,11 @@
RegisterSaver::restore_result_registers(masm);
+ // Non standard control word may be leaked out through a safepoint blob, and we can
+ // deopt at a poll point with the non standard control word. However, we should make
+ // sure the control word is correct after restore_result_registers.
+ __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
+
// All of the register save area has been popped of the stack. Only the
// return address remains.
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1229,13 +1229,10 @@
// Compiled java method case.
if (decode_offset != 0) {
- bool dummy_reexecute = false;
DebugInfoReadStream stream(nm, decode_offset);
decode_offset = stream.read_int();
method = (methodOop)nm->oop_at(stream.read_int());
- //fill_in_stack_trace does not need the reexecute information which is designed
- //for the deopt to reexecute
- bci = stream.read_bci_and_reexecute(dummy_reexecute);
+ bci = stream.read_bci();
} else {
if (fr.is_first_frame()) break;
address pc = fr.pc();
--- a/hotspot/src/share/vm/code/debugInfo.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/code/debugInfo.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -255,8 +255,7 @@
ScopeValue* read_object_value();
ScopeValue* get_cached_object();
// BCI encoding is mostly unsigned, but -1 is a distinguished value
- // Decoding based on encoding: bci = InvocationEntryBci + read_int()/2; reexecute = read_int()%2 == 1 ? true : false;
- int read_bci_and_reexecute(bool& reexecute) { int i = read_int(); reexecute = (i & 1) ? true : false; return (i >> 1) + InvocationEntryBci; }
+ int read_bci() { return read_int() + InvocationEntryBci; }
};
// DebugInfoWriteStream specializes CompressedWriteStream for
@@ -269,6 +268,5 @@
public:
DebugInfoWriteStream(DebugInformationRecorder* recorder, int initial_size);
void write_handle(jobject h);
- //Encoding bci and reexecute into one word as (bci - InvocationEntryBci)*2 + reexecute
- void write_bci_and_reexecute(int bci, bool reexecute) { write_int(((bci - InvocationEntryBci) << 1) + (reexecute ? 1 : 0)); }
+ void write_bci(int bci) { write_int(bci - InvocationEntryBci); }
};
--- a/hotspot/src/share/vm/code/debugInfoRec.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/code/debugInfoRec.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-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
@@ -292,13 +292,16 @@
int stream_offset = stream()->position();
last_pd->set_scope_decode_offset(stream_offset);
+ // Record reexecute bit into pcDesc
+ last_pd->set_should_reexecute(reexecute);
+
// serialize sender stream offest
stream()->write_int(sender_stream_offset);
// serialize scope
jobject method_enc = (method == NULL)? NULL: method->encoding();
stream()->write_int(oop_recorder()->find_index(method_enc));
- stream()->write_bci_and_reexecute(bci, reexecute);
+ stream()->write_bci(bci);
assert(method == NULL ||
(method->is_native() && bci == 0) ||
(!method->is_native() && 0 <= bci && bci < method->code_size()) ||
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -966,7 +966,7 @@
PcDesc* pd = pc_desc_at(pc);
guarantee(pd != NULL, "scope must be present");
return new ScopeDesc(this, pd->scope_decode_offset(),
- pd->obj_decode_offset());
+ pd->obj_decode_offset(), pd->should_reexecute());
}
@@ -1932,7 +1932,7 @@
PcDesc* pd = pc_desc_at(ic->end_of_call());
assert(pd != NULL, "PcDesc must exist");
for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
- pd->obj_decode_offset());
+ pd->obj_decode_offset(), pd->should_reexecute());
!sd->is_top(); sd = sd->sender()) {
sd->verify();
}
@@ -2181,7 +2181,7 @@
PcDesc* p = pc_desc_near(begin+1);
if (p != NULL && p->real_pc(this) <= end) {
return new ScopeDesc(this, p->scope_decode_offset(),
- p->obj_decode_offset());
+ p->obj_decode_offset(), p->should_reexecute());
}
return NULL;
}
--- a/hotspot/src/share/vm/code/pcDesc.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/code/pcDesc.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -26,9 +26,11 @@
# include "incls/_pcDesc.cpp.incl"
PcDesc::PcDesc(int pc_offset, int scope_decode_offset, int obj_decode_offset) {
+ assert(sizeof(PcDescFlags) <= 4, "occupies more than a word");
_pc_offset = pc_offset;
_scope_decode_offset = scope_decode_offset;
_obj_decode_offset = obj_decode_offset;
+ _flags.word = 0;
}
address PcDesc::real_pc(const nmethod* code) const {
@@ -50,6 +52,7 @@
tty->print(" ");
sd->method()->print_short_name(tty);
tty->print(" @%d", sd->bci());
+ tty->print(" reexecute=%s", sd->should_reexecute()?"true":"false");
tty->cr();
}
#endif
--- a/hotspot/src/share/vm/code/pcDesc.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/code/pcDesc.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -34,6 +34,13 @@
int _scope_decode_offset; // offset for scope in nmethod
int _obj_decode_offset;
+ union PcDescFlags {
+ int word;
+ struct {
+ unsigned int reexecute: 1;
+ } bits;
+ } _flags;
+
public:
int pc_offset() const { return _pc_offset; }
int scope_decode_offset() const { return _scope_decode_offset; }
@@ -53,6 +60,10 @@
upper_offset_limit = (unsigned int)-1 >> 1
};
+ // Flags
+ bool should_reexecute() const { return _flags.bits.reexecute; }
+ void set_should_reexecute(bool z) { _flags.bits.reexecute = z; }
+
// Returns the real pc
address real_pc(const nmethod* code) const;
--- a/hotspot/src/share/vm/code/scopeDesc.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/code/scopeDesc.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -26,17 +26,19 @@
# include "incls/_scopeDesc.cpp.incl"
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute) {
_code = code;
_decode_offset = decode_offset;
_objects = decode_object_values(obj_decode_offset);
+ _reexecute = reexecute;
decode_body();
}
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute) {
_code = code;
_decode_offset = decode_offset;
_objects = decode_object_values(DebugInformationRecorder::serialized_null);
+ _reexecute = reexecute;
decode_body();
}
@@ -45,8 +47,8 @@
_code = parent->_code;
_decode_offset = parent->_sender_decode_offset;
_objects = parent->_objects;
+ _reexecute = false; //reexecute only applies to the first scope
decode_body();
- assert(_reexecute == false, "reexecute not allowed");
}
@@ -57,7 +59,6 @@
_sender_decode_offset = DebugInformationRecorder::serialized_null;
_method = methodHandle(_code->method());
_bci = InvocationEntryBci;
- _reexecute = false;
_locals_decode_offset = DebugInformationRecorder::serialized_null;
_expressions_decode_offset = DebugInformationRecorder::serialized_null;
_monitors_decode_offset = DebugInformationRecorder::serialized_null;
@@ -67,7 +68,7 @@
_sender_decode_offset = stream->read_int();
_method = methodHandle((methodOop) stream->read_oop());
- _bci = stream->read_bci_and_reexecute(_reexecute);
+ _bci = stream->read_bci();
// decode offsets for body and sender
_locals_decode_offset = stream->read_int();
--- a/hotspot/src/share/vm/code/scopeDesc.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/code/scopeDesc.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -39,8 +39,7 @@
DebugInfoReadStream buffer(code, pc_desc->scope_decode_offset());
int ignore_sender = buffer.read_int();
_method = methodOop(buffer.read_oop());
- bool dummy_reexecute; //only methodOop and bci are needed!
- _bci = buffer.read_bci_and_reexecute(dummy_reexecute);
+ _bci = buffer.read_bci();
}
methodOop method() { return _method; }
@@ -53,12 +52,12 @@
class ScopeDesc : public ResourceObj {
public:
// Constructor
- ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset);
+ ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute);
// Calls above, giving default value of "serialized_null" to the
// "obj_decode_offset" argument. (We don't use a default argument to
// avoid a .hpp-.hpp dependency.)
- ScopeDesc(const nmethod* code, int decode_offset);
+ ScopeDesc(const nmethod* code, int decode_offset, bool reexecute);
// JVM state
methodHandle method() const { return _method; }
--- a/hotspot/src/share/vm/includeDB_compiler1 Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_compiler1 Tue Aug 25 13:08:40 2009 -0700
@@ -409,8 +409,6 @@
compileBroker.cpp c1_Compiler.hpp
-frame.hpp c1_Defs.hpp
-
frame_<arch>.cpp c1_Runtime1.hpp
globals.cpp c1_globals.hpp
@@ -433,8 +431,6 @@
os_<os_arch>.cpp c1_Runtime1.hpp
-registerMap.hpp c1_Defs.hpp
-
safepoint.cpp c1_globals.hpp
sharedRuntime.cpp c1_Runtime1.hpp
--- a/hotspot/src/share/vm/memory/universe.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -749,7 +749,10 @@
assert(mode == UnscaledNarrowOop ||
mode == ZeroBasedNarrowOop ||
mode == HeapBasedNarrowOop, "mode is invalid");
-
+ // Return specified base for the first request.
+ if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
+ return (char*)HeapBaseMinAddress;
+ }
const size_t total_size = heap_size + HeapBaseMinAddress;
if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) {
if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) &&
@@ -857,7 +860,7 @@
// Can't reserve heap below 4Gb.
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
} else {
- assert(Universe::narrow_oop_shift() == 0, "use unscaled narrow oop");
+ Universe::set_narrow_oop_shift(0);
if (PrintCompressedOopsMode) {
tty->print(", 32-bits Oops");
}
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -376,7 +376,7 @@
product(intx, AutoBoxCacheMax, 128, \
"Sets max value cached by the java.lang.Integer autobox cache") \
\
- product(bool, DoEscapeAnalysis, false, \
+ product(bool, DoEscapeAnalysis, true, \
"Perform escape analysis") \
\
notproduct(bool, PrintEscapeAnalysis, false, \
--- a/hotspot/src/share/vm/opto/callnode.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -493,7 +493,8 @@
if (!printed)
_method->print_short_name(st);
st->print(" @ bci:%d",_bci);
- st->print(" reexecute:%s", _reexecute==Reexecute_True?"true":"false");
+ if(_reexecute == Reexecute_True)
+ st->print(" reexecute");
} else {
st->print(" runtime stub");
}
--- a/hotspot/src/share/vm/opto/chaitin.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -458,6 +458,16 @@
// Post-Allocation peephole copy removal
void post_allocate_copy_removal();
Node *skip_copies( Node *c );
+ // Replace the old node with the current live version of that value
+ // and yank the old value if it's dead.
+ int replace_and_yank_if_dead( Node *old, OptoReg::Name nreg,
+ Block *current_block, Node_List& value, Node_List& regnd ) {
+ Node* v = regnd[nreg];
+ assert(v->outcnt() != 0, "no dead values");
+ old->replace_by(v);
+ return yank_if_dead(old, current_block, &value, ®nd);
+ }
+
int yank_if_dead( Node *old, Block *current_block, Node_List *value, Node_List *regnd );
int elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List ®nd, bool can_change_regs );
int use_prior_register( Node *copy, uint idx, Node *def, Block *current_block, Node_List &value, Node_List ®nd );
--- a/hotspot/src/share/vm/opto/compile.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1545,7 +1545,7 @@
if((loop_opts_cnt > 0) && (has_loops() || has_split_ifs())) {
{
TracePhase t2("idealLoop", &_t_idealLoop, true);
- PhaseIdealLoop ideal_loop( igvn, NULL, true );
+ PhaseIdealLoop ideal_loop( igvn, true );
loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop 1", 2);
if (failing()) return;
@@ -1553,7 +1553,7 @@
// Loop opts pass if partial peeling occurred in previous pass
if(PartialPeelLoop && major_progress() && (loop_opts_cnt > 0)) {
TracePhase t3("idealLoop", &_t_idealLoop, true);
- PhaseIdealLoop ideal_loop( igvn, NULL, false );
+ PhaseIdealLoop ideal_loop( igvn, false );
loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop 2", 2);
if (failing()) return;
@@ -1561,10 +1561,15 @@
// Loop opts pass for loop-unrolling before CCP
if(major_progress() && (loop_opts_cnt > 0)) {
TracePhase t4("idealLoop", &_t_idealLoop, true);
- PhaseIdealLoop ideal_loop( igvn, NULL, false );
+ PhaseIdealLoop ideal_loop( igvn, false );
loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop 3", 2);
}
+ if (!failing()) {
+ // Verify that last round of loop opts produced a valid graph
+ NOT_PRODUCT( TracePhase t2("idealLoopVerify", &_t_idealLoopVerify, TimeCompiler); )
+ PhaseIdealLoop::verify(igvn);
+ }
}
if (failing()) return;
@@ -1597,12 +1602,20 @@
while(major_progress() && (loop_opts_cnt > 0)) {
TracePhase t2("idealLoop", &_t_idealLoop, true);
assert( cnt++ < 40, "infinite cycle in loop optimization" );
- PhaseIdealLoop ideal_loop( igvn, NULL, true );
+ PhaseIdealLoop ideal_loop( igvn, true );
loop_opts_cnt--;
if (major_progress()) print_method("PhaseIdealLoop iterations", 2);
if (failing()) return;
}
}
+
+ {
+ // Verify that all previous optimizations produced a valid graph
+ // at least to this point, even if no loop optimizations were done.
+ NOT_PRODUCT( TracePhase t2("idealLoopVerify", &_t_idealLoopVerify, TimeCompiler); )
+ PhaseIdealLoop::verify(igvn);
+ }
+
{
NOT_PRODUCT( TracePhase t2("macroExpand", &_t_macroExpand, TimeCompiler); )
PhaseMacroExpand mex(igvn);
@@ -2520,7 +2533,7 @@
// If original bytecodes contained a mixture of floats and doubles
// check if the optimizer has made it homogenous, item (3).
- if( Use24BitFPMode && Use24BitFP &&
+ if( Use24BitFPMode && Use24BitFP && UseSSE == 0 &&
frc.get_float_count() > 32 &&
frc.get_double_count() == 0 &&
(10 * frc.get_call_count() < frc.get_float_count()) ) {
--- a/hotspot/src/share/vm/opto/domgraph.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/domgraph.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -396,7 +396,7 @@
// nodes (using the is_CFG() call) and places them in a dominator tree. Thus,
// it needs a count of the CFG nodes for the mapping table. This is the
// Lengauer & Tarjan O(E-alpha(E,V)) algorithm.
-void PhaseIdealLoop::Dominators( ) {
+void PhaseIdealLoop::Dominators() {
ResourceMark rm;
// Setup mappings from my Graph to Tarjan's stuff and back
// Note: Tarjan uses 1-based arrays
@@ -454,7 +454,7 @@
// flow into the main graph (and hence into ROOT) but are not reachable
// from above. Such code is dead, but requires a global pass to detect
// it; this global pass was the 'build_loop_tree' pass run just prior.
- if( whead->is_Region() ) {
+ if( !_verify_only && whead->is_Region() ) {
for( uint i = 1; i < whead->req(); i++ ) {
if (!has_node(whead->in(i))) {
// Kill dead input path
--- a/hotspot/src/share/vm/opto/loopnode.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1420,13 +1420,12 @@
}
//=============================================================================
-//------------------------------PhaseIdealLoop---------------------------------
+//----------------------------build_and_optimize-------------------------------
// Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to
// its corresponding LoopNode. If 'optimize' is true, do some loop cleanups.
-PhaseIdealLoop::PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me, bool do_split_ifs )
- : PhaseTransform(Ideal_Loop),
- _igvn(igvn),
- _dom_lca_tags(C->comp_arena()) {
+void PhaseIdealLoop::build_and_optimize(bool do_split_ifs) {
+ int old_progress = C->major_progress();
+
// Reset major-progress flag for the driver's heuristics
C->clear_major_progress();
@@ -1465,18 +1464,20 @@
}
// No loops after all
- if( !_ltree_root->_child ) C->set_has_loops(false);
+ if( !_ltree_root->_child && !_verify_only ) C->set_has_loops(false);
// There should always be an outer loop containing the Root and Return nodes.
// If not, we have a degenerate empty program. Bail out in this case.
if (!has_node(C->root())) {
- C->clear_major_progress();
- C->record_method_not_compilable("empty program detected during loop optimization");
+ if (!_verify_only) {
+ C->clear_major_progress();
+ C->record_method_not_compilable("empty program detected during loop optimization");
+ }
return;
}
// Nothing to do, so get out
- if( !C->has_loops() && !do_split_ifs && !verify_me) {
+ if( !C->has_loops() && !do_split_ifs && !_verify_me && !_verify_only ) {
_igvn.optimize(); // Cleanup NeverBranches
return;
}
@@ -1486,7 +1487,7 @@
// Split shared headers and insert loop landing pads.
// Do not bother doing this on the Root loop of course.
- if( !verify_me && _ltree_root->_child ) {
+ if( !_verify_me && !_verify_only && _ltree_root->_child ) {
if( _ltree_root->_child->beautify_loops( this ) ) {
// Re-build loop tree!
_ltree_root->_child = NULL;
@@ -1515,24 +1516,26 @@
Dominators();
- // As a side effect, Dominators removed any unreachable CFG paths
- // into RegionNodes. It doesn't do this test against Root, so
- // we do it here.
- for( uint i = 1; i < C->root()->req(); i++ ) {
- if( !_nodes[C->root()->in(i)->_idx] ) { // Dead path into Root?
- _igvn.hash_delete(C->root());
- C->root()->del_req(i);
- _igvn._worklist.push(C->root());
- i--; // Rerun same iteration on compressed edges
+ if (!_verify_only) {
+ // As a side effect, Dominators removed any unreachable CFG paths
+ // into RegionNodes. It doesn't do this test against Root, so
+ // we do it here.
+ for( uint i = 1; i < C->root()->req(); i++ ) {
+ if( !_nodes[C->root()->in(i)->_idx] ) { // Dead path into Root?
+ _igvn.hash_delete(C->root());
+ C->root()->del_req(i);
+ _igvn._worklist.push(C->root());
+ i--; // Rerun same iteration on compressed edges
+ }
}
+
+ // Given dominators, try to find inner loops with calls that must
+ // always be executed (call dominates loop tail). These loops do
+ // not need a separate safepoint.
+ Node_List cisstack(a);
+ _ltree_root->check_safepts(visited, cisstack);
}
- // Given dominators, try to find inner loops with calls that must
- // always be executed (call dominates loop tail). These loops do
- // not need a separate safepoint.
- Node_List cisstack(a);
- _ltree_root->check_safepts(visited, cisstack);
-
// Walk the DATA nodes and place into loops. Find earliest control
// node. For CFG nodes, the _nodes array starts out and remains
// holding the associated IdealLoopTree pointer. For DATA nodes, the
@@ -1548,11 +1551,11 @@
// it will be processed among C->top() inputs
worklist.push( C->top() );
visited.set( C->top()->_idx ); // Set C->top() as visited now
- build_loop_early( visited, worklist, nstack, verify_me );
+ build_loop_early( visited, worklist, nstack );
// Given early legal placement, try finding counted loops. This placement
// is good enough to discover most loop invariants.
- if( !verify_me )
+ if( !_verify_me && !_verify_only )
_ltree_root->counted_loop( this );
// Find latest loop placement. Find ideal loop placement.
@@ -1562,16 +1565,25 @@
worklist.push( C->root() );
NOT_PRODUCT( C->verify_graph_edges(); )
worklist.push( C->top() );
- build_loop_late( visited, worklist, nstack, verify_me );
+ build_loop_late( visited, worklist, nstack );
+
+ if (_verify_only) {
+ // restore major progress flag
+ for (int i = 0; i < old_progress; i++)
+ C->set_major_progress();
+ assert(C->unique() == unique, "verification mode made Nodes? ? ?");
+ assert(_igvn._worklist.size() == 0, "shouldn't push anything");
+ return;
+ }
// clear out the dead code
while(_deadlist.size()) {
- igvn.remove_globally_dead_node(_deadlist.pop());
+ _igvn.remove_globally_dead_node(_deadlist.pop());
}
#ifndef PRODUCT
C->verify_graph_edges();
- if( verify_me ) { // Nested verify pass?
+ if( _verify_me ) { // Nested verify pass?
// Check to see if the verify mode is broken
assert(C->unique() == unique, "non-optimize mode made Nodes? ? ?");
return;
@@ -1678,7 +1690,7 @@
void PhaseIdealLoop::verify() const {
int old_progress = C->major_progress();
ResourceMark rm;
- PhaseIdealLoop loop_verify( _igvn, this, false );
+ PhaseIdealLoop loop_verify( _igvn, this );
VectorSet visited(Thread::current()->resource_area());
fail = 0;
@@ -2138,54 +2150,58 @@
// optimizing an infinite loop?
l = _ltree_root; // Oops, found infinite loop
- // Insert the NeverBranch between 'm' and it's control user.
- NeverBranchNode *iff = new (C, 1) NeverBranchNode( m );
- _igvn.register_new_node_with_optimizer(iff);
- set_loop(iff, l);
- Node *if_t = new (C, 1) CProjNode( iff, 0 );
- _igvn.register_new_node_with_optimizer(if_t);
- set_loop(if_t, l);
+ if (!_verify_only) {
+ // Insert the NeverBranch between 'm' and it's control user.
+ NeverBranchNode *iff = new (C, 1) NeverBranchNode( m );
+ _igvn.register_new_node_with_optimizer(iff);
+ set_loop(iff, l);
+ Node *if_t = new (C, 1) CProjNode( iff, 0 );
+ _igvn.register_new_node_with_optimizer(if_t);
+ set_loop(if_t, l);
- Node* cfg = NULL; // Find the One True Control User of m
- for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
- Node* x = m->fast_out(j);
- if (x->is_CFG() && x != m && x != iff)
- { cfg = x; break; }
+ Node* cfg = NULL; // Find the One True Control User of m
+ for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
+ Node* x = m->fast_out(j);
+ if (x->is_CFG() && x != m && x != iff)
+ { cfg = x; break; }
+ }
+ assert(cfg != NULL, "must find the control user of m");
+ uint k = 0; // Probably cfg->in(0)
+ while( cfg->in(k) != m ) k++; // But check incase cfg is a Region
+ cfg->set_req( k, if_t ); // Now point to NeverBranch
+
+ // Now create the never-taken loop exit
+ Node *if_f = new (C, 1) CProjNode( iff, 1 );
+ _igvn.register_new_node_with_optimizer(if_f);
+ set_loop(if_f, l);
+ // Find frame ptr for Halt. Relies on the optimizer
+ // V-N'ing. Easier and quicker than searching through
+ // the program structure.
+ Node *frame = new (C, 1) ParmNode( C->start(), TypeFunc::FramePtr );
+ _igvn.register_new_node_with_optimizer(frame);
+ // Halt & Catch Fire
+ Node *halt = new (C, TypeFunc::Parms) HaltNode( if_f, frame );
+ _igvn.register_new_node_with_optimizer(halt);
+ set_loop(halt, l);
+ C->root()->add_req(halt);
}
- assert(cfg != NULL, "must find the control user of m");
- uint k = 0; // Probably cfg->in(0)
- while( cfg->in(k) != m ) k++; // But check incase cfg is a Region
- cfg->set_req( k, if_t ); // Now point to NeverBranch
-
- // Now create the never-taken loop exit
- Node *if_f = new (C, 1) CProjNode( iff, 1 );
- _igvn.register_new_node_with_optimizer(if_f);
- set_loop(if_f, l);
- // Find frame ptr for Halt. Relies on the optimizer
- // V-N'ing. Easier and quicker than searching through
- // the program structure.
- Node *frame = new (C, 1) ParmNode( C->start(), TypeFunc::FramePtr );
- _igvn.register_new_node_with_optimizer(frame);
- // Halt & Catch Fire
- Node *halt = new (C, TypeFunc::Parms) HaltNode( if_f, frame );
- _igvn.register_new_node_with_optimizer(halt);
- set_loop(halt, l);
- C->root()->add_req(halt);
set_loop(C->root(), _ltree_root);
}
}
// Weeny check for irreducible. This child was already visited (this
// IS the post-work phase). Is this child's loop header post-visited
// as well? If so, then I found another entry into the loop.
- while( is_postvisited(l->_head) ) {
- // found irreducible
- l->_irreducible = 1; // = true
- l = l->_parent;
- _has_irreducible_loops = true;
- // Check for bad CFG here to prevent crash, and bailout of compile
- if (l == NULL) {
- C->record_method_not_compilable("unhandled CFG detected during loop optimization");
- return pre_order;
+ if (!_verify_only) {
+ while( is_postvisited(l->_head) ) {
+ // found irreducible
+ l->_irreducible = 1; // = true
+ l = l->_parent;
+ _has_irreducible_loops = true;
+ // Check for bad CFG here to prevent crash, and bailout of compile
+ if (l == NULL) {
+ C->record_method_not_compilable("unhandled CFG detected during loop optimization");
+ return pre_order;
+ }
}
}
@@ -2253,7 +2269,7 @@
// Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping.
// First pass computes the earliest controlling node possible. This is the
// controlling input with the deepest dominating depth.
-void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me ) {
+void PhaseIdealLoop::build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ) {
while (worklist.size() != 0) {
// Use local variables nstack_top_n & nstack_top_i to cache values
// on nstack's top.
@@ -2285,7 +2301,7 @@
// (the old code here would yank a 2nd safepoint after seeing a
// first one, even though the 1st did not dominate in the loop body
// and thus could be avoided indefinitely)
- if( !verify_me && ilt->_has_sfpt && n->Opcode() == Op_SafePoint &&
+ if( !_verify_only && !_verify_me && ilt->_has_sfpt && n->Opcode() == Op_SafePoint &&
is_deleteable_safept(n)) {
Node *in = n->in(TypeFunc::Control);
lazy_replace(n,in); // Pull safepoint now
@@ -2408,12 +2424,31 @@
return LCA;
}
-//------------------------------get_late_ctrl----------------------------------
-// Compute latest legal control.
-Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) {
- assert(early != NULL, "early control should not be NULL");
+bool PhaseIdealLoop::verify_dominance(Node* n, Node* use, Node* LCA, Node* early) {
+ bool had_error = false;
+#ifdef ASSERT
+ if (early != C->root()) {
+ // Make sure that there's a dominance path from use to LCA
+ Node* d = use;
+ while (d != LCA) {
+ d = idom(d);
+ if (d == C->root()) {
+ tty->print_cr("*** Use %d isn't dominated by def %s", use->_idx, n->_idx);
+ n->dump();
+ use->dump();
+ had_error = true;
+ break;
+ }
+ }
+ }
+#endif
+ return had_error;
+}
+
+Node* PhaseIdealLoop::compute_lca_of_uses(Node* n, Node* early, bool verify) {
// Compute LCA over list of uses
+ bool had_error = false;
Node *LCA = NULL;
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax && LCA != early; i++) {
Node* c = n->fast_out(i);
@@ -2423,15 +2458,34 @@
for( uint j=1; j<c->req(); j++ ) {// For all inputs
if( c->in(j) == n ) { // Found matching input?
Node *use = c->in(0)->in(j);
+ if (_verify_only && use->is_top()) continue;
LCA = dom_lca_for_get_late_ctrl( LCA, use, n );
+ if (verify) had_error = verify_dominance(n, use, LCA, early) || had_error;
}
}
} else {
// For CFG data-users, use is in the block just prior
Node *use = has_ctrl(c) ? get_ctrl(c) : c->in(0);
LCA = dom_lca_for_get_late_ctrl( LCA, use, n );
+ if (verify) had_error = verify_dominance(n, use, LCA, early) || had_error;
}
}
+ assert(!had_error, "bad dominance");
+ return LCA;
+}
+
+//------------------------------get_late_ctrl----------------------------------
+// Compute latest legal control.
+Node *PhaseIdealLoop::get_late_ctrl( Node *n, Node *early ) {
+ assert(early != NULL, "early control should not be NULL");
+
+ Node* LCA = compute_lca_of_uses(n, early);
+#ifdef ASSERT
+ if (LCA == C->root() && LCA != early) {
+ // def doesn't dominate uses so print some useful debugging output
+ compute_lca_of_uses(n, early, true);
+ }
+#endif
// if this is a load, check for anti-dependent stores
// We use a conservative algorithm to identify potential interfering
@@ -2576,7 +2630,7 @@
//------------------------------build_loop_late--------------------------------
// Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping.
// Second pass finds latest legal placement, and ideal loop placement.
-void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me ) {
+void PhaseIdealLoop::build_loop_late( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ) {
while (worklist.size() != 0) {
Node *n = worklist.pop();
// Only visit once
@@ -2612,7 +2666,7 @@
}
} else {
// All of n's children have been processed, complete post-processing.
- build_loop_late_post(n, verify_me);
+ build_loop_late_post(n);
if (nstack.is_empty()) {
// Finished all nodes on stack.
// Process next node on the worklist.
@@ -2631,9 +2685,9 @@
//------------------------------build_loop_late_post---------------------------
// Put Data nodes into some loop nest, by setting the _nodes[]->loop mapping.
// Second pass finds latest legal placement, and ideal loop placement.
-void PhaseIdealLoop::build_loop_late_post( Node *n, const PhaseIdealLoop *verify_me ) {
+void PhaseIdealLoop::build_loop_late_post( Node *n ) {
- if (n->req() == 2 && n->Opcode() == Op_ConvI2L && !C->major_progress()) {
+ if (n->req() == 2 && n->Opcode() == Op_ConvI2L && !C->major_progress() && !_verify_only) {
_igvn._worklist.push(n); // Maybe we'll normalize it, if no more loops.
}
@@ -2714,6 +2768,7 @@
if( get_loop(legal)->_nest < get_loop(least)->_nest )
least = legal;
}
+ assert(early == legal || legal != C->root(), "bad dominance of inputs");
// Try not to place code on a loop entry projection
// which can inhibit range check elimination.
@@ -2731,8 +2786,8 @@
#ifdef ASSERT
// If verifying, verify that 'verify_me' has a legal location
// and choose it as our location.
- if( verify_me ) {
- Node *v_ctrl = verify_me->get_ctrl_no_update(n);
+ if( _verify_me ) {
+ Node *v_ctrl = _verify_me->get_ctrl_no_update(n);
Node *legal = LCA;
while( early != legal ) { // While not at earliest legal
if( legal == v_ctrl ) break; // Check for prior good location
--- a/hotspot/src/share/vm/opto/loopnode.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-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
@@ -442,6 +442,9 @@
uint *_preorders;
uint _max_preorder;
+ const PhaseIdealLoop* _verify_me;
+ bool _verify_only;
+
// Allocate _preorders[] array
void allocate_preorders() {
_max_preorder = C->unique()+8;
@@ -497,6 +500,12 @@
Node_Array _dom_lca_tags;
void init_dom_lca_tags();
void clear_dom_lca_tags();
+
+ // Helper for debugging bad dominance relationships
+ bool verify_dominance(Node* n, Node* use, Node* LCA, Node* early);
+
+ Node* compute_lca_of_uses(Node* n, Node* early, bool verify = false);
+
// Inline wrapper for frequent cases:
// 1) only one use
// 2) a use is the same as the current LCA passed as 'n1'
@@ -511,6 +520,7 @@
return find_non_split_ctrl(n);
}
Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag );
+
// true if CFG node d dominates CFG node n
bool is_dominator(Node *d, Node *n);
@@ -621,9 +631,9 @@
IdealLoopTree *sort( IdealLoopTree *loop, IdealLoopTree *innermost );
// Place Data nodes in some loop nest
- void build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me );
- void build_loop_late ( VectorSet &visited, Node_List &worklist, Node_Stack &nstack, const PhaseIdealLoop *verify_me );
- void build_loop_late_post ( Node* n, const PhaseIdealLoop *verify_me );
+ void build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack );
+ void build_loop_late ( VectorSet &visited, Node_List &worklist, Node_Stack &nstack );
+ void build_loop_late_post ( Node* n );
// Array of immediate dominance info for each CFG node indexed by node idx
private:
@@ -662,6 +672,19 @@
// Is safept not required by an outer loop?
bool is_deleteable_safept(Node* sfpt);
+ // Perform verification that the graph is valid.
+ PhaseIdealLoop( PhaseIterGVN &igvn) :
+ PhaseTransform(Ideal_Loop),
+ _igvn(igvn),
+ _dom_lca_tags(C->comp_arena()),
+ _verify_me(NULL),
+ _verify_only(true) {
+ build_and_optimize(false);
+ }
+
+ // build the loop tree and perform any requested optimizations
+ void build_and_optimize(bool do_split_if);
+
public:
// Dominators for the sea of nodes
void Dominators();
@@ -671,7 +694,32 @@
Node *dom_lca_internal( Node *n1, Node *n2 ) const;
// Compute the Ideal Node to Loop mapping
- PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me, bool do_split_ifs );
+ PhaseIdealLoop( PhaseIterGVN &igvn, bool do_split_ifs) :
+ PhaseTransform(Ideal_Loop),
+ _igvn(igvn),
+ _dom_lca_tags(C->comp_arena()),
+ _verify_me(NULL),
+ _verify_only(false) {
+ build_and_optimize(do_split_ifs);
+ }
+
+ // Verify that verify_me made the same decisions as a fresh run.
+ PhaseIdealLoop( PhaseIterGVN &igvn, const PhaseIdealLoop *verify_me) :
+ PhaseTransform(Ideal_Loop),
+ _igvn(igvn),
+ _dom_lca_tags(C->comp_arena()),
+ _verify_me(verify_me),
+ _verify_only(false) {
+ build_and_optimize(false);
+ }
+
+ // Build and verify the loop tree without modifying the graph. This
+ // is useful to verify that all inputs properly dominate their uses.
+ static void verify(PhaseIterGVN& igvn) {
+#ifdef ASSERT
+ PhaseIdealLoop v(igvn);
+#endif
+ }
// True if the method has at least 1 irreducible loop
bool _has_irreducible_loops;
--- a/hotspot/src/share/vm/opto/phase.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/phase.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -53,6 +53,7 @@
elapsedTimer Phase::_t_registerMethod;
elapsedTimer Phase::_t_temporaryTimer1;
elapsedTimer Phase::_t_temporaryTimer2;
+elapsedTimer Phase::_t_idealLoopVerify;
// Subtimers for _t_optimizer
elapsedTimer Phase::_t_iterGVN;
@@ -88,51 +89,52 @@
tty->print_cr ("Accumulated compiler times:");
tty->print_cr ("---------------------------");
tty->print_cr (" Total compilation: %3.3f sec.", Phase::_t_totalCompilation.seconds());
- tty->print (" method compilation : %3.3f sec", Phase::_t_methodCompilation.seconds());
+ tty->print (" method compilation : %3.3f sec", Phase::_t_methodCompilation.seconds());
tty->print ("/%d bytes",_total_bytes_compiled);
tty->print_cr (" (%3.0f bytes per sec) ", Phase::_total_bytes_compiled / Phase::_t_methodCompilation.seconds());
- tty->print_cr (" stub compilation : %3.3f sec.", Phase::_t_stubCompilation.seconds());
+ tty->print_cr (" stub compilation : %3.3f sec.", Phase::_t_stubCompilation.seconds());
tty->print_cr (" Phases:");
- tty->print_cr (" parse : %3.3f sec", Phase::_t_parser.seconds());
+ tty->print_cr (" parse : %3.3f sec", Phase::_t_parser.seconds());
if (DoEscapeAnalysis) {
- tty->print_cr (" escape analysis : %3.3f sec", Phase::_t_escapeAnalysis.seconds());
+ tty->print_cr (" escape analysis : %3.3f sec", Phase::_t_escapeAnalysis.seconds());
}
- tty->print_cr (" optimizer : %3.3f sec", Phase::_t_optimizer.seconds());
+ tty->print_cr (" optimizer : %3.3f sec", Phase::_t_optimizer.seconds());
if( Verbose || WizardMode ) {
- tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds());
- tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds());
- tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds());
- tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds());
- tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds());
+ tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds());
+ tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds());
+ tty->print_cr (" idealLoopVerify: %3.3f sec", Phase::_t_idealLoopVerify.seconds());
+ tty->print_cr (" ccp : %3.3f sec", Phase::_t_ccp.seconds());
+ tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds());
+ tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds());
double optimizer_subtotal = Phase::_t_iterGVN.seconds() +
Phase::_t_idealLoop.seconds() + Phase::_t_ccp.seconds() +
Phase::_t_graphReshaping.seconds();
double percent_of_optimizer = ((optimizer_subtotal == 0.0) ? 0.0 : (optimizer_subtotal / Phase::_t_optimizer.seconds() * 100.0));
- tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", optimizer_subtotal, percent_of_optimizer);
+ tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", optimizer_subtotal, percent_of_optimizer);
}
- tty->print_cr (" matcher : %3.3f sec", Phase::_t_matcher.seconds());
- tty->print_cr (" scheduler : %3.3f sec", Phase::_t_scheduler.seconds());
- tty->print_cr (" regalloc : %3.3f sec", Phase::_t_registerAllocation.seconds());
+ tty->print_cr (" matcher : %3.3f sec", Phase::_t_matcher.seconds());
+ tty->print_cr (" scheduler : %3.3f sec", Phase::_t_scheduler.seconds());
+ tty->print_cr (" regalloc : %3.3f sec", Phase::_t_registerAllocation.seconds());
if( Verbose || WizardMode ) {
- tty->print_cr (" ctorChaitin : %3.3f sec", Phase::_t_ctorChaitin.seconds());
- tty->print_cr (" buildIFG : %3.3f sec", Phase::_t_buildIFGphysical.seconds());
- tty->print_cr (" computeLive : %3.3f sec", Phase::_t_computeLive.seconds());
- tty->print_cr (" regAllocSplit: %3.3f sec", Phase::_t_regAllocSplit.seconds());
+ tty->print_cr (" ctorChaitin : %3.3f sec", Phase::_t_ctorChaitin.seconds());
+ tty->print_cr (" buildIFG : %3.3f sec", Phase::_t_buildIFGphysical.seconds());
+ tty->print_cr (" computeLive : %3.3f sec", Phase::_t_computeLive.seconds());
+ tty->print_cr (" regAllocSplit : %3.3f sec", Phase::_t_regAllocSplit.seconds());
tty->print_cr (" postAllocCopyRemoval: %3.3f sec", Phase::_t_postAllocCopyRemoval.seconds());
- tty->print_cr (" fixupSpills : %3.3f sec", Phase::_t_fixupSpills.seconds());
+ tty->print_cr (" fixupSpills : %3.3f sec", Phase::_t_fixupSpills.seconds());
double regalloc_subtotal = Phase::_t_ctorChaitin.seconds() +
Phase::_t_buildIFGphysical.seconds() + Phase::_t_computeLive.seconds() +
Phase::_t_regAllocSplit.seconds() + Phase::_t_fixupSpills.seconds() +
Phase::_t_postAllocCopyRemoval.seconds();
double percent_of_regalloc = ((regalloc_subtotal == 0.0) ? 0.0 : (regalloc_subtotal / Phase::_t_registerAllocation.seconds() * 100.0));
- tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc);
+ tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc);
}
- tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
- tty->print_cr (" blockOrdering: %3.3f sec", Phase::_t_blockOrdering.seconds());
- tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds());
- tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds());
- tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds());
- tty->print_cr (" ------------ : ----------");
+ tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
+ tty->print_cr (" blockOrdering : %3.3f sec", Phase::_t_blockOrdering.seconds());
+ tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds());
+ tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds());
+ tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds());
+ tty->print_cr (" -------------- : ----------");
double phase_subtotal = Phase::_t_parser.seconds() +
(DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) +
Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() +
@@ -143,7 +145,7 @@
double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0;
// counters inside Compile::CodeGen include time for adapters and stubs
// so phase-total can be greater than 100%
- tty->print_cr (" total : %3.3f sec, %3.2f %%", phase_subtotal, percent_of_method_compile);
+ tty->print_cr (" total : %3.3f sec, %3.2f %%", phase_subtotal, percent_of_method_compile);
assert( percent_of_method_compile > expected_method_compile_coverage ||
phase_subtotal < minimum_meaningful_method_compile,
@@ -157,8 +159,8 @@
tty->cr();
tty->print_cr (" temporaryTimer2: %3.3f sec", Phase::_t_temporaryTimer2.seconds());
}
- tty->print_cr (" output : %3.3f sec", Phase::_t_output.seconds());
- tty->print_cr (" isched : %3.3f sec", Phase::_t_instrSched.seconds());
- tty->print_cr (" bldOopMaps: %3.3f sec", Phase::_t_buildOopMaps.seconds());
+ tty->print_cr (" output : %3.3f sec", Phase::_t_output.seconds());
+ tty->print_cr (" isched : %3.3f sec", Phase::_t_instrSched.seconds());
+ tty->print_cr (" bldOopMaps : %3.3f sec", Phase::_t_buildOopMaps.seconds());
}
#endif
--- a/hotspot/src/share/vm/opto/phase.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/phase.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-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
@@ -83,6 +83,7 @@
static elapsedTimer _t_registerMethod;
static elapsedTimer _t_temporaryTimer1;
static elapsedTimer _t_temporaryTimer2;
+ static elapsedTimer _t_idealLoopVerify;
// Subtimers for _t_optimizer
static elapsedTimer _t_iterGVN;
--- a/hotspot/src/share/vm/opto/phaseX.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1622,9 +1622,11 @@
// old goes dead?
if( old ) {
switch (old->outcnt()) {
- case 0: // Kill all his inputs, and recursively kill other dead nodes.
+ case 0:
+ // Put into the worklist to kill later. We do not kill it now because the
+ // recursive kill will delete the current node (this) if dead-loop exists
if (!old->is_top())
- igvn->remove_dead_node( old );
+ igvn->_worklist.push( old );
break;
case 1:
if( old->is_Store() || old->has_special_unique_user() )
--- a/hotspot/src/share/vm/opto/postaloc.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/opto/postaloc.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -88,6 +88,7 @@
value->map(old_reg,NULL); // Yank from value/regnd maps
regnd->map(old_reg,NULL); // This register's value is now unknown
}
+ assert(old->req() <= 2, "can't handle more inputs");
Node *tmp = old->req() > 1 ? old->in(1) : NULL;
old->disconnect_inputs(NULL);
if( !tmp ) break;
@@ -530,6 +531,16 @@
// Do not change from int to pointer
Node *val = skip_copies(n);
+ // Clear out a dead definition before starting so that the
+ // elimination code doesn't have to guard against it. The
+ // definition could in fact be a kill projection with a count of
+ // 0 which is safe but since those are uninteresting for copy
+ // elimination just delete them as well.
+ if (regnd[nreg] != NULL && regnd[nreg]->outcnt() == 0) {
+ regnd.map(nreg, NULL);
+ value.map(nreg, NULL);
+ }
+
uint n_ideal_reg = n->ideal_reg();
if( is_single_register(n_ideal_reg) ) {
// If Node 'n' does not change the value mapped by the register,
@@ -537,8 +548,7 @@
// mapping so 'n' will go dead.
if( value[nreg] != val ) {
if (eliminate_copy_of_constant(val, n, b, value, regnd, nreg, OptoReg::Bad)) {
- n->replace_by(regnd[nreg]);
- j -= yank_if_dead(n,b,&value,®nd);
+ j -= replace_and_yank_if_dead(n, nreg, b, value, regnd);
} else {
// Update the mapping: record new Node defined by the register
regnd.map(nreg,n);
@@ -546,10 +556,9 @@
// Node after skipping all copies.
value.map(nreg,val);
}
- } else if( !may_be_copy_of_callee(n) && regnd[nreg]->outcnt() != 0 ) {
+ } else if( !may_be_copy_of_callee(n) ) {
assert( n->is_Copy(), "" );
- n->replace_by(regnd[nreg]);
- j -= yank_if_dead(n,b,&value,®nd);
+ j -= replace_and_yank_if_dead(n, nreg, b, value, regnd);
}
} else {
// If the value occupies a register pair, record same info
@@ -565,18 +574,16 @@
}
if( value[nreg] != val || value[nreg_lo] != val ) {
if (eliminate_copy_of_constant(val, n, b, value, regnd, nreg, nreg_lo)) {
- n->replace_by(regnd[nreg]);
- j -= yank_if_dead(n,b,&value,®nd);
+ j -= replace_and_yank_if_dead(n, nreg, b, value, regnd);
} else {
regnd.map(nreg , n );
regnd.map(nreg_lo, n );
value.map(nreg ,val);
value.map(nreg_lo,val);
}
- } else if( !may_be_copy_of_callee(n) && regnd[nreg]->outcnt() != 0 ) {
+ } else if( !may_be_copy_of_callee(n) ) {
assert( n->is_Copy(), "" );
- n->replace_by(regnd[nreg]);
- j -= yank_if_dead(n,b,&value,®nd);
+ j -= replace_and_yank_if_dead(n, nreg, b, value, regnd);
}
}
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-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
@@ -402,7 +402,7 @@
address scopes_data = nm->scopes_data_begin();
for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
- ScopeDesc sc0(nm, pcd->scope_decode_offset());
+ ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute());
ScopeDesc *sd = &sc0;
while( !sd->is_top() ) { sd = sd->sender(); }
int bci = sd->bci();
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -1233,10 +1233,8 @@
// Check that UseCompressedOops can be set with the max heap size allocated
// by ergonomics.
if (MaxHeapSize <= max_heap_for_compressed_oops()) {
- if (FLAG_IS_DEFAULT(UseCompressedOops)) {
- // Turn off until bug is fixed.
- // the following line to return it to default status.
- // FLAG_SET_ERGO(bool, UseCompressedOops, true);
+ if (FLAG_IS_DEFAULT(UseCompressedOops) && !UseG1GC) {
+ FLAG_SET_ERGO(bool, UseCompressedOops, true);
}
#ifdef _WIN64
if (UseLargePages && UseCompressedOops) {
--- a/hotspot/src/share/vm/runtime/vframe.hpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/runtime/vframe.hpp Tue Aug 25 13:08:40 2009 -0700
@@ -402,12 +402,7 @@
DebugInfoReadStream buffer(nm(), decode_offset);
_sender_decode_offset = buffer.read_int();
_method = methodOop(buffer.read_oop());
- // Deoptimization needs reexecute bit to determine whether to reexecute the bytecode
- // only at the time when it "unpack_frames", and the reexecute bit info could always
- // be obtained from the scopeDesc in the compiledVFrame. As a result, we don't keep
- // the reexecute bit here.
- bool dummy_reexecute;
- _bci = buffer.read_bci_and_reexecute(dummy_reexecute);
+ _bci = buffer.read_bci();
assert(_method->is_method(), "checking type of decoded method");
}
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Aug 21 20:39:41 2009 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Tue Aug 25 13:08:40 2009 -0700
@@ -593,6 +593,7 @@
\
nonstatic_field(PcDesc, _pc_offset, int) \
nonstatic_field(PcDesc, _scope_decode_offset, int) \
+ nonstatic_field(PcDesc, _flags, PcDesc::PcDescFlags) \
\
/***************************************************/ \
/* CodeBlobs (NOTE: incomplete, but only a little) */ \
@@ -1158,6 +1159,7 @@
/***************************************/ \
\
declare_toplevel_type(PcDesc) \
+ declare_integer_type(PcDesc::PcDescFlags) \
\
/************************/ \
/* OopMap and OopMapSet */ \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6795465/Test6795465.java Tue Aug 25 13:08:40 2009 -0700
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6795465
+ * @summary Crash in assembler_sparc.cpp with client compiler on solaris-sparc
+ *
+ * @run main Test6795465
+ */
+
+public class Test6795465 {
+ static long var_1 = -1;
+
+ void test() {
+ long var_2 = var_1 * 1;
+ var_2 = var_2 + (new byte[1])[0];
+ }
+
+ public static void main(String[] args) {
+ Test6795465 t = new Test6795465();
+ for (int i = 0; i < 200000; i++) {
+ t.test();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6866651/Test.java Tue Aug 25 13:08:40 2009 -0700
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6866651
+ * @summary delay dead node elimination in set_req_X to prevent killing the current node when it is in use
+ *
+ * @run main Test
+ */
+
+public class Test {
+
+ static int sum() {
+ int s = 0;
+ for (int x = 1, y = 0; x != 0; x++, y--) {
+ s ^= y;
+ }
+ return s;
+ }
+
+ public static void main(final String[] args) {
+ for (int k = 0; k < 2; k++) {
+ System.err.println(String.valueOf(sum()));
+ }
+ }
+}