8012972: Incremental Inlining should support scalar replaced object in debug info
Summary: store in _first_index not absolute index but an index relative to the last (youngest) jvms->_scloff value
Reviewed-by: roland, twisti
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Aug 23 11:41:37 2013 -0700
@@ -1718,7 +1718,7 @@
CodeCache::print_summary(&s, detailed);
}
ttyLocker ttyl;
- tty->print_cr(s.as_string());
+ tty->print(s.as_string());
}
// ------------------------------------------------------------------
--- a/hotspot/src/share/vm/opto/callnode.cpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp Fri Aug 23 11:41:37 2013 -0700
@@ -458,7 +458,7 @@
st->print("={");
uint nf = spobj->n_fields();
if (nf > 0) {
- uint first_ind = spobj->first_index();
+ uint first_ind = spobj->first_index(mcall->jvms());
Node* fld_node = mcall->in(first_ind);
ciField* cifield;
if (iklass != NULL) {
@@ -1063,7 +1063,6 @@
int scloff = jvms->scloff();
int endoff = jvms->endoff();
assert(endoff == (int)req(), "no other states or debug info after me");
- assert(jvms->scl_size() == 0, "parsed code should not have scalar objects");
Node* top = Compile::current()->top();
for (uint i = 0; i < grow_by; i++) {
ins_req(monoff, top);
@@ -1079,32 +1078,31 @@
const int MonitorEdges = 2;
assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges");
assert(req() == jvms()->endoff(), "correct sizing");
- assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects");
int nextmon = jvms()->scloff();
if (GenerateSynchronizationCode) {
- add_req(lock->box_node());
- add_req(lock->obj_node());
+ ins_req(nextmon, lock->box_node());
+ ins_req(nextmon+1, lock->obj_node());
} else {
Node* top = Compile::current()->top();
- add_req(top);
- add_req(top);
+ ins_req(nextmon, top);
+ ins_req(nextmon, top);
}
- jvms()->set_scloff(nextmon+MonitorEdges);
+ jvms()->set_scloff(nextmon + MonitorEdges);
jvms()->set_endoff(req());
}
void SafePointNode::pop_monitor() {
// Delete last monitor from debug info
- assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects");
debug_only(int num_before_pop = jvms()->nof_monitors());
- const int MonitorEdges = (1<<JVMState::logMonitorEdges);
+ const int MonitorEdges = 2;
+ assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges");
int scloff = jvms()->scloff();
int endoff = jvms()->endoff();
int new_scloff = scloff - MonitorEdges;
int new_endoff = endoff - MonitorEdges;
jvms()->set_scloff(new_scloff);
jvms()->set_endoff(new_endoff);
- while (scloff > new_scloff) del_req(--scloff);
+ while (scloff > new_scloff) del_req_ordered(--scloff);
assert(jvms()->nof_monitors() == num_before_pop-1, "");
}
@@ -1169,13 +1167,12 @@
}
SafePointScalarObjectNode*
-SafePointScalarObjectNode::clone(int jvms_adj, Dict* sosn_map) const {
+SafePointScalarObjectNode::clone(Dict* sosn_map) const {
void* cached = (*sosn_map)[(void*)this];
if (cached != NULL) {
return (SafePointScalarObjectNode*)cached;
}
SafePointScalarObjectNode* res = (SafePointScalarObjectNode*)Node::clone();
- res->_first_index += jvms_adj;
sosn_map->Insert((void*)this, (void*)res);
return res;
}
--- a/hotspot/src/share/vm/opto/callnode.hpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/opto/callnode.hpp Fri Aug 23 11:41:37 2013 -0700
@@ -449,14 +449,17 @@
// at a safepoint.
class SafePointScalarObjectNode: public TypeNode {
- uint _first_index; // First input edge index of a SafePoint node where
+ uint _first_index; // First input edge relative index of a SafePoint node where
// states of the scalarized object fields are collected.
+ // It is relative to the last (youngest) jvms->_scloff.
uint _n_fields; // Number of non-static fields of the scalarized object.
DEBUG_ONLY(AllocateNode* _alloc;)
virtual uint hash() const ; // { return NO_HASH; }
virtual uint cmp( const Node &n ) const;
+ uint first_index() const { return _first_index; }
+
public:
SafePointScalarObjectNode(const TypeOopPtr* tp,
#ifdef ASSERT
@@ -469,7 +472,10 @@
virtual const RegMask &out_RegMask() const;
virtual uint match_edge(uint idx) const;
- uint first_index() const { return _first_index; }
+ uint first_index(JVMState* jvms) const {
+ assert(jvms != NULL, "missed JVMS");
+ return jvms->scloff() + _first_index;
+ }
uint n_fields() const { return _n_fields; }
#ifdef ASSERT
@@ -485,7 +491,7 @@
// corresponds appropriately to "this" in "new_call". Assumes that
// "sosn_map" is a map, specific to the translation of "s" to "new_call",
// mapping old SafePointScalarObjectNodes to new, to avoid multiple copies.
- SafePointScalarObjectNode* clone(int jvms_adj, Dict* sosn_map) const;
+ SafePointScalarObjectNode* clone(Dict* sosn_map) const;
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
--- a/hotspot/src/share/vm/opto/generateOptoStub.cpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp Fri Aug 23 11:41:37 2013 -0700
@@ -61,6 +61,7 @@
JVMState* jvms = new (C) JVMState(0);
jvms->set_bci(InvocationEntryBci);
jvms->set_monoff(max_map);
+ jvms->set_scloff(max_map);
jvms->set_endoff(max_map);
{
SafePointNode *map = new (C) SafePointNode( max_map, jvms );
--- a/hotspot/src/share/vm/opto/macro.cpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/opto/macro.cpp Fri Aug 23 11:41:37 2013 -0700
@@ -72,6 +72,8 @@
int jvms_adj = new_dbg_start - old_dbg_start;
assert (new_dbg_start == newcall->req(), "argument count mismatch");
+ // SafePointScalarObject node could be referenced several times in debug info.
+ // Use Dict to record cloned nodes.
Dict* sosn_map = new Dict(cmpkey,hashkey);
for (uint i = old_dbg_start; i < oldcall->req(); i++) {
Node* old_in = oldcall->in(i);
@@ -79,8 +81,8 @@
if (old_in != NULL && old_in->is_SafePointScalarObject()) {
SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject();
uint old_unique = C->unique();
- Node* new_in = old_sosn->clone(jvms_adj, sosn_map);
- if (old_unique != C->unique()) {
+ Node* new_in = old_sosn->clone(sosn_map);
+ if (old_unique != C->unique()) { // New node?
new_in->set_req(0, C->root()); // reset control edge
new_in = transform_later(new_in); // Register new node.
}
@@ -725,7 +727,11 @@
while (safepoints.length() > 0) {
SafePointNode* sfpt = safepoints.pop();
Node* mem = sfpt->memory();
- uint first_ind = sfpt->req();
+ assert(sfpt->jvms() != NULL, "missed JVMS");
+ // Fields of scalar objs are referenced only at the end
+ // of regular debuginfo at the last (youngest) JVMS.
+ // Record relative start index.
+ uint first_ind = (sfpt->req() - sfpt->jvms()->scloff());
SafePointScalarObjectNode* sobj = new (C) SafePointScalarObjectNode(res_type,
#ifdef ASSERT
alloc,
@@ -799,7 +805,7 @@
for (int i = start; i < end; i++) {
if (sfpt_done->in(i)->is_SafePointScalarObject()) {
SafePointScalarObjectNode* scobj = sfpt_done->in(i)->as_SafePointScalarObject();
- if (scobj->first_index() == sfpt_done->req() &&
+ if (scobj->first_index(jvms) == sfpt_done->req() &&
scobj->n_fields() == (uint)nfields) {
assert(scobj->alloc() == alloc, "sanity");
sfpt_done->set_req(i, res);
--- a/hotspot/src/share/vm/opto/node.cpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/opto/node.cpp Fri Aug 23 11:41:37 2013 -0700
@@ -773,6 +773,21 @@
_in[_cnt] = NULL; // NULL out emptied slot
}
+//------------------------------del_req_ordered--------------------------------
+// Delete the required edge and compact the edge array with preserved order
+void Node::del_req_ordered( uint idx ) {
+ assert( idx < _cnt, "oob");
+ assert( !VerifyHashTableKeys || _hash_lock == 0,
+ "remove node from hash table before modifying it");
+ // First remove corresponding def-use edge
+ Node *n = in(idx);
+ if (n != NULL) n->del_out((Node *)this);
+ if (idx < _cnt - 1) { // Not last edge ?
+ Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*)));
+ }
+ _in[--_cnt] = NULL; // NULL out emptied slot
+}
+
//------------------------------ins_req----------------------------------------
// Insert a new required input at the end
void Node::ins_req( uint idx, Node *n ) {
--- a/hotspot/src/share/vm/opto/node.hpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/opto/node.hpp Fri Aug 23 11:41:37 2013 -0700
@@ -384,6 +384,7 @@
void add_req( Node *n ); // Append a NEW required input
void add_req_batch( Node* n, uint m ); // Append m NEW required inputs (all n).
void del_req( uint idx ); // Delete required edge & compact
+ void del_req_ordered( uint idx ); // Delete required edge & compact with preserved order
void ins_req( uint i, Node *n ); // Insert a NEW required input
void set_req( uint i, Node *n ) {
assert( is_not_dead(n), "can not use dead node");
--- a/hotspot/src/share/vm/opto/output.cpp Fri Aug 23 03:14:54 2013 -0700
+++ b/hotspot/src/share/vm/opto/output.cpp Fri Aug 23 11:41:37 2013 -0700
@@ -639,7 +639,7 @@
new ConstantOopWriteValue(cik->java_mirror()->constant_encoding()));
Compile::set_sv_for_object_node(objs, sv);
- uint first_ind = spobj->first_index();
+ uint first_ind = spobj->first_index(sfpt->jvms());
for (uint i = 0; i < spobj->n_fields(); i++) {
Node* fld_node = sfpt->in(first_ind+i);
(void)FillLocArray(sv->field_values()->length(), sfpt, fld_node, sv->field_values(), objs);
@@ -894,7 +894,7 @@
GrowableArray<MonitorValue*> *monarray = new GrowableArray<MonitorValue*>(num_mon);
// Loop over monitors and insert into array
- for(idx = 0; idx < num_mon; idx++) {
+ for (idx = 0; idx < num_mon; idx++) {
// Grab the node that defines this monitor
Node* box_node = sfn->monitor_box(jvms, idx);
Node* obj_node = sfn->monitor_obj(jvms, idx);
@@ -902,11 +902,11 @@
// Create ScopeValue for object
ScopeValue *scval = NULL;
- if( obj_node->is_SafePointScalarObject() ) {
+ if (obj_node->is_SafePointScalarObject()) {
SafePointScalarObjectNode* spobj = obj_node->as_SafePointScalarObject();
scval = Compile::sv_for_node_id(objs, spobj->_idx);
if (scval == NULL) {
- const Type *t = obj_node->bottom_type();
+ const Type *t = spobj->bottom_type();
ciKlass* cik = t->is_oopptr()->klass();
assert(cik->is_instance_klass() ||
cik->is_array_klass(), "Not supported allocation.");
@@ -914,14 +914,14 @@
new ConstantOopWriteValue(cik->java_mirror()->constant_encoding()));
Compile::set_sv_for_object_node(objs, sv);
- uint first_ind = spobj->first_index();
+ uint first_ind = spobj->first_index(youngest_jvms);
for (uint i = 0; i < spobj->n_fields(); i++) {
Node* fld_node = sfn->in(first_ind+i);
(void)FillLocArray(sv->field_values()->length(), sfn, fld_node, sv->field_values(), objs);
}
scval = sv;
}
- } else if( !obj_node->is_Con() ) {
+ } else if (!obj_node->is_Con()) {
OptoReg::Name obj_reg = _regalloc->get_reg_first(obj_node);
if( obj_node->bottom_type()->base() == Type::NarrowOop ) {
scval = new_loc_value( _regalloc, obj_reg, Location::narrowoop );