mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
6706829: Compressed Oops: add debug info for narrow oops
Add support for narrow oops in debug info to avoid decoding. Reviewed-by: rasbold, never
This commit is contained in:
parent
63c98ed888
commit
659ca734bb
11 changed files with 169 additions and 48 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -39,9 +39,9 @@ import sun.jvm.hotspot.utilities.*;
|
||||||
<P> Encoding: </P>
|
<P> Encoding: </P>
|
||||||
<PRE>
|
<PRE>
|
||||||
bits:
|
bits:
|
||||||
Where: [15]
|
Type: [3..0]
|
||||||
Type: [14..12]
|
Where: [4]
|
||||||
Offset: [11..0]
|
Offset: [31..5]
|
||||||
</PRE>
|
</PRE>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ public class Location {
|
||||||
// Location::Type constants
|
// Location::Type constants
|
||||||
TYPE_NORMAL = db.lookupIntConstant("Location::normal").intValue();
|
TYPE_NORMAL = db.lookupIntConstant("Location::normal").intValue();
|
||||||
TYPE_OOP = db.lookupIntConstant("Location::oop").intValue();
|
TYPE_OOP = db.lookupIntConstant("Location::oop").intValue();
|
||||||
|
TYPE_NARROWOOP = db.lookupIntConstant("Location::narrowoop").intValue();
|
||||||
TYPE_INT_IN_LONG = db.lookupIntConstant("Location::int_in_long").intValue();
|
TYPE_INT_IN_LONG = db.lookupIntConstant("Location::int_in_long").intValue();
|
||||||
TYPE_LNG = db.lookupIntConstant("Location::lng").intValue();
|
TYPE_LNG = db.lookupIntConstant("Location::lng").intValue();
|
||||||
TYPE_FLOAT_IN_DBL = db.lookupIntConstant("Location::float_in_dbl").intValue();
|
TYPE_FLOAT_IN_DBL = db.lookupIntConstant("Location::float_in_dbl").intValue();
|
||||||
|
@ -115,6 +116,8 @@ public class Location {
|
||||||
public static final Type NORMAL = new Type("normal");
|
public static final Type NORMAL = new Type("normal");
|
||||||
/** Oop (please GC me!) */
|
/** Oop (please GC me!) */
|
||||||
public static final Type OOP = new Type("oop");
|
public static final Type OOP = new Type("oop");
|
||||||
|
/** NarrowOop (please GC me!) */
|
||||||
|
public static final Type NARROWOOP = new Type("narrowoop");
|
||||||
/** Long held in one register */
|
/** Long held in one register */
|
||||||
public static final Type INT_IN_LONG = new Type("int_in_long");
|
public static final Type INT_IN_LONG = new Type("int_in_long");
|
||||||
/** Long held in one register */
|
/** Long held in one register */
|
||||||
|
@ -142,6 +145,8 @@ public class Location {
|
||||||
return TYPE_NORMAL;
|
return TYPE_NORMAL;
|
||||||
} else if (this == OOP) {
|
} else if (this == OOP) {
|
||||||
return TYPE_OOP;
|
return TYPE_OOP;
|
||||||
|
} else if (this == NARROWOOP) {
|
||||||
|
return TYPE_NARROWOOP;
|
||||||
} else if (this == INT_IN_LONG) {
|
} else if (this == INT_IN_LONG) {
|
||||||
return TYPE_INT_IN_LONG;
|
return TYPE_INT_IN_LONG;
|
||||||
} else if (this == LNG) {
|
} else if (this == LNG) {
|
||||||
|
@ -170,6 +175,7 @@ public class Location {
|
||||||
// constants in Type enum
|
// constants in Type enum
|
||||||
private static int TYPE_NORMAL;
|
private static int TYPE_NORMAL;
|
||||||
private static int TYPE_OOP;
|
private static int TYPE_OOP;
|
||||||
|
private static int TYPE_NARROWOOP;
|
||||||
private static int TYPE_INT_IN_LONG;
|
private static int TYPE_INT_IN_LONG;
|
||||||
private static int TYPE_LNG;
|
private static int TYPE_LNG;
|
||||||
private static int TYPE_FLOAT_IN_DBL;
|
private static int TYPE_FLOAT_IN_DBL;
|
||||||
|
@ -185,7 +191,7 @@ public class Location {
|
||||||
Location(Where where, Type type, int offset) {
|
Location(Where where, Type type, int offset) {
|
||||||
setWhere(where);
|
setWhere(where);
|
||||||
setType(type);
|
setType(type);
|
||||||
setOffset(offset & 0x0000FFFF);
|
setOffset(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Where getWhere() {
|
public Where getWhere() {
|
||||||
|
@ -205,6 +211,8 @@ public class Location {
|
||||||
return Type.NORMAL;
|
return Type.NORMAL;
|
||||||
} else if (type == TYPE_OOP) {
|
} else if (type == TYPE_OOP) {
|
||||||
return Type.OOP;
|
return Type.OOP;
|
||||||
|
} else if (type == TYPE_NARROWOOP) {
|
||||||
|
return Type.NARROWOOP;
|
||||||
} else if (type == TYPE_INT_IN_LONG) {
|
} else if (type == TYPE_INT_IN_LONG) {
|
||||||
return Type.INT_IN_LONG;
|
return Type.INT_IN_LONG;
|
||||||
} else if (type == TYPE_LNG) {
|
} else if (type == TYPE_LNG) {
|
||||||
|
@ -238,6 +246,10 @@ public class Location {
|
||||||
return getType() == Type.OOP;
|
return getType() == Type.OOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean holdsNarrowOop() {
|
||||||
|
return getType() == Type.NARROWOOP;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean holdsInt() {
|
public boolean holdsInt() {
|
||||||
return getType() == Type.INT_IN_LONG;
|
return getType() == Type.INT_IN_LONG;
|
||||||
}
|
}
|
||||||
|
@ -266,7 +278,7 @@ public class Location {
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
Assert.that(getWhere() == Where.ON_STACK, "wrong Where");
|
Assert.that(getWhere() == Where.ON_STACK, "wrong Where");
|
||||||
}
|
}
|
||||||
return getOffset() << VM.getVM().getLogAddressSize();
|
return getOffset() * (int)VM.getVM().getIntSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRegisterNumber() {
|
public int getRegisterNumber() {
|
||||||
|
@ -296,6 +308,8 @@ public class Location {
|
||||||
if (type == Type.NORMAL) {
|
if (type == Type.NORMAL) {
|
||||||
} else if (type == Type.OOP) {
|
} else if (type == Type.OOP) {
|
||||||
tty.print(",oop");
|
tty.print(",oop");
|
||||||
|
} else if (type == Type.NARROWOOP) {
|
||||||
|
tty.print(",narrowoop");
|
||||||
} else if (type == Type.INT_IN_LONG) {
|
} else if (type == Type.INT_IN_LONG) {
|
||||||
tty.print(",int");
|
tty.print(",int");
|
||||||
} else if (type == Type.LNG) {
|
} else if (type == Type.LNG) {
|
||||||
|
@ -314,26 +328,26 @@ public class Location {
|
||||||
|
|
||||||
/** Serialization of debugging information */
|
/** Serialization of debugging information */
|
||||||
public Location(DebugInfoReadStream stream) {
|
public Location(DebugInfoReadStream stream) {
|
||||||
value = (0x0000FFFF & stream.readInt());
|
value = stream.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: not yet implementable
|
// FIXME: not yet implementable
|
||||||
// void write_on(DebugInfoWriteStream* stream);
|
// void write_on(DebugInfoWriteStream* stream);
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Internals only below this point
|
// Internals only below this point
|
||||||
//
|
//
|
||||||
|
|
||||||
private void setWhere(Where where) {
|
private void setWhere(Where where) {
|
||||||
value |= (where.getValue() << WHERE_SHIFT);
|
value |= ((where.getValue() << WHERE_SHIFT) & WHERE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setType(Type type) {
|
private void setType(Type type) {
|
||||||
value |= (type.getValue() << TYPE_SHIFT);
|
value |= ((type.getValue() << TYPE_SHIFT) & TYPE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setOffset(int offset) {
|
private void setOffset(int offset) {
|
||||||
value |= (offset << OFFSET_SHIFT);
|
value |= ((offset << OFFSET_SHIFT) & OFFSET_MASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,6 +206,16 @@ public class CompiledVFrame extends JavaVFrame {
|
||||||
Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" );
|
Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" );
|
||||||
}
|
}
|
||||||
return new StackValue(valueAddr.getJLongAt(0) & 0xFFFFFFFF);
|
return new StackValue(valueAddr.getJLongAt(0) & 0xFFFFFFFF);
|
||||||
|
} else if (loc.holdsNarrowOop()) { // Holds an narrow oop?
|
||||||
|
if (loc.isRegister() && VM.getVM().isBigEndian()) {
|
||||||
|
// The callee has no clue whether the register holds an narrow oop,
|
||||||
|
// 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()));
|
||||||
|
} else {
|
||||||
|
return new StackValue(valueAddr.getCompOopHandleAt(0));
|
||||||
|
}
|
||||||
} else if( loc.holdsOop() ) { // Holds an oop?
|
} else if( loc.holdsOop() ) { // Holds an oop?
|
||||||
return new StackValue(valueAddr.getOopHandleAt(0));
|
return new StackValue(valueAddr.getOopHandleAt(0));
|
||||||
} else if( loc.holdsDouble() ) {
|
} else if( loc.holdsDouble() ) {
|
||||||
|
|
|
@ -621,6 +621,11 @@ public class VM {
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns true if this is a isBigEndian, false otherwise */
|
||||||
|
public boolean isBigEndian() {
|
||||||
|
return isBigEndian;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns true if this is a "core" build, false if either C1 or C2
|
/** Returns true if this is a "core" build, false if either C1 or C2
|
||||||
is present */
|
is present */
|
||||||
public boolean isCore() {
|
public boolean isCore() {
|
||||||
|
|
|
@ -1135,6 +1135,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
||||||
buf.append("normal");
|
buf.append("normal");
|
||||||
} else if (type == Location.Type.OOP) {
|
} else if (type == Location.Type.OOP) {
|
||||||
buf.append("oop");
|
buf.append("oop");
|
||||||
|
} else if (type == Location.Type.NARROWOOP) {
|
||||||
|
buf.append("narrowoop");
|
||||||
} else if (type == Location.Type.INT_IN_LONG) {
|
} else if (type == Location.Type.INT_IN_LONG) {
|
||||||
buf.append("int");
|
buf.append("int");
|
||||||
} else if (type == Location.Type.LNG) {
|
} else if (type == Location.Type.LNG) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
#include "incls/_location.cpp.incl"
|
#include "incls/_location.cpp.incl"
|
||||||
|
|
||||||
void Location::print_on(outputStream* st) const {
|
void Location::print_on(outputStream* st) const {
|
||||||
if(type() == invalid && !legal_offset_in_bytes(offset() * BytesPerInt)) {
|
if(type() == invalid) {
|
||||||
// product of Location::invalid_loc() or Location::Location().
|
// product of Location::invalid_loc() or Location::Location().
|
||||||
switch (where()) {
|
switch (where()) {
|
||||||
case on_stack: st->print("empty"); break;
|
case on_stack: st->print("empty"); break;
|
||||||
|
@ -42,6 +42,7 @@ void Location::print_on(outputStream* st) const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case normal: break;
|
case normal: break;
|
||||||
case oop: st->print(",oop"); break;
|
case oop: st->print(",oop"); break;
|
||||||
|
case narrowoop: st->print(",narrowoop"); break;
|
||||||
case int_in_long: st->print(",int"); break;
|
case int_in_long: st->print(",int"); break;
|
||||||
case lng: st->print(",long"); break;
|
case lng: st->print(",long"); break;
|
||||||
case float_in_dbl: st->print(",float"); break;
|
case float_in_dbl: st->print(",float"); break;
|
||||||
|
@ -53,17 +54,17 @@ void Location::print_on(outputStream* st) const {
|
||||||
|
|
||||||
|
|
||||||
Location::Location(DebugInfoReadStream* stream) {
|
Location::Location(DebugInfoReadStream* stream) {
|
||||||
_value = (uint16_t) stream->read_int();
|
_value = (juint) stream->read_int();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Location::write_on(DebugInfoWriteStream* stream) {
|
void Location::write_on(DebugInfoWriteStream* stream) {
|
||||||
stream->write_int(_value & 0x0000FFFF);
|
stream->write_int(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Valid argument to Location::new_stk_loc()?
|
// Valid argument to Location::new_stk_loc()?
|
||||||
bool Location::legal_offset_in_bytes(int offset_in_bytes) {
|
bool Location::legal_offset_in_bytes(int offset_in_bytes) {
|
||||||
if ((offset_in_bytes % BytesPerInt) != 0) return false;
|
if ((offset_in_bytes % BytesPerInt) != 0) return false;
|
||||||
return (offset_in_bytes / BytesPerInt) < (OFFSET_MASK >> OFFSET_SHIFT);
|
return (juint)(offset_in_bytes / BytesPerInt) < (OFFSET_MASK >> OFFSET_SHIFT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,10 +28,10 @@
|
||||||
//
|
//
|
||||||
// Encoding:
|
// Encoding:
|
||||||
//
|
//
|
||||||
// bits:
|
// bits (use low bits for best compression):
|
||||||
// Where: [15]
|
// Type: [3..0]
|
||||||
// Type: [14..12]
|
// Where: [4]
|
||||||
// Offset: [11..0]
|
// Offset: [31..5]
|
||||||
|
|
||||||
class Location VALUE_OBJ_CLASS_SPEC {
|
class Location VALUE_OBJ_CLASS_SPEC {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
@ -42,6 +42,7 @@ class Location VALUE_OBJ_CLASS_SPEC {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
|
invalid, // Invalid location
|
||||||
normal, // Ints, floats, double halves
|
normal, // Ints, floats, double halves
|
||||||
oop, // Oop (please GC me!)
|
oop, // Oop (please GC me!)
|
||||||
int_in_long, // Integer held in long register
|
int_in_long, // Integer held in long register
|
||||||
|
@ -49,21 +50,21 @@ class Location VALUE_OBJ_CLASS_SPEC {
|
||||||
float_in_dbl, // Float held in double register
|
float_in_dbl, // Float held in double register
|
||||||
dbl, // Double held in one register
|
dbl, // Double held in one register
|
||||||
addr, // JSR return address
|
addr, // JSR return address
|
||||||
invalid // Invalid location
|
narrowoop // Narrow Oop (please GC me!)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
OFFSET_MASK = (jchar) 0x0FFF,
|
TYPE_MASK = (juint) 0x0F,
|
||||||
OFFSET_SHIFT = 0,
|
TYPE_SHIFT = 0,
|
||||||
TYPE_MASK = (jchar) 0x7000,
|
WHERE_MASK = (juint) 0x10,
|
||||||
TYPE_SHIFT = 12,
|
WHERE_SHIFT = 4,
|
||||||
WHERE_MASK = (jchar) 0x8000,
|
OFFSET_MASK = (juint) 0xFFFFFFE0,
|
||||||
WHERE_SHIFT = 15
|
OFFSET_SHIFT = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t _value;
|
juint _value;
|
||||||
|
|
||||||
// Create a bit-packed Location
|
// Create a bit-packed Location
|
||||||
Location(Where where_, Type type_, unsigned offset_) {
|
Location(Where where_, Type type_, unsigned offset_) {
|
||||||
|
@ -74,9 +75,9 @@ class Location VALUE_OBJ_CLASS_SPEC {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set(Where where_, Type type_, unsigned offset_) {
|
inline void set(Where where_, Type type_, unsigned offset_) {
|
||||||
_value = (uint16_t) ((where_ << WHERE_SHIFT) |
|
_value = (juint) ((where_ << WHERE_SHIFT) |
|
||||||
(type_ << TYPE_SHIFT) |
|
(type_ << TYPE_SHIFT) |
|
||||||
((offset_ << OFFSET_SHIFT) & OFFSET_MASK));
|
((offset_ << OFFSET_SHIFT) & OFFSET_MASK));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -86,7 +87,7 @@ class Location VALUE_OBJ_CLASS_SPEC {
|
||||||
// Register location Factory
|
// Register location Factory
|
||||||
static Location new_reg_loc( Type t, VMReg reg ) { return Location(in_register, t, reg->value()); }
|
static Location new_reg_loc( Type t, VMReg reg ) { return Location(in_register, t, reg->value()); }
|
||||||
// Default constructor
|
// Default constructor
|
||||||
Location() { set(on_stack,invalid,(unsigned) -1); }
|
Location() { set(on_stack,invalid,0); }
|
||||||
|
|
||||||
// Bit field accessors
|
// Bit field accessors
|
||||||
Where where() const { return (Where) ((_value & WHERE_MASK) >> WHERE_SHIFT);}
|
Where where() const { return (Where) ((_value & WHERE_MASK) >> WHERE_SHIFT);}
|
||||||
|
|
|
@ -334,6 +334,9 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c
|
||||||
case Type::InstPtr:
|
case Type::InstPtr:
|
||||||
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->isa_oopptr()->const_oop());
|
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->isa_oopptr()->const_oop());
|
||||||
break;
|
break;
|
||||||
|
case Type::NarrowOop:
|
||||||
|
st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_oopptr()->const_oop());
|
||||||
|
break;
|
||||||
case Type::RawPtr:
|
case Type::RawPtr:
|
||||||
st->print(" %s%d]=#Raw" INTPTR_FORMAT,msg,i,t->is_rawptr());
|
st->print(" %s%d]=#Raw" INTPTR_FORMAT,msg,i,t->is_rawptr());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1967,6 +1967,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
|
||||||
!n->is_Proj() &&
|
!n->is_Proj() &&
|
||||||
nop != Op_CreateEx &&
|
nop != Op_CreateEx &&
|
||||||
nop != Op_CheckCastPP &&
|
nop != Op_CheckCastPP &&
|
||||||
|
nop != Op_DecodeN &&
|
||||||
!n->is_Mem() ) {
|
!n->is_Mem() ) {
|
||||||
Node *x = n->clone();
|
Node *x = n->clone();
|
||||||
call->set_req( TypeFunc::Parms, x );
|
call->set_req( TypeFunc::Parms, x );
|
||||||
|
@ -2075,20 +2076,27 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
|
||||||
case Op_CmpP:
|
case Op_CmpP:
|
||||||
// Do this transformation here to preserve CmpPNode::sub() and
|
// Do this transformation here to preserve CmpPNode::sub() and
|
||||||
// other TypePtr related Ideal optimizations (for example, ptr nullness).
|
// other TypePtr related Ideal optimizations (for example, ptr nullness).
|
||||||
if( n->in(1)->is_DecodeN() ) {
|
if (n->in(1)->is_DecodeN() || n->in(2)->is_DecodeN()) {
|
||||||
|
Node* in1 = n->in(1);
|
||||||
|
Node* in2 = n->in(2);
|
||||||
|
if (!in1->is_DecodeN()) {
|
||||||
|
in2 = in1;
|
||||||
|
in1 = n->in(2);
|
||||||
|
}
|
||||||
|
assert(in1->is_DecodeN(), "sanity");
|
||||||
|
|
||||||
Compile* C = Compile::current();
|
Compile* C = Compile::current();
|
||||||
Node* in2 = NULL;
|
Node* new_in2 = NULL;
|
||||||
if( n->in(2)->is_DecodeN() ) {
|
if (in2->is_DecodeN()) {
|
||||||
in2 = n->in(2)->in(1);
|
new_in2 = in2->in(1);
|
||||||
} else if ( n->in(2)->Opcode() == Op_ConP ) {
|
} else if (in2->Opcode() == Op_ConP) {
|
||||||
const Type* t = n->in(2)->bottom_type();
|
const Type* t = in2->bottom_type();
|
||||||
if (t == TypePtr::NULL_PTR) {
|
if (t == TypePtr::NULL_PTR) {
|
||||||
Node *in1 = n->in(1);
|
|
||||||
if (Matcher::clone_shift_expressions) {
|
if (Matcher::clone_shift_expressions) {
|
||||||
// x86, ARM and friends can handle 2 adds in addressing mode.
|
// x86, ARM and friends can handle 2 adds in addressing mode.
|
||||||
// Decode a narrow oop and do implicit NULL check in address
|
// Decode a narrow oop and do implicit NULL check in address
|
||||||
// [R12 + narrow_oop_reg<<3 + offset]
|
// [R12 + narrow_oop_reg<<3 + offset]
|
||||||
in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
|
new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
|
||||||
} else {
|
} else {
|
||||||
// Don't replace CmpP(o ,null) if 'o' is used in AddP
|
// Don't replace CmpP(o ,null) if 'o' is used in AddP
|
||||||
// to generate implicit NULL check on Sparc where
|
// to generate implicit NULL check on Sparc where
|
||||||
|
@ -2099,16 +2107,22 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i >= in1->outcnt()) {
|
if (i >= in1->outcnt()) {
|
||||||
in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
|
new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (t->isa_oopptr()) {
|
} else if (t->isa_oopptr()) {
|
||||||
in2 = ConNode::make(C, t->make_narrowoop());
|
new_in2 = ConNode::make(C, t->make_narrowoop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( in2 != NULL ) {
|
if (new_in2 != NULL) {
|
||||||
Node* cmpN = new (C, 3) CmpNNode(n->in(1)->in(1), in2);
|
Node* cmpN = new (C, 3) CmpNNode(in1->in(1), new_in2);
|
||||||
n->subsume_by( cmpN );
|
n->subsume_by( cmpN );
|
||||||
|
if (in1->outcnt() == 0) {
|
||||||
|
in1->disconnect_inputs(NULL);
|
||||||
|
}
|
||||||
|
if (in2->outcnt() == 0) {
|
||||||
|
in2->disconnect_inputs(NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2214,6 +2228,9 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) {
|
||||||
// Replacing Opaque nodes with their input in final_graph_reshaping_impl(),
|
// Replacing Opaque nodes with their input in final_graph_reshaping_impl(),
|
||||||
// requires that the walk visits a node's inputs before visiting the node.
|
// requires that the walk visits a node's inputs before visiting the node.
|
||||||
static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &fpu ) {
|
static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &fpu ) {
|
||||||
|
ResourceArea *area = Thread::current()->resource_area();
|
||||||
|
Unique_Node_List sfpt(area);
|
||||||
|
|
||||||
fpu._visited.set(root->_idx); // first, mark node as visited
|
fpu._visited.set(root->_idx); // first, mark node as visited
|
||||||
uint cnt = root->req();
|
uint cnt = root->req();
|
||||||
Node *n = root;
|
Node *n = root;
|
||||||
|
@ -2224,6 +2241,8 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re
|
||||||
Node* m = n->in(i);
|
Node* m = n->in(i);
|
||||||
++i;
|
++i;
|
||||||
if (m != NULL && !fpu._visited.test_set(m->_idx)) {
|
if (m != NULL && !fpu._visited.test_set(m->_idx)) {
|
||||||
|
if (m->is_SafePoint() && m->as_SafePoint()->jvms() != NULL)
|
||||||
|
sfpt.push(m);
|
||||||
cnt = m->req();
|
cnt = m->req();
|
||||||
nstack.push(n, i); // put on stack parent and next input's index
|
nstack.push(n, i); // put on stack parent and next input's index
|
||||||
n = m;
|
n = m;
|
||||||
|
@ -2240,6 +2259,41 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re
|
||||||
nstack.pop(); // Shift to the next node on stack
|
nstack.pop(); // Shift to the next node on stack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Go over safepoints nodes to skip DecodeN nodes for debug edges.
|
||||||
|
// It could be done for an uncommon traps or any safepoints/calls
|
||||||
|
// if the DecodeN node is referenced only in a debug info.
|
||||||
|
while (sfpt.size() > 0) {
|
||||||
|
n = sfpt.pop();
|
||||||
|
JVMState *jvms = n->as_SafePoint()->jvms();
|
||||||
|
assert(jvms != NULL, "sanity");
|
||||||
|
int start = jvms->debug_start();
|
||||||
|
int end = n->req();
|
||||||
|
bool is_uncommon = (n->is_CallStaticJava() &&
|
||||||
|
n->as_CallStaticJava()->uncommon_trap_request() != 0);
|
||||||
|
for (int j = start; j < end; j++) {
|
||||||
|
Node* in = n->in(j);
|
||||||
|
if (in->is_DecodeN()) {
|
||||||
|
bool safe_to_skip = true;
|
||||||
|
if (!is_uncommon ) {
|
||||||
|
// Is it safe to skip?
|
||||||
|
for (uint i = 0; i < in->outcnt(); i++) {
|
||||||
|
Node* u = in->raw_out(i);
|
||||||
|
if (!u->is_SafePoint() ||
|
||||||
|
u->is_Call() && u->as_Call()->has_non_debug_use(n)) {
|
||||||
|
safe_to_skip = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (safe_to_skip) {
|
||||||
|
n->set_req(j, in->in(1));
|
||||||
|
}
|
||||||
|
if (in->outcnt() == 0) {
|
||||||
|
in->disconnect_inputs(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------final_graph_reshaping--------------------------
|
//------------------------------final_graph_reshaping--------------------------
|
||||||
|
|
|
@ -685,6 +685,8 @@ void Compile::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local,
|
||||||
} else if( t->base() == Type::Int && OptoReg::is_reg(regnum) ) {
|
} else if( t->base() == Type::Int && OptoReg::is_reg(regnum) ) {
|
||||||
array->append(new_loc_value( _regalloc, regnum, Matcher::int_in_long
|
array->append(new_loc_value( _regalloc, regnum, Matcher::int_in_long
|
||||||
? Location::int_in_long : Location::normal ));
|
? Location::int_in_long : Location::normal ));
|
||||||
|
} else if( t->base() == Type::NarrowOop ) {
|
||||||
|
array->append(new_loc_value( _regalloc, regnum, Location::narrowoop ));
|
||||||
} else {
|
} else {
|
||||||
array->append(new_loc_value( _regalloc, regnum, _regalloc->is_oop(local) ? Location::oop : Location::normal ));
|
array->append(new_loc_value( _regalloc, regnum, _regalloc->is_oop(local) ? Location::oop : Location::normal ));
|
||||||
}
|
}
|
||||||
|
@ -704,6 +706,13 @@ void Compile::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local,
|
||||||
case Type::KlassPtr: // fall through
|
case Type::KlassPtr: // fall through
|
||||||
array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->encoding()));
|
array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->encoding()));
|
||||||
break;
|
break;
|
||||||
|
case Type::NarrowOop:
|
||||||
|
if (t == TypeNarrowOop::NULL_PTR) {
|
||||||
|
array->append(new ConstantOopWriteValue(NULL));
|
||||||
|
} else {
|
||||||
|
array->append(new ConstantOopWriteValue(t->make_ptr()->isa_oopptr()->const_oop()->encoding()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Type::Int:
|
case Type::Int:
|
||||||
array->append(new ConstantIntValue(t->is_int()->get_con()));
|
array->append(new ConstantIntValue(t->is_int()->get_con()));
|
||||||
break;
|
break;
|
||||||
|
@ -878,9 +887,14 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) {
|
||||||
}
|
}
|
||||||
} else if( !obj_node->is_Con() ) {
|
} else if( !obj_node->is_Con() ) {
|
||||||
OptoReg::Name obj_reg = _regalloc->get_reg_first(obj_node);
|
OptoReg::Name obj_reg = _regalloc->get_reg_first(obj_node);
|
||||||
scval = new_loc_value( _regalloc, obj_reg, Location::oop );
|
if( obj_node->bottom_type()->base() == Type::NarrowOop ) {
|
||||||
|
scval = new_loc_value( _regalloc, obj_reg, Location::narrowoop );
|
||||||
|
} else {
|
||||||
|
scval = new_loc_value( _regalloc, obj_reg, Location::oop );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
scval = new ConstantOopWriteValue(obj_node->bottom_type()->is_instptr()->const_oop()->encoding());
|
const TypePtr *tp = obj_node->bottom_type()->make_ptr();
|
||||||
|
scval = new ConstantOopWriteValue(tp->is_instptr()->const_oop()->encoding());
|
||||||
}
|
}
|
||||||
|
|
||||||
OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node);
|
OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -86,6 +86,22 @@ StackValue* StackValue::create_stack_value(const frame* fr, const RegisterMap* r
|
||||||
case Location::lng:
|
case Location::lng:
|
||||||
// Long value in an aligned adjacent pair
|
// Long value in an aligned adjacent pair
|
||||||
return new StackValue(*(intptr_t*)value_addr);
|
return new StackValue(*(intptr_t*)value_addr);
|
||||||
|
case Location::narrowoop: {
|
||||||
|
union { intptr_t p; narrowOop noop;} value;
|
||||||
|
value.p = (intptr_t) CONST64(0xDEADDEAFDEADDEAF);
|
||||||
|
if (loc.is_register()) {
|
||||||
|
// The callee has no clue whether the register holds an int,
|
||||||
|
// long or is unused. He always saves a long. Here we know
|
||||||
|
// a long was saved, but we only want an int back. Narrow the
|
||||||
|
// saved long to the int that the JVM wants.
|
||||||
|
value.noop = (narrowOop) *(julong*) value_addr;
|
||||||
|
} else {
|
||||||
|
value.noop = *(narrowOop*) value_addr;
|
||||||
|
}
|
||||||
|
// Decode narrowoop and wrap a handle around the oop
|
||||||
|
Handle h(oopDesc::decode_heap_oop(value.noop));
|
||||||
|
return new StackValue(h);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
case Location::oop: {
|
case Location::oop: {
|
||||||
Handle h(*(oop *)value_addr); // Wrap a handle around the oop
|
Handle h(*(oop *)value_addr); // Wrap a handle around the oop
|
||||||
|
|
|
@ -1577,6 +1577,7 @@ static inline uint64_t cast_uint64_t(size_t x)
|
||||||
\
|
\
|
||||||
declare_constant(Location::normal) \
|
declare_constant(Location::normal) \
|
||||||
declare_constant(Location::oop) \
|
declare_constant(Location::oop) \
|
||||||
|
declare_constant(Location::narrowoop) \
|
||||||
declare_constant(Location::int_in_long) \
|
declare_constant(Location::int_in_long) \
|
||||||
declare_constant(Location::lng) \
|
declare_constant(Location::lng) \
|
||||||
declare_constant(Location::float_in_dbl) \
|
declare_constant(Location::float_in_dbl) \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue