提交 aaf77f5e 编写于 作者: T trims

Merge

/* /*
* 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.*; ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) {
......
...@@ -295,3 +295,9 @@ jprt.test.targets = \ ...@@ -295,3 +295,9 @@ jprt.test.targets = \
${jprt.my.windows.i586.test.targets}, \ ${jprt.my.windows.i586.test.targets}, \
${jprt.my.windows.x64.test.targets} ${jprt.my.windows.x64.test.targets}
# The default test/Makefile targets that should be run
# Example:
# jprt.make.rule.test.targets=*-*-*-packtest
#jprt.make.rule.test.targets=*-product-*-packtest
...@@ -1129,8 +1129,8 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { ...@@ -1129,8 +1129,8 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) {
#else #else
__ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 0)); __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 0));
// push and pop the part at src + wordSize, adding wordSize for the previous push // push and pop the part at src + wordSize, adding wordSize for the previous push
__ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), wordSize)); __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 2 * wordSize));
__ popl (frame_map()->address_for_slot(dest->double_stack_ix(), wordSize)); __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 2 * wordSize));
__ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 0)); __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 0));
#endif // _LP64 #endif // _LP64
......
/* /*
* 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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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);
} }
/* /*
* 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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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);}
......
...@@ -157,6 +157,7 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -157,6 +157,7 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node *a12 = add1->in(2); Node *a12 = add1->in(2);
const Type *t12 = phase->type( a12 ); const Type *t12 = phase->type( a12 );
if( t12->singleton() && t12 != Type::TOP && (add1 != add1->in(1)) ) { if( t12->singleton() && t12 != Type::TOP && (add1 != add1->in(1)) ) {
assert(add1->in(1) != this, "dead loop in AddNode::Ideal");
add2 = add1->clone(); add2 = add1->clone();
add2->set_req(2, in(2)); add2->set_req(2, in(2));
add2 = phase->transform(add2); add2 = phase->transform(add2);
...@@ -173,6 +174,7 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) { ...@@ -173,6 +174,7 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node *a22 = add2->in(2); Node *a22 = add2->in(2);
const Type *t22 = phase->type( a22 ); const Type *t22 = phase->type( a22 );
if( t22->singleton() && t22 != Type::TOP && (add2 != add2->in(1)) ) { if( t22->singleton() && t22 != Type::TOP && (add2 != add2->in(1)) ) {
assert(add2->in(1) != this, "dead loop in AddNode::Ideal");
Node *addx = add2->clone(); Node *addx = add2->clone();
addx->set_req(1, in(1)); addx->set_req(1, in(1));
addx->set_req(2, add2->in(1)); addx->set_req(2, add2->in(1));
......
...@@ -334,6 +334,9 @@ static void format_helper( PhaseRegAlloc *regalloc, outputStream* st, Node *n, c ...@@ -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 ) { ...@@ -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 ) { ...@@ -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 && UseImplicitNullCheckForNarrowOop) {
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 ) { ...@@ -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 ) { ...@@ -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 ...@@ -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 ...@@ -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--------------------------
......
...@@ -1212,6 +1212,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, ...@@ -1212,6 +1212,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
Deoptimization::Action_make_not_entrant, Deoptimization::Action_make_not_entrant,
NULL, "assert_null"); NULL, "assert_null");
} else { } else {
replace_in_map(value, zerocon(type));
builtin_throw(reason); builtin_throw(reason);
} }
} }
...@@ -1960,6 +1961,7 @@ Node* GraphKit::null_check_oop(Node* value, Node* *null_control, ...@@ -1960,6 +1961,7 @@ Node* GraphKit::null_check_oop(Node* value, Node* *null_control,
// method will be compiled to handle NULLs. // method will be compiled to handle NULLs.
PreserveJVMState pjvms(this); PreserveJVMState pjvms(this);
set_control(*null_control); set_control(*null_control);
replace_in_map(value, null());
uncommon_trap(Deoptimization::Reason_null_check, uncommon_trap(Deoptimization::Reason_null_check,
Deoptimization::Action_make_not_entrant); Deoptimization::Action_make_not_entrant);
(*null_control) = top(); // NULL path is dead (*null_control) = top(); // NULL path is dead
......
...@@ -58,6 +58,9 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe ...@@ -58,6 +58,9 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe
not_null_block = _succs[0]; not_null_block = _succs[0];
null_block = _succs[1]; null_block = _succs[1];
} }
while (null_block->is_Empty() == Block::empty_with_goto) {
null_block = null_block->_succs[0];
}
// Search the exception block for an uncommon trap. // Search the exception block for an uncommon trap.
// (See Parse::do_if and Parse::do_ifnull for the reason // (See Parse::do_if and Parse::do_ifnull for the reason
...@@ -149,6 +152,10 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe ...@@ -149,6 +152,10 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe
const TypePtr *adr_type = NULL; // Do not need this return value here const TypePtr *adr_type = NULL; // Do not need this return value here
const Node* base = mach->get_base_and_disp(offset, adr_type); const Node* base = mach->get_base_and_disp(offset, adr_type);
if (base == NULL || base == NodeSentinel) { if (base == NULL || base == NodeSentinel) {
// Narrow oop address doesn't have base, only index
if( val->bottom_type()->isa_narrowoop() &&
MacroAssembler::needs_explicit_null_check(offset) )
continue; // Give up if offset is beyond page size
// cannot reason about it; is probably not implicit null exception // cannot reason about it; is probably not implicit null exception
} else { } else {
const TypePtr* tptr = base->bottom_type()->is_ptr(); const TypePtr* tptr = base->bottom_type()->is_ptr();
......
...@@ -932,7 +932,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) { ...@@ -932,7 +932,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
// to fold a StoreP and an AddP together (as part of an // to fold a StoreP and an AddP together (as part of an
// address expression) and the AddP and StoreP have // address expression) and the AddP and StoreP have
// different controls. // different controls.
if( !x->is_Load() ) _igvn._worklist.yank(x); if( !x->is_Load() && !x->is_DecodeN() ) _igvn._worklist.yank(x);
} }
_igvn.remove_dead_node(n); _igvn.remove_dead_node(n);
} }
......
...@@ -685,6 +685,8 @@ void Compile::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, ...@@ -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, ...@@ -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) { ...@@ -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);
......
...@@ -527,6 +527,7 @@ uint PhaseChaitin::Split( uint maxlrg ) { ...@@ -527,6 +527,7 @@ uint PhaseChaitin::Split( uint maxlrg ) {
// Initialize needs_phi and needs_split // Initialize needs_phi and needs_split
bool needs_phi = false; bool needs_phi = false;
bool needs_split = false; bool needs_split = false;
bool has_phi = false;
// Walk the predecessor blocks to check inputs for that live range // Walk the predecessor blocks to check inputs for that live range
// Grab predecessor block header // Grab predecessor block header
n1 = b->pred(1); n1 = b->pred(1);
...@@ -570,28 +571,30 @@ uint PhaseChaitin::Split( uint maxlrg ) { ...@@ -570,28 +571,30 @@ uint PhaseChaitin::Split( uint maxlrg ) {
} }
} // End for all potential Phi inputs } // End for all potential Phi inputs
// If a phi is needed, check for it // check block for appropriate phinode & update edges
if( needs_phi ) { for( insidx = 1; insidx <= b->end_idx(); insidx++ ) {
// check block for appropriate phinode & update edges n1 = b->_nodes[insidx];
for( insidx = 1; insidx <= b->end_idx(); insidx++ ) { // bail if this is not a phi
n1 = b->_nodes[insidx]; phi = n1->is_Phi() ? n1->as_Phi() : NULL;
// bail if this is not a phi if( phi == NULL ) {
phi = n1->is_Phi() ? n1->as_Phi() : NULL; // Keep track of index of first non-PhiNode instruction in block
if( phi == NULL ) { non_phi = insidx;
// Keep track of index of first non-PhiNode instruction in block // break out of the for loop as we have handled all phi nodes
non_phi = insidx; break;
// break out of the for loop as we have handled all phi nodes }
break; // must be looking at a phi
} if( Find_id(n1) == lidxs.at(slidx) ) {
// must be looking at a phi // found the necessary phi
if( Find_id(n1) == lidxs.at(slidx) ) { needs_phi = false;
// found the necessary phi has_phi = true;
needs_phi = false; // initialize the Reaches entry for this LRG
// initialize the Reaches entry for this LRG Reachblock[slidx] = phi;
Reachblock[slidx] = phi; break;
break; } // end if found correct phi
} // end if found correct phi } // end for all phi's
} // end for all phi's
// If a phi is needed or exist, check for it
if( needs_phi || has_phi ) {
// add new phinode if one not already found // add new phinode if one not already found
if( needs_phi ) { if( needs_phi ) {
// create a new phi node and insert it into the block // create a new phi node and insert it into the block
...@@ -695,7 +698,8 @@ uint PhaseChaitin::Split( uint maxlrg ) { ...@@ -695,7 +698,8 @@ uint PhaseChaitin::Split( uint maxlrg ) {
} }
} }
assert( u, "at least 1 valid input expected" ); assert( u, "at least 1 valid input expected" );
if( i >= cnt ) { // Didn't find 2+ unique inputs? if( i >= cnt ) { // Found one unique input
assert(Find_id(n) == Find_id(u), "should be the same lrg");
n->replace_by(u); // Then replace with unique input n->replace_by(u); // Then replace with unique input
n->disconnect_inputs(NULL); n->disconnect_inputs(NULL);
b->_nodes.remove(insidx); b->_nodes.remove(insidx);
......
...@@ -1204,15 +1204,17 @@ void Arguments::set_ergonomics_flags() { ...@@ -1204,15 +1204,17 @@ void Arguments::set_ergonomics_flags() {
// Turn off until bug is fixed. // Turn off until bug is fixed.
// FLAG_SET_ERGO(bool, UseCompressedOops, true); // FLAG_SET_ERGO(bool, UseCompressedOops, true);
} }
#ifdef _WIN64
if (UseLargePages && UseCompressedOops) {
// Cannot allocate guard pages for implicit checks in indexed addressing
// mode, when large pages are specified on windows.
FLAG_SET_DEFAULT(UseImplicitNullCheckForNarrowOop, false);
}
#endif // _WIN64
} else { } else {
if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) { if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) {
// If specified, give a warning // If specified, give a warning
if (UseConcMarkSweepGC){ warning( "Max heap size too large for Compressed Oops");
warning("Compressed Oops does not work with CMS");
} else {
warning(
"Max heap size too large for Compressed Oops");
}
FLAG_SET_DEFAULT(UseCompressedOops, false); FLAG_SET_DEFAULT(UseCompressedOops, false);
} }
} }
......
...@@ -294,6 +294,9 @@ class CommandLineFlags { ...@@ -294,6 +294,9 @@ class CommandLineFlags {
lp64_product(bool, CheckCompressedOops, trueInDebug, \ lp64_product(bool, CheckCompressedOops, trueInDebug, \
"generate checks in encoding/decoding code") \ "generate checks in encoding/decoding code") \
\ \
product(bool, UseImplicitNullCheckForNarrowOop, true, \
"generate implicit null check in indexed addressing mode.") \
\
/* UseMembar is theoretically a temp flag used for memory barrier \ /* UseMembar is theoretically a temp flag used for memory barrier \
* removal testing. It was supposed to be removed before FCS but has \ * removal testing. It was supposed to be removed before FCS but has \
* been re-added (see 6401008) */ \ * been re-added (see 6401008) */ \
......
/* /*
* 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 ...@@ -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
......
...@@ -2756,13 +2756,17 @@ void Threads::threads_do(ThreadClosure* tc) { ...@@ -2756,13 +2756,17 @@ void Threads::threads_do(ThreadClosure* tc) {
// For now, just manually iterate through them. // For now, just manually iterate through them.
tc->do_thread(VMThread::vm_thread()); tc->do_thread(VMThread::vm_thread());
Universe::heap()->gc_threads_do(tc); Universe::heap()->gc_threads_do(tc);
{ WatcherThread *wt = WatcherThread::watcher_thread();
// Grab the Terminator_lock to prevent watcher_thread from being terminated. // Strictly speaking, the following NULL check isn't sufficient to make sure
MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag); // the data for WatcherThread is still valid upon being examined. However,
WatcherThread *wt = WatcherThread::watcher_thread(); // considering that WatchThread terminates when the VM is on the way to
if (wt != NULL) // exit at safepoint, the chance of the above is extremely small. The right
tc->do_thread(wt); // way to prevent termination of WatcherThread would be to acquire
} // Terminator_lock, but we can't do that without violating the lock rank
// checking in some cases.
if (wt != NULL)
tc->do_thread(wt);
// If CompilerThreads ever become non-JavaThreads, add them here // If CompilerThreads ever become non-JavaThreads, add them here
} }
......
...@@ -380,7 +380,8 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment, ...@@ -380,7 +380,8 @@ ReservedHeapSpace::ReservedHeapSpace(size_t size, size_t alignment,
bool large, char* requested_address) : bool large, char* requested_address) :
ReservedSpace(size, alignment, large, ReservedSpace(size, alignment, large,
requested_address, requested_address,
UseCompressedOops ? lcm(os::vm_page_size(), alignment) : 0) { UseCompressedOops && UseImplicitNullCheckForNarrowOop ?
lcm(os::vm_page_size(), alignment) : 0) {
// Only reserved space for the java heap should have a noaccess_prefix // Only reserved space for the java heap should have a noaccess_prefix
// if using compressed oops. // if using compressed oops.
protect_noaccess_prefix(size); protect_noaccess_prefix(size);
...@@ -391,7 +392,8 @@ ReservedHeapSpace::ReservedHeapSpace(const size_t prefix_size, ...@@ -391,7 +392,8 @@ ReservedHeapSpace::ReservedHeapSpace(const size_t prefix_size,
const size_t suffix_size, const size_t suffix_size,
const size_t suffix_align) : const size_t suffix_align) :
ReservedSpace(prefix_size, prefix_align, suffix_size, suffix_align, ReservedSpace(prefix_size, prefix_align, suffix_size, suffix_align,
UseCompressedOops ? lcm(os::vm_page_size(), prefix_align) : 0) { UseCompressedOops && UseImplicitNullCheckForNarrowOop ?
lcm(os::vm_page_size(), prefix_align) : 0) {
protect_noaccess_prefix(prefix_size+suffix_size); protect_noaccess_prefix(prefix_size+suffix_size);
} }
......
...@@ -1577,6 +1577,7 @@ static inline uint64_t cast_uint64_t(size_t x) ...@@ -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) \
......
# #
# Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. # Copyright 1995-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
...@@ -19,17 +19,18 @@ ...@@ -19,17 +19,18 @@
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, # Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or # CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions. # have any questions.
# #
# #
# #
# Makefile to run jtreg # Makefile to run various jdk tests
# #
# Get OS/ARCH specifics
OSNAME = $(shell uname -s) OSNAME = $(shell uname -s)
SLASH_JAVA = /java
ifeq ($(OSNAME), SunOS) ifeq ($(OSNAME), SunOS)
PLATFORM = solaris PLATFORM = solaris
JCT_PLATFORM = solaris
ARCH = $(shell uname -p) ARCH = $(shell uname -p)
ifeq ($(ARCH), i386) ifeq ($(ARCH), i386)
ARCH=i586 ARCH=i586
...@@ -37,203 +38,165 @@ ifeq ($(OSNAME), SunOS) ...@@ -37,203 +38,165 @@ ifeq ($(OSNAME), SunOS)
endif endif
ifeq ($(OSNAME), Linux) ifeq ($(OSNAME), Linux)
PLATFORM = linux PLATFORM = linux
JCT_PLATFORM = linux
ARCH = $(shell uname -m) ARCH = $(shell uname -m)
ifeq ($(ARCH), i386) ifeq ($(ARCH), i386)
ARCH=i586 ARCH = i586
endif endif
endif endif
ifeq ($(OSNAME), Windows_NT) ifeq ($(OSNAME), Windows_NT)
PLATFORM = windows PLATFORM = windows
JCT_PLATFORM = win32 SLASH_JAVA = J:
ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64) ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64)
ARCH=ia64 ARCH = ia64
else else
ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),AMD64) ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),AMD64)
ARCH=x64 ARCH = x64
else else
ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),EM64T) ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),EM64T)
ARCH=x64 ARCH = x64
else else
ARCH=i586 ARCH = i586
endif endif
endif endif
endif endif
EXESUFFIX = .exe
endif endif
# Default bundle of all test results (passed or not) # Utilities used
JPRT_ARCHIVE_BUNDLE=$(TEST_ROOT)/JPRT_ARCHIVE_BUNDLE.zip CD = cd
CP = cp
ECHO = echo
MKDIR = mkdir
ZIP = zip
# Default home for JTREG # Root of this test area (important to use full paths in some places)
ifeq ($(PLATFORM), windows) TEST_ROOT := $(shell pwd)
JT_HOME = J:/svc/jct-tools3.2.2_01
else # Root of all test results
JT_HOME = /java/svc/jct-tools3.2.2_01 ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput
# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
ifndef PRODUCT_HOME
# Try to use j2sdk-image if it exists
ABS_JDK_IMAGE = $(ABS_BUILD_ROOT)/j2sdk-image
PRODUCT_HOME := \
$(shell \
if [ -d $(ABS_JDK_IMAGE) ] ; then \
$(ECHO) "$(ABS_JDK_IMAGE)"; \
else \
$(ECHO) "$(ABS_BUILD_ROOT)" ; \
fi)
endif endif
# Default JTREG to run # Expect JPRT to set JAVA_ARGS (e.g. -server etc.)
JTREG = $(JT_HOME)/$(JCT_PLATFORM)/bin/jtreg JAVA_OPTIONS =
ifdef JAVA_ARGS
JAVA_OPTIONS = $(JAVA_ARGS)
endif
# Root of this test area # Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results)
TEST_ROOT := $(shell pwd) ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
ifdef JPRT_ARCHIVE_BUNDLE
ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE)
endif
# Default JDK to test # How to create the test bundle (pass or fail, we want to create this)
JAVA_HOME = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH) BUNDLE_UP = ( $(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)` \
&& $(CD) $(ABS_TEST_OUTPUT_DIR) \
&& $(ZIP) -q -r $(ARCHIVE_BUNDLE) . )
BUNDLE_UP_FAILED = ( exitCode=$$? && $(BUNDLE_UP) && exit $${exitCode} )
# The test directories to run ################################################################
DEFAULT_TESTDIRS = serviceability
TESTDIRS = $(DEFAULT_TESTDIRS)
# Files that hold total passed and failed counts (passed==0 is bad) # Default make rule (runs jtreg_tests)
JTREG_TOTALS_DIR = $(TEST_ROOT)/JTREG_TOTALS_$(PLATFORM)_$(ARCH) all: jtreg_tests
JTREG_FAILED = $(JTREG_TOTALS_DIR)/failed_count @$(ECHO) "Testing completed successfully"
JTREG_PASSED = $(JTREG_TOTALS_DIR)/passed_count
# Root of all test results # Prep for output
JTREG_ALL_OUTPUT_DIRNAME = JTREG_OUTPUT_$(PLATFORM)_$(ARCH) prep: clean
JTREG_ALL_OUTPUT_DIR = $(TEST_ROOT)/$(JTREG_ALL_OUTPUT_DIRNAME) @$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
@$(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)`
# Test results for one test directory
JTREG_TEST_OUTPUT_DIR = $(JTREG_ALL_OUTPUT_DIR)/$@
JTREG_TEST_REPORT_DIR = $(JTREG_TEST_OUTPUT_DIR)/JTreport
JTREG_TEST_WORK_DIR = $(JTREG_TEST_OUTPUT_DIR)/JTwork
JTREG_TEST_SUMMARY = $(JTREG_TEST_REPORT_DIR)/summary.txt
# Temp files used by this Makefile
JTREG_TEST_TEMP_DIR = $(JTREG_ALL_OUTPUT_DIR)/$@/temp
JTREG_TEMP_PASSED = $(JTREG_TEST_TEMP_DIR)/passed
JTREG_TEMP_FAILED = $(JTREG_TEST_TEMP_DIR)/failed
JTREG_TEMP_OUTPUT = $(JTREG_TEST_TEMP_DIR)/output
JTREG_TEMP_RESULTS = $(JTREG_TEST_TEMP_DIR)/results
# JTREG options (different for 2.1.6 and 3.2.2_01)
JTREG_COMMON_OPTIONS = -r:$(JTREG_TEST_REPORT_DIR) \
-w:$(JTREG_TEST_WORK_DIR) \
-testjdk:$(JAVA_HOME) \
-automatic \
-verbose:all
JTREG_216_OPTIONS = $(JTREG_COMMON_OPTIONS) $@ $(JAVA_ARGS)
JTREG_322_OPTIONS = $(JTREG_COMMON_OPTIONS) $(JAVA_ARGS:%=-vmoption:%) $@
# Default make rule
all: clean check tests
# Chaeck to make sure these directories exist
check: $(JT_HOME) $(JAVA_HOME) $(JTREG)
# Prime the test run
primecounts: FRC
@rm -f -r $(JTREG_TOTALS_DIR)
@mkdir -p $(JTREG_TOTALS_DIR)
@echo "0" > $(JTREG_FAILED)
@echo "0" > $(JTREG_PASSED)
# Run the tests and determine the 'make' command exit status
# Ultimately we determine the make exit code based on the passed/failed count
tests: primecounts $(TESTDIRS)
@echo "JTREG TOTAL: passed=`cat $(JTREG_PASSED)` failed=`cat $(JTREG_FAILED)`"
zip -q -r $(JPRT_ARCHIVE_BUNDLE) $(JTREG_ALL_OUTPUT_DIRNAME)
@if [ `cat $(JTREG_FAILED)` -ne 0 -o \
`cat $(JTREG_PASSED)` -le 0 ] ; then \
echo "JTREG FAILED"; \
exit 1; \
else \
echo "JTREG PASSED"; \
exit 0; \
fi
# Just make sure these directires exist
$(JT_HOME) $(JAVA_HOME): FRC
@if [ ! -d $@ ] ; then \
echo "ERROR: Directory $@ does not exist"; \
exit 1; \
fi
# Make sure this file exists
$(JTREG): FRC
@if [ ! -f $@ ] ; then \
echo "ERROR: File $@ does not exist"; \
exit 1; \
fi
# Process each test directory one by one, this rule always completes.
# Note that the use of 'tee' tosses the jtreg process exit status, this
# is as expected because even if jtreg fails, we need to save the
# output. So we update the JTREG_PASSED and JTREG_FAILED count files.
# Note that missing the 'results:' line in the last few lines of output
# will indicate a failure (or a bump by one of the JTREG_FAILED file.
# Note that passed: 0 or no passed: indication means a failure.
# Note that any indication of the word 'failed' indicates failure.
# Ultimately if the contents of JTREG_FAILED is not 0, we have failed
# tests, and if the contents of JTREG_PASSED is 0, we consider that a
# failure.
$(TESTDIRS): FRC
@if [ ! -d $@ ] ; then \
echo "ERROR: Directory $@ does not exist"; \
exit 1; \
fi
@echo "---------------------------------------------------"
@rm -f -r $(JTREG_TEST_OUTPUT_DIR)
@mkdir -p $(JTREG_TEST_OUTPUT_DIR)
@mkdir -p $(JTREG_TEST_WORK_DIR)
@mkdir -p $(JTREG_TEST_WORK_DIR)/scratch
@mkdir -p $(JTREG_TEST_REPORT_DIR)
@mkdir -p $(JTREG_TEST_TEMP_DIR)
@echo "Testing $@"
@echo "Using JAVA_HOME=$(JAVA_HOME)"
@echo "Using JAVA_ARGS=$(JAVA_ARGS)"
@if [ "`$(JTREG) -help 2>&1 | fgrep -- -vmoption`" != "" ] ; then \
echo "Assume we are using jtreg 3.2.2_01 or newer"; \
echo "$(JTREG) $(JTREG_322_OPTIONS)"; \
$(JTREG) $(JTREG_322_OPTIONS) 2>&1 | tee $(JTREG_TEMP_OUTPUT) ; \
else \
echo "Assume we are using jtreg 2.1.6"; \
echo "$(JTREG) $(JTREG_216_OPTIONS)"; \
$(JTREG) $(JTREG_216_OPTIONS) 2>&1 | tee $(JTREG_TEMP_OUTPUT) ; \
fi
@echo "---------------------------------------------------"
@echo "Extracting passed and failed counts from jtreg output"
@tail -10 $(JTREG_TEMP_OUTPUT) | fgrep -i 'results:' | \
tail -1 | tee $(JTREG_TEMP_RESULTS)
@sed -e 's@.*\ passed:\ \([1-9][0-9]*\).*@\1@' $(JTREG_TEMP_RESULTS) \
> $(JTREG_TEMP_PASSED)
@if [ "`cat $(JTREG_TEMP_PASSED)`" = "" ] ; then \
echo "ERROR: No passed indication in results"; \
expr `cat $(JTREG_FAILED)` '+' 1 > $(JTREG_FAILED); \
elif [ `cat $(JTREG_TEMP_PASSED)` -le 0 ] ; then \
echo "ERROR: Passed count appears to be 0"; \
expr `cat $(JTREG_FAILED)` '+' 1 > $(JTREG_FAILED); \
elif [ "`fgrep -i failed $(JTREG_TEMP_RESULTS)`" = "" ] ; then \
echo "No indication anything failed"; \
expr `cat $(JTREG_PASSED)` '+' `cat $(JTREG_TEMP_PASSED)` \
> $(JTREG_PASSED); \
else \
sed -e 's@.*\ failed:\ \([1-9][0-9]*\).*@\1@' $(JTREG_TEMP_FAILED) \
> $(JTREG_TEMP_FAILED); \
if [ "`cat $(JTREG_TEMP_FAILED)`" = "" ] ; then \
echo "ERROR: Failed pattern but no failed count in results"; \
expr `cat $(JTREG_FAILED)` '+' 1 > $(JTREG_FAILED); \
elif [ `cat $(JTREG_TEMP_FAILED)` -le 0 ] ; then \
echo "ERROR: Failed count is 0, did something failed or not?"; \
expr `cat $(JTREG_FAILED)` '+' 1 > $(JTREG_FAILED); \
else \
expr `cat $(JTREG_FAILED)` '+' `cat $(JTREG_TEMP_FAILED)` \
> $(JTREG_FAILED); \
fi; \
fi
@echo "---------------------------------------------------"
@echo "Summary: "
@if [ -f $(JTREG_TEST_SUMMARY) ] ; then \
cat $(JTREG_TEST_SUMMARY) ; \
else \
echo "ERROR: Missing $(JTREG_TEST_SUMMARY)"; \
fi
@echo "---------------------------------------------------"
# Cleanup # Cleanup
clean: clean:
rm -f -r $(JTREG_ALL_OUTPUT_DIR) $(RM) -r $(ABS_TEST_OUTPUT_DIR)
rm -f $(JPRT_ARCHIVE_BUNDLE) $(RM) $(ARCHIVE_BUNDLE)
################################################################
# jtreg tests
# Expect JT_HOME to be set for jtreg tests. (home for jtreg)
JT_HOME = $(SLASH_JAVA)/re/jtreg/4.0/promoted/latest/binaries/jtreg
ifdef JPRT_JTREG_HOME
JT_HOME = $(JPRT_JTREG_HOME)
endif
# Expect JPRT to set TESTDIRS to the jtreg test dirs
JTREG_TESTDIRS = demo/jvmti/gctest demo/jvmti/hprof
ifdef TESTDIRS
JTREG_TESTDIRS = $(TESTDIRS)
endif
# Default JTREG to run (win32 script works for everybody)
JTREG = $(JT_HOME)/win32/bin/jtreg
# Option to tell jtreg to not run tests marked with "ignore"
ifeq ($(PLATFORM), windows)
JTREG_KEY_OPTION = -k:!ignore
else
JTREG_KEY_OPTION = -k:\!ignore
endif
#EXTRA_JTREG_OPTIONS =
jtreg_tests: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG)
$(JTREG) -a -v:fail,error \
$(JTREG_KEY_OPTION) \
$(EXTRA_JTREG_OPTIONS) \
-r:$(ABS_TEST_OUTPUT_DIR)/JTreport \
-w:$(ABS_TEST_OUTPUT_DIR)/JTwork \
-jdk:$(PRODUCT_HOME) \
$(JAVA_OPTIONS:%=-vmoption:%) \
$(JTREG_TESTDIRS) \
|| $(BUNDLE_UP_FAILED)
$(BUNDLE_UP)
PHONY_LIST += jtreg_tests
################################################################
# packtest
# Expect JPRT to set JPRT_PACKTEST_HOME.
PACKTEST_HOME = /net/jprt-web.sfbay.sun.com/jprt/allproducts/packtest
ifdef JPRT_PACKTEST_HOME
PACKTEST_HOME = $(JPRT_PACKTEST_HOME)
endif
#EXTRA_PACKTEST_OPTIONS =
packtest: prep $(PACKTEST_HOME)/ptest $(PRODUCT_HOME)
( $(CD) $(PACKTEST_HOME) && \
$(PACKTEST_HOME)/ptest \
-t "$(PRODUCT_HOME)" \
$(PACKTEST_STRESS_OPTION) \
$(EXTRA_PACKTEST_OPTIONS) \
-W $(ABS_TEST_OUTPUT_DIR) \
$(JAVA_OPTIONS:%=-J %) \
) || $(BUNDLE_UP_FAILED)
$(BUNDLE_UP)
packtest_stress: PACKTEST_STRESS_OPTION=-s
packtest_stress: packtest
PHONY_LIST += packtest packtest_stress
################################################################
# Phony targets (e.g. these are not filenames)
.PHONY: all clean prep $(PHONY_LIST)
FRC: ################################################################
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册