7003454: order constants in constant table by number of references in code
authortwisti
Wed, 16 Nov 2011 01:39:50 -0800
changeset 11190 d561d41f241a
parent 11189 c1ad8528ae68
child 11191 d54ab5dcba83
7003454: order constants in constant table by number of references in code Reviewed-by: kvn, never, bdelsart
hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
hotspot/src/cpu/sparc/vm/sparc.ad
hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp
hotspot/src/cpu/x86/vm/assembler_x86.hpp
hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
hotspot/src/cpu/x86/vm/x86_32.ad
hotspot/src/cpu/x86/vm/x86_64.ad
hotspot/src/share/vm/adlc/adlparse.cpp
hotspot/src/share/vm/adlc/output_c.cpp
hotspot/src/share/vm/asm/assembler.hpp
hotspot/src/share/vm/opto/compile.cpp
hotspot/src/share/vm/opto/compile.hpp
hotspot/src/share/vm/opto/machnode.cpp
hotspot/src/share/vm/opto/matcher.hpp
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Nov 16 01:39:50 2011 -0800
@@ -855,12 +855,6 @@
     Lookaside  = 1 << 4
   };
 
-  // test if x is within signed immediate range for nbits
-  static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 )  <= x   &&   x  <  ( intptr_t(1) << nbits-1 ); }
-
-  // test if -4096 <= x <= 4095
-  static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
-
   static bool is_in_wdisp_range(address a, address b, int nbits) {
     intptr_t d = intptr_t(b) - intptr_t(a);
     return is_simm(d, nbits + 2);
@@ -1203,7 +1197,7 @@
     if (!UseCBCond || cbcond_before()) return false;
     intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc());
     assert( (x & 3) == 0, "not word aligned");
