This commit is contained in:
Vladimir Kozlov 2008-07-31 13:42:21 -07:00
commit 73379adb82
35 changed files with 3875 additions and 558 deletions

View File

@ -38,6 +38,8 @@ OPT_CFLAGS/SLOWER = -xO2
# Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876) # Problem with SS12 compiler, dtrace doesn't like the .o files (bug 6693876)
ifeq ($(COMPILER_REV), 5.9) ifeq ($(COMPILER_REV), 5.9)
# To avoid jvm98 crash
OPT_CFLAGS/instanceKlass.o = $(OPT_CFLAGS/SLOWER)
# Not clear this workaround could be skipped in some cases. # Not clear this workaround could be skipped in some cases.
OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/vmGCOperations.o = $(OPT_CFLAGS/SLOWER)
OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER) OPT_CFLAGS/java.o = $(OPT_CFLAGS/SLOWER)

View File

@ -779,9 +779,9 @@ class StubGenerator: public StubCodeGenerator {
__ shrl(end, CardTableModRefBS::card_shift); __ shrl(end, CardTableModRefBS::card_shift);
__ subl(end, start); // end --> count __ subl(end, start); // end --> count
__ BIND(L_loop); __ BIND(L_loop);
ExternalAddress base((address)ct->byte_map_base); intptr_t disp = (intptr_t) ct->byte_map_base;
Address index(start, count, Address::times_1, 0); Address cardtable(start, count, Address::times_1, disp);
__ movbyte(ArrayAddress(base, index), 0); __ movb(cardtable, 0);
__ decrement(count); __ decrement(count);
__ jcc(Assembler::greaterEqual, L_loop); __ jcc(Assembler::greaterEqual, L_loop);
} }

View File

@ -1222,8 +1222,16 @@ class StubGenerator: public StubCodeGenerator {
__ shrq(end, CardTableModRefBS::card_shift); __ shrq(end, CardTableModRefBS::card_shift);
__ subq(end, start); // number of bytes to copy __ subq(end, start); // number of bytes to copy
intptr_t disp = (intptr_t) ct->byte_map_base;
if (__ is_simm32(disp)) {
Address cardtable(noreg, noreg, Address::no_scale, disp);
__ lea(scratch, cardtable);
} else {
ExternalAddress cardtable((address)disp);
__ lea(scratch, cardtable);
}
const Register count = end; // 'end' register contains bytes count now const Register count = end; // 'end' register contains bytes count now
__ lea(scratch, ExternalAddress((address)ct->byte_map_base));
__ addq(start, scratch); __ addq(start, scratch);
__ BIND(L_loop); __ BIND(L_loop);
__ movb(Address(start, count, Address::times_1), 0); __ movb(Address(start, count, Address::times_1), 0);

View File

@ -3825,6 +3825,8 @@ int MatchRule::is_expensive() const {
strcmp(opType,"ConvL2D")==0 || strcmp(opType,"ConvL2D")==0 ||
strcmp(opType,"ConvL2F")==0 || strcmp(opType,"ConvL2F")==0 ||
strcmp(opType,"ConvL2I")==0 || strcmp(opType,"ConvL2I")==0 ||
strcmp(opType,"DecodeN")==0 ||
strcmp(opType,"EncodeP")==0 ||
strcmp(opType,"RoundDouble")==0 || strcmp(opType,"RoundDouble")==0 ||
strcmp(opType,"RoundFloat")==0 || strcmp(opType,"RoundFloat")==0 ||
strcmp(opType,"ReverseBytesI")==0 || strcmp(opType,"ReverseBytesI")==0 ||

View File

@ -351,7 +351,7 @@ void ciBlock::set_exception_range(int start_bci, int limit_bci) {
} }
#ifndef PRODUCT #ifndef PRODUCT
static char *flagnames[] = { static const char *flagnames[] = {
"Processed", "Processed",
"Handler", "Handler",
"MayThrow", "MayThrow",

View File

@ -188,10 +188,6 @@ void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) {
} }
} }
void OopMap::set_stack_obj(VMReg reg) {
set_xxx(reg, OopMapValue::stack_obj, VMRegImpl::Bad());
}
// OopMapSet // OopMapSet
OopMapSet::OopMapSet() { OopMapSet::OopMapSet() {
@ -399,8 +395,7 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
if ( loc != NULL ) { if ( loc != NULL ) {
if ( omv.type() == OopMapValue::oop_value ) { if ( omv.type() == OopMapValue::oop_value ) {
#ifdef ASSERT #ifdef ASSERT
if (COMPILER2_PRESENT(!DoEscapeAnalysis &&) if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
(((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
!Universe::heap()->is_in_or_null(*loc)) { !Universe::heap()->is_in_or_null(*loc)) {
tty->print_cr("# Found non oop pointer. Dumping state at failure"); tty->print_cr("# Found non oop pointer. Dumping state at failure");
// try to dump out some helpful debugging information // try to dump out some helpful debugging information
@ -431,17 +426,6 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
} }
} }
} }
#ifdef COMPILER2
if (DoEscapeAnalysis) {
for (OopMapStream oms(map, OopMapValue::stack_obj); !oms.is_done(); oms.next()) {
omv = oms.current();
assert(omv.is_stack_loc(), "should refer to stack location");
oop loc = (oop) fr->oopmapreg_to_location(omv.reg(),reg_map);
oop_fn->do_oop(&loc);
}
}
#endif // COMPILER2
} }
@ -540,9 +524,6 @@ void print_register_type(OopMapValue::oop_types x, VMReg optional,
st->print("Derived_oop_" ); st->print("Derived_oop_" );
optional->print_on(st); optional->print_on(st);
break; break;
case OopMapValue::stack_obj:
st->print("Stack");
break;
default: default:
ShouldNotReachHere(); ShouldNotReachHere();
} }

View File

@ -46,7 +46,7 @@ private:
public: public:
// Constants // Constants
enum { type_bits = 6, enum { type_bits = 5,
register_bits = BitsPerShort - type_bits }; register_bits = BitsPerShort - type_bits };
enum { type_shift = 0, enum { type_shift = 0,
@ -63,8 +63,7 @@ public:
value_value = 2, value_value = 2,
narrowoop_value = 4, narrowoop_value = 4,
callee_saved_value = 8, callee_saved_value = 8,
derived_oop_value= 16, derived_oop_value= 16 };
stack_obj = 32 };
// Constructors // Constructors
OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); } OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); }
@ -93,14 +92,12 @@ public:
bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; } bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; }
bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; } bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; }
bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; } bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; }
bool is_stack_obj() { return mask_bits(value(), type_mask_in_place) == stack_obj; }
void set_oop() { set_value((value() & register_mask_in_place) | oop_value); } void set_oop() { set_value((value() & register_mask_in_place) | oop_value); }
void set_value() { set_value((value() & register_mask_in_place) | value_value); } void set_value() { set_value((value() & register_mask_in_place) | value_value); }
void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); } void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); }
void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); } void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); }
void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); } void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); }
void set_stack_obj() { set_value((value() & register_mask_in_place) | stack_obj); }
VMReg reg() const { return VMRegImpl::as_VMReg(mask_bits(value(), register_mask_in_place) >> register_shift); } VMReg reg() const { return VMRegImpl::as_VMReg(mask_bits(value(), register_mask_in_place) >> register_shift); }
oop_types type() const { return (oop_types)mask_bits(value(), type_mask_in_place); } oop_types type() const { return (oop_types)mask_bits(value(), type_mask_in_place); }
@ -180,7 +177,6 @@ class OopMap: public ResourceObj {
void set_dead ( VMReg local); void set_dead ( VMReg local);
void set_callee_saved( VMReg local, VMReg caller_machine_register ); void set_callee_saved( VMReg local, VMReg caller_machine_register );
void set_derived_oop ( VMReg local, VMReg derived_from_local_register ); void set_derived_oop ( VMReg local, VMReg derived_from_local_register );
void set_stack_obj( VMReg local);
void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional); void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional);
int heap_size() const; int heap_size() const;

