changeset 182:44abbb0d4c18

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
author kvn
date Thu, 05 Jun 2008 13:02:51 -0700
parents 823298b11afc
children d4dbd9f91680
files src/cpu/sparc/vm/sparc.ad src/cpu/x86/vm/assembler_x86_64.cpp src/cpu/x86/vm/assembler_x86_64.hpp src/cpu/x86/vm/x86_64.ad src/share/vm/ci/ciMethod.cpp src/share/vm/opto/compile.cpp
diffstat 6 files changed, 64 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- 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 %{
--- 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);
--- 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);
--- 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 %{
--- 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();
   )
 }
 
--- 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;
   }