-    return is_simm(x, 12);
+    return is_simm12(x);
   }
 
   // Tells assembler you know that next instruction is delayed
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -765,7 +765,7 @@
 void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) {
   add_debug_info_for_null_check_here(op->info());
   __ load_klass(O0, G3_scratch);
-  if (__ is_simm13(op->vtable_offset())) {
+  if (Assembler::is_simm13(op->vtable_offset())) {
     __ ld_ptr(G3_scratch, op->vtable_offset(), G5_method);
   } else {
     // This will generate 2 instructions
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -315,7 +315,7 @@
   __ cmp_and_br_short(O7_temp, T_VOID, Assembler::equal, Assembler::pt, L_ok_4);
   extract_conversion_vminfo(_masm, L5_conversion, O5_temp);
   __ ld_ptr(L4_saved_args_base, __ argument_offset(O5_temp, O5_temp), O7_temp);
-  assert(__ is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13");
+  assert(Assembler::is_simm13(RETURN_VALUE_PLACEHOLDER), "must be simm13");
   __ cmp_and_brx_short(O7_temp, (int32_t) RETURN_VALUE_PLACEHOLDER, Assembler::equal, Assembler::pt, L_ok_4);
   __ stop("damaged ricochet frame: RETURN_VALUE_PLACEHOLDER not found");
   __ BIND(L_ok_4);
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -767,7 +767,7 @@
   // In the 64bit build because of wider slots and STACKBIAS we can run
   // out of bits in the displacement to do loads and stores.  Use g3 as
   // temporary displacement.
-  if (! __ is_simm13(extraspace)) {
+  if (!Assembler::is_simm13(extraspace)) {
     __ set(extraspace, G3_scratch);
     __ sub(SP, G3_scratch, SP);
   } else {
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Nov 16 01:39:50 2011 -0800
@@ -566,7 +566,7 @@
     } else {
       klass_load_size = 1*BytesPerInstWord;
     }
-    if( Assembler::is_simm13(v_off) ) {
+    if (Assembler::is_simm13(v_off)) {
       return klass_load_size +
              (2*BytesPerInstWord +           // ld_ptr, ld_ptr
              NativeCall::instruction_size);  // call; delay slot
@@ -1019,17 +1019,31 @@
 
 
 //=============================================================================
-const bool Matcher::constant_table_absolute_addressing = false;
 const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask;
 
+int Compile::ConstantTable::calculate_table_base_offset() const {
+  if (UseRDPCForConstantTableBase) {
+    // The table base offset might be less but then it fits into
+    // simm13 anyway and we are good (cf. MachConstantBaseNode::emit).
+    return Assembler::min_simm13();
+  } else {
+    int offset = -(size() / 2);
+    if (!Assembler::is_simm13(offset)) {
+      offset = Assembler::min_simm13();
+    }
+    return offset;
+  }
+}
+
 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
   Compile* C = ra_->C;
   Compile::ConstantTable& constant_table = C->constant_table();
   MacroAssembler _masm(&cbuf);
 
   Register r = as_Register(ra_->get_encode(this));
-  CodeSection* cs = __ code()->consts();
-  int consts_size = cs->align_at_start(cs->size());
+  CodeSection* consts_section = __ code()->consts();
+  int consts_size = consts_section->align_at_start(consts_section->size());
+  assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size));
 
   if (UseRDPCForConstantTableBase) {
     // For the following RDPC logic to work correctly the consts
@@ -1037,30 +1051,37 @@
     // assert checks for that.  The layout and the SECT_* constants
     // are defined in src/share/vm/asm/codeBuffer.hpp.
     assert(CodeBuffer::SECT_CONSTS + 1 == CodeBuffer::SECT_INSTS, "must be");
-    int offset = __ offset();
+    int insts_offset = __ offset();
+
+    // Layout:
+    //
+    // |----------- consts section ------------|----------- insts section -----------...
+    // |------ constant table -----|- padding -|------------------x----
+    //                                                            \ current PC (RDPC instruction)
+    // |<------------- consts_size ----------->|<- insts_offset ->|
+    //                                                            \ table base
+    // The table base offset is later added to the load displacement
+    // so it has to be negative.
+    int table_base_offset = -(consts_size + insts_offset);
     int disp;
 
     // If the displacement from the current PC to the constant table
     // base fits into simm13 we set the constant table base to the
     // current PC.
-    if (__ is_simm13(-(consts_size + offset))) {
-      constant_table.set_table_base_offset(-(consts_size + offset));
+    if (Assembler::is_simm13(table_base_offset)) {
+      constant_table.set_table_base_offset(table_base_offset);
       disp = 0;
     } else {
-      // If the offset of the top constant (last entry in the table)
-      // fits into simm13 we set the constant table base to the actual
-      // table base.
-      if (__ is_simm13(constant_table.top_offset())) {
-        constant_table.set_table_base_offset(0);
-        disp = consts_size + offset;
-      } else {
-        // Otherwise we set the constant table base in the middle of the
-        // constant table.
-        int half_consts_size = consts_size / 2;
-        assert(half_consts_size * 2 == consts_size, "sanity");
-        constant_table.set_table_base_offset(-half_consts_size);  // table base offset gets added to the load displacement.
-        disp = half_consts_size + offset;
-      }
+      // Otherwise we set the constant table base offset to the
+      // maximum negative displacement of load instructions to keep
+      // the disp as small as possible:
+      //
+      // |<------------- consts_size ----------->|<- insts_offset ->|
+      // |<--------- min_simm13 --------->|<-------- disp --------->|
+      //                                  \ table base
+      table_base_offset = Assembler::min_simm13();
+      constant_table.set_table_base_offset(table_base_offset);
+      disp = (consts_size + insts_offset) + table_base_offset;
     }
 
     __ rdpc(r);
@@ -1072,8 +1093,7 @@
   }
   else {
     // Materialize the constant table base.
-    assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size));
-    address baseaddr = cs->start() + -(constant_table.table_base_offset());
+    address baseaddr = consts_section->start() + -(constant_table.table_base_offset());
     RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
     AddressLiteral base(baseaddr, rspec);
     __ set(base, r);
@@ -1169,6 +1189,13 @@
     __ save(SP, G3, SP);
   }
   C->set_frame_complete( __ offset() );
+
+  if (!UseRDPCForConstantTableBase && C->has_mach_constant_base_node()) {
+    // NOTE: We set the table base offset here because users might be
+    // emitted before MachConstantBaseNode.
+    Compile::ConstantTable& constant_table = C->constant_table();
+    constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
+  }
 }
 
 uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
@@ -1843,7 +1870,7 @@
 bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
   // The passed offset is relative to address of the branch.
   // Don't need to adjust the offset.
-  return UseCBCond && Assembler::is_simm(offset, 12);
+  return UseCBCond && Assembler::is_simm12(offset);
 }
 
 const bool Matcher::isSimpleConstant64(jlong value) {
@@ -2072,8 +2099,8 @@
   %}
 
   enc_class form3_mem_reg_long_unaligned_marshal( memory mem, iRegL reg ) %{
-    assert( Assembler::is_simm13($mem$$disp  ), "need disp and disp+4" );
-    assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" );
+    assert(Assembler::is_simm13($mem$$disp  ), "need disp and disp+4");
+    assert(Assembler::is_simm13($mem$$disp+4), "need disp and disp+4");
     guarantee($mem$$index == R_G0_enc, "double index?");
     emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp+4, R_G0_enc, R_O7_enc );
     emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp,   R_G0_enc, $reg$$reg );
@@ -2082,8 +2109,8 @@
   %}
 
   enc_class form3_mem_reg_double_unaligned( memory mem, RegD_low reg ) %{
-    assert( Assembler::is_simm13($mem$$disp  ), "need disp and disp+4" );
-    assert( Assembler::is_simm13($mem$$disp+4), "need disp and disp+4" );
+    assert(Assembler::is_simm13($mem$$disp  ), "need disp and disp+4");
+    assert(Assembler::is_simm13($mem$$disp+4), "need disp and disp+4");
     guarantee($mem$$index == R_G0_enc, "double index?");
     // Load long with 2 instructions
     emit_form3_mem_reg(cbuf, this, $primary, -1, $mem$$base, $mem$$disp,   R_G0_enc, $reg$$reg+0 );
@@ -2563,7 +2590,7 @@
       }
       int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
       int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