View File

@ -83,7 +83,7 @@ static bool is_init_with_ea(ciMethod* callee_method,
ciMethod* caller_method, Compile* C) { ciMethod* caller_method, Compile* C) {
// True when EA is ON and a java constructor is called or // True when EA is ON and a java constructor is called or
// a super constructor is called from an inlined java constructor. // a super constructor is called from an inlined java constructor.
return DoEscapeAnalysis && EliminateAllocations && return C->do_escape_analysis() && EliminateAllocations &&
( callee_method->is_initializer() || ( callee_method->is_initializer() ||
(caller_method->is_initializer() && (caller_method->is_initializer() &&
caller_method != C->method() && caller_method != C->method() &&

View File

@ -373,7 +373,7 @@
product(intx, AutoBoxCacheMax, 128, \ product(intx, AutoBoxCacheMax, 128, \
"Sets max value cached by the java.lang.Integer autobox cache") \ "Sets max value cached by the java.lang.Integer autobox cache") \
\ \
product(bool, DoEscapeAnalysis, false, \ product(bool, DoEscapeAnalysis, true, \
"Perform escape analysis") \ "Perform escape analysis") \
\ \
notproduct(bool, PrintEscapeAnalysis, false, \ notproduct(bool, PrintEscapeAnalysis, false, \
@ -388,6 +388,9 @@
product(intx, EliminateAllocationArraySizeLimit, 64, \ product(intx, EliminateAllocationArraySizeLimit, 64, \
"Array size (number of elements) limit for scalar replacement") \ "Array size (number of elements) limit for scalar replacement") \
\ \
product(intx, ValueSearchLimit, 1000, \
"Recursion limit in PhaseMacroExpand::value_from_mem_phi") \
\
product(intx, MaxLabelRootDepth, 1100, \ product(intx, MaxLabelRootDepth, 1100, \
"Maximum times call Label_Root to prevent stack overflow") \ "Maximum times call Label_Root to prevent stack overflow") \
\ \

View File

@ -631,61 +631,13 @@ uint CallNode::match_edge(uint idx) const {
bool CallNode::may_modify(const TypePtr *addr_t, PhaseTransform *phase) { bool CallNode::may_modify(const TypePtr *addr_t, PhaseTransform *phase) {
const TypeOopPtr *adrInst_t = addr_t->isa_oopptr(); const TypeOopPtr *adrInst_t = addr_t->isa_oopptr();
// if not an InstPtr or not an instance type, assume the worst // If not an OopPtr or not an instance type, assume the worst.
if (adrInst_t == NULL || !adrInst_t->is_known_instance_field()) { // Note: currently this method is called only for instance types.
if (adrInst_t == NULL || !adrInst_t->is_known_instance()) {
return true; return true;
} }
Compile *C = phase->C; // The instance_id is set only for scalar-replaceable allocations which
int offset = adrInst_t->offset(); // are not passed as arguments according to Escape Analysis.
assert(adrInst_t->klass_is_exact() && offset >= 0, "should be valid offset");
ciKlass* adr_k = adrInst_t->klass();
assert(adr_k->is_loaded() &&
adr_k->is_java_klass() &&
!adr_k->is_interface(),
"only non-abstract classes are expected");
int base_idx = C->get_alias_index(adrInst_t);
int size = BytesPerLong; // If we don't know the size, assume largest.
if (adrInst_t->isa_instptr()) {
ciField* field = C->alias_type(base_idx)->field();
if (field != NULL) {
size = field->size_in_bytes();
}
} else {
assert(adrInst_t->isa_aryptr(), "only arrays are expected");
size = type2aelembytes(adr_k->as_array_klass()->element_type()->basic_type());
}
ciMethod * meth = is_CallStaticJava() ? as_CallStaticJava()->method() : NULL;
BCEscapeAnalyzer *bcea = (meth != NULL) ? meth->get_bcea() : NULL;
const TypeTuple * d = tf()->domain();
for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
const Type* t = d->field_at(i);
Node *arg = in(i);
const Type *at = phase->type(arg);
if (at == TypePtr::NULL_PTR || at == Type::TOP)
continue; // null can't affect anything
const TypeOopPtr *at_ptr = at->isa_oopptr();
if (!arg->is_top() && (t->isa_oopptr() != NULL ||
t->isa_ptr() && at_ptr != NULL)) {
assert(at_ptr != NULL, "expecting an OopPtr");
ciKlass* at_k = at_ptr->klass();
if ((adrInst_t->base() == at_ptr->base()) &&
at_k->is_loaded() &&
at_k->is_java_klass()) {
// If we have found an argument matching addr_t, check if the field
// at the specified offset is modified.
if ((at_k->is_interface() || adr_k == at_k ||
adr_k->is_subclass_of(at_k) && !at_ptr->klass_is_exact()) &&
(bcea == NULL ||
bcea->is_arg_modified(i - TypeFunc::Parms, offset, size))) {
return true;
}
}
}
}
return false; return false;
} }

View File

@ -713,7 +713,9 @@ PhiNode* PhiNode::split_out_instance(const TypePtr* at, PhaseIterGVN *igvn) cons
assert(type() == Type::MEMORY && assert(type() == Type::MEMORY &&
(t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM || (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM ||
t->isa_oopptr() && !t->is_oopptr()->is_known_instance() && t->isa_oopptr() && !t->is_oopptr()->is_known_instance() &&
t->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop), t->is_oopptr()->cast_to_exactness(true)
->is_oopptr()->cast_to_ptr_type(t_oop->ptr())
->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop),
"bottom or raw memory required"); "bottom or raw memory required");
// Check if an appropriate node already exists. // Check if an appropriate node already exists.
@ -1089,6 +1091,8 @@ Node* PhiNode::unique_input(PhaseTransform* phase) {
if (rc == NULL || phase->type(rc) == Type::TOP) if (rc == NULL || phase->type(rc) == Type::TOP)
continue; // ignore unreachable control path continue; // ignore unreachable control path
Node* n = in(i); Node* n = in(i);
if (n == NULL)
continue;
Node* un = n->uncast(); Node* un = n->uncast();
if (un == NULL || un == this || phase->type(un) == Type::TOP) { if (un == NULL || un == this || phase->type(un) == Type::TOP) {
continue; // ignore if top, or in(i) and "this" are in a data cycle continue; // ignore if top, or in(i) and "this" are in a data cycle

View File

@ -583,18 +583,32 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
NOT_PRODUCT( verify_graph_edges(); ) NOT_PRODUCT( verify_graph_edges(); )
// Perform escape analysis // Perform escape analysis
if (_do_escape_analysis) if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
_congraph = new ConnectionGraph(this); TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
if (_congraph != NULL) { // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction.
NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); ) PhaseGVN* igvn = initial_gvn();
_congraph->compute_escape(); Node* oop_null = igvn->zerocon(T_OBJECT);
if (failing()) return; Node* noop_null = igvn->zerocon(T_NARROWOOP);
_congraph = new(comp_arena()) ConnectionGraph(this);
bool has_non_escaping_obj = _congraph->compute_escape();
#ifndef PRODUCT #ifndef PRODUCT
if (PrintEscapeAnalysis) { if (PrintEscapeAnalysis) {
_congraph->dump(); _congraph->dump();
} }
#endif #endif
// Cleanup.
if (oop_null->outcnt() == 0)
igvn->hash_delete(oop_null);
if (noop_null->outcnt() == 0)
igvn->hash_delete(noop_null);
if (!has_non_escaping_obj) {
_congraph = NULL;
}
if (failing()) return;
} }
// Now optimize // Now optimize
Optimize(); Optimize();
@ -995,9 +1009,14 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
int offset = tj->offset(); int offset = tj->offset();
TypePtr::PTR ptr = tj->ptr(); TypePtr::PTR ptr = tj->ptr();
// Known instance (scalarizable allocation) alias only with itself.
bool is_known_inst = tj->isa_oopptr() != NULL &&
tj->is_oopptr()->is_known_instance();
// Process weird unsafe references. // Process weird unsafe references.
if (offset == Type::OffsetBot && (tj->isa_instptr() /*|| tj->isa_klassptr()*/)) { if (offset == Type::OffsetBot && (tj->isa_instptr() /*|| tj->isa_klassptr()*/)) {
assert(InlineUnsafeOps, "indeterminate pointers come only from unsafe ops"); assert(InlineUnsafeOps, "indeterminate pointers come only from unsafe ops");
assert(!is_known_inst, "scalarizable allocation should not have unsafe references");
tj = TypeOopPtr::BOTTOM; tj = TypeOopPtr::BOTTOM;
ptr = tj->ptr(); ptr = tj->ptr();
offset = tj->offset(); offset = tj->offset();
@ -1005,14 +1024,20 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
// Array pointers need some flattening // Array pointers need some flattening
const TypeAryPtr *ta = tj->isa_aryptr(); const TypeAryPtr *ta = tj->isa_aryptr();
if( ta && _AliasLevel >= 2 ) { if( ta && is_known_inst ) {
if ( offset != Type::OffsetBot &&
offset > arrayOopDesc::length_offset_in_bytes() ) {
offset = Type::OffsetBot; // Flatten constant access into array body only
tj = ta = TypeAryPtr::make(ptr, ta->ary(), ta->klass(), true, offset, ta->instance_id());
}
} else if( ta && _AliasLevel >= 2 ) {
// For arrays indexed by constant indices, we flatten the alias // For arrays indexed by constant indices, we flatten the alias
// space to include all of the array body. Only the header, klass // space to include all of the array body. Only the header, klass
// and array length can be accessed un-aliased. // and array length can be accessed un-aliased.
if( offset != Type::OffsetBot ) { if( offset != Type::OffsetBot ) {
if( ta->const_oop() ) { // methodDataOop or methodOop if( ta->const_oop() ) { // methodDataOop or methodOop
offset = Type::OffsetBot; // Flatten constant access into array body offset = Type::OffsetBot; // Flatten constant access into array body
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),ta->ary(),ta->klass(),false,Type::OffsetBot, ta->instance_id()); tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),ta->ary(),ta->klass(),false,offset);
} else if( offset == arrayOopDesc::length_offset_in_bytes() ) { } else if( offset == arrayOopDesc::length_offset_in_bytes() ) {
// range is OK as-is. // range is OK as-is.
tj = ta = TypeAryPtr::RANGE; tj = ta = TypeAryPtr::RANGE;
@ -1026,29 +1051,29 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
ptr = TypePtr::BotPTR; ptr = TypePtr::BotPTR;
} else { // Random constant offset into array body } else { // Random constant offset into array body
offset = Type::OffsetBot; // Flatten constant access into array body offset = Type::OffsetBot; // Flatten constant access into array body
tj = ta = TypeAryPtr::make(ptr,ta->ary(),ta->klass(),false,Type::OffsetBot, ta->instance_id()); tj = ta = TypeAryPtr::make(ptr,ta->ary(),ta->klass(),false,offset);
} }
} }
// Arrays of fixed size alias with arrays of unknown size. // Arrays of fixed size alias with arrays of unknown size.
if (ta->size() != TypeInt::POS) { if (ta->size() != TypeInt::POS) {
const TypeAry *tary = TypeAry::make(ta->elem(), TypeInt::POS); const TypeAry *tary = TypeAry::make(ta->elem(), TypeInt::POS);
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,ta->klass(),false,offset, ta->instance_id()); tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,ta->klass(),false,offset);
} }
// Arrays of known objects become arrays of unknown objects. // Arrays of known objects become arrays of unknown objects.
if (ta->elem()->isa_narrowoop() && ta->elem() != TypeNarrowOop::BOTTOM) { if (ta->elem()->isa_narrowoop() && ta->elem() != TypeNarrowOop::BOTTOM) {
const TypeAry *tary = TypeAry::make(TypeNarrowOop::BOTTOM, ta->size()); const TypeAry *tary = TypeAry::make(TypeNarrowOop::BOTTOM, ta->size());
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset, ta->instance_id()); tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset);
} }
if (ta->elem()->isa_oopptr() && ta->elem() != TypeInstPtr::BOTTOM) { if (ta->elem()->isa_oopptr() && ta->elem() != TypeInstPtr::BOTTOM) {
const TypeAry *tary = TypeAry::make(TypeInstPtr::BOTTOM, ta->size()); const TypeAry *tary = TypeAry::make(TypeInstPtr::BOTTOM, ta->size());
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset, ta->instance_id()); tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset);
} }
// Arrays of bytes and of booleans both use 'bastore' and 'baload' so // Arrays of bytes and of booleans both use 'bastore' and 'baload' so
// cannot be distinguished by bytecode alone. // cannot be distinguished by bytecode alone.
if (ta->elem() == TypeInt::BOOL) { if (ta->elem() == TypeInt::BOOL) {
const TypeAry *tary = TypeAry::make(TypeInt::BYTE, ta->size()); const TypeAry *tary = TypeAry::make(TypeInt::BYTE, ta->size());
ciKlass* aklass = ciTypeArrayKlass::make(T_BYTE); ciKlass* aklass = ciTypeArrayKlass::make(T_BYTE);
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,aklass,false,offset, ta->instance_id()); tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,aklass,false,offset);
} }
// During the 2nd round of IterGVN, NotNull castings are removed. // During the 2nd round of IterGVN, NotNull castings are removed.
// Make sure the Bottom and NotNull variants alias the same. // Make sure the Bottom and NotNull variants alias the same.
@ -1068,21 +1093,24 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
if( ptr == TypePtr::Constant ) { if( ptr == TypePtr::Constant ) {
// No constant oop pointers (such as Strings); they alias with // No constant oop pointers (such as Strings); they alias with
// unknown strings. // unknown strings.
assert(!is_known_inst, "not scalarizable allocation");
tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset); tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
} else if( to->is_known_instance_field() ) { } else if( is_known_inst ) {
tj = to; // Keep NotNull and klass_is_exact for instance type tj = to; // Keep NotNull and klass_is_exact for instance type
} else if( ptr == TypePtr::NotNull || to->klass_is_exact() ) { } else if( ptr == TypePtr::NotNull || to->klass_is_exact() ) {
// During the 2nd round of IterGVN, NotNull castings are removed. // During the 2nd round of IterGVN, NotNull castings are removed.
// Make sure the Bottom and NotNull variants alias the same. // Make sure the Bottom and NotNull variants alias the same.
// Also, make sure exact and non-exact variants alias the same. // Also, make sure exact and non-exact variants alias the same.
tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset, to->instance_id()); tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
} }
// Canonicalize the holder of this field // Canonicalize the holder of this field
ciInstanceKlass *k = to->klass()->as_instance_klass(); ciInstanceKlass *k = to->klass()->as_instance_klass();
if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) { if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) {
// First handle header references such as a LoadKlassNode, even if the // First handle header references such as a LoadKlassNode, even if the
// object's klass is unloaded at compile time (4965979). // object's klass is unloaded at compile time (4965979).
tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset, to->instance_id()); if (!is_known_inst) { // Do it only for non-instance types
tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset);
}
} else if (offset < 0 || offset >= k->size_helper() * wordSize) { } else if (offset < 0 || offset >= k->size_helper() * wordSize) {
to = NULL; to = NULL;
tj = TypeOopPtr::BOTTOM; tj = TypeOopPtr::BOTTOM;
@ -1090,7 +1118,11 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
} else { } else {
ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset); ciInstanceKlass *canonical_holder = k->get_canonical_holder(offset);
if (!k->equals(canonical_holder) || tj->offset() != offset) { if (!k->equals(canonical_holder) || tj->offset() != offset) {
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, false, NULL, offset, to->instance_id()); if( is_known_inst ) {
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, true, NULL, offset, to->instance_id());
} else {
tj = to = TypeInstPtr::make(to->ptr(), canonical_holder, false, NULL, offset);
}
} }
} }
} }
@ -1276,7 +1308,9 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
assert(flat != TypePtr::BOTTOM, "cannot alias-analyze an untyped ptr"); assert(flat != TypePtr::BOTTOM, "cannot alias-analyze an untyped ptr");
if (flat->isa_oopptr() && !flat->isa_klassptr()) { if (flat->isa_oopptr() && !flat->isa_klassptr()) {
const TypeOopPtr* foop = flat->is_oopptr(); const TypeOopPtr* foop = flat->is_oopptr();
const TypePtr* xoop = foop->cast_to_exactness(!foop->klass_is_exact())->is_ptr(); // Scalarizable allocations have exact klass always.
bool exact = !foop->klass_is_exact() || foop->is_known_instance();
const TypePtr* xoop = foop->cast_to_exactness(exact)->is_ptr();
assert(foop == flatten_alias_type(xoop), "exactness must not affect alias type"); assert(foop == flatten_alias_type(xoop), "exactness must not affect alias type");
} }
assert(flat == flatten_alias_type(flat), "exact bit doesn't matter"); assert(flat == flatten_alias_type(flat), "exact bit doesn't matter");

