# HG changeset patch # User trims # Date 1221699758 25200 # Node ID 75e0a5b79b1f6ad5a9a9a06c69f51d96cd48003b # Parent 51798f0e554f3ff9bdbc276402672bea45f9b85f# Parent 7484fa4b88252d1906da1dbd5620b4972a79ad84 Merge diff -r 51798f0e554f -r 75e0a5b79b1f agent/src/share/classes/sun/jvm/hotspot/code/Location.java --- a/agent/src/share/classes/sun/jvm/hotspot/code/Location.java Thu Sep 11 11:25:43 2008 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/code/Location.java Wed Sep 17 18:02:38 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,9 +39,9 @@

Encoding:

     bits:
-    Where:  [15]
-    Type:   [14..12]
-    Offset: [11..0]
+    Type:   [3..0]
+    Where:  [4]
+    Offset: [31..5]
     
*/ @@ -69,6 +69,7 @@ // Location::Type constants TYPE_NORMAL = db.lookupIntConstant("Location::normal").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_LNG = db.lookupIntConstant("Location::lng").intValue(); TYPE_FLOAT_IN_DBL = db.lookupIntConstant("Location::float_in_dbl").intValue(); @@ -115,6 +116,8 @@ public static final Type NORMAL = new Type("normal"); /** Oop (please GC me!) */ 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 */ public static final Type INT_IN_LONG = new Type("int_in_long"); /** Long held in one register */ @@ -142,6 +145,8 @@ return TYPE_NORMAL; } else if (this == OOP) { return TYPE_OOP; + } else if (this == NARROWOOP) { + return TYPE_NARROWOOP; } else if (this == INT_IN_LONG) { return TYPE_INT_IN_LONG; } else if (this == LNG) { @@ -170,6 +175,7 @@ // constants in Type enum private static int TYPE_NORMAL; private static int TYPE_OOP; + private static int TYPE_NARROWOOP; private static int TYPE_INT_IN_LONG; private static int TYPE_LNG; private static int TYPE_FLOAT_IN_DBL; @@ -185,7 +191,7 @@ Location(Where where, Type type, int offset) { setWhere(where); setType(type); - setOffset(offset & 0x0000FFFF); + setOffset(offset); } public Where getWhere() { @@ -205,6 +211,8 @@ return Type.NORMAL; } else if (type == TYPE_OOP) { return Type.OOP; + } else if (type == TYPE_NARROWOOP) { + return Type.NARROWOOP; } else if (type == TYPE_INT_IN_LONG) { return Type.INT_IN_LONG; } else if (type == TYPE_LNG) { @@ -238,6 +246,10 @@ return getType() == Type.OOP; } + public boolean holdsNarrowOop() { + return getType() == Type.NARROWOOP; + } + public boolean holdsInt() { return getType() == Type.INT_IN_LONG; } @@ -266,7 +278,7 @@ if (Assert.ASSERTS_ENABLED) { Assert.that(getWhere() == Where.ON_STACK, "wrong Where"); } - return getOffset() << VM.getVM().getLogAddressSize(); + return getOffset() * (int)VM.getVM().getIntSize(); } public int getRegisterNumber() { @@ -296,6 +308,8 @@ if (type == Type.NORMAL) { } else if (type == Type.OOP) { tty.print(",oop"); + } else if (type == Type.NARROWOOP) { + tty.print(",narrowoop"); } else if (type == Type.INT_IN_LONG) { tty.print(",int"); } else if (type == Type.LNG) { @@ -314,26 +328,26 @@ /** Serialization of debugging information */ public Location(DebugInfoReadStream stream) { - value = (0x0000FFFF & stream.readInt()); + value = stream.readInt(); } // FIXME: not yet implementable // void write_on(DebugInfoWriteStream* stream); - //-------------------------------------------------------------------------------- + //----------------------------------------------------------------------------- // Internals only below this point // private void setWhere(Where where) { - value |= (where.getValue() << WHERE_SHIFT); + value |= ((where.getValue() << WHERE_SHIFT) & WHERE_MASK); } private void setType(Type type) { - value |= (type.getValue() << TYPE_SHIFT); + value |= ((type.getValue() << TYPE_SHIFT) & TYPE_MASK); } private void setOffset(int offset) { - value |= (offset << OFFSET_SHIFT); + value |= ((offset << OFFSET_SHIFT) & OFFSET_MASK); } } diff -r 51798f0e554f -r 75e0a5b79b1f agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Thu Sep 11 11:25:43 2008 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java Wed Sep 17 18:02:38 2008 -0700 @@ -206,6 +206,16 @@ Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" ); } 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? return new StackValue(valueAddr.getOopHandleAt(0)); } else if( loc.holdsDouble() ) { diff -r 51798f0e554f -r 75e0a5b79b1f agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Thu Sep 11 11:25:43 2008 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Wed Sep 17 18:02:38 2008 -0700 @@ -621,6 +621,11 @@ 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 is present */ public boolean isCore() { diff -r 51798f0e554f -r 75e0a5b79b1f agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java --- a/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Thu Sep 11 11:25:43 2008 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java Wed Sep 17 18:02:38 2008 -0700 @@ -1135,6 +1135,8 @@ buf.append("normal"); } else if (type == Location.Type.OOP) { buf.append("oop"); + } else if (type == Location.Type.NARROWOOP) { + buf.append("narrowoop"); } else if (type == Location.Type.INT_IN_LONG) { buf.append("int"); } else if (type == Location.Type.LNG) { diff -r 51798f0e554f -r 75e0a5b79b1f make/jprt.properties --- a/make/jprt.properties Thu Sep 11 11:25:43 2008 -0700 +++ b/make/jprt.properties Wed Sep 17 18:02:38 2008 -0700 @@ -295,3 +295,9 @@ ${jprt.my.windows.i586.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 + diff -r 51798f0e554f -r 75e0a5b79b1f src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -1129,8 +1129,8 @@ #else __ 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 - __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), wordSize)); - __ popl (frame_map()->address_for_slot(dest->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(), 2 * wordSize)); __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 0)); #endif // _LP64 diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/code/location.cpp --- a/src/share/vm/code/location.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/code/location.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #include "incls/_location.cpp.incl" 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(). switch (where()) { case on_stack: st->print("empty"); break; @@ -42,6 +42,7 @@ switch (type()) { case normal: break; case oop: st->print(",oop"); break; + case narrowoop: st->print(",narrowoop"); break; case int_in_long: st->print(",int"); break; case lng: st->print(",long"); break; case float_in_dbl: st->print(",float"); break; @@ -53,17 +54,17 @@ Location::Location(DebugInfoReadStream* stream) { - _value = (uint16_t) stream->read_int(); + _value = (juint) stream->read_int(); } void Location::write_on(DebugInfoWriteStream* stream) { - stream->write_int(_value & 0x0000FFFF); + stream->write_int(_value); } // Valid argument to Location::new_stk_loc()? bool Location::legal_offset_in_bytes(int offset_in_bytes) { 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); } diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/code/location.hpp --- a/src/share/vm/code/location.hpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/code/location.hpp Wed Sep 17 18:02:38 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,10 @@ // // Encoding: // -// bits: -// Where: [15] -// Type: [14..12] -// Offset: [11..0] +// bits (use low bits for best compression): +// Type: [3..0] +// Where: [4] +// Offset: [31..5] class Location VALUE_OBJ_CLASS_SPEC { friend class VMStructs; @@ -42,6 +42,7 @@ }; enum Type { + invalid, // Invalid location normal, // Ints, floats, double halves oop, // Oop (please GC me!) int_in_long, // Integer held in long register @@ -49,21 +50,21 @@ float_in_dbl, // Float held in double register dbl, // Double held in one register addr, // JSR return address - invalid // Invalid location + narrowoop // Narrow Oop (please GC me!) }; private: enum { - OFFSET_MASK = (jchar) 0x0FFF, - OFFSET_SHIFT = 0, - TYPE_MASK = (jchar) 0x7000, - TYPE_SHIFT = 12, - WHERE_MASK = (jchar) 0x8000, - WHERE_SHIFT = 15 + TYPE_MASK = (juint) 0x0F, + TYPE_SHIFT = 0, + WHERE_MASK = (juint) 0x10, + WHERE_SHIFT = 4, + OFFSET_MASK = (juint) 0xFFFFFFE0, + OFFSET_SHIFT = 5 }; - uint16_t _value; + juint _value; // Create a bit-packed Location Location(Where where_, Type type_, unsigned offset_) { @@ -74,9 +75,9 @@ } inline void set(Where where_, Type type_, unsigned offset_) { - _value = (uint16_t) ((where_ << WHERE_SHIFT) | - (type_ << TYPE_SHIFT) | - ((offset_ << OFFSET_SHIFT) & OFFSET_MASK)); + _value = (juint) ((where_ << WHERE_SHIFT) | + (type_ << TYPE_SHIFT) | + ((offset_ << OFFSET_SHIFT) & OFFSET_MASK)); } public: @@ -86,7 +87,7 @@ // Register location Factory static Location new_reg_loc( Type t, VMReg reg ) { return Location(in_register, t, reg->value()); } // Default constructor - Location() { set(on_stack,invalid,(unsigned) -1); } + Location() { set(on_stack,invalid,0); } // Bit field accessors Where where() const { return (Where) ((_value & WHERE_MASK) >> WHERE_SHIFT);} diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/addnode.cpp --- a/src/share/vm/opto/addnode.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/addnode.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -157,6 +157,7 @@ Node *a12 = add1->in(2); const Type *t12 = phase->type( a12 ); if( t12->singleton() && t12 != Type::TOP && (add1 != add1->in(1)) ) { + assert(add1->in(1) != this, "dead loop in AddNode::Ideal"); add2 = add1->clone(); add2->set_req(2, in(2)); add2 = phase->transform(add2); @@ -173,6 +174,7 @@ Node *a22 = add2->in(2); const Type *t22 = phase->type( a22 ); if( t22->singleton() && t22 != Type::TOP && (add2 != add2->in(1)) ) { + assert(add2->in(1) != this, "dead loop in AddNode::Ideal"); Node *addx = add2->clone(); addx->set_req(1, in(1)); addx->set_req(2, add2->in(1)); diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/callnode.cpp --- a/src/share/vm/opto/callnode.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/callnode.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -334,6 +334,9 @@ case Type::InstPtr: st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->isa_oopptr()->const_oop()); break; + case Type::NarrowOop: + st->print(" %s%d]=#Ptr" INTPTR_FORMAT,msg,i,t->make_ptr()->isa_oopptr()->const_oop()); + break; case Type::RawPtr: st->print(" %s%d]=#Raw" INTPTR_FORMAT,msg,i,t->is_rawptr()); break; diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/compile.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -1967,6 +1967,7 @@ !n->is_Proj() && nop != Op_CreateEx && nop != Op_CheckCastPP && + nop != Op_DecodeN && !n->is_Mem() ) { Node *x = n->clone(); call->set_req( TypeFunc::Parms, x ); @@ -2075,20 +2076,27 @@ case Op_CmpP: // Do this transformation here to preserve CmpPNode::sub() and // 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(); - Node* in2 = NULL; - if( n->in(2)->is_DecodeN() ) { - in2 = n->in(2)->in(1); - } else if ( n->in(2)->Opcode() == Op_ConP ) { - const Type* t = n->in(2)->bottom_type(); - if (t == TypePtr::NULL_PTR) { - Node *in1 = n->in(1); + Node* new_in2 = NULL; + if (in2->is_DecodeN()) { + new_in2 = in2->in(1); + } else if (in2->Opcode() == Op_ConP) { + const Type* t = in2->bottom_type(); + if (t == TypePtr::NULL_PTR && UseImplicitNullCheckForNarrowOop) { if (Matcher::clone_shift_expressions) { // x86, ARM and friends can handle 2 adds in addressing mode. // Decode a narrow oop and do implicit NULL check in address // [R12 + narrow_oop_reg<<3 + offset] - in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); + new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); } else { // Don't replace CmpP(o ,null) if 'o' is used in AddP // to generate implicit NULL check on Sparc where @@ -2099,16 +2107,22 @@ break; } if (i >= in1->outcnt()) { - in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); + new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); } } } else if (t->isa_oopptr()) { - in2 = ConNode::make(C, t->make_narrowoop()); + new_in2 = ConNode::make(C, t->make_narrowoop()); } } - if( in2 != NULL ) { - Node* cmpN = new (C, 3) CmpNNode(n->in(1)->in(1), in2); + if (new_in2 != NULL) { + Node* cmpN = new (C, 3) CmpNNode(in1->in(1), new_in2); n->subsume_by( cmpN ); + if (in1->outcnt() == 0) { + in1->disconnect_inputs(NULL); + } + if (in2->outcnt() == 0) { + in2->disconnect_inputs(NULL); + } } } break; @@ -2214,6 +2228,9 @@ // Replacing Opaque nodes with their input in final_graph_reshaping_impl(), // 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 ) { + ResourceArea *area = Thread::current()->resource_area(); + Unique_Node_List sfpt(area); + fpu._visited.set(root->_idx); // first, mark node as visited uint cnt = root->req(); Node *n = root; @@ -2224,6 +2241,8 @@ Node* m = n->in(i); ++i; if (m != NULL && !fpu._visited.test_set(m->_idx)) { + if (m->is_SafePoint() && m->as_SafePoint()->jvms() != NULL) + sfpt.push(m); cnt = m->req(); nstack.push(n, i); // put on stack parent and next input's index n = m; @@ -2240,6 +2259,41 @@ 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-------------------------- diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/graphKit.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -1212,6 +1212,7 @@ Deoptimization::Action_make_not_entrant, NULL, "assert_null"); } else { + replace_in_map(value, zerocon(type)); builtin_throw(reason); } } @@ -1960,6 +1961,7 @@ // method will be compiled to handle NULLs. PreserveJVMState pjvms(this); set_control(*null_control); + replace_in_map(value, null()); uncommon_trap(Deoptimization::Reason_null_check, Deoptimization::Action_make_not_entrant); (*null_control) = top(); // NULL path is dead diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/lcm.cpp --- a/src/share/vm/opto/lcm.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/lcm.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -58,6 +58,9 @@ not_null_block = _succs[0]; 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. // (See Parse::do_if and Parse::do_ifnull for the reason @@ -149,6 +152,10 @@ const TypePtr *adr_type = NULL; // Do not need this return value here const Node* base = mach->get_base_and_disp(offset, adr_type); 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 } else { const TypePtr* tptr = base->bottom_type()->is_ptr(); diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/loopopts.cpp --- a/src/share/vm/opto/loopopts.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/loopopts.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -932,7 +932,7 @@ // to fold a StoreP and an AddP together (as part of an // address expression) and the AddP and StoreP have // 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); } diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/output.cpp --- a/src/share/vm/opto/output.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/output.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -685,6 +685,8 @@ } else if( t->base() == Type::Int && OptoReg::is_reg(regnum) ) { array->append(new_loc_value( _regalloc, regnum, Matcher::int_in_long ? Location::int_in_long : Location::normal )); + } else if( t->base() == Type::NarrowOop ) { + array->append(new_loc_value( _regalloc, regnum, Location::narrowoop )); } else { array->append(new_loc_value( _regalloc, regnum, _regalloc->is_oop(local) ? Location::oop : Location::normal )); } @@ -704,6 +706,13 @@ case Type::KlassPtr: // fall through array->append(new ConstantOopWriteValue(t->isa_oopptr()->const_oop()->encoding())); 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: array->append(new ConstantIntValue(t->is_int()->get_con())); break; @@ -878,9 +887,14 @@ } } else if( !obj_node->is_Con() ) { 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 { - 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); diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/opto/reg_split.cpp --- a/src/share/vm/opto/reg_split.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/opto/reg_split.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -527,6 +527,7 @@ // Initialize needs_phi and needs_split bool needs_phi = false; bool needs_split = false; + bool has_phi = false; // Walk the predecessor blocks to check inputs for that live range // Grab predecessor block header n1 = b->pred(1); @@ -570,28 +571,30 @@ } } // End for all potential Phi inputs - // If a phi is needed, check for it - if( needs_phi ) { - // check block for appropriate phinode & update edges - for( insidx = 1; insidx <= b->end_idx(); insidx++ ) { - n1 = b->_nodes[insidx]; - // bail if this is not a phi - phi = n1->is_Phi() ? n1->as_Phi() : NULL; - if( phi == NULL ) { - // Keep track of index of first non-PhiNode instruction in block - non_phi = insidx; - // 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) ) { - // found the necessary phi - needs_phi = false; - // initialize the Reaches entry for this LRG - Reachblock[slidx] = phi; - break; - } // end if found correct phi - } // end for all phi's + // check block for appropriate phinode & update edges + for( insidx = 1; insidx <= b->end_idx(); insidx++ ) { + n1 = b->_nodes[insidx]; + // bail if this is not a phi + phi = n1->is_Phi() ? n1->as_Phi() : NULL; + if( phi == NULL ) { + // Keep track of index of first non-PhiNode instruction in block + non_phi = insidx; + // 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) ) { + // found the necessary phi + needs_phi = false; + has_phi = true; + // initialize the Reaches entry for this LRG + Reachblock[slidx] = phi; + break; + } // end if found correct phi + } // 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 if( needs_phi ) { // create a new phi node and insert it into the block @@ -695,7 +698,8 @@ } } 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->disconnect_inputs(NULL); b->_nodes.remove(insidx); diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/runtime/arguments.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -1204,15 +1204,17 @@ // Turn off until bug is fixed. // 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 { if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) { // If specified, give a warning - if (UseConcMarkSweepGC){ - warning("Compressed Oops does not work with CMS"); - } else { - warning( - "Max heap size too large for Compressed Oops"); - } + warning( "Max heap size too large for Compressed Oops"); FLAG_SET_DEFAULT(UseCompressedOops, false); } } diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/runtime/globals.hpp Wed Sep 17 18:02:38 2008 -0700 @@ -294,6 +294,9 @@ lp64_product(bool, CheckCompressedOops, trueInDebug, \ "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 \ * removal testing. It was supposed to be removed before FCS but has \ * been re-added (see 6401008) */ \ diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/runtime/stackValue.cpp --- a/src/share/vm/runtime/stackValue.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/runtime/stackValue.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,6 +86,22 @@ case Location::lng: // Long value in an aligned adjacent pair 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 case Location::oop: { Handle h(*(oop *)value_addr); // Wrap a handle around the oop diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/runtime/thread.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -2756,13 +2756,17 @@ // For now, just manually iterate through them. tc->do_thread(VMThread::vm_thread()); Universe::heap()->gc_threads_do(tc); - { - // Grab the Terminator_lock to prevent watcher_thread from being terminated. - MutexLockerEx mu(Terminator_lock, Mutex::_no_safepoint_check_flag); - WatcherThread *wt = WatcherThread::watcher_thread(); - if (wt != NULL) - tc->do_thread(wt); - } + WatcherThread *wt = WatcherThread::watcher_thread(); + // Strictly speaking, the following NULL check isn't sufficient to make sure + // the data for WatcherThread is still valid upon being examined. However, + // considering that WatchThread terminates when the VM is on the way to + // exit at safepoint, the chance of the above is extremely small. The right + // 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 } diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/runtime/virtualspace.cpp --- a/src/share/vm/runtime/virtualspace.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/runtime/virtualspace.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -380,7 +380,8 @@ bool large, char* requested_address) : ReservedSpace(size, alignment, large, 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 // if using compressed oops. protect_noaccess_prefix(size); @@ -391,7 +392,8 @@ const size_t suffix_size, const size_t 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); } diff -r 51798f0e554f -r 75e0a5b79b1f src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Thu Sep 11 11:25:43 2008 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Wed Sep 17 18:02:38 2008 -0700 @@ -1577,6 +1577,7 @@ \ declare_constant(Location::normal) \ declare_constant(Location::oop) \ + declare_constant(Location::narrowoop) \ declare_constant(Location::int_in_long) \ declare_constant(Location::lng) \ declare_constant(Location::float_in_dbl) \ diff -r 51798f0e554f -r 75e0a5b79b1f test/Makefile --- a/test/Makefile Thu Sep 11 11:25:43 2008 -0700 +++ b/test/Makefile Wed Sep 17 18:02:38 2008 -0700 @@ -1,5 +1,5 @@ # -# 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. # # This code is free software; you can redistribute it and/or modify it @@ -19,17 +19,18 @@ # 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. -# +# # # -# Makefile to run jtreg +# Makefile to run various jdk tests # +# Get OS/ARCH specifics OSNAME = $(shell uname -s) +SLASH_JAVA = /java ifeq ($(OSNAME), SunOS) PLATFORM = solaris - JCT_PLATFORM = solaris ARCH = $(shell uname -p) ifeq ($(ARCH), i386) ARCH=i586 @@ -37,203 +38,165 @@ endif ifeq ($(OSNAME), Linux) PLATFORM = linux - JCT_PLATFORM = linux ARCH = $(shell uname -m) ifeq ($(ARCH), i386) - ARCH=i586 + ARCH = i586 endif endif ifeq ($(OSNAME), Windows_NT) PLATFORM = windows - JCT_PLATFORM = win32 + SLASH_JAVA = J: ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64) - ARCH=ia64 + ARCH = ia64 else ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),AMD64) - ARCH=x64 + ARCH = x64 else ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),EM64T) - ARCH=x64 + ARCH = x64 else - ARCH=i586 + ARCH = i586 endif endif endif -endif - -# Default bundle of all test results (passed or not) -JPRT_ARCHIVE_BUNDLE=$(TEST_ROOT)/JPRT_ARCHIVE_BUNDLE.zip - -# Default home for JTREG -ifeq ($(PLATFORM), windows) - JT_HOME = J:/svc/jct-tools3.2.2_01 -else - JT_HOME = /java/svc/jct-tools3.2.2_01 + EXESUFFIX = .exe endif -# Default JTREG to run -JTREG = $(JT_HOME)/$(JCT_PLATFORM)/bin/jtreg - -# Root of this test area -TEST_ROOT := $(shell pwd) - -# Default JDK to test -JAVA_HOME = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH) +# Utilities used +CD = cd +CP = cp +ECHO = echo +MKDIR = mkdir +ZIP = zip -# The test directories to run -DEFAULT_TESTDIRS = serviceability -TESTDIRS = $(DEFAULT_TESTDIRS) - -# Files that hold total passed and failed counts (passed==0 is bad) -JTREG_TOTALS_DIR = $(TEST_ROOT)/JTREG_TOTALS_$(PLATFORM)_$(ARCH) -JTREG_FAILED = $(JTREG_TOTALS_DIR)/failed_count -JTREG_PASSED = $(JTREG_TOTALS_DIR)/passed_count +# Root of this test area (important to use full paths in some places) +TEST_ROOT := $(shell pwd) # Root of all test results -JTREG_ALL_OUTPUT_DIRNAME = JTREG_OUTPUT_$(PLATFORM)_$(ARCH) -JTREG_ALL_OUTPUT_DIR = $(TEST_ROOT)/$(JTREG_ALL_OUTPUT_DIRNAME) - -# 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) +ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH) +ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput -# 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) +# 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 -# 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 +# Expect JPRT to set JAVA_ARGS (e.g. -server etc.) +JAVA_OPTIONS = +ifdef JAVA_ARGS + JAVA_OPTIONS = $(JAVA_ARGS) +endif -# 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 "---------------------------------------------------" +# Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results) +ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip +ifdef JPRT_ARCHIVE_BUNDLE + ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE) +endif + +# How to create the test bundle (pass or fail, we want to create this) +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} ) + +################################################################ + +# Default make rule (runs jtreg_tests) +all: jtreg_tests + @$(ECHO) "Testing completed successfully" + +# Prep for output +prep: clean + @$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR) + @$(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)` # Cleanup clean: - rm -f -r $(JTREG_ALL_OUTPUT_DIR) - rm -f $(JPRT_ARCHIVE_BUNDLE) + $(RM) -r $(ABS_TEST_OUTPUT_DIR) + $(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 = -FRC: +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) + +################################################################ +