# HG changeset patch # User kvn # Date 1212696171 25200 # Node ID 44abbb0d4c18ba6fbdb3ea98940b619a0cd1c37d # Parent 823298b11afc43e469fe88d8afa2835327277749 6709093: Compressed Oops: reduce size of compiled methods Summary: exclude UEP size from nmethod code size and use narrow klass oop to load prototype header. Reviewed-by: jrose, never diff -r 823298b11afc -r 44abbb0d4c18 src/cpu/sparc/vm/sparc.ad --- a/src/cpu/sparc/vm/sparc.ad Wed Jun 04 21:56:27 2008 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Thu Jun 05 13:02:51 2008 -0700 @@ -5975,7 +5975,8 @@ %} instruct decodeHeapOop(iRegP dst, iRegN src) %{ - predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); + predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull && + n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant); match(Set dst (DecodeN src)); format %{ "decode_heap_oop $src, $dst" %} ins_encode %{ @@ -5985,7 +5986,8 @@ %} instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{ - predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); + predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull || + n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant); match(Set dst (DecodeN src)); format %{ "decode_heap_oop_not_null $src, $dst" %} ins_encode %{ diff -r 823298b11afc -r 44abbb0d4c18 src/cpu/x86/vm/assembler_x86_64.cpp --- a/src/cpu/x86/vm/assembler_x86_64.cpp Wed Jun 04 21:56:27 2008 -0700 +++ b/src/cpu/x86/vm/assembler_x86_64.cpp Thu Jun 05 13:02:51 2008 -0700 @@ -5007,8 +5007,7 @@ jcc(Assembler::notEqual, cas_label); // The bias pattern is present in the object's header. Need to check // whether the bias owner and the epoch are both still current. - load_klass(tmp_reg, obj_reg); - movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + load_prototype_header(tmp_reg, obj_reg); orq(tmp_reg, r15_thread); xorq(tmp_reg, swap_reg); andq(tmp_reg, ~((int) markOopDesc::age_mask_in_place)); @@ -5082,8 +5081,7 @@ // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - load_klass(tmp_reg, obj_reg); - movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + load_prototype_header(tmp_reg, obj_reg); orq(tmp_reg, r15_thread); if (os::is_MP()) { lock(); @@ -5113,8 +5111,7 @@ // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - load_klass(tmp_reg, obj_reg); - movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + load_prototype_header(tmp_reg, obj_reg); if (os::is_MP()) { lock(); } @@ -5158,6 +5155,16 @@ } } +void MacroAssembler::load_prototype_header(Register dst, Register src) { + if (UseCompressedOops) { + movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); + movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + } else { + movq(dst, Address(src, oopDesc::klass_offset_in_bytes())); + movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); + } +} + void MacroAssembler::store_klass(Register dst, Register src) { if (UseCompressedOops) { encode_heap_oop_not_null(src); diff -r 823298b11afc -r 44abbb0d4c18 src/cpu/x86/vm/assembler_x86_64.hpp --- a/src/cpu/x86/vm/assembler_x86_64.hpp Wed Jun 04 21:56:27 2008 -0700 +++ b/src/cpu/x86/vm/assembler_x86_64.hpp Thu Jun 05 13:02:51 2008 -0700 @@ -1111,6 +1111,8 @@ void store_klass(Register dst, Register src); void store_klass_gap(Register dst, Register src); + void load_prototype_header(Register dst, Register src); + void load_heap_oop(Register dst, Address src); void store_heap_oop(Address dst, Register src); void encode_heap_oop(Register r); diff -r 823298b11afc -r 44abbb0d4c18 src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Wed Jun 04 21:56:27 2008 -0700 +++ b/src/cpu/x86/vm/x86_64.ad Thu Jun 05 13:02:51 2008 -0700 @@ -6149,7 +6149,7 @@ match(Set dst (LoadNKlass mem)); ins_cost(125); // XXX - format %{ "movl $dst, $mem\t# compressed klass ptr\n\t" %} + format %{ "movl $dst, $mem\t# compressed klass ptr" %} ins_encode %{ Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); Register dst = as_Register($dst$$reg); @@ -7089,7 +7089,8 @@ %} instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{ - predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); + predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull && + n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant); match(Set dst (DecodeN src)); effect(KILL cr); format %{ "decode_heap_oop $dst,$src" %} @@ -7105,7 +7106,8 @@ %} instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{ - predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); + predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull || + n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant); match(Set dst (DecodeN src)); format %{ "decode_heap_oop_not_null $dst,$src" %} ins_encode %{ diff -r 823298b11afc -r 44abbb0d4c18 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Wed Jun 04 21:56:27 2008 -0700 +++ b/src/share/vm/ci/ciMethod.cpp Thu Jun 05 13:02:51 2008 -0700 @@ -878,7 +878,7 @@ (TieredCompilation && code->compiler() != NULL && code->compiler()->is_c1())) { return 0; } - return code->code_size(); + return code->code_end() - code->verified_entry_point(); ) } diff -r 823298b11afc -r 44abbb0d4c18 src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Wed Jun 04 21:56:27 2008 -0700 +++ b/src/share/vm/opto/compile.cpp Thu Jun 05 13:02:51 2008 -0700 @@ -1992,11 +1992,49 @@ } case Op_AddP: { // Assert sane base pointers - const Node *addp = n->in(AddPNode::Address); + Node *addp = n->in(AddPNode::Address); assert( !addp->is_AddP() || addp->in(AddPNode::Base)->is_top() || // Top OK for allocation addp->in(AddPNode::Base) == n->in(AddPNode::Base), "Base pointers must match" ); +#ifdef _LP64 + if (UseCompressedOops && + addp->Opcode() == Op_ConP && + addp == n->in(AddPNode::Base) && + n->in(AddPNode::Offset)->is_Con()) { + // Use addressing with narrow klass to load with offset on x86. + // On sparc loading 32-bits constant and decoding it have less + // instructions (4) then load 64-bits constant (7). + // Do this transformation here since IGVN will convert ConN back to ConP. + const Type* t = addp->bottom_type(); + if (t->isa_oopptr()) { + Node* nn = NULL; + + // Look for existing ConN node of the same exact type. + Compile* C = Compile::current(); + Node* r = C->root(); + uint cnt = r->outcnt(); + for (uint i = 0; i < cnt; i++) { + Node* m = r->raw_out(i); + if (m!= NULL && m->Opcode() == Op_ConN && + m->bottom_type()->is_narrowoop()->make_oopptr() == t) { + nn = m; + break; + } + } + if (nn != NULL) { + // Decode a narrow oop to match address + // [R12 + narrow_oop_reg<<3 + offset] + nn = new (C, 2) DecodeNNode(nn, t); + n->set_req(AddPNode::Base, nn); + n->set_req(AddPNode::Address, nn); + if (addp->outcnt() == 0) { + addp->disconnect_inputs(NULL); + } + } + } + } +#endif break; }