File diff suppressed because it is too large Load Diff

View File

@ -178,23 +178,33 @@ public:
// count of outgoing edges // count of outgoing edges
uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); } uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); }
// node index of target of outgoing edge "e" // node index of target of outgoing edge "e"
uint edge_target(uint e) const; uint edge_target(uint e) const {
assert(_edges != NULL, "valid edge index");
return (_edges->at(e) >> EdgeShift);
}
// type of outgoing edge "e" // type of outgoing edge "e"
EdgeType edge_type(uint e) const; EdgeType edge_type(uint e) const {
assert(_edges != NULL, "valid edge index");
return (EdgeType) (_edges->at(e) & EdgeMask);
}
// add a edge of the specified type pointing to the specified target // add a edge of the specified type pointing to the specified target
void add_edge(uint targIdx, EdgeType et); void add_edge(uint targIdx, EdgeType et);
// remove an edge of the specified type pointing to the specified target // remove an edge of the specified type pointing to the specified target
void remove_edge(uint targIdx, EdgeType et); void remove_edge(uint targIdx, EdgeType et);
#ifndef PRODUCT #ifndef PRODUCT
void dump() const; void dump(bool print_state=true) const;
#endif #endif
}; };
class ConnectionGraph: public ResourceObj { class ConnectionGraph: public ResourceObj {
private: private:
GrowableArray<PointsToNode>* _nodes; // Connection graph nodes indexed GrowableArray<PointsToNode> _nodes; // Connection graph nodes indexed
// by ideal node index. // by ideal node index.
Unique_Node_List _delayed_worklist; // Nodes to be processed before Unique_Node_List _delayed_worklist; // Nodes to be processed before
@ -207,24 +217,22 @@ private:
// is still being collected. If false, // is still being collected. If false,
// no new nodes will be processed. // no new nodes will be processed.
bool _has_allocations; // Indicates whether method has any
// non-escaping allocations.
uint _phantom_object; // Index of globally escaping object uint _phantom_object; // Index of globally escaping object
// that pointer values loaded from // that pointer values loaded from
// a field which has not been set // a field which has not been set
// are assumed to point to. // are assumed to point to.
uint _oop_null; // ConP(#NULL)
uint _noop_null; // ConN(#NULL)
Compile * _compile; // Compile object for current compilation Compile * _compile; // Compile object for current compilation
// address of an element in _nodes. Used when the element is to be modified // Address of an element in _nodes. Used when the element is to be modified
PointsToNode *ptnode_adr(uint idx) { PointsToNode *ptnode_adr(uint idx) const {
if ((uint)_nodes->length() <= idx) { // There should be no new ideal nodes during ConnectionGraph build,
// expand _nodes array // growableArray::adr_at() will throw assert otherwise.
PointsToNode dummy = _nodes->at_grow(idx); return _nodes.adr_at(idx);
}
return _nodes->adr_at(idx);
} }
uint nodes_size() const { return _nodes.length(); }
// Add node to ConnectionGraph. // Add node to ConnectionGraph.
void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done); void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done);
@ -307,30 +315,30 @@ private:
// Set the escape state of a node // Set the escape state of a node
void set_escape_state(uint ni, PointsToNode::EscapeState es); void set_escape_state(uint ni, PointsToNode::EscapeState es);
// Get Compile object for current compilation.
Compile *C() const { return _compile; }
public: public:
ConnectionGraph(Compile *C); ConnectionGraph(Compile *C);
// Check for non-escaping candidates
static bool has_candidates(Compile *C);
// Compute the escape information // Compute the escape information
void compute_escape(); bool compute_escape();
// escape state of a node // escape state of a node
PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase); PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase);
// other information we have collected // other information we have collected
bool is_scalar_replaceable(Node *n) { bool is_scalar_replaceable(Node *n) {
if (_collecting) if (_collecting || (n->_idx >= nodes_size()))
return false; return false;
PointsToNode ptn = _nodes->at_grow(n->_idx); PointsToNode* ptn = ptnode_adr(n->_idx);
return ptn.escape_state() == PointsToNode::NoEscape && ptn._scalar_replaceable; return ptn->escape_state() == PointsToNode::NoEscape && ptn->_scalar_replaceable;
} }
bool hidden_alias(Node *n) { bool hidden_alias(Node *n) {
if (_collecting) if (_collecting || (n->_idx >= nodes_size()))
return true; return true;
PointsToNode ptn = _nodes->at_grow(n->_idx); PointsToNode* ptn = ptnode_adr(n->_idx);
return (ptn.escape_state() != PointsToNode::NoEscape) || ptn._hidden_alias; return (ptn->escape_state() != PointsToNode::NoEscape) || ptn->_hidden_alias;
} }
#ifndef PRODUCT #ifndef PRODUCT

