# HG changeset patch # User kvn # Date 1208974836 25200 # Node ID b130b98db9cfed04e220ba16d597662957703593 # Parent 9e5a7340635ed52f88abae85be5db9227721bcca 6689060: Escape Analysis does not work with Compressed Oops Summary: 64-bits VM crashes with -XX:+AggresiveOpts (Escape Analysis + Compressed Oops) Reviewed-by: never, sgoldman diff -r 9e5a7340635e -r b130b98db9cf src/cpu/sparc/vm/assembler_sparc.cpp --- a/src/cpu/sparc/vm/assembler_sparc.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -3647,6 +3647,12 @@ srlx(r, LogMinObjAlignmentInBytes, r); } +void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) { + assert (UseCompressedOops, "must be compressed"); + sub(src, G6_heapbase, dst); + srlx(dst, LogMinObjAlignmentInBytes, dst); +} + // Same algorithm as oops.inline.hpp decode_heap_oop. void MacroAssembler::decode_heap_oop(Register src, Register dst) { assert (UseCompressedOops, "must be compressed"); @@ -3665,6 +3671,14 @@ add(r, G6_heapbase, r); } +void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { + // Do not add assert code to this unless you change vtableStubs_sparc.cpp + // pd_code_size_limit. + assert (UseCompressedOops, "must be compressed"); + sllx(src, LogMinObjAlignmentInBytes, dst); + add(dst, G6_heapbase, dst); +} + void MacroAssembler::reinit_heapbase() { if (UseCompressedOops) { // call indirectly to solve generation ordering problem diff -r 9e5a7340635e -r b130b98db9cf src/cpu/sparc/vm/assembler_sparc.hpp --- a/src/cpu/sparc/vm/assembler_sparc.hpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Wed Apr 23 11:20:36 2008 -0700 @@ -1998,6 +1998,8 @@ } void encode_heap_oop_not_null(Register r); void decode_heap_oop_not_null(Register r); + void encode_heap_oop_not_null(Register src, Register dst); + void decode_heap_oop_not_null(Register src, Register dst); // Support for managing the JavaThread pointer (i.e.; the reference to // thread-local information). diff -r 9e5a7340635e -r b130b98db9cf src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Thu Apr 17 07:16:03 2008 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Wed Apr 23 11:20:36 2008 -0700 @@ -5957,15 +5957,27 @@ // Convert oop pointer into compressed form instruct encodeHeapOop(iRegN dst, iRegP src) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() != TypePtr::NotNull); match(Set dst (EncodeP src)); - format %{ "SRL $src,3,$dst\t encodeHeapOop" %} + format %{ "encode_heap_oop $src, $dst" %} ins_encode %{ __ encode_heap_oop($src$$Register, $dst$$Register); %} ins_pipe(ialu_reg); %} +instruct encodeHeapOop_not_null(iRegN dst, iRegP src) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (EncodeP src)); + format %{ "encode_heap_oop_not_null $src, $dst" %} + ins_encode %{ + __ encode_heap_oop_not_null($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + instruct decodeHeapOop(iRegP dst, iRegN src) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); match(Set dst (DecodeN src)); format %{ "decode_heap_oop $src, $dst" %} ins_encode %{ @@ -5974,6 +5986,16 @@ ins_pipe(ialu_reg); %} +instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (DecodeN src)); + format %{ "decode_heap_oop_not_null $src, $dst" %} + ins_encode %{ + __ decode_heap_oop_not_null($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + // Store Zero into Aligned Packed Bytes instruct storeA8B0(memory mem, immI0 zero) %{ diff -r 9e5a7340635e -r b130b98db9cf src/cpu/x86/vm/assembler_x86_64.cpp --- a/src/cpu/x86/vm/assembler_x86_64.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/cpu/x86/vm/assembler_x86_64.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -4150,7 +4150,7 @@ if (oop_result->is_valid()) { movq(oop_result, Address(r15_thread, JavaThread::vm_result_offset())); movptr(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); - verify_oop(oop_result); + verify_oop(oop_result, "broken oop in call_VM_base"); } } @@ -4689,6 +4689,10 @@ popq(r12); } +#ifndef PRODUCT +extern "C" void findpc(intptr_t x); +#endif + void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) { // In order to get locks to work, we need to fake a in_VM state if (ShowMessageBoxOnError ) { @@ -4707,6 +4711,11 @@ if (os::message_box(msg, "Execution stopped, print registers?")) { ttyLocker ttyl; tty->print_cr("rip = 0x%016lx", pc); +#ifndef PRODUCT + tty->cr(); + findpc(pc); + tty->cr(); +#endif tty->print_cr("rax = 0x%016lx", regs[15]); tty->print_cr("rbx = 0x%016lx", regs[12]); tty->print_cr("rcx = 0x%016lx", regs[14]); @@ -5187,7 +5196,7 @@ bind(ok); popq(rscratch1); #endif - verify_oop(r); + verify_oop(r, "broken oop in encode_heap_oop"); testq(r, r); cmovq(Assembler::equal, r, r12_heapbase); subq(r, r12_heapbase); @@ -5203,11 +5212,28 @@ stop("null oop passed to encode_heap_oop_not_null"); bind(ok); #endif - verify_oop(r); + verify_oop(r, "broken oop in encode_heap_oop_not_null"); subq(r, r12_heapbase); shrq(r, LogMinObjAlignmentInBytes); } +void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + testq(src, src); + jcc(Assembler::notEqual, ok); + stop("null oop passed to encode_heap_oop_not_null2"); + bind(ok); +#endif + verify_oop(src, "broken oop in encode_heap_oop_not_null2"); + if (dst != src) { + movq(dst, src); + } + subq(dst, r12_heapbase); + shrq(dst, LogMinObjAlignmentInBytes); +} + void MacroAssembler::decode_heap_oop(Register r) { assert (UseCompressedOops, "should be compressed"); #ifdef ASSERT @@ -5232,7 +5258,7 @@ leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); #endif bind(done); - verify_oop(r); + verify_oop(r, "broken oop in decode_heap_oop"); } void MacroAssembler::decode_heap_oop_not_null(Register r) { @@ -5243,6 +5269,14 @@ leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); } +void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { + assert (UseCompressedOops, "should only be used for compressed headers"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); + leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); +} + Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { switch (cond) { // Note some conditions are synonyms for others diff -r 9e5a7340635e -r b130b98db9cf src/cpu/x86/vm/assembler_x86_64.hpp --- a/src/cpu/x86/vm/assembler_x86_64.hpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/cpu/x86/vm/assembler_x86_64.hpp Wed Apr 23 11:20:36 2008 -0700 @@ -1111,6 +1111,8 @@ void decode_heap_oop(Register r); void encode_heap_oop_not_null(Register r); void decode_heap_oop_not_null(Register r); + void encode_heap_oop_not_null(Register dst, Register src); + void decode_heap_oop_not_null(Register dst, Register src); // Stack frame creation/removal void enter(); diff -r 9e5a7340635e -r b130b98db9cf src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -913,11 +913,12 @@ // Stack after saving c_rarg3: // [tos + 0]: saved c_rarg3 // [tos + 1]: saved c_rarg2 - // [tos + 2]: saved flags - // [tos + 3]: return address - // * [tos + 4]: error message (char*) - // * [tos + 5]: object to verify (oop) - // * [tos + 6]: saved rax - saved by caller and bashed + // [tos + 2]: saved r12 (several TemplateTable methods use it) + // [tos + 3]: saved flags + // [tos + 4]: return address + // * [tos + 5]: error message (char*) + // * [tos + 6]: object to verify (oop) + // * [tos + 7]: saved rax - saved by caller and bashed // * = popped on exit address generate_verify_oop() { StubCodeMark mark(this, "StubRoutines", "verify_oop"); @@ -928,12 +929,24 @@ __ pushfq(); __ incrementl(ExternalAddress((address) StubRoutines::verify_oop_count_addr())); + __ pushq(r12); + // save c_rarg2 and c_rarg3 __ pushq(c_rarg2); __ pushq(c_rarg3); + enum { + // After previous pushes. + oop_to_verify = 6 * wordSize, + saved_rax = 7 * wordSize, + + // Before the call to MacroAssembler::debug(), see below. + return_addr = 16 * wordSize, + error_msg = 17 * wordSize + }; + // get object - __ movq(rax, Address(rsp, 5 * wordSize)); + __ movq(rax, Address(rsp, oop_to_verify)); // make sure object is 'reasonable' __ testq(rax, rax); @@ -946,6 +959,9 @@ __ cmpq(c_rarg2, c_rarg3); __ jcc(Assembler::notZero, error); + // set r12 to heapbase for load_klass() + __ reinit_heapbase(); + // make sure klass is 'reasonable' __ load_klass(rax, rax); // get klass __ testq(rax, rax); @@ -971,40 +987,45 @@ // return if everything seems ok __ bind(exit); - __ movq(rax, Address(rsp, 6 * wordSize)); // get saved rax back - __ popq(c_rarg3); // restore c_rarg3 - __ popq(c_rarg2); // restore c_rarg2 + __ movq(rax, Address(rsp, saved_rax)); // get saved rax back + __ popq(c_rarg3); // restore c_rarg3 + __ popq(c_rarg2); // restore c_rarg2 + __ popq(r12); // restore r12 __ popfq(); // restore flags __ ret(3 * wordSize); // pop caller saved stuff // handle errors __ bind(error); - __ movq(rax, Address(rsp, 6 * wordSize)); // get saved rax back - __ popq(c_rarg3); // get saved c_rarg3 back - __ popq(c_rarg2); // get saved c_rarg2 back + __ movq(rax, Address(rsp, saved_rax)); // get saved rax back + __ popq(c_rarg3); // get saved c_rarg3 back + __ popq(c_rarg2); // get saved c_rarg2 back + __ popq(r12); // get saved r12 back __ popfq(); // get saved flags off stack -- // will be ignored __ pushaq(); // push registers // (rip is already // already pushed) - // debug(char* msg, int64_t regs[]) + // debug(char* msg, int64_t pc, int64_t regs[]) // We've popped the registers we'd saved (c_rarg3, c_rarg2 and flags), and // pushed all the registers, so now the stack looks like: // [tos + 0] 16 saved registers // [tos + 16] return address - // [tos + 17] error message (char*) - - __ movq(c_rarg0, Address(rsp, 17 * wordSize)); // pass address of error message - __ movq(c_rarg1, rsp); // pass address of regs on stack + // * [tos + 17] error message (char*) + // * [tos + 18] object to verify (oop) + // * [tos + 19] saved rax - saved by caller and bashed + // * = popped on exit + + __ movq(c_rarg0, Address(rsp, error_msg)); // pass address of error message + __ movq(c_rarg1, Address(rsp, return_addr)); // pass return address + __ movq(c_rarg2, rsp); // pass address of regs on stack __ movq(r12, rsp); // remember rsp __ subq(rsp, frame::arg_reg_save_area_bytes);// windows __ andq(rsp, -16); // align stack as required by ABI BLOCK_COMMENT("call MacroAssembler::debug"); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug))); __ movq(rsp, r12); // restore rsp - __ reinit_heapbase(); // r12 is heapbase - __ popaq(); // pop registers + __ popaq(); // pop registers (includes r12) __ ret(3 * wordSize); // pop caller saved stuff return start; @@ -1038,7 +1059,7 @@ assert_different_registers(Rtmp, Rint); __ movslq(Rtmp, Rint); __ cmpq(Rtmp, Rint); - __ jccb(Assembler::equal, L); + __ jcc(Assembler::equal, L); __ stop("high 32-bits of int value are not 0"); __ bind(L); #endif diff -r 9e5a7340635e -r b130b98db9cf src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Thu Apr 17 07:16:03 2008 -0700 +++ b/src/cpu/x86/vm/x86_64.ad Wed Apr 23 11:20:36 2008 -0700 @@ -6080,7 +6080,8 @@ predicate(n->in(MemNode::Address)->bottom_type()->is_narrow()); ins_cost(125); // XXX - format %{ "movl $dst, $mem\t# compressed class" %} + format %{ "movl $dst, $mem\t# compressed class\n\t" + "decode_heap_oop $dst,$dst" %} ins_encode %{ Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); Register dst = as_Register($dst$$reg); @@ -6349,7 +6350,7 @@ instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{ match(Set dst src); effect(KILL cr); - format %{ "xorq $dst, $src\t# compressed ptr" %} + format %{ "xorq $dst, $src\t# compressed NULL ptr" %} ins_encode %{ Register dst = $dst$$Register; __ xorq(dst, dst); @@ -6361,7 +6362,8 @@ match(Set dst src); ins_cost(125); - format %{ "movl $dst, $src\t# compressed ptr" %} + format %{ "movq $dst, $src\t# compressed ptr\n\t" + "encode_heap_oop_not_null $dst,$dst" %} ins_encode %{ address con = (address)$src$$constant; Register dst = $dst$$Register; @@ -6996,6 +6998,7 @@ // Convert oop pointer into compressed form instruct encodeHeapOop(rRegN dst, rRegP src, rFlagsReg cr) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() != TypePtr::NotNull); match(Set dst (EncodeP src)); effect(KILL cr); format %{ "encode_heap_oop $dst,$src" %} @@ -7010,7 +7013,21 @@ ins_pipe(ialu_reg_long); %} +instruct encodeHeapOop_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (EncodeP src)); + effect(KILL cr); + format %{ "encode_heap_oop_not_null $dst,$src" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + __ encode_heap_oop_not_null(d, s); + %} + ins_pipe(ialu_reg_long); +%} + instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); match(Set dst (DecodeN src)); effect(KILL cr); format %{ "decode_heap_oop $dst,$src" %} @@ -7025,6 +7042,18 @@ ins_pipe(ialu_reg_long); %} +instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (DecodeN src)); + format %{ "decode_heap_oop_not_null $dst,$src" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + __ decode_heap_oop_not_null(d, s); + %} + ins_pipe(ialu_reg_long); +%} + //----------Conditional Move--------------------------------------------------- // Jump diff -r 9e5a7340635e -r b130b98db9cf src/share/vm/opto/connode.cpp --- a/src/share/vm/opto/connode.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/share/vm/opto/connode.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -563,6 +563,26 @@ return this; } +const Type *DecodeNNode::Value( PhaseTransform *phase ) const { + if (phase->type( in(1) ) == TypeNarrowOop::NULL_PTR) { + return TypePtr::NULL_PTR; + } + return bottom_type(); +} + +Node* DecodeNNode::decode(PhaseGVN* phase, Node* value) { + if (value->Opcode() == Op_EncodeP) { + // (DecodeN (EncodeP p)) -> p + return value->in(1); + } + const Type* newtype = value->bottom_type(); + if (newtype == TypeNarrowOop::NULL_PTR) { + return phase->transform(new (phase->C, 1) ConPNode(TypePtr::NULL_PTR)); + } else { + return phase->transform(new (phase->C, 2) DecodeNNode(value, newtype->is_narrowoop()->make_oopptr())); + } +} + Node* EncodePNode::Identity(PhaseTransform* phase) { const Type *t = phase->type( in(1) ); if( t == Type::TOP ) return in(1); @@ -574,14 +594,26 @@ return this; } +const Type *EncodePNode::Value( PhaseTransform *phase ) const { + if (phase->type( in(1) ) == TypePtr::NULL_PTR) { + return TypeNarrowOop::NULL_PTR; + } + return bottom_type(); +} Node* EncodePNode::encode(PhaseGVN* phase, Node* value) { + if (value->Opcode() == Op_DecodeN) { + // (EncodeP (DecodeN p)) -> p + return value->in(1); + } const Type* newtype = value->bottom_type(); if (newtype == TypePtr::NULL_PTR) { return phase->transform(new (phase->C, 1) ConNNode(TypeNarrowOop::NULL_PTR)); + } else if (newtype->isa_oopptr()) { + return phase->transform(new (phase->C, 2) EncodePNode(value, newtype->is_oopptr()->make_narrowoop())); } else { - return phase->transform(new (phase->C, 2) EncodePNode(value, - newtype->is_oopptr()->make_narrowoop())); + ShouldNotReachHere(); + return NULL; // to make C++ compiler happy. } } diff -r 9e5a7340635e -r b130b98db9cf src/share/vm/opto/connode.hpp --- a/src/share/vm/opto/connode.hpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/share/vm/opto/connode.hpp Wed Apr 23 11:20:36 2008 -0700 @@ -282,6 +282,7 @@ } virtual int Opcode() const; virtual Node *Identity( PhaseTransform *phase ); + virtual const Type *Value( PhaseTransform *phase ) const; virtual uint ideal_reg() const { return Op_RegN; } static Node* encode(PhaseGVN* phase, Node* value); @@ -300,7 +301,10 @@ } virtual int Opcode() const; virtual Node *Identity( PhaseTransform *phase ); + virtual const Type *Value( PhaseTransform *phase ) const; virtual uint ideal_reg() const { return Op_RegP; } + + static Node* decode(PhaseGVN* phase, Node* value); }; //------------------------------Conv2BNode------------------------------------- diff -r 9e5a7340635e -r b130b98db9cf src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/share/vm/opto/escape.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -215,6 +215,10 @@ VectorSet visited(Thread::current()->resource_area()); GrowableArray worklist; +#ifdef ASSERT + Node *orig_n = n; +#endif + n = n->uncast(); PointsToNode npt = _nodes->at_grow(n->_idx); @@ -223,8 +227,14 @@ ptset.set(n->_idx); return; } - assert(npt._node != NULL, "unregistered node"); - +#ifdef ASSERT + if (npt._node == NULL) { + if (orig_n != n) + orig_n->dump(); + n->dump(); + assert(npt._node != NULL, "unregistered node"); + } +#endif worklist.push(n->_idx); while(worklist.length() > 0) { int ni = worklist.pop(); @@ -266,7 +276,7 @@ PointsToNode *ptn = ptnode_adr(ni); // Mark current edges as visited and move deferred edges to separate array. - for (; i < ptn->edge_count(); i++) { + while (i < ptn->edge_count()) { uint t = ptn->edge_target(i); #ifdef ASSERT assert(!visited->test_set(t), "expecting no duplications"); @@ -276,6 +286,8 @@ if (ptn->edge_type(i) == PointsToNode::DeferredEdge) { ptn->remove_edge(t, PointsToNode::DeferredEdge); deferred_edges->append(t); + } else { + i++; } } for (int next = 0; next < deferred_edges->length(); ++next) { @@ -1716,6 +1728,8 @@ } case Op_CastPP: case Op_CheckCastPP: + case Op_EncodeP: + case Op_DecodeN: { add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); int ti = n->in(1)->_idx; @@ -1743,12 +1757,6 @@ add_node(n, PointsToNode::JavaObject, es, true); break; } - case Op_CreateEx: - { - // assume that all exception objects globally escape - add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true); - break; - } case Op_ConN: { // assume all narrow oop constants globally escape except for null @@ -1761,6 +1769,12 @@ add_node(n, PointsToNode::JavaObject, es, true); break; } + case Op_CreateEx: + { + // assume that all exception objects globally escape + add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true); + break; + } case Op_LoadKlass: { add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true); @@ -1976,10 +1990,11 @@ break; } case Op_LoadP: + case Op_LoadN: { const Type *t = phase->type(n); #ifdef ASSERT - if (t->isa_ptr() == NULL) + if (!t->isa_narrowoop() && t->isa_ptr() == NULL) assert(false, "Op_LoadP"); #endif @@ -2060,11 +2075,16 @@ break; } case Op_StoreP: + case Op_StoreN: case Op_StorePConditional: case Op_CompareAndSwapP: + case Op_CompareAndSwapN: { Node *adr = n->in(MemNode::Address); const Type *adr_type = phase->type(adr); + if (adr_type->isa_narrowoop()) { + adr_type = adr_type->is_narrowoop()->make_oopptr(); + } #ifdef ASSERT if (!adr_type->isa_oopptr()) assert(phase->type(adr) == TypeRawPtr::NOTNULL, "Op_StoreP"); diff -r 9e5a7340635e -r b130b98db9cf src/share/vm/opto/macro.cpp --- a/src/share/vm/opto/macro.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/share/vm/opto/macro.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -584,7 +584,7 @@ const Type *field_type; // The next code is taken from Parse::do_get_xxx(). - if (basic_elem_type == T_OBJECT) { + if (basic_elem_type == T_OBJECT || basic_elem_type == T_ARRAY) { if (!elem_type->is_loaded()) { field_type = TypeInstPtr::BOTTOM; } else if (field != NULL && field->is_constant()) { @@ -597,6 +597,10 @@ } else { field_type = TypeOopPtr::make_from_klass(elem_type->as_klass()); } + if (UseCompressedOops) { + field_type = field_type->is_oopptr()->make_narrowoop(); + basic_elem_type = T_NARROWOOP; + } } else { field_type = Type::get_const_basic_type(basic_elem_type); } @@ -659,6 +663,13 @@ #endif return false; } + if (UseCompressedOops && field_type->isa_narrowoop()) { + // Enable "DecodeN(EncodeP(Allocate)) --> Allocate" transformation + // to be able scalar replace the allocation. + _igvn.set_delay_transform(false); + field_val = DecodeNNode::decode(&_igvn, field_val); + _igvn.set_delay_transform(true); + } sfpt->add_req(field_val); } JVMState *jvms = sfpt->jvms(); diff -r 9e5a7340635e -r b130b98db9cf src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/share/vm/opto/memnode.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -754,13 +754,12 @@ const TypeNarrowOop* narrowtype; if (rt->isa_narrowoop()) { narrowtype = rt->is_narrowoop(); - rt = narrowtype->make_oopptr(); } else { narrowtype = rt->is_oopptr()->make_narrowoop(); } Node* load = gvn.transform(new (C, 3) LoadNNode(ctl, mem, adr, adr_type, narrowtype)); - return new (C, 2) DecodeNNode(load, rt); + return DecodeNNode::decode(&gvn, load); } else #endif { @@ -1841,15 +1840,7 @@ (UseCompressedOops && val->bottom_type()->isa_klassptr() && adr->bottom_type()->isa_rawptr())) { const TypePtr* type = val->bottom_type()->is_ptr(); - Node* cp; - if (type->isa_oopptr()) { - const TypeNarrowOop* etype = type->is_oopptr()->make_narrowoop(); - cp = gvn.transform(new (C, 2) EncodePNode(val, etype)); - } else if (type == TypePtr::NULL_PTR) { - cp = gvn.transform(new (C, 1) ConNNode(TypeNarrowOop::NULL_PTR)); - } else { - ShouldNotReachHere(); - } + Node* cp = EncodePNode::encode(&gvn, val); return new (C, 4) StoreNNode(ctl, mem, adr, adr_type, cp); } else #endif diff -r 9e5a7340635e -r b130b98db9cf src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 17 07:16:03 2008 -0700 +++ b/src/share/vm/runtime/sharedRuntime.cpp Wed Apr 23 11:20:36 2008 -0700 @@ -2176,6 +2176,8 @@ #ifndef PRODUCT bool AdapterHandlerLibrary::contains(CodeBlob* b) { + if (_handlers == NULL) return false; + for (int i = 0 ; i < _handlers->length() ; i++) { AdapterHandlerEntry* a = get_entry(i); if ( a != NULL && b == CodeCache::find_blob(a->get_i2c_entry()) ) return true;