-      if( __ is_simm13(v_off) ) {
+      if (Assembler::is_simm13(v_off)) {
         __ ld_ptr(G3, v_off, G5_method);
       } else {
         // Generate 2 instructions
@@ -3336,7 +3363,7 @@
 
 // Integer Immediate: 8-bit
 operand immI8() %{
-  predicate(Assembler::is_simm(n->get_int(), 8));
+  predicate(Assembler::is_simm8(n->get_int()));
   match(ConI);
   op_cost(0);
   format %{ %}
@@ -3365,7 +3392,7 @@
 
 // Integer Immediate: 16-bit
 operand immI16() %{
-  predicate(Assembler::is_simm(n->get_int(), 16));
+  predicate(Assembler::is_simm16(n->get_int()));
   match(ConI);
   op_cost(0);
   format %{ %}
@@ -3393,7 +3420,7 @@
 
 // Integer Immediate: 11-bit
 operand immI11() %{
-  predicate(Assembler::is_simm(n->get_int(),11));
+  predicate(Assembler::is_simm11(n->get_int()));
   match(ConI);
   op_cost(0);
   format %{ %}
@@ -3402,7 +3429,7 @@
 
 // Integer Immediate: 5-bit
 operand immI5() %{
-  predicate(Assembler::is_simm(n->get_int(), 5));
+  predicate(Assembler::is_simm5(n->get_int()));
   match(ConI);
   op_cost(0);
   format %{ %}
@@ -3634,7 +3661,7 @@
 
 // Integer Immediate: 5-bit
 operand immL5() %{
-  predicate(n->get_long() == (int)n->get_long() && Assembler::is_simm((int)n->get_long(), 5));
+  predicate(n->get_long() == (int)n->get_long() && Assembler::is_simm5((int)n->get_long()));
   match(ConL);
   op_cost(0);
   format %{ %}
@@ -9251,13 +9278,16 @@
 
   format %{  "ADD    $constanttablebase, $constantoffset, O7\n\t"
              "LD     [O7 + $switch_val], O7\n\t"
-             "JUMP   O7"
-         %}
+             "JUMP   O7" %}
   ins_encode %{
     // Calculate table address into a register.
     Register table_reg;
     Register label_reg = O7;
-    if (constant_offset() == 0) {
+    // If we are calculating the size of this instruction don't trust
+    // zero offsets because they might change when
+    // MachConstantBaseNode decides to optimize the constant table
+    // base.
+    if ((constant_offset() == 0) && !Compile::current()->in_scratch_emit_size()) {
       table_reg = $constanttablebase;
     } else {
       table_reg = O7;
--- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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
@@ -83,7 +83,7 @@
   }
 #endif
   int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
-  if( __ is_simm13(v_off) ) {
+  if (Assembler::is_simm13(v_off)) {
     __ ld_ptr(G3, v_off, G5_method);
   } else {
     __ set(v_off,G5);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Wed Nov 16 01:39:50 2011 -0800
@@ -693,17 +693,6 @@
   static address locate_next_instruction(address inst);
 
   // Utilities
-
-#ifdef _LP64
- static bool is_simm(int64_t x, int nbits) { return -(CONST64(1) << (nbits-1)) <= x &&
-                                                    x < (CONST64(1) << (nbits-1)); }
- static bool is_simm32(int64_t x) { return x == (int64_t)(int32_t)x; }
-#else
- static bool is_simm(int32_t x, int nbits) { return -(1 << (nbits-1)) <= x &&
-                                                    x < (1 << (nbits-1)); }
- static bool is_simm32(int32_t x) { return true; }
-#endif // _LP64
-
   static bool is_polling_page_far() NOT_LP64({ return false;});
 
   // Generic instructions
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -1268,7 +1268,7 @@
            __ subptr(end, start); // number of bytes to copy
 
           intptr_t disp = (intptr_t) ct->byte_map_base;
-          if (__ is_simm32(disp)) {
+          if (Assembler::is_simm32(disp)) {
             Address cardtable(noreg, noreg, Address::no_scale, disp);
             __ lea(scratch, cardtable);
           } else {
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Wed Nov 16 01:39:50 2011 -0800
@@ -507,9 +507,12 @@
 
 
 //=============================================================================
-const bool Matcher::constant_table_absolute_addressing = true;
 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
 
+int Compile::ConstantTable::calculate_table_base_offset() const {
+  return 0;  // absolute addressing, no offset
+}
+
 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
   // Empty encoding
 }
@@ -639,6 +642,12 @@
   }
 #endif
 
+  if (C->has_mach_constant_base_node()) {
+    // NOTE: We set the table base offset here because users might be
+    // emitted before MachConstantBaseNode.
+    Compile::ConstantTable& constant_table = C->constant_table();
+    constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
+  }
 }
 
 uint MachPrologNode::size(PhaseRegAlloc *ra_) const {
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Wed Nov 16 01:39:50 2011 -0800
@@ -843,9 +843,12 @@
 
 
 //=============================================================================
-const bool Matcher::constant_table_absolute_addressing = true;
 const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
 
+int Compile::ConstantTable::calculate_table_base_offset() const {
+  return 0;  // absolute addressing, no offset
+}
+
 void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
   // Empty encoding
 }
@@ -977,6 +980,13 @@
     masm.bind(L);
   }
 #endif
+
+  if (C->has_mach_constant_base_node()) {
+    // NOTE: We set the table base offset here because users might be
+    // emitted before MachConstantBaseNode.
+    Compile::ConstantTable& constant_table = C->constant_table();
+    constant_table.set_table_base_offset(constant_table.calculate_table_base_offset());
+  }
 }
 
 uint MachPrologNode::size(PhaseRegAlloc* ra_) const
--- a/hotspot/src/share/vm/adlc/adlparse.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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
@@ -3115,7 +3115,7 @@
   encoding->add_code("    _constant = C->constant_table().add");
 
   // Parse everything in ( ) expression.
-  encoding->add_code("(");
+  encoding->add_code("(this, ");
   next_char();  // Skip '('
   int parens_depth = 1;
 
@@ -3130,7 +3130,8 @@
     }
     else if (_curchar == ')') {
       parens_depth--;
-      encoding->add_code(")");
+      if (parens_depth > 0)
+        encoding->add_code(")");
       next_char();
     }
     else {
@@ -3157,7 +3158,7 @@
   }
 
   // Finish code line.
-  encoding->add_code(";");
+  encoding->add_code(");");
 
   if (_AD._adlocation_debug) {
     encoding->add_code(end_line_marker());
--- a/hotspot/src/share/vm/adlc/output_c.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/share/vm/adlc/output_c.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -2585,9 +2585,9 @@
   // Output instruction's emit prototype
   fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident);
 
-  // For ideal jump nodes, allocate a jump table.
+  // For ideal jump nodes, add a jump-table entry.
   if (inst.is_ideal_jump()) {
-    fprintf(fp, "  _constant = C->constant_table().allocate_jump_table(this);\n");
+    fprintf(fp, "  _constant = C->constant_table().add_jump_table(this);\n");
   }
 
   // If user did not define an encode section,
--- a/hotspot/src/share/vm/asm/assembler.hpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/share/vm/asm/assembler.hpp	Wed Nov 16 01:39:50 2011 -0800
@@ -257,6 +257,29 @@
   // ensure buf contains all code (call this before using/copying the code)
   void flush();
 
+  // min and max values for signed immediate ranges
+  static int min_simm(int nbits) { return -(intptr_t(1) << (nbits - 1))    ; }
+  static int max_simm(int nbits) { return  (intptr_t(1) << (nbits - 1)) - 1; }
+
+  // Define some:
+  static int min_simm10() { return min_simm(10); }
+  static int min_simm13() { return min_simm(13); }
+  static int min_simm16() { return min_simm(16); }
+
+  // Test if x is within signed immediate range for nbits
+  static bool is_simm(intptr_t x, int nbits) { return min_simm(nbits) <= x && x <= max_simm(nbits); }
+
+  // Define some:
+  static bool is_simm5( intptr_t x) { return is_simm(x, 5 ); }
+  static bool is_simm8( intptr_t x) { return is_simm(x, 8 ); }
+  static bool is_simm10(intptr_t x) { return is_simm(x, 10); }
+  static bool is_simm11(intptr_t x) { return is_simm(x, 11); }
+  static bool is_simm12(intptr_t x) { return is_simm(x, 12); }
+  static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
+  static bool is_simm16(intptr_t x) { return is_simm(x, 16); }
+  static bool is_simm26(intptr_t x) { return is_simm(x, 26); }
+  static bool is_simm32(intptr_t x) { return is_simm(x, 32); }
+
   // Accessors
   CodeBuffer*   code() const;          // _code_section->outer()
   CodeSection*  code_section() const   { return _code_section; }
--- a/hotspot/src/share/vm/opto/compile.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -3052,24 +3052,13 @@
   return false;
 }
 
-// Emit constants grouped in the following order:
-static BasicType type_order[] = {
-  T_FLOAT,    // 32-bit
-  T_OBJECT,   // 32 or 64-bit
-  T_ADDRESS,  // 32 or 64-bit
-  T_DOUBLE,   // 64-bit
-  T_LONG,     // 64-bit
-  T_VOID,     // 32 or 64-bit (jump-tables are at the end of the constant table for code emission reasons)
-  T_ILLEGAL
-};
-
 static int type_to_size_in_bytes(BasicType t) {
   switch (t) {
   case T_LONG:    return sizeof(jlong  );
   case T_FLOAT:   return sizeof(jfloat );
   case T_DOUBLE:  return sizeof(jdouble);
     // We use T_VOID as marker for jump-table entries (labels) which
-    // need an interal word relocation.
+    // need an internal word relocation.
   case T_VOID:
   case T_ADDRESS:
   case T_OBJECT:  return sizeof(jobject);
@@ -3079,87 +3068,92 @@
   return -1;
 }
 
+int Compile::ConstantTable::qsort_comparator(Constant* a, Constant* b) {
+  // sort descending
+  if (a->freq() > b->freq())  return -1;
+  if (a->freq() < b->freq())  return  1;
+  return 0;
+}
+
 void Compile::ConstantTable::calculate_offsets_and_size() {
-  int size = 0;
-  for (int t = 0; type_order[t] != T_ILLEGAL; t++) {
-    BasicType type = type_order[t];
-
-    for (int i = 0; i < _constants.length(); i++) {
-      Constant con = _constants.at(i);
-      if (con.type() != type)  continue;  // Skip other types.
-
-      // Align size for type.
-      int typesize = type_to_size_in_bytes(con.type());
-      size = align_size_up(size, typesize);
-
-      // Set offset.
-      con.set_offset(size);
-      _constants.at_put(i, con);
-
-      // Add type size.
-      size = size + typesize;
+  // First, sort the array by frequencies.
+  _constants.sort(qsort_comparator);
+
+#ifdef ASSERT
+  // Make sure all jump-table entries were sorted to the end of the
+  // array (they have a negative frequency).
+  bool found_void = false;
+  for (int i = 0; i < _constants.length(); i++) {
+    Constant con = _constants.at(i);
+    if (con.type() == T_VOID)
+      found_void = true;  // jump-tables
+    else
+      assert(!found_void, "wrong sorting");
+  }
+#endif
+
+  int offset = 0;
+  for (int i = 0; i < _constants.length(); i++) {
+    Constant* con = _constants.adr_at(i);
+
+    // Align offset for type.
+    int typesize = type_to_size_in_bytes(con->type());
+    offset = align_size_up(offset, typesize);
+    con->set_offset(offset);   // set constant's offset
+
+    if (con->type() == T_VOID) {
+      MachConstantNode* n = (MachConstantNode*) con->get_jobject();
+      offset = offset + typesize * n->outcnt();  // expand jump-table
+    } else {
+      offset = offset + typesize;
     }
   }
 
   // Align size up to the next section start (which is insts; see
   // CodeBuffer::align_at_start).
   assert(_size == -1, "already set?");
-  _size = align_size_up(size, CodeEntryAlignment);
-
-  if (Matcher::constant_table_absolute_addressing) {
-    set_table_base_offset(0);  // No table base offset required
-  } else {
-    if (UseRDPCForConstantTableBase) {
-      // table base offset is set in MachConstantBaseNode::emit
-    } else {
-      // When RDPC is not used, the table base is set into the middle of
-      // the constant table.
-      int half_size = _size / 2;
-      assert(half_size * 2 == _size, "sanity");
-      set_table_base_offset(-half_size);
-    }
-  }
+  _size = align_size_up(offset, CodeEntryAlignment);
 }
 
 void Compile::ConstantTable::emit(CodeBuffer& cb) {
   MacroAssembler _masm(&cb);
-  for (int t = 0; type_order[t] != T_ILLEGAL; t++) {
-    BasicType type = type_order[t];
-
-    for (int i = 0; i < _constants.length(); i++) {
-      Constant con = _constants.at(i);
-      if (con.type() != type)  continue;  // Skip other types.
-
-      address constant_addr;
-      switch (con.type()) {
-      case T_LONG:   constant_addr = _masm.long_constant(  con.get_jlong()  ); break;
-      case T_FLOAT:  constant_addr = _masm.float_constant( con.get_jfloat() ); break;
-      case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break;
-      case T_OBJECT: {
-        jobject obj = con.get_jobject();
-        int oop_index = _masm.oop_recorder()->find_index(obj);
-        constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index));
-        break;
+  for (int i = 0; i < _constants.length(); i++) {
+    Constant con = _constants.at(i);
+    address constant_addr;
+    switch (con.type()) {
+    case T_LONG:   constant_addr = _masm.long_constant(  con.get_jlong()  ); break;
+    case T_FLOAT:  constant_addr = _masm.float_constant( con.get_jfloat() ); break;
+    case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break;
+    case T_OBJECT: {
+      jobject obj = con.get_jobject();
+      int oop_index = _masm.oop_recorder()->find_index(obj);
+      constant_addr = _masm.address_constant((address) obj, oop_Relocation::spec(oop_index));
+      break;
+    }
+    case T_ADDRESS: {
+      address addr = (address) con.get_jobject();
+      constant_addr = _masm.address_constant(addr);
+      break;
+    }
+    // We use T_VOID as marker for jump-table entries (labels) which
+    // need an internal word relocation.
+    case T_VOID: {
+      MachConstantNode* n = (MachConstantNode*) con.get_jobject();
+      // Fill the jump-table with a dummy word.  The real value is
+      // filled in later in fill_jump_table.
+      address dummy = (address) n;
+      constant_addr = _masm.address_constant(dummy);
+      // Expand jump-table
+      for (uint i = 1; i < n->outcnt(); i++) {
+        address temp_addr = _masm.address_constant(dummy + i);
+        assert(temp_addr, "consts section too small");
       }
-      case T_ADDRESS: {
-        address addr = (address) con.get_jobject();
-        constant_addr = _masm.address_constant(addr);
-        break;
-      }
-      // We use T_VOID as marker for jump-table entries (labels) which
-      // need an interal word relocation.
-      case T_VOID: {
-        // Write a dummy word.  The real value is filled in later
-        // in fill_jump_table_in_constant_table.
-        address addr = (address) con.get_jobject();
-        constant_addr = _masm.address_constant(addr);
-        break;
-      }
-      default: ShouldNotReachHere();
-      }
-      assert(constant_addr != NULL, "consts section too small");
-      assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset()));
+      break;
     }
+    default: ShouldNotReachHere();
+    }
+    assert(constant_addr, "consts section too small");
+    assert((constant_addr - _masm.code()->consts()->start()) == con.offset(), err_msg("must be: %d == %d", constant_addr - _masm.code()->consts()->start(), con.offset()));
   }
 }
 
@@ -3175,19 +3169,21 @@
   if (con.can_be_reused()) {
     int idx = _constants.find(con);
     if (idx != -1 && _constants.at(idx).can_be_reused()) {
+      _constants.adr_at(idx)->inc_freq(con.freq());  // increase the frequency by the current value
       return;
     }
   }
   (void) _constants.append(con);
 }
 
-Compile::Constant Compile::ConstantTable::add(BasicType type, jvalue value) {
-  Constant con(type, value);
+Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, BasicType type, jvalue value) {
+  Block* b = Compile::current()->cfg()->_bbs[n->_idx];
+  Constant con(type, value, b->_freq);
   add(con);
   return con;
 }
 
-Compile::Constant Compile::ConstantTable::add(MachOper* oper) {
+Compile::Constant Compile::ConstantTable::add(MachConstantNode* n, MachOper* oper) {
   jvalue value;
   BasicType type = oper->type()->basic_type();
   switch (type) {
@@ -3198,20 +3194,18 @@
   case T_ADDRESS: value.l = (jobject) oper->constant(); break;
   default: ShouldNotReachHere();
   }
-  return add(type, value);
+  return add(n, type, value);
 }
 
-Compile::Constant Compile::ConstantTable::allocate_jump_table(MachConstantNode* n) {
+Compile::Constant Compile::ConstantTable::add_jump_table(MachConstantNode* n) {
   jvalue value;
   // We can use the node pointer here to identify the right jump-table
   // as this method is called from Compile::Fill_buffer right before
   // the MachNodes are emitted and the jump-table is filled (means the
   // MachNode pointers do not change anymore).
   value.l = (jobject) n;
-  Constant con(T_VOID, value, false);  // Labels of a jump-table cannot be reused.
-  for (uint i = 0; i < n->outcnt(); i++) {
-    add(con);
-  }
+  Constant con(T_VOID, value, next_jump_table_freq(), false);  // Labels of a jump-table cannot be reused.
+  add(con);
   return con;
 }
 
@@ -3230,9 +3224,9 @@
   MacroAssembler _masm(&cb);
   address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
 
-  for (int i = 0; i < labels.length(); i++) {
+  for (uint i = 0; i < n->outcnt(); i++) {
     address* constant_addr = &jump_table_base[i];
-    assert(*constant_addr == (address) n, "all jump-table entries must contain node pointer");
+    assert(*constant_addr == (((address) n) + i), err_msg("all jump-table entries must contain adjusted node pointer: " INTPTR_FORMAT " == " INTPTR_FORMAT, *constant_addr, (((address) n) + i)));
     *constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
     cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
   }
--- a/hotspot/src/share/vm/opto/compile.hpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Nov 16 01:39:50 2011 -0800
@@ -150,14 +150,16 @@
     BasicType _type;
     jvalue    _value;
     int       _offset;         // offset of this constant (in bytes) relative to the constant table base.
+    float     _freq;
     bool      _can_be_reused;  // true (default) if the value can be shared with other users.
 
   public:
-    Constant() : _type(T_ILLEGAL), _offset(-1), _can_be_reused(true) { _value.l = 0; }
-    Constant(BasicType type, jvalue value, bool can_be_reused = true) :
+    Constant() : _type(T_ILLEGAL), _offset(-1), _freq(0.0f), _can_be_reused(true) { _value.l = 0; }
+    Constant(BasicType type, jvalue value, float freq = 0.0f, bool can_be_reused = true) :
       _type(type),
       _value(value),
       _offset(-1),
+      _freq(freq),
       _can_be_reused(can_be_reused)
     {}
 
@@ -173,6 +175,9 @@
     int         offset()  const    { return _offset; }
     void    set_offset(int offset) {        _offset = offset; }
 
+    float       freq()    const    { return _freq;         }
+    void    inc_freq(float freq)   {        _freq += freq; }
+
     bool    can_be_reused() const  { return _can_be_reused; }
   };
 
@@ -182,41 +187,51 @@
     GrowableArray<Constant> _constants;          // Constants of this table.
     int                     _size;               // Size in bytes the emitted constant table takes (including padding).
     int                     _table_base_offset;  // Offset of the table base that gets added to the constant offsets.
+    int                     _nof_jump_tables;    // Number of jump-tables in this constant table.
+
+    static int qsort_comparator(Constant* a, Constant* b);
+
+    // We use negative frequencies to keep the order of the
+    // jump-tables in which they were added.  Otherwise we get into
+    // trouble with relocation.
+    float next_jump_table_freq() { return -1.0f * (++_nof_jump_tables); }
 
   public:
     ConstantTable() :
       _size(-1),
-      _table_base_offset(-1)  // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
+      _table_base_offset(-1),  // We can use -1 here since the constant table is always bigger than 2 bytes (-(size / 2), see MachConstantBaseNode::emit).
+      _nof_jump_tables(0)
     {}
 
-    int size() const { assert(_size != -1, "size not yet calculated"); return _size; }
+    int size() const { assert(_size != -1, "not calculated yet"); return _size; }
 
-    void set_table_base_offset(int x)  { assert(_table_base_offset == -1, "set only once");                        _table_base_offset = x; }
-    int      table_base_offset() const { assert(_table_base_offset != -1, "table base offset not yet set"); return _table_base_offset; }
+    int calculate_table_base_offset() const;  // AD specific
+    void set_table_base_offset(int x)  { assert(_table_base_offset == -1 || x == _table_base_offset, "can't change"); _table_base_offset = x; }
+    int      table_base_offset() const { assert(_table_base_offset != -1, "not set yet");                      return _table_base_offset; }
 
     void emit(CodeBuffer& cb);
 
     // Returns the offset of the last entry (the top) of the constant table.
-    int  top_offset() const { assert(_constants.top().offset() != -1, "constant not yet bound"); return _constants.top().offset(); }
+    int  top_offset() const { assert(_constants.top().offset() != -1, "not bound yet"); return _constants.top().offset(); }
 
     void calculate_offsets_and_size();
     int  find_offset(Constant& con) const;
 
     void     add(Constant& con);
-    Constant add(BasicType type, jvalue value);
-    Constant add(MachOper* oper);
-    Constant add(jfloat f) {
+    Constant add(MachConstantNode* n, BasicType type, jvalue value);
+    Constant add(MachConstantNode* n, MachOper* oper);
+    Constant add(MachConstantNode* n, jfloat f) {
       jvalue value; value.f = f;
-      return add(T_FLOAT, value);
+      return add(n, T_FLOAT, value);
     }
-    Constant add(jdouble d) {
+    Constant add(MachConstantNode* n, jdouble d) {
       jvalue value; value.d = d;
-      return add(T_DOUBLE, value);
+      return add(n, T_DOUBLE, value);
     }
 
-    // Jump table
-    Constant allocate_jump_table(MachConstantNode* n);
-    void         fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
+    // Jump-table
+    Constant  add_jump_table(MachConstantNode* n);
+    void     fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
   };
 
  private:
--- a/hotspot/src/share/vm/opto/machnode.cpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/share/vm/opto/machnode.cpp	Wed Nov 16 01:39:50 2011 -0800
@@ -480,21 +480,20 @@
 
 //=============================================================================
 int MachConstantNode::constant_offset() {
-  int offset = _constant.offset();
   // Bind the offset lazily.
-  if (offset == -1) {
+  if (_constant.offset() == -1) {
     Compile::ConstantTable& constant_table = Compile::current()->constant_table();
-    // If called from Compile::scratch_emit_size assume the worst-case
-    // for load offsets: half the constant table size.
-    // NOTE: Don't return or calculate the actual offset (which might
-    // be zero) because that leads to problems with e.g. jumpXtnd on
-    // some architectures (cf. add-optimization in SPARC jumpXtnd).
-    if (Compile::current()->in_scratch_emit_size())
-      return constant_table.size() / 2;
-    offset = constant_table.table_base_offset() + constant_table.find_offset(_constant);
-    _constant.set_offset(offset);
+    int offset = constant_table.find_offset(_constant);
+    // If called from Compile::scratch_emit_size return the
+    // pre-calculated offset.
+    // NOTE: If the AD file does some table base offset optimizations
+    // later the AD file needs to take care of this fact.
+    if (Compile::current()->in_scratch_emit_size()) {
+      return constant_table.calculate_table_base_offset() + offset;
+    }
+    _constant.set_offset(constant_table.table_base_offset() + offset);
   }
-  return offset;
+  return _constant.offset();
 }
 
 
--- a/hotspot/src/share/vm/opto/matcher.hpp	Mon Nov 14 18:38:03 2011 -0800
+++ b/hotspot/src/share/vm/opto/matcher.hpp	Wed Nov 16 01:39:50 2011 -0800
@@ -371,10 +371,6 @@
   // registers?  True for Intel but false for most RISCs
   static const bool clone_shift_expressions;
 
-  // Should constant table entries be accessed with loads using
-  // absolute addressing?  True for x86 but false for most RISCs.
-  static const bool constant_table_absolute_addressing;
-
   static bool narrow_oop_use_complex_address();
 
   // Generate implicit null check for narrow oops if it can fold