View File

@ -473,10 +473,12 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) {
print_prop("is_dontcare", "false"); print_prop("is_dontcare", "false");
} }
#ifdef ASSERT
Node* old = C->matcher()->find_old_node(node); Node* old = C->matcher()->find_old_node(node);
if (old != NULL) { if (old != NULL) {
print_prop("old_node_idx", old->_idx); print_prop("old_node_idx", old->_idx);
} }
#endif
} }
if (node->is_Proj()) { if (node->is_Proj()) {

View File

@ -725,6 +725,11 @@ static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) {
int true_path = phi->is_diamond_phi(); int true_path = phi->is_diamond_phi();
if( true_path == 0 ) return NULL; if( true_path == 0 ) return NULL;
// Make sure that iff and the control of the phi are different. This
// should really only happen for dead control flow since it requires
// an illegal cycle.
if (phi->in(0)->in(1)->in(0) == iff) return NULL;
// phi->region->if_proj->ifnode->bool->cmp // phi->region->if_proj->ifnode->bool->cmp
BoolNode *bol2 = phi->in(0)->in(1)->in(0)->in(1)->as_Bool(); BoolNode *bol2 = phi->in(0)->in(1)->in(0)->in(1)->as_Bool();
@ -751,6 +756,7 @@ static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) {
} }
Node* new_bol = (flip ? phase->transform( bol2->negate(phase) ) : bol2); Node* new_bol = (flip ? phase->transform( bol2->negate(phase) ) : bol2);
assert(new_bol != iff->in(1), "must make progress");
iff->set_req(1, new_bol); iff->set_req(1, new_bol);
// Intervening diamond probably goes dead // Intervening diamond probably goes dead
phase->C->set_major_progress(); phase->C->set_major_progress();

View File

@ -322,7 +322,7 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, int *ready_cnt, VectorSe
uint choice = 0; // Bigger is most important uint choice = 0; // Bigger is most important
uint latency = 0; // Bigger is scheduled first uint latency = 0; // Bigger is scheduled first
uint score = 0; // Bigger is better uint score = 0; // Bigger is better
uint idx; // Index in worklist int idx = -1; // Index in worklist
for( uint i=0; i<cnt; i++ ) { // Inspect entire worklist for( uint i=0; i<cnt; i++ ) { // Inspect entire worklist
// Order in worklist is used to break ties. // Order in worklist is used to break ties.
@ -412,9 +412,10 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, int *ready_cnt, VectorSe
} }
} // End of for all ready nodes in worklist } // End of for all ready nodes in worklist
Node *n = worklist[idx]; // Get the winner assert(idx >= 0, "index should be set");
Node *n = worklist[(uint)idx]; // Get the winner
worklist.map(idx,worklist.pop()); // Compress worklist worklist.map((uint)idx, worklist.pop()); // Compress worklist
return n; return n;
} }
@ -599,7 +600,14 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect
assert(cfg->_bbs[oop_store->_idx]->_dom_depth <= this->_dom_depth, "oop_store must dominate card-mark"); assert(cfg->_bbs[oop_store->_idx]->_dom_depth <= this->_dom_depth, "oop_store must dominate card-mark");
} }
} }
if( n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_MemBarAcquire ) { if( n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_MemBarAcquire &&
n->req() > TypeFunc::Parms ) {
// MemBarAcquire could be created without Precedent edge.
// del_req() replaces the specified edge with the last input edge
// and then removes the last edge. If the specified edge > number of
// edges the last edge will be moved outside of the input edges array
// and the edge will be lost. This is why this code should be
// executed only when Precedent (== TypeFunc::Parms) edge is present.
Node *x = n->in(TypeFunc::Parms); Node *x = n->in(TypeFunc::Parms);
n->del_req(TypeFunc::Parms); n->del_req(TypeFunc::Parms);
n->add_prec(x); n->add_prec(x);

View File

@ -578,7 +578,8 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) {
Node *cmov = conditional_move( n ); Node *cmov = conditional_move( n );
if( cmov ) return cmov; if( cmov ) return cmov;
} }
if( n->is_CFG() || n_op == Op_StorePConditional || n_op == Op_StoreLConditional || n_op == Op_CompareAndSwapI || n_op == Op_CompareAndSwapL ||n_op == Op_CompareAndSwapP) return n; if( n->is_CFG() || n->is_LoadStore() )
return n;
if( n_op == Op_Opaque1 || // Opaque nodes cannot be mod'd if( n_op == Op_Opaque1 || // Opaque nodes cannot be mod'd
n_op == Op_Opaque2 ) { n_op == Op_Opaque2 ) {
if( !C->major_progress() ) // If chance of no more loop opts... if( !C->major_progress() ) // If chance of no more loop opts...
@ -1891,18 +1892,19 @@ void PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, N
_igvn.hash_delete(use); _igvn.hash_delete(use);
use->set_req(j, n_clone); use->set_req(j, n_clone);
_igvn._worklist.push(use); _igvn._worklist.push(use);
Node* use_c;
if (!use->is_Phi()) { if (!use->is_Phi()) {
Node* use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0);
set_ctrl(n_clone, use_c);
assert(!loop->is_member(get_loop(use_c)), "should be outside loop");
get_loop(use_c)->_body.push(n_clone);
} else { } else {
// Use in a phi is considered a use in the associated predecessor block // Use in a phi is considered a use in the associated predecessor block
Node *prevbb = use->in(0)->in(j); use_c = use->in(0)->in(j);
set_ctrl(n_clone, prevbb);
assert(!loop->is_member(get_loop(prevbb)), "should be outside loop");
get_loop(prevbb)->_body.push(n_clone);
} }
if (use_c->is_CountedLoop()) {
use_c = use_c->in(LoopNode::EntryControl);
}
set_ctrl(n_clone, use_c);
assert(!loop->is_member(get_loop(use_c)), "should be outside loop");
get_loop(use_c)->_body.push(n_clone);
_igvn.register_new_node_with_optimizer(n_clone); _igvn.register_new_node_with_optimizer(n_clone);
#if !defined(PRODUCT) #if !defined(PRODUCT)
if (TracePartialPeeling) { if (TracePartialPeeling) {

View File

@ -194,9 +194,10 @@ void PhaseMacroExpand::eliminate_card_mark(Node *p2x) {
} }
// Search for a memory operation for the specified memory slice. // Search for a memory operation for the specified memory slice.
static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc) { static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) {
Node *orig_mem = mem; Node *orig_mem = mem;
Node *alloc_mem = alloc->in(TypeFunc::Memory); Node *alloc_mem = alloc->in(TypeFunc::Memory);
const TypeOopPtr *tinst = phase->C->get_adr_type(alias_idx)->isa_oopptr();
while (true) { while (true) {
if (mem == alloc_mem || mem == start_mem ) { if (mem == alloc_mem || mem == start_mem ) {
return mem; // hit one of our sentinals return mem; // hit one of our sentinals
@ -208,7 +209,13 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me
// already know that the object is safe to eliminate. // already know that the object is safe to eliminate.
if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) { if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) {
return in; return in;
} else if (in->is_Call() || in->is_MemBar()) { } else if (in->is_Call()) {
CallNode *call = in->as_Call();
if (!call->may_modify(tinst, phase)) {
mem = call->in(TypeFunc::Memory);
}
mem = in->in(TypeFunc::Memory);
} else if (in->is_MemBar()) {
mem = in->in(TypeFunc::Memory); mem = in->in(TypeFunc::Memory);
} else { } else {
assert(false, "unexpected projection"); assert(false, "unexpected projection");
@ -231,8 +238,7 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me
} else { } else {
return mem; return mem;
} }
if (mem == orig_mem) assert(mem != orig_mem, "dead memory loop");
return mem;
} }
} }
@ -241,27 +247,50 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me
// on the input paths. // on the input paths.
// Note: this function is recursive, its depth is limied by the "level" argument // Note: this function is recursive, its depth is limied by the "level" argument
// Returns the computed Phi, or NULL if it cannot compute it. // Returns the computed Phi, or NULL if it cannot compute it.
Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, int level) { Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level) {
assert(mem->is_Phi(), "sanity");
if (level <= 0) {
return NULL;
}
int alias_idx = C->get_alias_index(adr_t); int alias_idx = C->get_alias_index(adr_t);
int offset = adr_t->offset(); int offset = adr_t->offset();
int instance_id = adr_t->instance_id(); int instance_id = adr_t->instance_id();
// Check if an appropriate value phi already exists.
Node* region = mem->in(0);
for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) {
Node* phi = region->fast_out(k);
if (phi->is_Phi() && phi != mem &&
phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) {
return phi;
}
}
// Check if an appropriate new value phi already exists.
Node* new_phi = NULL;
uint size = value_phis->size();
for (uint i=0; i < size; i++) {
if ( mem->_idx == value_phis->index_at(i) ) {
return value_phis->node_at(i);
}
}
if (level <= 0) {
return NULL; // Give up: phi tree too deep
}
Node *start_mem = C->start()->proj_out(TypeFunc::Memory); Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
Node *alloc_mem = alloc->in(TypeFunc::Memory); Node *alloc_mem = alloc->in(TypeFunc::Memory);
uint length = mem->req(); uint length = mem->req();
GrowableArray <Node *> values(length, length, NULL); GrowableArray <Node *> values(length, length, NULL);
// create a new Phi for the value
PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset);
transform_later(phi);
value_phis->push(phi, mem->_idx);
for (uint j = 1; j < length; j++) { for (uint j = 1; j < length; j++) {
Node *in = mem->in(j); Node *in = mem->in(j);
if (in == NULL || in->is_top()) { if (in == NULL || in->is_top()) {
values.at_put(j, in); values.at_put(j, in);
} else { } else {
Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc); Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc, &_igvn);
if (val == start_mem || val == alloc_mem) { if (val == start_mem || val == alloc_mem) {
// hit a sentinel, return appropriate 0 value // hit a sentinel, return appropriate 0 value
values.at_put(j, _igvn.zerocon(ft)); values.at_put(j, _igvn.zerocon(ft));
@ -280,33 +309,18 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *
} else if(val->is_Proj() && val->in(0) == alloc) { } else if(val->is_Proj() && val->in(0) == alloc) {
values.at_put(j, _igvn.zerocon(ft)); values.at_put(j, _igvn.zerocon(ft));
} else if (val->is_Phi()) { } else if (val->is_Phi()) {
// Check if an appropriate node already exists. val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, value_phis, level-1);
Node* region = val->in(0); if (val == NULL) {
Node* old_phi = NULL; return NULL;
for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) {
Node* phi = region->fast_out(k);
if (phi->is_Phi() && phi != val &&
phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) {
old_phi = phi;
break;
}
}
if (old_phi == NULL) {
val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, level-1);
if (val == NULL) {
return NULL;
}
values.at_put(j, val);
} else {
values.at_put(j, old_phi);
} }
values.at_put(j, val);
} else { } else {
return NULL; // unknown node on this path assert(false, "unknown node on this path");
return NULL; // unknown node on this path
} }
} }
} }
// create a new Phi for the value // Set Phi's inputs
PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset);
for (uint j = 1; j < length; j++) { for (uint j = 1; j < length; j++) {
if (values.at(j) == mem) { if (values.at(j) == mem) {
phi->init_req(j, phi); phi->init_req(j, phi);
@ -314,7 +328,6 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *
phi->init_req(j, values.at(j)); phi->init_req(j, values.at(j));
} }
} }
transform_later(phi);
return phi; return phi;
} }
@ -329,7 +342,8 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type
Node *start_mem = C->start()->proj_out(TypeFunc::Memory); Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
Node *alloc_ctrl = alloc->in(TypeFunc::Control); Node *alloc_ctrl = alloc->in(TypeFunc::Control);
Node *alloc_mem = alloc->in(TypeFunc::Memory); Node *alloc_mem = alloc->in(TypeFunc::Memory);
VectorSet visited(Thread::current()->resource_area()); Arena *a = Thread::current()->resource_area();
VectorSet visited(a);
bool done = sfpt_mem == alloc_mem; bool done = sfpt_mem == alloc_mem;
@ -338,7 +352,7 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type
if (visited.test_set(mem->_idx)) { if (visited.test_set(mem->_idx)) {
return NULL; // found a loop, give up return NULL; // found a loop, give up
} }
mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc); mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc, &_igvn);
if (mem == start_mem || mem == alloc_mem) { if (mem == start_mem || mem == alloc_mem) {
done = true; // hit a sentinel, return appropriate 0 value done = true; // hit a sentinel, return appropriate 0 value
} else if (mem->is_Initialize()) { } else if (mem->is_Initialize()) {
@ -362,7 +376,7 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type
Node *unique_input = NULL; Node *unique_input = NULL;
Node *top = C->top(); Node *top = C->top();
for (uint i = 1; i < mem->req(); i++) { for (uint i = 1; i < mem->req(); i++) {
Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc); Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc, &_igvn);
if (n == NULL || n == top || n == mem) { if (n == NULL || n == top || n == mem) {
continue; continue;
} else if (unique_input == NULL) { } else if (unique_input == NULL) {
@ -389,9 +403,18 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type
return mem->in(MemNode::ValueIn); return mem->in(MemNode::ValueIn);
} else if (mem->is_Phi()) { } else if (mem->is_Phi()) {
// attempt to produce a Phi reflecting the values on the input paths of the Phi // attempt to produce a Phi reflecting the values on the input paths of the Phi
Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, 8); Node_Stack value_phis(a, 8);
Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, ValueSearchLimit);
if (phi != NULL) { if (phi != NULL) {
return phi; return phi;
} else {
// Kill all new Phis
while(value_phis.is_nonempty()) {
Node* n = value_phis.node();
_igvn.hash_delete(n);
_igvn.subsume_node(n, C->top());
value_phis.pop();
}
} }
} }
} }
@ -448,7 +471,7 @@ bool PhaseMacroExpand::can_eliminate_allocation(AllocateNode *alloc, GrowableArr
Node* n = use->fast_out(k); Node* n = use->fast_out(k);
if (!n->is_Store() && n->Opcode() != Op_CastP2X) { if (!n->is_Store() && n->Opcode() != Op_CastP2X) {
DEBUG_ONLY(disq_node = n;) DEBUG_ONLY(disq_node = n;)
if (n->is_Load()) { if (n->is_Load() || n->is_LoadStore()) {
NOT_PRODUCT(fail_eliminate = "Field load";) NOT_PRODUCT(fail_eliminate = "Field load";)
} else { } else {
NOT_PRODUCT(fail_eliminate = "Not store field referrence";) NOT_PRODUCT(fail_eliminate = "Not store field referrence";)

View File

@ -79,7 +79,7 @@ private:
const TypeFunc* slow_call_type, const TypeFunc* slow_call_type,
address slow_call_address); address slow_call_address);
Node *value_from_mem(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc); Node *value_from_mem(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc);
Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc, int level); Node *value_from_mem_phi(Node *mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level);
bool eliminate_allocate_node(AllocateNode *alloc); bool eliminate_allocate_node(AllocateNode *alloc);
bool can_eliminate_allocation(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints); bool can_eliminate_allocation(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints);

View File

@ -94,14 +94,19 @@ Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr,
if (tinst == NULL || !tinst->is_known_instance_field()) if (tinst == NULL || !tinst->is_known_instance_field())
return mchain; // don't try to optimize non-instance types return mchain; // don't try to optimize non-instance types
uint instance_id = tinst->instance_id(); uint instance_id = tinst->instance_id();
Node *start_mem = phase->C->start()->proj_out(TypeFunc::Memory);
Node *prev = NULL; Node *prev = NULL;
Node *result = mchain; Node *result = mchain;
while (prev != result) { while (prev != result) {
prev = result; prev = result;
if (result == start_mem)
break; // hit one of our sentinals
// skip over a call which does not affect this memory slice // skip over a call which does not affect this memory slice
if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) { if (result->is_Proj() && result->as_Proj()->_con == TypeFunc::Memory) {
Node *proj_in = result->in(0); Node *proj_in = result->in(0);
if (proj_in->is_Call()) { if (proj_in->is_Allocate() && proj_in->_idx == instance_id) {
break; // hit one of our sentinals
} else if (proj_in->is_Call()) {
CallNode *call = proj_in->as_Call(); CallNode *call = proj_in->as_Call();
if (!call->may_modify(t_adr, phase)) { if (!call->may_modify(t_adr, phase)) {
result = call->in(TypeFunc::Memory); result = call->in(TypeFunc::Memory);
@ -115,6 +120,8 @@ Node *MemNode::optimize_simple_memory_chain(Node *mchain, const TypePtr *t_adr,
} }
} else if (proj_in->is_MemBar()) { } else if (proj_in->is_MemBar()) {
result = proj_in->in(TypeFunc::Memory); result = proj_in->in(TypeFunc::Memory);
} else {
assert(false, "unexpected projection");
} }
} else if (result->is_MergeMem()) { } else if (result->is_MergeMem()) {
result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty); result = step_through_mergemem(phase, result->as_MergeMem(), t_adr, NULL, tty);
@ -135,7 +142,9 @@ Node *MemNode::optimize_memory_chain(Node *mchain, const TypePtr *t_adr, PhaseGV
const TypePtr *t = mphi->adr_type(); const TypePtr *t = mphi->adr_type();
if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM || if (t == TypePtr::BOTTOM || t == TypeRawPtr::BOTTOM ||
t->isa_oopptr() && !t->is_oopptr()->is_known_instance() && t->isa_oopptr() && !t->is_oopptr()->is_known_instance() &&
t->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop) { t->is_oopptr()->cast_to_exactness(true)
->is_oopptr()->cast_to_ptr_type(t_oop->ptr())
->is_oopptr()->cast_to_instance_id(t_oop->instance_id()) == t_oop) {
// clone the Phi with our address type // clone the Phi with our address type
result = mphi->split_out_instance(t_adr, igvn); result = mphi->split_out_instance(t_adr, igvn);
} else { } else {

View File

@ -607,6 +607,7 @@ public:
}; };
//------------------------------LoadStoreNode--------------------------- //------------------------------LoadStoreNode---------------------------
// Note: is_Mem() method returns 'true' for this class.
class LoadStoreNode : public Node { class LoadStoreNode : public Node {
public: public:
enum { enum {

View File

@ -1399,6 +1399,10 @@ public:
uint index() const { uint index() const {
return _inode_top->indx; return _inode_top->indx;
} }
uint index_at(uint i) const {
assert(_inodes + i <= _inode_top, "in range");
return _inodes[i].indx;
}
void set_node(Node *n) { void set_node(Node *n) {
_inode_top->node = n; _inode_top->node = n;
} }

View File

@ -479,7 +479,7 @@ class Parse : public GraphKit {
float branch_prediction(float &cnt, BoolTest::mask btest, int target_bci); float branch_prediction(float &cnt, BoolTest::mask btest, int target_bci);
bool seems_never_taken(float prob); bool seems_never_taken(float prob);
void do_ifnull(BoolTest::mask btest); void do_ifnull(BoolTest::mask btest, Node* c);
void do_if(BoolTest::mask btest, Node* c); void do_if(BoolTest::mask btest, Node* c);
void repush_if_args(); void repush_if_args();
void adjust_map_after_if(BoolTest::mask btest, Node* c, float prob, void adjust_map_after_if(BoolTest::mask btest, Node* c, float prob,

View File

@ -875,6 +875,8 @@ bool Parse::seems_never_taken(float prob) {
return prob < PROB_MIN; return prob < PROB_MIN;
} }
//-------------------------------repush_if_args--------------------------------
// Push arguments of an "if" bytecode back onto the stack by adjusting _sp.
inline void Parse::repush_if_args() { inline void Parse::repush_if_args() {
#ifndef PRODUCT #ifndef PRODUCT
if (PrintOpto && WizardMode) { if (PrintOpto && WizardMode) {
@ -892,7 +894,7 @@ inline void Parse::repush_if_args() {
} }
//----------------------------------do_ifnull---------------------------------- //----------------------------------do_ifnull----------------------------------
void Parse::do_ifnull(BoolTest::mask btest) { void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
int target_bci = iter().get_dest(); int target_bci = iter().get_dest();
Block* branch_block = successor_for_bci(target_bci); Block* branch_block = successor_for_bci(target_bci);
@ -904,7 +906,7 @@ void Parse::do_ifnull(BoolTest::mask btest) {
// (An earlier version of do_ifnull omitted this trap for OSR methods.) // (An earlier version of do_ifnull omitted this trap for OSR methods.)
#ifndef PRODUCT #ifndef PRODUCT
if (PrintOpto && Verbose) if (PrintOpto && Verbose)
tty->print_cr("Never-taken backedge stops compilation at bci %d",bci()); tty->print_cr("Never-taken edge stops compilation at bci %d",bci());
#endif #endif
repush_if_args(); // to gather stats on loop repush_if_args(); // to gather stats on loop
// We need to mark this branch as taken so that if we recompile we will // We need to mark this branch as taken so that if we recompile we will
@ -923,18 +925,7 @@ void Parse::do_ifnull(BoolTest::mask btest) {
return; return;
} }
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint(target_bci);
explicit_null_checks_inserted++; explicit_null_checks_inserted++;
Node* a = null();
Node* b = pop();
Node* c = _gvn.transform( new (C, 3) CmpPNode(b, a) );
// Make a cast-away-nullness that is control dependent on the test
const Type *t = _gvn.type(b);
const Type *t_not_null = t->join(TypePtr::NOTNULL);
Node *cast = new (C, 2) CastPPNode(b,t_not_null);
// Generate real control flow // Generate real control flow
Node *tst = _gvn.transform( new (C, 2) BoolNode( c, btest ) ); Node *tst = _gvn.transform( new (C, 2) BoolNode( c, btest ) );
@ -996,7 +987,7 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
if (prob == PROB_UNKNOWN) { if (prob == PROB_UNKNOWN) {
#ifndef PRODUCT #ifndef PRODUCT
if (PrintOpto && Verbose) if (PrintOpto && Verbose)
tty->print_cr("Never-taken backedge stops compilation at bci %d",bci()); tty->print_cr("Never-taken edge stops compilation at bci %d",bci());
#endif #endif
repush_if_args(); // to gather stats on loop repush_if_args(); // to gather stats on loop
// We need to mark this branch as taken so that if we recompile we will // We need to mark this branch as taken so that if we recompile we will
@ -2100,11 +2091,15 @@ void Parse::do_one_bytecode() {
break; break;
} }
case Bytecodes::_ifnull: case Bytecodes::_ifnull: btest = BoolTest::eq; goto handle_if_null;
do_ifnull(BoolTest::eq); case Bytecodes::_ifnonnull: btest = BoolTest::ne; goto handle_if_null;
break; handle_if_null:
case Bytecodes::_ifnonnull: // If this is a backwards branch in the bytecodes, add Safepoint
do_ifnull(BoolTest::ne); maybe_add_safepoint(iter().get_dest());
a = null();
b = pop();
c = _gvn.transform( new (C, 3) CmpPNode(b, a) );
do_ifnull(btest, c);
break; break;
case Bytecodes::_if_acmpeq: btest = BoolTest::eq; goto handle_if_acmp; case Bytecodes::_if_acmpeq: btest = BoolTest::eq; goto handle_if_acmp;

View File

@ -1196,8 +1196,10 @@ void SuperWord::construct_bb() {
Node *n = lp()->fast_out(i); Node *n = lp()->fast_out(i);
if (in_bb(n) && (n->is_Phi() && n->bottom_type() == Type::MEMORY)) { if (in_bb(n) && (n->is_Phi() && n->bottom_type() == Type::MEMORY)) {
Node* n_tail = n->in(LoopNode::LoopBackControl); Node* n_tail = n->in(LoopNode::LoopBackControl);
_mem_slice_head.push(n); if (n_tail != n->in(LoopNode::EntryControl)) {
_mem_slice_tail.push(n_tail); _mem_slice_head.push(n);
_mem_slice_tail.push(n_tail);
}
} }
} }

View File

@ -2218,7 +2218,7 @@ const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const {
return make(ptr, _offset); return make(ptr, _offset);
} }
//-----------------------------cast_to_instance------------------------------- //-----------------------------cast_to_instance_id----------------------------
const TypeOopPtr *TypeOopPtr::cast_to_instance_id(int instance_id) const { const TypeOopPtr *TypeOopPtr::cast_to_instance_id(int instance_id) const {
// There are no instances of a general oop. // There are no instances of a general oop.
// Return self unchanged. // Return self unchanged.
@ -2610,8 +2610,7 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr,
// Ptr is never Null // Ptr is never Null
assert( ptr != Null, "NULL pointers are not typed" ); assert( ptr != Null, "NULL pointers are not typed" );
if ( instance_id > 0 ) assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
xk = true; // instances are always exactly typed
if (!UseExactTypes) xk = false; if (!UseExactTypes) xk = false;
if (ptr == Constant) { if (ptr == Constant) {
// Note: This case includes meta-object constants, such as methods. // Note: This case includes meta-object constants, such as methods.
@ -2650,16 +2649,10 @@ const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const {
return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id); return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id);
} }
//-----------------------------cast_to_instance------------------------------- //-----------------------------cast_to_instance_id----------------------------
const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const { const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const {
if( instance_id == _instance_id ) return this; if( instance_id == _instance_id ) return this;
bool exact = _klass_is_exact; return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id);
PTR ptr_t = _ptr;
if ( instance_id > 0 ) { // instances are always exactly typed
if (UseExactTypes) exact = true;
ptr_t = NotNull;
}
return make(ptr_t, klass(), exact, const_oop(), _offset, instance_id);
} }
//------------------------------xmeet_unloaded--------------------------------- //------------------------------xmeet_unloaded---------------------------------
@ -2899,6 +2892,7 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const {
xk = above_centerline(ptr) ? tinst_xk : false; xk = above_centerline(ptr) ? tinst_xk : false;
// Watch out for Constant vs. AnyNull interface. // Watch out for Constant vs. AnyNull interface.
if (ptr == Constant) ptr = NotNull; // forget it was a constant if (ptr == Constant) ptr = NotNull; // forget it was a constant
instance_id = InstanceBot;
} }
ciObject* o = NULL; // the Constant value, if any ciObject* o = NULL; // the Constant value, if any
if (ptr == Constant) { if (ptr == Constant) {
@ -2989,6 +2983,7 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const {
// class hierarchy - which means we have to fall to at least NotNull. // class hierarchy - which means we have to fall to at least NotNull.
if( ptr == TopPTR || ptr == AnyNull || ptr == Constant ) if( ptr == TopPTR || ptr == AnyNull || ptr == Constant )
ptr = NotNull; ptr = NotNull;
instance_id = InstanceBot;
// Now we find the LCA of Java classes // Now we find the LCA of Java classes
ciKlass* k = this_klass->least_common_ancestor(tinst_klass); ciKlass* k = this_klass->least_common_ancestor(tinst_klass);
@ -3101,8 +3096,7 @@ const TypeAryPtr *TypeAryPtr::make( PTR ptr, const TypeAry *ary, ciKlass* k, boo
assert(!(k == NULL && ary->_elem->isa_int()), assert(!(k == NULL && ary->_elem->isa_int()),
"integral arrays must be pre-equipped with a class"); "integral arrays must be pre-equipped with a class");
if (!xk) xk = ary->ary_must_be_exact(); if (!xk) xk = ary->ary_must_be_exact();
if ( instance_id > 0 ) assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
xk = true; // instances are always exactly typed
if (!UseExactTypes) xk = (ptr == Constant); if (!UseExactTypes) xk = (ptr == Constant);
return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id))->hashcons(); return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id))->hashcons();
} }
@ -3113,8 +3107,7 @@ const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ci
"integral arrays must be pre-equipped with a class"); "integral arrays must be pre-equipped with a class");
assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" );
if (!xk) xk = (o != NULL) || ary->ary_must_be_exact(); if (!xk) xk = (o != NULL) || ary->ary_must_be_exact();
if ( instance_id > 0 ) assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
xk = true; // instances are always exactly typed
if (!UseExactTypes) xk = (ptr == Constant); if (!UseExactTypes) xk = (ptr == Constant);
return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id))->hashcons(); return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id))->hashcons();
} }
@ -3134,16 +3127,10 @@ const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const {
return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id); return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id);
} }
//-----------------------------cast_to_instance------------------------------- //-----------------------------cast_to_instance_id----------------------------
const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const { const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const {
if( instance_id == _instance_id ) return this; if( instance_id == _instance_id ) return this;
bool exact = _klass_is_exact; return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id);
PTR ptr_t = _ptr;
if ( instance_id > 0 ) { // instances are always exactly typed
if (UseExactTypes) exact = true;
ptr_t = NotNull;
}
return make(ptr_t, const_oop(), _ary, klass(), exact, _offset, instance_id);
} }
//-----------------------------narrow_size_type------------------------------- //-----------------------------narrow_size_type-------------------------------
@ -3300,6 +3287,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const {
} else { } else {
// Something like byte[int+] meets char[int+]. // Something like byte[int+] meets char[int+].
// This must fall to bottom, not (int[-128..65535])[int+]. // This must fall to bottom, not (int[-128..65535])[int+].
instance_id = InstanceBot;
tary = TypeAry::make(Type::BOTTOM, tary->_size); tary = TypeAry::make(Type::BOTTOM, tary->_size);
} }
} }
@ -3316,6 +3304,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const {
if( tap->const_oop() != NULL && !o->equals(tap->const_oop()) ) { if( tap->const_oop() != NULL && !o->equals(tap->const_oop()) ) {
ptr = NotNull; ptr = NotNull;
o = NULL; o = NULL;
instance_id = InstanceBot;
} }
} else if( above_centerline(_ptr) ) { } else if( above_centerline(_ptr) ) {
o = tap->const_oop(); o = tap->const_oop();

View File

@ -2495,6 +2495,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
if (match_option(option, "-XX:+PrintVMOptions", &tail)) { if (match_option(option, "-XX:+PrintVMOptions", &tail)) {
PrintVMOptions = true; PrintVMOptions = true;
} }
if (match_option(option, "-XX:-PrintVMOptions", &tail)) {
PrintVMOptions = false;
}
} }
// Parse default .hotspotrc settings file // Parse default .hotspotrc settings file

View File

@ -1,23 +1,24 @@
/* /*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * 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.
* *
*/ */

View File

@ -1,24 +1,24 @@
/* /*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * 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.
* *
*/ */

View File

@ -1,24 +1,24 @@
/* /*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * 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.
* *
*/ */

View File

@ -0,0 +1,60 @@
/*
* Copyright 2008 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 6700047
* @summary C2 failed in idom_no_update
* @run main Test6700047
*/
public class Test6700047 {
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
intToLeftPaddedAsciiBytes();
}
}
public static int intToLeftPaddedAsciiBytes() {
int offset = 40;
int q;
int r;
int i = 100;
int result = 1;
while (offset > 0) {
q = (i * 52429);
r = i;
offset--;
i = q;
if (i == 0) {
break;
}
}
if (offset > 0) {
for(int j = 0; j < offset; j++) {
result++;
}
}
return result;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
/*
* Copyright 2008 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 6724218
* @summary Fix raise_LCA_above_marks() early termination
* @run main/othervm -Xbatch -XX:CompileCommand=exclude,Test.update Test
*/
public class Test {
Test next = null;
Object value = null;
static boolean _closed = false;
static int size = 0;
static Test list = null;
static int cache_size = 0;
static Test cache = null;
Object get(int i) {
Test t = list;
list = t.next;
size -= 1;
Object o = t.value;
if (i > 0) {
t.next = cache;
t.value = null;
cache = t;
cache_size = +1;
}
return o;
}
void update() {
// Exclude compilation of this one.
if (size == 0) {
Test t;
if (cache_size > 0) {
t = cache;
cache = t.next;
cache_size = -1;
} else {
t = new Test();
}
t.value = new Object();
t.next = list;
list = t;
size += 1;
}
}
synchronized Object test(int i) {
while (true) {
if (_closed) {
return null;
} else if (size > 0) {
return get(i);
}
update();
}
}
public static void main(String argv[]) throws Exception {
Test t = new Test();
int lim = 500000;
Object o;
for (int j = 0; j < lim; j++) {
o = t.test(j&1);
if (o == null) {
throw new Exception("*** Failed on iteration " + j);
}
if ((j&1) == 0) {
t.update();
}
}
}
}

File diff suppressed because it is too large Load Diff