changeset 1968:2f644f85485d

6961690: load oops from constant table on SPARC Summary: oops should be loaded from the constant table of an nmethod instead of materializing them with a long code sequence. Reviewed-by: never, kvn
author twisti
date Fri, 03 Dec 2010 01:34:31 -0800
parents 5ddfcf4b079e
children b856cd7f4e60
files src/cpu/sparc/vm/assembler_sparc.cpp src/cpu/sparc/vm/assembler_sparc.hpp src/cpu/sparc/vm/assembler_sparc.inline.hpp src/cpu/sparc/vm/sparc.ad src/cpu/sparc/vm/vm_version_sparc.hpp src/cpu/x86/vm/assembler_x86.cpp src/cpu/x86/vm/assembler_x86.hpp src/cpu/x86/vm/x86_32.ad src/cpu/x86/vm/x86_64.ad src/os/linux/vm/vmError_linux.cpp src/share/vm/adlc/adlparse.cpp src/share/vm/adlc/adlparse.hpp src/share/vm/adlc/archDesc.hpp src/share/vm/adlc/formssel.cpp src/share/vm/adlc/formssel.hpp src/share/vm/adlc/output_c.cpp src/share/vm/adlc/output_h.cpp src/share/vm/asm/assembler.hpp src/share/vm/asm/assembler.inline.hpp src/share/vm/compiler/disassembler.cpp src/share/vm/opto/c2_globals.hpp src/share/vm/opto/compile.cpp src/share/vm/opto/compile.hpp src/share/vm/opto/gcm.cpp src/share/vm/opto/machnode.cpp src/share/vm/opto/machnode.hpp src/share/vm/opto/matcher.hpp src/share/vm/opto/node.hpp src/share/vm/opto/output.cpp src/share/vm/opto/postaloc.cpp src/share/vm/utilities/debug.cpp
diffstat 31 files changed, 1809 insertions(+), 844 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/assembler_sparc.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/sparc/vm/assembler_sparc.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -1443,6 +1443,45 @@
   }
 }
 
+int MacroAssembler::size_of_set64(jlong value) {
+  v9_dep();
+
+  int hi = (int)(value >> 32);
+  int lo = (int)(value & ~0);
+  int count = 0;
+
+  // (Matcher::isSimpleConstant64 knows about the following optimizations.)
+  if (Assembler::is_simm13(lo) && value == lo) {
+    count++;
+  } else if (hi == 0) {
+    count++;
+    if (low10(lo) != 0)
+      count++;
+  }
+  else if (hi == -1) {
+    count += 2;
+  }
+  else if (lo == 0) {
+    if (Assembler::is_simm13(hi)) {
+      count++;
+    } else {
+      count++;
+      if (low10(hi) != 0)
+        count++;
+    }
+    count++;
+  }
+  else {
+    count += 2;
+    if (low10(hi) != 0)
+      count++;
+    if (low10(lo) != 0)
+      count++;
+    count += 2;
+  }
+  return count;
+}
+
 // compute size in bytes of sparc frame, given
 // number of extraWords
 int MacroAssembler::total_frame_size_in_bytes(int extraWords) {
--- a/src/cpu/sparc/vm/assembler_sparc.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -1621,6 +1621,10 @@
 
   void sub(    Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3              ) | rs1(s1) | rs2(s2) ); }
   void sub(    Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3              ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
+
+  // Note: offset is added to s2.
+  inline void sub(Register s1, RegisterOrConstant s2, Register d, int offset = 0);
+
   void subcc(  Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); }
   void subcc(  Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
   void subc(   Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(subc_op3             ) | rs1(s1) | rs2(s2) ); }
@@ -1895,6 +1899,9 @@
   void patchable_set(intptr_t value, Register d);
   void set64(jlong value, Register d, Register tmp);
 
+  // Compute size of set64.
+  static int size_of_set64(jlong value);
+
   // sign-extend 32 to 64
   inline void signx( Register s, Register d ) { sra( s, G0, d); }
   inline void signx( Register d )             { sra( d, G0, d); }
--- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -328,6 +328,11 @@
 inline void Assembler::stdcq(  int crd, Register s1, Register s2) { v8_only();  emit_long( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); }
 inline void Assembler::stdcq(  int crd, Register s1, int simm13a) { v8_only();  emit_data( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
 
+inline void Assembler::sub(Register s1, RegisterOrConstant s2, Register d, int offset) {
+  if (s2.is_register())  sub(s1, s2.as_register(),          d);
+  else                 { sub(s1, s2.as_constant() + offset, d); offset = 0; }
+  if (offset != 0)       sub(d,  offset,                    d);
+}
 
 // pp 231
 
--- a/src/cpu/sparc/vm/sparc.ad	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/sparc/vm/sparc.ad	Fri Dec 03 01:34:31 2010 -0800
@@ -667,6 +667,20 @@
   return offset;
 }
 
+static inline jdouble replicate_immI(int con, int count, int width) {
+  // Load a constant replicated "count" times with width "width"
+  int bit_width = width * 8;
+  jlong elt_val = con;
+  elt_val &= (((jlong) 1) << bit_width) - 1;  // mask off sign bits
+  jlong val = elt_val;
+  for (int i = 0; i < count - 1; i++) {
+    val <<= bit_width;
+    val |= elt_val;
+  }
+  jdouble dval = *((jdouble*) &val);  // coerce to double type
+  return dval;
+}
+
 // Standard Sparc opcode form2 field breakdown
 static inline void emit2_19(CodeBuffer &cbuf, int f30, int f29, int f25, int f22, int f20, int f19, int f0 ) {
   f0 &= (1<<19)-1;     // Mask displacement to 19 bits
@@ -1008,6 +1022,90 @@
 
 
 //=============================================================================
+const bool Matcher::constant_table_absolute_addressing = false;
+const RegMask& MachConstantBaseNode::_out_RegMask = PTR_REG_mask;
+
+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());
+
+  if (UseRDPCForConstantTableBase) {
+    // For the following RDPC logic to work correctly the consts
+    // section must be allocated right before the insts section.  This
+    // 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 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));
+      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;
+      }
+    }
+
+    __ rdpc(r);
+
+    if (disp != 0) {
+      assert(r != O7, "need temporary");
+      __ sub(r, __ ensure_simm13_or_reg(disp, O7), r);
+    }
+  }
+  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());
+    RelocationHolder rspec = internal_word_Relocation::spec(baseaddr);
+    AddressLiteral base(baseaddr, rspec);
+    __ set(base, r);
+  }
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc*) const {
+  if (UseRDPCForConstantTableBase) {
+    // This is really the worst case but generally it's only 1 instruction.
+    return 4 /*rdpc*/ + 4 /*sub*/ + MacroAssembler::worst_case_size_of_set();
+  } else {
+    return MacroAssembler::worst_case_size_of_set();
+  }
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+  char reg[128];
+  ra_->dump_register(this, reg);
+  if (UseRDPCForConstantTableBase) {
+    st->print("RDPC   %s\t! constant table base", reg);
+  } else {
+    st->print("SET    &constanttable,%s\t! constant table base", reg);
+  }
+}
+#endif
+
+
+//=============================================================================
 
 #ifndef PRODUCT
 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
@@ -2247,25 +2345,6 @@
     __ delayed()->nop();
   %}
 
-  enc_class jump_enc( iRegX switch_val, o7RegI table) %{
-    MacroAssembler _masm(&cbuf);
-
-    Register switch_reg       = as_Register($switch_val$$reg);
-    Register table_reg        = O7;
-
-    address table_base = __ address_table_constant(_index2label);
-    RelocationHolder rspec = internal_word_Relocation::spec(table_base);
-
-    // Move table address into a register.
-    __ set(table_base, table_reg, rspec);
-
-    // Jump to base address + switch value
-    __ ld_ptr(table_reg, switch_reg, table_reg);
-    __ jmp(table_reg, G0);
-    __ delayed()->nop();
-
-  %}
-
   enc_class enc_ba( Label labl ) %{
     MacroAssembler _masm(&cbuf);
     Label &L = *($labl$$label);
@@ -2384,20 +2463,6 @@
     cbuf.insts()->emit_int32(op);
   %}
 
-  // Utility encoding for loading a 64 bit Pointer into a register
-  // The 64 bit pointer is stored in the generated code stream
-  enc_class SetPtr( immP src, iRegP rd ) %{
-    Register dest = reg_to_register_object($rd$$reg);
-    MacroAssembler _masm(&cbuf);
-    // [RGV] This next line should be generated from ADLC
-    if ( _opnds[1]->constant_is_oop() ) {
-      intptr_t val = $src$$constant;
-      __ set_oop_constant((jobject)val, dest);
-    } else {          // non-oop pointers, e.g. card mark base, heap top
-      __ set($src$$constant, dest);
-    }
-  %}
-
   enc_class Set13( immI13 src, iRegI rd ) %{
     emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, $src$$constant );
   %}
@@ -2411,10 +2476,6 @@
     __ set($src$$constant, reg_to_register_object($rd$$reg));
   %}
 
-  enc_class SetNull( iRegI rd ) %{
-    emit3_simm13( cbuf, Assembler::arith_op, $rd$$reg, Assembler::or_op3, 0, 0 );
-  %}
-
   enc_class call_epilog %{
     if( VerifyStackAtCalls ) {
       MacroAssembler _masm(&cbuf);
@@ -2778,35 +2839,6 @@
     __ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst);
   %}
 
-  enc_class LdImmL (immL src, iRegL dst, o7RegL tmp) %{   // Load Immediate
-    MacroAssembler _masm(&cbuf);
-    Register dest = reg_to_register_object($dst$$reg);
-    Register temp = reg_to_register_object($tmp$$reg);
-    __ set64( $src$$constant, dest, temp );
-  %}
-
-  enc_class LdReplImmI(immI src, regD dst, o7RegP tmp, int count, int width) %{
-    // Load a constant replicated "count" times with width "width"
-    int bit_width = $width$$constant * 8;
-    jlong elt_val = $src$$constant;
-    elt_val  &= (((jlong)1) << bit_width) - 1; // mask off sign bits
-    jlong val = elt_val;
-    for (int i = 0; i < $count$$constant - 1; i++) {
-        val <<= bit_width;
-        val |= elt_val;
-    }
-    jdouble dval = *(jdouble*)&val; // coerce to double type
-    MacroAssembler _masm(&cbuf);
-    address double_address = __ double_constant(dval);
-    RelocationHolder rspec = internal_word_Relocation::spec(double_address);
-    AddressLiteral addrlit(double_address, rspec);
-
-    __ sethi(addrlit, $tmp$$Register);
-    // XXX This is a quick fix for 6833573.
-    //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
-    __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
-  %}
-
   // Compiler ensures base is doubleword aligned and cnt is count of doublewords
   enc_class enc_Clear_Array(iRegX cnt, iRegP base, iRegX temp) %{
     MacroAssembler _masm(&cbuf);
@@ -3521,6 +3553,29 @@
   interface(CONST_INTER);
 %}
 
+// Pointer Immediate: 32 or 64-bit
+operand immP_set() %{
+  predicate(!VM_Version::is_niagara1_plus());
+  match(ConP);
+
+  op_cost(5);
+  // formats are generated automatically for constants and base registers
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Pointer Immediate: 32 or 64-bit
+// From Niagara2 processors on a load should be better than materializing.
+operand immP_load() %{
+  predicate(VM_Version::is_niagara1_plus());
+  match(ConP);
+
+  op_cost(5);
+  // formats are generated automatically for constants and base registers
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
 operand immP13() %{
   predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095));
   match(ConP);
@@ -3616,6 +3671,26 @@
   interface(CONST_INTER);
 %}
 
+// Long Immediate: cheap (materialize in <= 3 instructions)
+operand immL_cheap() %{
+  predicate(!VM_Version::is_niagara1_plus() || MacroAssembler::size_of_set64(n->get_long()) <= 3);
+  match(ConL);
+  op_cost(0);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Long Immediate: expensive (materialize in > 3 instructions)
+operand immL_expensive() %{
+  predicate(VM_Version::is_niagara1_plus() && MacroAssembler::size_of_set64(n->get_long()) > 3);
+  match(ConL);
+  op_cost(0);
+
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
 // Double Immediate
 operand immD() %{
   match(ConD);
@@ -5981,25 +6056,58 @@
   ins_pipe(ialu_imm);
 %}
 
-instruct loadConP(iRegP dst, immP src) %{
-  match(Set dst src);
+#ifndef _LP64
+instruct loadConP(iRegP dst, immP con) %{
+  match(Set dst con);
+  ins_cost(DEFAULT_COST * 3/2);
+  format %{ "SET    $con,$dst\t!ptr" %}
+  ins_encode %{
+    // [RGV] This next line should be generated from ADLC
+    if (_opnds[1]->constant_is_oop()) {
+      intptr_t val = $con$$constant;
+      __ set_oop_constant((jobject) val, $dst$$Register);
+    } else {          // non-oop pointers, e.g. card mark base, heap top
+      __ set($con$$constant, $dst$$Register);
+    }
+  %}
+  ins_pipe(loadConP);
+%}
+#else
+instruct loadConP_set(iRegP dst, immP_set con) %{
+  match(Set dst con);
   ins_cost(DEFAULT_COST * 3/2);
-  format %{ "SET    $src,$dst\t!ptr" %}
-  // This rule does not use "expand" unlike loadConI because then
-  // the result type is not known to be an Oop.  An ADLC
-  // enhancement will be needed to make that work - not worth it!
-
-  ins_encode( SetPtr( src, dst ) );
+  format %{ "SET    $con,$dst\t! ptr" %}
+  ins_encode %{
+    // [RGV] This next line should be generated from ADLC
+    if (_opnds[1]->constant_is_oop()) {
+      intptr_t val = $con$$constant;
+      __ set_oop_constant((jobject) val, $dst$$Register);
+    } else {          // non-oop pointers, e.g. card mark base, heap top
+      __ set($con$$constant, $dst$$Register);
+    }
+  %}
   ins_pipe(loadConP);
-
-%}
+%}
+
+instruct loadConP_load(iRegP dst, immP_load con) %{
+  match(Set dst con);
+  ins_cost(MEMORY_REF_COST);
+  format %{ "LD     [$constanttablebase + $constantoffset],$dst\t! load from constant table: ptr=$con" %}
+  ins_encode %{
+    __ ld_ptr($constanttablebase, $constantoffset($con), $dst$$Register);
+  %}
+  ins_pipe(loadConP);
+%}
+#endif // _LP64
 
 instruct loadConP0(iRegP dst, immP0 src) %{
   match(Set dst src);
 
   size(4);
   format %{ "CLR    $dst\t!ptr" %}
-  ins_encode( SetNull( dst ) );
+  ins_encode %{
+    __ clr($dst$$Register);
+  %}
   ins_pipe(ialu_imm);
 %}
 
@@ -6019,7 +6127,9 @@
 
   size(4);
   format %{ "CLR    $dst\t! compressed NULL ptr" %}
-  ins_encode( SetNull( dst ) );
+  ins_encode %{
+    __ clr($dst$$Register);
+  %}
   ins_pipe(ialu_imm);
 %}
 
@@ -6034,13 +6144,26 @@
   ins_pipe(ialu_hi_lo_reg);
 %}
 
-instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{
-  // %%% maybe this should work like loadConD
-  match(Set dst src);
+// Materialize long value (predicated by immL_cheap).
+instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{
+  match(Set dst con);
   effect(KILL tmp);
-  ins_cost(DEFAULT_COST * 4);
-  format %{ "SET64   $src,$dst KILL $tmp\t! long" %}
-  ins_encode( LdImmL(src, dst, tmp) );
+  ins_cost(DEFAULT_COST * 3);
+  format %{ "SET64   $con,$dst KILL $tmp\t! cheap long" %}
+  ins_encode %{
+    __ set64($con$$constant, $dst$$Register, $tmp$$Register);
+  %}
+  ins_pipe(loadConL);
+%}
+
+// Load long value from constant table (predicated by immL_expensive).
+instruct loadConL_ldx(iRegL dst, immL_expensive con) %{
+  match(Set dst con);
+  ins_cost(MEMORY_REF_COST);
+  format %{ "LDX     [$constanttablebase + $constantoffset],$dst\t! load from constant table: long=$con" %}
+  ins_encode %{
+    __ ldx($constanttablebase, $constantoffset($con), $dst$$Register);
+  %}
   ins_pipe(loadConL);
 %}
 
@@ -6063,50 +6186,24 @@
   ins_pipe(ialu_imm);
 %}
 
-instruct loadConF(regF dst, immF src, o7RegP tmp) %{
-  match(Set dst src);
-  effect(KILL tmp);
-
-#ifdef _LP64
-  size(8*4);
-#else
-  size(2*4);
-#endif
-
-  format %{ "SETHI  hi(&$src),$tmp\t!get float $src from table\n\t"
-            "LDF    [$tmp+lo(&$src)],$dst" %}
+instruct loadConF(regF dst, immF con) %{
+  match(Set dst con);
+  size(4);
+  format %{ "LDF    [$constanttablebase + $constantoffset],$dst\t! load from constant table: float=$con" %}
   ins_encode %{
-    address float_address = __ float_constant($src$$constant);
-    RelocationHolder rspec = internal_word_Relocation::spec(float_address);
-    AddressLiteral addrlit(float_address, rspec);
-
-    __ sethi(addrlit, $tmp$$Register);
-    __ ldf(FloatRegisterImpl::S, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
+    __ ldf(FloatRegisterImpl::S, $constanttablebase, $constantoffset($con), $dst$$FloatRegister);
   %}
   ins_pipe(loadConFD);
 %}
 
-instruct loadConD(regD dst, immD src, o7RegP tmp) %{
-  match(Set dst src);
-  effect(KILL tmp);
-
-#ifdef _LP64
-  size(8*4);
-#else
-  size(2*4);
-#endif
-
-  format %{ "SETHI  hi(&$src),$tmp\t!get double $src from table\n\t"
-            "LDDF   [$tmp+lo(&$src)],$dst" %}
+instruct loadConD(regD dst, immD con) %{
+  match(Set dst con);
+  size(4);
+  format %{ "LDDF   [$constanttablebase + $constantoffset],$dst\t! load from constant table: double=$con" %}
   ins_encode %{
-    address double_address = __ double_constant($src$$constant);
-    RelocationHolder rspec = internal_word_Relocation::spec(double_address);
-    AddressLiteral addrlit(double_address, rspec);
-
-    __ sethi(addrlit, $tmp$$Register);
     // XXX This is a quick fix for 6833573.
-    //__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
-    __ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
+    //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), $dst$$FloatRegister);
+    __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset($con), as_DoubleFloatRegister($dst$$reg));
   %}
   ins_pipe(loadConFD);
 %}
@@ -8558,16 +8655,15 @@
 %}
 
 // Replicate scalar constant to packed byte values in Double register
-instruct Repl8B_immI(regD dst, immI13 src, o7RegP tmp) %{
-  match(Set dst (Replicate8B src));
-#ifdef _LP64
-  size(36);
-#else
-  size(8);
-#endif
-  format %{ "SETHI  hi(&Repl8($src)),$tmp\t!get Repl8B($src) from table\n\t"
-            "LDDF   [$tmp+lo(&Repl8($src))],$dst" %}
-  ins_encode( LdReplImmI(src, dst, tmp, (8), (1)) );
+instruct Repl8B_immI(regD dst, immI13 con) %{
+  match(Set dst (Replicate8B con));
+  size(4);
+  format %{ "LDDF   [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl8B($con)" %}
+  ins_encode %{
+    // XXX This is a quick fix for 6833573.
+    //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), $dst$$FloatRegister);
+    __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 8, 1)), as_DoubleFloatRegister($dst$$reg));
+  %}
   ins_pipe(loadConFD);
 %}
 
@@ -8594,16 +8690,15 @@
 %}
 
 // Replicate scalar constant to packed char values in Double register
-instruct Repl4C_immI(regD dst, immI src, o7RegP tmp) %{
-  match(Set dst (Replicate4C src));
-#ifdef _LP64
-  size(36);
-#else
-  size(8);
-#endif
-  format %{ "SETHI  hi(&Repl4($src)),$tmp\t!get Repl4C($src) from table\n\t"
-            "LDDF   [$tmp+lo(&Repl4($src))],$dst" %}
-  ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) );
+instruct Repl4C_immI(regD dst, immI con) %{
+  match(Set dst (Replicate4C con));
+  size(4);
+  format %{ "LDDF   [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4C($con)" %}
+  ins_encode %{
+    // XXX This is a quick fix for 6833573.
+    //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister);
+    __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), as_DoubleFloatRegister($dst$$reg));
+  %}
   ins_pipe(loadConFD);
 %}
 
@@ -8630,16 +8725,15 @@
 %}
 
 // Replicate scalar constant to packed short values in Double register
-instruct Repl4S_immI(regD dst, immI src, o7RegP tmp) %{
-  match(Set dst (Replicate4S src));
-#ifdef _LP64
-  size(36);
-#else
-  size(8);
-#endif
-  format %{ "SETHI  hi(&Repl4($src)),$tmp\t!get Repl4S($src) from table\n\t"
-            "LDDF   [$tmp+lo(&Repl4($src))],$dst" %}
-  ins_encode( LdReplImmI(src, dst, tmp, (4), (2)) );
+instruct Repl4S_immI(regD dst, immI con) %{
+  match(Set dst (Replicate4S con));
+  size(4);
+  format %{ "LDDF   [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl4S($con)" %}
+  ins_encode %{
+    // XXX This is a quick fix for 6833573.
+    //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), $dst$$FloatRegister);
+    __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 4, 2)), as_DoubleFloatRegister($dst$$reg));
+  %}
   ins_pipe(loadConFD);
 %}
 
@@ -8664,16 +8758,15 @@
 %}
 
 // Replicate scalar zero constant to packed int values in Double register
-instruct Repl2I_immI(regD dst, immI src, o7RegP tmp) %{
-  match(Set dst (Replicate2I src));
-#ifdef _LP64
-  size(36);
-#else
-  size(8);
-#endif
-  format %{ "SETHI  hi(&Repl2($src)),$tmp\t!get Repl2I($src) from table\n\t"
-            "LDDF   [$tmp+lo(&Repl2($src))],$dst" %}
-  ins_encode( LdReplImmI(src, dst, tmp, (2), (4)) );
+instruct Repl2I_immI(regD dst, immI con) %{
+  match(Set dst (Replicate2I con));
+  size(4);
+  format %{ "LDDF   [$constanttablebase + $constantoffset],$dst\t! load from constant table: Repl2I($con)" %}
+  ins_encode %{
+    // XXX This is a quick fix for 6833573.
+    //__ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), $dst$$FloatRegister);
+    __ ldf(FloatRegisterImpl::D, $constanttablebase, $constantoffset(replicate_immI($con$$constant, 2, 4)), as_DoubleFloatRegister($dst$$reg));
+  %}
   ins_pipe(loadConFD);
 %}
 
@@ -8929,12 +9022,26 @@
 
   ins_cost(350);
 
-  format %{  "SETHI  [hi(table_base)],O7\n\t"
-             "ADD    O7, lo(table_base), O7\n\t"
-             "LD     [O7+$switch_val], O7\n\t"
+  format %{  "ADD    $constanttablebase, $constantoffset, O7\n\t"
+             "LD     [O7 + $switch_val], O7\n\t"
              "JUMP   O7"
          %}
-  ins_encode( jump_enc( switch_val, table) );
+  ins_encode %{
+    // Calculate table address into a register.
+    Register table_reg;
+    Register label_reg = O7;
+    if (constant_offset() == 0) {
+      table_reg = $constanttablebase;
+    } else {
+      table_reg = O7;
+      __ add($constanttablebase, $constantoffset, table_reg);
+    }
+
+    // Jump to base address + switch value
+    __ ld_ptr(table_reg, $switch_val$$Register, label_reg);
+    __ jmp(label_reg, G0);
+    __ delayed()->nop();
+  %}
   ins_pc_relative(1);
   ins_pipe(ialu_reg_reg);
 %}
--- a/src/cpu/sparc/vm/vm_version_sparc.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/sparc/vm/vm_version_sparc.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -80,9 +80,6 @@
   static bool  is_sparc64(int features) { return (features & fmaf_instructions_m) != 0; }
 
   static int maximum_niagara1_processor_count() { return 32; }
-  // Returns true if the platform is in the niagara line and
-  // newer than the niagara1.
-  static bool is_niagara1_plus();
 
 public:
   // Initialization
@@ -105,6 +102,9 @@
   static bool is_ultra3()               { return (_features & ultra3_m) == ultra3_m; }
   static bool is_sun4v()                { return (_features & sun4v_m) != 0; }
   static bool is_niagara1()             { return is_niagara1(_features); }
+  // Returns true if the platform is in the niagara line and
+  // newer than the niagara1.
+  static bool is_niagara1_plus();
   static bool is_sparc64()              { return is_sparc64(_features); }
 
   static bool has_fast_fxtof()          { return has_v9() && !is_ultra3(); }
--- a/src/cpu/x86/vm/assembler_x86.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -2649,6 +2649,37 @@
   emit_byte(0xC0 | encode);
 }
 
+void Assembler::sqrtsd(XMMRegister dst, Address src) {
+  NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+  InstructionMark im(this);
+  emit_byte(0xF2);
+  prefix(src, dst);
+  emit_byte(0x0F);
+  emit_byte(0x51);
+  emit_operand(dst, src);
+}
+
+void Assembler::sqrtss(XMMRegister dst, XMMRegister src) {
+  // HMM Table D-1 says sse2
+  // NOT_LP64(assert(VM_Version::supports_sse(), ""));
+  NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+  emit_byte(0xF3);
+  int encode = prefix_and_encode(dst->encoding(), src->encoding());
+  emit_byte(0x0F);
+  emit_byte(0x51);
+  emit_byte(0xC0 | encode);
+}
+
+void Assembler::sqrtss(XMMRegister dst, Address src) {
+  NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+  InstructionMark im(this);
+  emit_byte(0xF3);
+  prefix(src, dst);
+  emit_byte(0x0F);
+  emit_byte(0x51);
+  emit_operand(dst, src);
+}
+
 void Assembler::stmxcsr( Address dst) {
   NOT_LP64(assert(VM_Version::supports_sse(), ""));
   InstructionMark im(this);
@@ -4358,16 +4389,6 @@
   emit_byte(0xE8 | encode);
 }
 
-void Assembler::sqrtsd(XMMRegister dst, Address src) {
-  NOT_LP64(assert(VM_Version::supports_sse2(), ""));
-  InstructionMark im(this);
-  emit_byte(0xF2);
-  prefix(src, dst);
-  emit_byte(0x0F);
-  emit_byte(0x51);
-  emit_operand(dst, src);
-}
-
 void Assembler::subq(Address dst, int32_t imm32) {
   InstructionMark im(this);
   prefixq(dst);
@@ -4929,10 +4950,6 @@
 }
 
 
-void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) {
-  movsd(dst, as_Address(src));
-}
-
 void MacroAssembler::pop_callee_saved_registers() {
   pop(rcx);
   pop(rdx);
--- a/src/cpu/x86/vm/assembler_x86.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/x86/vm/assembler_x86.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -1353,6 +1353,10 @@
   void sqrtsd(XMMRegister dst, Address src);
   void sqrtsd(XMMRegister dst, XMMRegister src);
 
+  // Compute Square Root of Scalar Single-Precision Floating-Point Value
+  void sqrtss(XMMRegister dst, Address src);
+  void sqrtss(XMMRegister dst, XMMRegister src);
+
   void std() { emit_byte(0xfd); }
 
   void stmxcsr( Address dst );
@@ -2125,6 +2129,9 @@
   void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); }
   void comisd(XMMRegister dst, AddressLiteral src);
 
+  void fadd_s(Address src)        { Assembler::fadd_s(src); }
+  void fadd_s(AddressLiteral src) { Assembler::fadd_s(as_Address(src)); }
+
   void fldcw(Address src) { Assembler::fldcw(src); }
   void fldcw(AddressLiteral src);
 
@@ -2138,6 +2145,9 @@
   void fld_x(Address src) { Assembler::fld_x(src); }
   void fld_x(AddressLiteral src);
 
+  void fmul_s(Address src)        { Assembler::fmul_s(src); }
+  void fmul_s(AddressLiteral src) { Assembler::fmul_s(as_Address(src)); }
+
   void ldmxcsr(Address src) { Assembler::ldmxcsr(src); }
   void ldmxcsr(AddressLiteral src);
 
@@ -2154,10 +2164,50 @@
 
 public:
 
-  void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); }
-  void movsd(Address dst, XMMRegister src)     { Assembler::movsd(dst, src); }
-  void movsd(XMMRegister dst, Address src)     { Assembler::movsd(dst, src); }
-  void movsd(XMMRegister dst, AddressLiteral src);
+  void addsd(XMMRegister dst, XMMRegister src)    { Assembler::addsd(dst, src); }
+  void addsd(XMMRegister dst, Address src)        { Assembler::addsd(dst, src); }
+  void addsd(XMMRegister dst, AddressLiteral src) { Assembler::addsd(dst, as_Address(src)); }
+
+  void addss(XMMRegister dst, XMMRegister src)    { Assembler::addss(dst, src); }
+  void addss(XMMRegister dst, Address src)        { Assembler::addss(dst, src); }
+  void addss(XMMRegister dst, AddressLiteral src) { Assembler::addss(dst, as_Address(src)); }
+
+  void divsd(XMMRegister dst, XMMRegister src)    { Assembler::divsd(dst, src); }
+  void divsd(XMMRegister dst, Address src)        { Assembler::divsd(dst, src); }
+  void divsd(XMMRegister dst, AddressLiteral src) { Assembler::divsd(dst, as_Address(src)); }
+
+  void divss(XMMRegister dst, XMMRegister src)    { Assembler::divss(dst, src); }
+  void divss(XMMRegister dst, Address src)        { Assembler::divss(dst, src); }
+  void divss(XMMRegister dst, AddressLiteral src) { Assembler::divss(dst, as_Address(src)); }
+
+  void movsd(XMMRegister dst, XMMRegister src)    { Assembler::movsd(dst, src); }
+  void movsd(Address dst, XMMRegister src)        { Assembler::movsd(dst, src); }
+  void movsd(XMMRegister dst, Address src)        { Assembler::movsd(dst, src); }
+  void movsd(XMMRegister dst, AddressLiteral src) { Assembler::movsd(dst, as_Address(src)); }
+
+  void mulsd(XMMRegister dst, XMMRegister src)    { Assembler::mulsd(dst, src); }
+  void mulsd(XMMRegister dst, Address src)        { Assembler::mulsd(dst, src); }
+  void mulsd(XMMRegister dst, AddressLiteral src) { Assembler::mulsd(dst, as_Address(src)); }
+
+  void mulss(XMMRegister dst, XMMRegister src)    { Assembler::mulss(dst, src); }
+  void mulss(XMMRegister dst, Address src)        { Assembler::mulss(dst, src); }
+  void mulss(XMMRegister dst, AddressLiteral src) { Assembler::mulss(dst, as_Address(src)); }
+
+  void sqrtsd(XMMRegister dst, XMMRegister src)    { Assembler::sqrtsd(dst, src); }
+  void sqrtsd(XMMRegister dst, Address src)        { Assembler::sqrtsd(dst, src); }
+  void sqrtsd(XMMRegister dst, AddressLiteral src) { Assembler::sqrtsd(dst, as_Address(src)); }
+
+  void sqrtss(XMMRegister dst, XMMRegister src)    { Assembler::sqrtss(dst, src); }
+  void sqrtss(XMMRegister dst, Address src)        { Assembler::sqrtss(dst, src); }
+  void sqrtss(XMMRegister dst, AddressLiteral src) { Assembler::sqrtss(dst, as_Address(src)); }
+
+  void subsd(XMMRegister dst, XMMRegister src)    { Assembler::subsd(dst, src); }
+  void subsd(XMMRegister dst, Address src)        { Assembler::subsd(dst, src); }
+  void subsd(XMMRegister dst, AddressLiteral src) { Assembler::subsd(dst, as_Address(src)); }
+
+  void subss(XMMRegister dst, XMMRegister src)    { Assembler::subss(dst, src); }
+  void subss(XMMRegister dst, Address src)        { Assembler::subss(dst, src); }
+  void subss(XMMRegister dst, AddressLiteral src) { Assembler::subss(dst, as_Address(src)); }
 
   void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); }
   void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); }
--- a/src/cpu/x86/vm/x86_32.ad	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/x86/vm/x86_32.ad	Fri Dec 03 01:34:31 2010 -0800
@@ -507,6 +507,25 @@
 
 
 //=============================================================================
+const bool Matcher::constant_table_absolute_addressing = true;
+const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+  // Empty encoding
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
+  return 0;
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+  st->print("# MachConstantBaseNode (empty encoding)");
+}
+#endif
+
+
+//=============================================================================
 #ifndef PRODUCT
 void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
   Compile* C = ra_->C;
@@ -1320,29 +1339,6 @@
 }
 
 
-static void emit_double_constant(CodeBuffer& cbuf, double x) {
-  int mark = cbuf.insts()->mark_off();
-  MacroAssembler _masm(&cbuf);
-  address double_address = __ double_constant(x);
-  cbuf.insts()->set_mark_off(mark);  // preserve mark across masm shift
-  emit_d32_reloc(cbuf,
-                 (int)double_address,
-                 internal_word_Relocation::spec(double_address),
-                 RELOC_DISP32);
-}
-
-static void emit_float_constant(CodeBuffer& cbuf, float x) {
-  int mark = cbuf.insts()->mark_off();
-  MacroAssembler _masm(&cbuf);
-  address float_address = __ float_constant(x);
-  cbuf.insts()->set_mark_off(mark);  // preserve mark across masm shift
-  emit_d32_reloc(cbuf,
-                 (int)float_address,
-                 internal_word_Relocation::spec(float_address),
-                 RELOC_DISP32);
-}
-
-
 const bool Matcher::match_rule_supported(int opcode) {
   if (!has_match_rule(opcode))
     return false;
@@ -1354,22 +1350,6 @@
   return regnum - 32; // The FP registers are in the second chunk
 }
 
-bool is_positive_zero_float(jfloat f) {
-  return jint_cast(f) == jint_cast(0.0F);
-}
-
-bool is_positive_one_float(jfloat f) {
-  return jint_cast(f) == jint_cast(1.0F);
-}
-
-bool is_positive_zero_double(jdouble d) {
-  return jlong_cast(d) == jlong_cast(0.0);
-}
-
-bool is_positive_one_double(jdouble d) {
-  return jlong_cast(d) == jlong_cast(1.0);
-}
-
 // This is UltraSparc specific, true just means we have fast l2f conversion
 const bool Matcher::convL2FSupported(void) {
   return true;
@@ -2036,67 +2016,6 @@
   %}
 
 
-  enc_class LdImmD (immD src) %{    // Load Immediate
-    if( is_positive_zero_double($src$$constant)) {
-      // FLDZ
-      emit_opcode(cbuf,0xD9);
-      emit_opcode(cbuf,0xEE);
-    } else if( is_positive_one_double($src$$constant)) {
-      // FLD1
-      emit_opcode(cbuf,0xD9);
-      emit_opcode(cbuf,0xE8);
-    } else {
-      emit_opcode(cbuf,0xDD);
-      emit_rm(cbuf, 0x0, 0x0, 0x5);
-      emit_double_constant(cbuf, $src$$constant);
-    }
-  %}
-
-
-  enc_class LdImmF (immF src) %{    // Load Immediate
-    if( is_positive_zero_float($src$$constant)) {
-      emit_opcode(cbuf,0xD9);
-      emit_opcode(cbuf,0xEE);
-    } else if( is_positive_one_float($src$$constant)) {
-      emit_opcode(cbuf,0xD9);
-      emit_opcode(cbuf,0xE8);
-    } else {
-      $$$emit8$primary;
-      // Load immediate does not have a zero or sign extended version
-      // for 8-bit immediates
-      // First load to TOS, then move to dst
-      emit_rm(cbuf, 0x0, 0x0, 0x5);
-      emit_float_constant(cbuf, $src$$constant);
-    }
-  %}
-
-  enc_class LdImmX (regX dst, immXF con) %{    // Load Immediate
-    emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
-    emit_float_constant(cbuf, $con$$constant);
-  %}
-
-  enc_class LdImmXD (regXD dst, immXD con) %{    // Load Immediate
-    emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
-    emit_double_constant(cbuf, $con$$constant);
-  %}
-
-  enc_class load_conXD (regXD dst, immXD con) %{ // Load double constant
-    // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
-    emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
-    emit_opcode(cbuf, 0x0F);
-    emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
-    emit_rm(cbuf, 0x0, $dst$$reg, 0x5);
-    emit_double_constant(cbuf, $con$$constant);
-  %}
-
-  enc_class Opc_MemImm_F(immF src) %{
-    cbuf.set_insts_mark();
-    $$$emit8$primary;
-    emit_rm(cbuf, 0x0, $secondary, 0x5);
-    emit_float_constant(cbuf, $src$$constant);
-  %}
-
-
   enc_class MovI2X_reg(regX dst, eRegI src) %{
     emit_opcode(cbuf, 0x66 );     // MOVD dst,src
     emit_opcode(cbuf, 0x0F );
@@ -4801,7 +4720,7 @@
   interface(CONST_INTER);
 %}
 
-// Double Immediate
+// Double Immediate one
 operand immD1() %{
   predicate( UseSSE<=1 && n->getd() == 1.0 );
   match(ConD);
@@ -4844,7 +4763,17 @@
 
 // Float Immediate zero
 operand immF0() %{
-  predicate( UseSSE == 0 && n->getf() == 0.0 );
+  predicate(UseSSE == 0 && n->getf() == 0.0F);
+  match(ConF);
+
+  op_cost(5);
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
+// Float Immediate one
+operand immF1() %{
+  predicate(UseSSE == 0 && n->getf() == 1.0F);
   match(ConF);
 
   op_cost(5);
@@ -7215,24 +7144,53 @@
 %}
 
 // The instruction usage is guarded by predicate in operand immF().
-instruct loadConF(regF dst, immF src) %{
-  match(Set dst src);
+instruct loadConF(regF dst, immF con) %{
+  match(Set dst con);
+  ins_cost(125);
+  format %{ "FLD_S  ST,[$constantaddress]\t# load from constant table: float=$con\n\t"
+            "FSTP   $dst" %}
+  ins_encode %{
+    __ fld_s($constantaddress($con));
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immF0().
+instruct loadConF0(regF dst, immF0 con) %{
+  match(Set dst con);
   ins_cost(125);
-
-  format %{ "FLD_S  ST,$src\n\t"
+  format %{ "FLDZ   ST\n\t"
             "FSTP   $dst" %}
-  opcode(0xD9, 0x00);       /* D9 /0 */
-  ins_encode(LdImmF(src), Pop_Reg_F(dst) );
-  ins_pipe( fpu_reg_con );
+  ins_encode %{
+    __ fldz();
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immF1().
+instruct loadConF1(regF dst, immF1 con) %{
+  match(Set dst con);
+  ins_cost(125);
+  format %{ "FLD1   ST\n\t"
+            "FSTP   $dst" %}
+  ins_encode %{
+    __ fld1();
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_con);
 %}
 
 // The instruction usage is guarded by predicate in operand immXF().
 instruct loadConX(regX dst, immXF con) %{
   match(Set dst con);
   ins_cost(125);
-  format %{ "MOVSS  $dst,[$con]" %}
-  ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x10), LdImmX(dst, con));
-  ins_pipe( pipe_slow );
+  format %{ "MOVSS  $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+  ins_encode %{
+    __ movflt($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 // The instruction usage is guarded by predicate in operand immXF0().
@@ -7240,28 +7198,63 @@
   match(Set dst src);
   ins_cost(100);
   format %{ "XORPS  $dst,$dst\t# float 0.0" %}
-  ins_encode( Opcode(0x0F), Opcode(0x57), RegReg(dst,dst));
-  ins_pipe( pipe_slow );
+  ins_encode %{
+    __ xorps($dst$$XMMRegister, $dst$$XMMRegister);
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 // The instruction usage is guarded by predicate in operand immD().
-instruct loadConD(regD dst, immD src) %{
-  match(Set dst src);
+instruct loadConD(regD dst, immD con) %{
+  match(Set dst con);
+  ins_cost(125);
+
+  format %{ "FLD_D  ST,[$constantaddress]\t# load from constant table: double=$con\n\t"
+            "FSTP   $dst" %}
+  ins_encode %{
+    __ fld_d($constantaddress($con));
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immD0().
+instruct loadConD0(regD dst, immD0 con) %{
+  match(Set dst con);
   ins_cost(125);
 
-  format %{ "FLD_D  ST,$src\n\t"
+  format %{ "FLDZ   ST\n\t"
             "FSTP   $dst" %}
-  ins_encode(LdImmD(src), Pop_Reg_D(dst) );
-  ins_pipe( fpu_reg_con );
+  ins_encode %{
+    __ fldz();
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_con);
+%}
+
+// The instruction usage is guarded by predicate in operand immD1().
+instruct loadConD1(regD dst, immD1 con) %{
+  match(Set dst con);
+  ins_cost(125);
+
+  format %{ "FLD1   ST\n\t"
+            "FSTP   $dst" %}
+  ins_encode %{
+    __ fld1();
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_con);
 %}
 
 // The instruction usage is guarded by predicate in operand immXD().
 instruct loadConXD(regXD dst, immXD con) %{
   match(Set dst con);
   ins_cost(125);
-  format %{ "MOVSD  $dst,[$con]" %}
-  ins_encode(load_conXD(dst, con));
-  ins_pipe( pipe_slow );
+  format %{ "MOVSD  $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+  ins_encode %{
+    __ movdbl($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 // The instruction usage is guarded by predicate in operand immXD0().
@@ -10303,41 +10296,45 @@
   ins_pipe( fpu_reg_mem );
 %}
 
-instruct addD_reg_imm1(regD dst, immD1 src) %{
+instruct addD_reg_imm1(regD dst, immD1 con) %{
   predicate(UseSSE<=1);
-  match(Set dst (AddD dst src));
+  match(Set dst (AddD dst con));
   ins_cost(125);
   format %{ "FLD1\n\t"
             "DADDp  $dst,ST" %}
-  opcode(0xDE, 0x00);
-  ins_encode( LdImmD(src),
-              OpcP, RegOpc(dst) );
-  ins_pipe( fpu_reg );
-%}
-
-instruct addD_reg_imm(regD dst, immD src) %{
+  ins_encode %{
+    __ fld1();
+    __ faddp($dst$$reg);
+  %}
+  ins_pipe(fpu_reg);
+%}
+
+instruct addD_reg_imm(regD dst, immD con) %{
   predicate(UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
-  match(Set dst (AddD dst src));
+  match(Set dst (AddD dst con));
   ins_cost(200);
-  format %{ "FLD_D  [$src]\n\t"
+  format %{ "FLD_D  [$constantaddress]\t# load from constant table: double=$con\n\t"
             "DADDp  $dst,ST" %}
-  opcode(0xDE, 0x00);       /* DE /0 */
-  ins_encode( LdImmD(src),
-              OpcP, RegOpc(dst));
-  ins_pipe( fpu_reg_mem );
+  ins_encode %{
+    __ fld_d($constantaddress($con));
+    __ faddp($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_mem);
 %}
 
 instruct addD_reg_imm_round(stackSlotD dst, regD src, immD con) %{
   predicate(UseSSE<=1 && _kids[0]->_kids[1]->_leaf->getd() != 0.0 && _kids[0]->_kids[1]->_leaf->getd() != 1.0 );
   match(Set dst (RoundDouble (AddD src con)));
   ins_cost(200);
-  format %{ "FLD_D  [$con]\n\t"
+  format %{ "FLD_D  [$constantaddress]\t# load from constant table: double=$con\n\t"
             "DADD   ST,$src\n\t"
             "FSTP_D $dst\t# D-round" %}
-  opcode(0xD8, 0x00);       /* D8 /0 */
-  ins_encode( LdImmD(con),
-              OpcP, RegOpc(src), Pop_Mem_D(dst));
-  ins_pipe( fpu_mem_reg_con );
+  ins_encode %{
+    __ fld_d($constantaddress($con));
+    __ fadd($src$$reg);
+    __ fstp_d(Address(rsp, $dst$$disp));
+  %}
+  ins_pipe(fpu_mem_reg_con);
 %}
 
 // Add two double precision floating point values in xmm
@@ -10352,9 +10349,11 @@
 instruct addXD_imm(regXD dst, immXD con) %{
   predicate(UseSSE>=2);
   match(Set dst (AddD dst con));
-  format %{ "ADDSD  $dst,[$con]" %}
-  ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x58), LdImmXD(dst, con) );
-  ins_pipe( pipe_slow );
+  format %{ "ADDSD  $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+  ins_encode %{
+    __ addsd($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct addXD_mem(regXD dst, memory mem) %{
@@ -10377,9 +10376,11 @@
 instruct subXD_imm(regXD dst, immXD con) %{
   predicate(UseSSE>=2);
   match(Set dst (SubD dst con));
-  format %{ "SUBSD  $dst,[$con]" %}
-  ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5C), LdImmXD(dst, con) );
-  ins_pipe( pipe_slow );
+  format %{ "SUBSD  $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+  ins_encode %{
+    __ subsd($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct subXD_mem(regXD dst, memory mem) %{
@@ -10402,9 +10403,11 @@
 instruct mulXD_imm(regXD dst, immXD con) %{
   predicate(UseSSE>=2);
   match(Set dst (MulD dst con));
-  format %{ "MULSD  $dst,[$con]" %}
-  ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x59), LdImmXD(dst, con) );
-  ins_pipe( pipe_slow );
+  format %{ "MULSD  $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+  ins_encode %{
+    __ mulsd($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct mulXD_mem(regXD dst, memory mem) %{
@@ -10428,9 +10431,11 @@
 instruct divXD_imm(regXD dst, immXD con) %{
   predicate(UseSSE>=2);
   match(Set dst (DivD dst con));
-  format %{ "DIVSD  $dst,[$con]" %}
-  ins_encode( Opcode(0xF2), Opcode(0x0F), Opcode(0x5E), LdImmXD(dst, con));
-  ins_pipe( pipe_slow );
+  format %{ "DIVSD  $dst,[$constantaddress]\t# load from constant table: double=$con" %}
+  ins_encode %{
+    __ divsd($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct divXD_mem(regXD dst, memory mem) %{
@@ -10481,16 +10486,17 @@
   ins_pipe( fpu_reg_reg );
 %}
 
-instruct mulD_reg_imm(regD dst, immD src) %{
+instruct mulD_reg_imm(regD dst, immD con) %{
   predicate( UseSSE<=1 && _kids[1]->_leaf->getd() != 0.0 && _kids[1]->_leaf->getd() != 1.0 );
-  match(Set dst (MulD dst src));
+  match(Set dst (MulD dst con));
   ins_cost(200);
-  format %{ "FLD_D  [$src]\n\t"
+  format %{ "FLD_D  [$constantaddress]\t# load from constant table: double=$con\n\t"
             "DMULp  $dst,ST" %}
-  opcode(0xDE, 0x1); /* DE /1 */
-  ins_encode( LdImmD(src),
-              OpcP, RegOpc(dst) );
-  ins_pipe( fpu_reg_mem );
+  ins_encode %{
+    __ fld_d($constantaddress($con));
+    __ fmulp($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_mem);
 %}
 
 
@@ -11224,9 +11230,11 @@
 instruct addX_imm(regX dst, immXF con) %{
   predicate(UseSSE>=1);
   match(Set dst (AddF dst con));
-  format %{ "ADDSS  $dst,[$con]" %}
-  ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x58), LdImmX(dst, con) );
-  ins_pipe( pipe_slow );
+  format %{ "ADDSS  $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+  ins_encode %{
+    __ addss($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct addX_mem(regX dst, memory mem) %{
@@ -11249,9 +11257,11 @@
 instruct subX_imm(regX dst, immXF con) %{
   predicate(UseSSE>=1);
   match(Set dst (SubF dst con));
-  format %{ "SUBSS  $dst,[$con]" %}
-  ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5C), LdImmX(dst, con) );
-  ins_pipe( pipe_slow );
+  format %{ "SUBSS  $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+  ins_encode %{
+    __ subss($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct subX_mem(regX dst, memory mem) %{
@@ -11274,9 +11284,11 @@
 instruct mulX_imm(regX dst, immXF con) %{
   predicate(UseSSE>=1);
   match(Set dst (MulF dst con));
-  format %{ "MULSS  $dst,[$con]" %}
-  ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x59), LdImmX(dst, con) );
-  ins_pipe( pipe_slow );
+  format %{ "MULSS  $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+  ins_encode %{
+    __ mulss($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct mulX_mem(regX dst, memory mem) %{
@@ -11299,9 +11311,11 @@
 instruct divX_imm(regX dst, immXF con) %{
   predicate(UseSSE>=1);
   match(Set dst (DivF dst con));
-  format %{ "DIVSS  $dst,[$con]" %}
-  ins_encode( Opcode(0xF3), Opcode(0x0F), Opcode(0x5E), LdImmX(dst, con) );
-  ins_pipe( pipe_slow );
+  format %{ "DIVSS  $dst,[$constantaddress]\t# load from constant table: float=$con" %}
+  ins_encode %{
+    __ divss($dst$$XMMRegister, $constantaddress($con));
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct divX_mem(regX dst, memory mem) %{
@@ -11456,31 +11470,33 @@
 
 
 // Spill to obtain 24-bit precision
-instruct addF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
+instruct addF24_reg_imm(stackSlotF dst, regF src, immF con) %{
   predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
-  match(Set dst (AddF src1 src2));
-  format %{ "FLD    $src1\n\t"
-            "FADD   $src2\n\t"
+  match(Set dst (AddF src con));
+  format %{ "FLD    $src\n\t"
+            "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
             "FSTP_S $dst"  %}
-  opcode(0xD8, 0x00);       /* D8 /0 */
-  ins_encode( Push_Reg_F(src1),
-              Opc_MemImm_F(src2),
-              Pop_Mem_F(dst));
-  ins_pipe( fpu_mem_reg_con );
+  ins_encode %{
+    __ fld_s($src$$reg - 1);  // FLD ST(i-1)
+    __ fadd_s($constantaddress($con));
+    __ fstp_s(Address(rsp, $dst$$disp));
+  %}
+  ins_pipe(fpu_mem_reg_con);
 %}
 //
 // This instruction does not round to 24-bits
-instruct addF_reg_imm(regF dst, regF src1, immF src2) %{
+instruct addF_reg_imm(regF dst, regF src, immF con) %{
   predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
-  match(Set dst (AddF src1 src2));
-  format %{ "FLD    $src1\n\t"
-            "FADD   $src2\n\t"
-            "FSTP_S $dst"  %}
-  opcode(0xD8, 0x00);       /* D8 /0 */
-  ins_encode( Push_Reg_F(src1),
-              Opc_MemImm_F(src2),
-              Pop_Reg_F(dst));
-  ins_pipe( fpu_reg_reg_con );
+  match(Set dst (AddF src con));
+  format %{ "FLD    $src\n\t"
+            "FADD_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+            "FSTP   $dst"  %}
+  ins_encode %{
+    __ fld_s($src$$reg - 1);  // FLD ST(i-1)
+    __ fadd_s($constantaddress($con));
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_reg_con);
 %}
 
 // Spill to obtain 24-bit precision
@@ -11559,29 +11575,35 @@
 %}
 
 // Spill to obtain 24-bit precision
-instruct mulF24_reg_imm(stackSlotF dst, regF src1, immF src2) %{
+instruct mulF24_reg_imm(stackSlotF dst, regF src, immF con) %{
   predicate(UseSSE==0 && Compile::current()->select_24_bit_instr());
-  match(Set dst (MulF src1 src2));
-
-  format %{ "FMULc $dst,$src1,$src2" %}
-  opcode(0xD8, 0x1);  /* D8 /1*/
-  ins_encode( Push_Reg_F(src1),
-              Opc_MemImm_F(src2),
-              Pop_Mem_F(dst));
-  ins_pipe( fpu_mem_reg_con );
+  match(Set dst (MulF src con));
+
+  format %{ "FLD    $src\n\t"
+            "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+            "FSTP_S $dst"  %}
+  ins_encode %{
+    __ fld_s($src$$reg - 1);  // FLD ST(i-1)
+    __ fmul_s($constantaddress($con));
+    __ fstp_s(Address(rsp, $dst$$disp));
+  %}
+  ins_pipe(fpu_mem_reg_con);
 %}
 //
 // This instruction does not round to 24-bits
-instruct mulF_reg_imm(regF dst, regF src1, immF src2) %{
+instruct mulF_reg_imm(regF dst, regF src, immF con) %{
   predicate(UseSSE==0 && !Compile::current()->select_24_bit_instr());
-  match(Set dst (MulF src1 src2));
-
-  format %{ "FMULc $dst. $src1, $src2" %}
-  opcode(0xD8, 0x1);  /* D8 /1*/
-  ins_encode( Push_Reg_F(src1),
-              Opc_MemImm_F(src2),
-              Pop_Reg_F(dst));
-  ins_pipe( fpu_reg_reg_con );
+  match(Set dst (MulF src con));
+
+  format %{ "FLD    $src\n\t"
+            "FMUL_S [$constantaddress]\t# load from constant table: float=$con\n\t"
+            "FSTP   $dst"  %}
+  ins_encode %{
+    __ fld_s($src$$reg - 1);  // FLD ST(i-1)
+    __ fmul_s($constantaddress($con));
+    __ fstp_d($dst$$reg);
+  %}
+  ins_pipe(fpu_reg_reg_con);
 %}
 
 
@@ -12939,16 +12961,11 @@
 instruct jumpXtnd(eRegI switch_val) %{
   match(Jump switch_val);
   ins_cost(350);
-
-  format %{  "JMP    [table_base](,$switch_val,1)\n\t" %}
-
-  ins_encode %{
-    address table_base  = __ address_table_constant(_index2label);
-
+  format %{  "JMP    [$constantaddress](,$switch_val,1)\n\t" %}
+  ins_encode %{
     // Jump to Address(table_base + switch_reg)
-    InternalAddress table(table_base);
     Address index(noreg, $switch_val$$Register, Address::times_1);
-    __ jump(ArrayAddress(table, index));
+    __ jump(ArrayAddress($constantaddress, index));
   %}
   ins_pc_relative(1);
   ins_pipe(pipe_jmp);
--- a/src/cpu/x86/vm/x86_64.ad	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/cpu/x86/vm/x86_64.ad	Fri Dec 03 01:34:31 2010 -0800
@@ -833,6 +833,25 @@
 
 
 //=============================================================================
+const bool Matcher::constant_table_absolute_addressing = true;
+const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
+
+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
+  // Empty encoding
+}
+
+uint MachConstantBaseNode::size(PhaseRegAlloc* ra_) const {
+  return 0;
+}
+
+#ifndef PRODUCT
+void MachConstantBaseNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
+  st->print("# MachConstantBaseNode (empty encoding)");
+}
+#endif
+
+
+//=============================================================================
 #ifndef PRODUCT
 void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const
 {
@@ -1922,28 +1941,6 @@
   return offset;
 }
 
-static void emit_double_constant(CodeBuffer& cbuf, double x) {
-  int mark = cbuf.insts()->mark_off();
-  MacroAssembler _masm(&cbuf);
-  address double_address = __ double_constant(x);
-  cbuf.insts()->set_mark_off(mark);  // preserve mark across masm shift
-  emit_d32_reloc(cbuf,
-                 (int) (double_address - cbuf.insts_end() - 4),
-                 internal_word_Relocation::spec(double_address),
-                 RELOC_DISP32);
-}
-
-static void emit_float_constant(CodeBuffer& cbuf, float x) {
-  int mark = cbuf.insts()->mark_off();
-  MacroAssembler _masm(&cbuf);
-  address float_address = __ float_constant(x);
-  cbuf.insts()->set_mark_off(mark);  // preserve mark across masm shift
-  emit_d32_reloc(cbuf,
-                 (int) (float_address - cbuf.insts_end() - 4),
-                 internal_word_Relocation::spec(float_address),
-                 RELOC_DISP32);
-}
-
 
 const bool Matcher::match_rule_supported(int opcode) {
   if (!has_match_rule(opcode))
@@ -2789,43 +2786,6 @@
     }
   %}
 
-  enc_class load_immF(regF dst, immF con)
-  %{
-    // XXX reg_mem doesn't support RIP-relative addressing yet
-    emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
-    emit_float_constant(cbuf, $con$$constant);
-  %}
-
-  enc_class load_immD(regD dst, immD con)
-  %{
-    // XXX reg_mem doesn't support RIP-relative addressing yet
-    emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
-    emit_double_constant(cbuf, $con$$constant);
-  %}
-
-  enc_class load_conF (regF dst, immF con) %{    // Load float constant
-    emit_opcode(cbuf, 0xF3);
-    if ($dst$$reg >= 8) {
-      emit_opcode(cbuf, Assembler::REX_R);
-    }
-    emit_opcode(cbuf, 0x0F);
-    emit_opcode(cbuf, 0x10);
-    emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
-    emit_float_constant(cbuf, $con$$constant);
-  %}
-
-  enc_class load_conD (regD dst, immD con) %{    // Load double constant
-    // UseXmmLoadAndClearUpper ? movsd(dst, con) : movlpd(dst, con)
-    emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0xF2 : 0x66);
-    if ($dst$$reg >= 8) {
-      emit_opcode(cbuf, Assembler::REX_R);
-    }
-    emit_opcode(cbuf, 0x0F);
-    emit_opcode(cbuf, UseXmmLoadAndClearUpper ? 0x10 : 0x12);
-    emit_rm(cbuf, 0x0, $dst$$reg & 7, 0x5); // 00 reg 101
-    emit_double_constant(cbuf, $con$$constant);
-  %}
-
   // Encode a reg-reg copy.  If it is useless, then empty encoding.
   enc_class enc_copy(rRegI dst, rRegI src)
   %{
@@ -2926,63 +2886,6 @@
     emit_d32(cbuf, 0x00);
   %}
 
-  enc_class jump_enc(rRegL switch_val, rRegI dest) %{
-    MacroAssembler masm(&cbuf);
-
-    Register switch_reg = as_Register($switch_val$$reg);
-    Register dest_reg   = as_Register($dest$$reg);
-    address table_base  = masm.address_table_constant(_index2label);
-
-    // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
-    // to do that and the compiler is using that register as one it can allocate.
-    // So we build it all by hand.
-    // Address index(noreg, switch_reg, Address::times_1);
-    // ArrayAddress dispatch(table, index);
-
-    Address dispatch(dest_reg, switch_reg, Address::times_1);
-
-    masm.lea(dest_reg, InternalAddress(table_base));
-    masm.jmp(dispatch);
-  %}
-
-  enc_class jump_enc_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{
-    MacroAssembler masm(&cbuf);
-
-    Register switch_reg = as_Register($switch_val$$reg);
-    Register dest_reg   = as_Register($dest$$reg);
-    address table_base  = masm.address_table_constant(_index2label);
-
-    // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
-    // to do that and the compiler is using that register as one it can allocate.
-    // So we build it all by hand.
-    // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
-    // ArrayAddress dispatch(table, index);
-
-    Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant);
-
-    masm.lea(dest_reg, InternalAddress(table_base));
-    masm.jmp(dispatch);
-  %}
-
-  enc_class jump_enc_offset(rRegL switch_val, immI2 shift, rRegI dest) %{
-    MacroAssembler masm(&cbuf);
-
-    Register switch_reg = as_Register($switch_val$$reg);
-    Register dest_reg   = as_Register($dest$$reg);
-    address table_base  = masm.address_table_constant(_index2label);
-
-    // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
-    // to do that and the compiler is using that register as one it can allocate.
-    // So we build it all by hand.
-    // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
-    // ArrayAddress dispatch(table, index);
-
-    Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant);
-    masm.lea(dest_reg, InternalAddress(table_base));
-    masm.jmp(dispatch);
-
-  %}
-
   enc_class lock_prefix()
   %{
     if (os::is_MP()) {
@@ -6641,12 +6544,11 @@
   ins_pipe(ialu_reg);
 %}
 
-instruct loadConP(rRegP dst, immP src)
-%{
-  match(Set dst src);
-
-  format %{ "movq    $dst, $src\t# ptr" %}
-  ins_encode(load_immP(dst, src));
+instruct loadConP(rRegP dst, immP con) %{
+  match(Set dst con);
+
+  format %{ "movq    $dst, $con\t# ptr" %}
+  ins_encode(load_immP(dst, con));
   ins_pipe(ialu_reg_fat); // XXX
 %}
 
@@ -6673,13 +6575,13 @@
   ins_pipe(ialu_reg);
 %}
 
-instruct loadConF(regF dst, immF src)
-%{
-  match(Set dst src);
+instruct loadConF(regF dst, immF con) %{
+  match(Set dst con);
   ins_cost(125);
-
-  format %{ "movss   $dst, [$src]" %}
-  ins_encode(load_conF(dst, src));
+  format %{ "movss   $dst, [$constantaddress]\t# load from constant table: float=$con" %}
+  ins_encode %{
+    __ movflt($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -6721,13 +6623,13 @@
 %}
 
 // Use the same format since predicate() can not be used here.
-instruct loadConD(regD dst, immD src)
-%{
-  match(Set dst src);
+instruct loadConD(regD dst, immD con) %{
+  match(Set dst con);
   ins_cost(125);
-
-  format %{ "movsd   $dst, [$src]" %}
-  ins_encode(load_conD(dst, src));
+  format %{ "movsd   $dst, [$constantaddress]\t# load from constant table: double=$con" %}
+  ins_encode %{
+    __ movdbl($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -7694,9 +7596,18 @@
   predicate(false);
   effect(TEMP dest);
 
-  format %{ "leaq    $dest, table_base\n\t"
+  format %{ "leaq    $dest, [$constantaddress]\n\t"
             "jmp     [$dest + $switch_val << $shift]\n\t" %}
-  ins_encode(jump_enc_offset(switch_val, shift, dest));
+  ins_encode %{
+    // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+    // to do that and the compiler is using that register as one it can allocate.
+    // So we build it all by hand.
+    // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant);
+    // ArrayAddress dispatch(table, index);
+    Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant);
+    __ lea($dest$$Register, $constantaddress);
+    __ jmp(dispatch);
+  %}
   ins_pipe(pipe_jmp);
   ins_pc_relative(1);
 %}
@@ -7706,9 +7617,18 @@
   ins_cost(350);
   effect(TEMP dest);
 
-  format %{ "leaq    $dest, table_base\n\t"
+  format %{ "leaq    $dest, [$constantaddress]\n\t"
             "jmp     [$dest + $switch_val << $shift + $offset]\n\t" %}
-  ins_encode(jump_enc_addr(switch_val, shift, offset, dest));
+  ins_encode %{
+    // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+    // to do that and the compiler is using that register as one it can allocate.
+    // So we build it all by hand.
+    // Address index(noreg, switch_reg, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
+    // ArrayAddress dispatch(table, index);
+    Address dispatch($dest$$Register, $switch_val$$Register, (Address::ScaleFactor) $shift$$constant, (int) $offset$$constant);
+    __ lea($dest$$Register, $constantaddress);
+    __ jmp(dispatch);
+  %}
   ins_pipe(pipe_jmp);
   ins_pc_relative(1);
 %}
@@ -7718,9 +7638,18 @@
   ins_cost(350);
   effect(TEMP dest);
 
-  format %{ "leaq    $dest, table_base\n\t"
+  format %{ "leaq    $dest, [$constantaddress]\n\t"
             "jmp     [$dest + $switch_val]\n\t" %}
-  ins_encode(jump_enc(switch_val, dest));
+  ins_encode %{
+    // We could use jump(ArrayAddress) except that the macro assembler needs to use r10
+    // to do that and the compiler is using that register as one it can allocate.
+    // So we build it all by hand.
+    // Address index(noreg, switch_reg, Address::times_1);
+    // ArrayAddress dispatch(table, index);
+    Address dispatch($dest$$Register, $switch_val$$Register, Address::times_1);
+    __ lea($dest$$Register, $constantaddress);
+    __ jmp(dispatch);
+  %}
   ins_pipe(pipe_jmp);
   ins_pc_relative(1);
 %}
@@ -10376,30 +10305,36 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct cmpF_cc_imm(rFlagsRegU cr, regF src1, immF src2)
-%{
-  match(Set cr (CmpF src1 src2));
+instruct cmpF_cc_imm(rFlagsRegU cr, regF src, immF con) %{
+  match(Set cr (CmpF src con));
 
   ins_cost(145);
-  format %{ "ucomiss $src1, $src2\n\t"
+  format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
             "jnp,s   exit\n\t"
             "pushfq\t# saw NaN, set CF\n\t"
             "andq    [rsp], #0xffffff2b\n\t"
             "popfq\n"
     "exit:   nop\t# avoid branch to branch" %}
-  opcode(0x0F, 0x2E);
-  ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2),
-             cmpfp_fixup);
-  ins_pipe(pipe_slow);
-%}
-
-instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src1, immF src2) %{
-  match(Set cr (CmpF src1 src2));
-
+  ins_encode %{
+    Label L_exit;
+    __ ucomiss($src$$XMMRegister, $constantaddress($con));
+    __ jcc(Assembler::noParity, L_exit);
+    __ pushf();
+    __ andq(rsp, 0xffffff2b);
+    __ popf();
+    __ bind(L_exit);
+    __ nop();
+  %}
+  ins_pipe(pipe_slow);
+%}
+
+instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{
+  match(Set cr (CmpF src con));
   ins_cost(100);
-  format %{ "ucomiss $src1, $src2" %}
-  opcode(0x0F, 0x2E);
-  ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2));
+  format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %}
+  ins_encode %{
+    __ ucomiss($src$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10458,30 +10393,36 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct cmpD_cc_imm(rFlagsRegU cr, regD src1, immD src2)
-%{
-  match(Set cr (CmpD src1 src2));
+instruct cmpD_cc_imm(rFlagsRegU cr, regD src, immD con) %{
+  match(Set cr (CmpD src con));
 
   ins_cost(145);
-  format %{ "ucomisd $src1, [$src2]\n\t"
+  format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
             "jnp,s   exit\n\t"
             "pushfq\t# saw NaN, set CF\n\t"
             "andq    [rsp], #0xffffff2b\n\t"
             "popfq\n"
     "exit:   nop\t# avoid branch to branch" %}
-  opcode(0x66, 0x0F, 0x2E);
-  ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2),
-             cmpfp_fixup);
-  ins_pipe(pipe_slow);
-%}
-
-instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src1, immD src2) %{
-  match(Set cr (CmpD src1 src2));
-
+  ins_encode %{
+    Label L_exit;
+    __ ucomisd($src$$XMMRegister, $constantaddress($con));
+    __ jcc(Assembler::noParity, L_exit);
+    __ pushf();
+    __ andq(rsp, 0xffffff2b);
+    __ popf();
+    __ bind(L_exit);
+    __ nop();
+  %}
+  ins_pipe(pipe_slow);
+%}
+
+instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{
+  match(Set cr (CmpD src con));
   ins_cost(100);
-  format %{ "ucomisd $src1, [$src2]" %}
-  opcode(0x66, 0x0F, 0x2E);
-  ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2));
+  format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con" %}
+  ins_encode %{
+    __ ucomisd($src$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10528,23 +10469,29 @@
 %}
 
 // Compare into -1,0,1
-instruct cmpF_imm(rRegI dst, regF src1, immF src2, rFlagsReg cr)
-%{
-  match(Set dst (CmpF3 src1 src2));
+instruct cmpF_imm(rRegI dst, regF src, immF con, rFlagsReg cr) %{
+  match(Set dst (CmpF3 src con));
   effect(KILL cr);
 
   ins_cost(275);
-  format %{ "ucomiss $src1, [$src2]\n\t"
+  format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con\n\t"
             "movl    $dst, #-1\n\t"
             "jp,s    done\n\t"
             "jb,s    done\n\t"
             "setne   $dst\n\t"
             "movzbl  $dst, $dst\n"
     "done:" %}
-
-  opcode(0x0F, 0x2E);
-  ins_encode(REX_reg_mem(src1, src2), OpcP, OpcS, load_immF(src1, src2),
-             cmpfp3(dst));
+  ins_encode %{
+    Label L_done;
+    Register Rdst = $dst$$Register;
+    __ ucomiss($src$$XMMRegister, $constantaddress($con));
+    __ movl(Rdst, -1);
+    __ jcc(Assembler::parity, L_done);
+    __ jcc(Assembler::below, L_done);
+    __ setb(Assembler::notEqual, Rdst);
+    __ movzbl(Rdst, Rdst);
+    __ bind(L_done);
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10591,23 +10538,29 @@
 %}
 
 // Compare into -1,0,1
-instruct cmpD_imm(rRegI dst, regD src1, immD src2, rFlagsReg cr)
-%{
-  match(Set dst (CmpD3 src1 src2));
+instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{
+  match(Set dst (CmpD3 src con));
   effect(KILL cr);
 
   ins_cost(275);
-  format %{ "ucomisd $src1, [$src2]\n\t"
+  format %{ "ucomisd $src, [$constantaddress]\t# load from constant table: double=$con\n\t"
             "movl    $dst, #-1\n\t"
             "jp,s    done\n\t"
             "jb,s    done\n\t"
             "setne   $dst\n\t"
             "movzbl  $dst, $dst\n"
     "done:" %}
-
-  opcode(0x66, 0x0F, 0x2E);
-  ins_encode(OpcP, REX_reg_mem(src1, src2), OpcS, OpcT, load_immD(src1, src2),
-             cmpfp3(dst));
+  ins_encode %{
+    Register Rdst = $dst$$Register;
+    Label L_done;
+    __ ucomisd($src$$XMMRegister, $constantaddress($con));
+    __ movl(Rdst, -1);
+    __ jcc(Assembler::parity, L_done);
+    __ jcc(Assembler::below, L_done);
+    __ setb(Assembler::notEqual, Rdst);
+    __ movzbl(Rdst, Rdst);
+    __ bind(L_done);
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10633,14 +10586,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct addF_imm(regF dst, immF src)
-%{
-  match(Set dst (AddF dst src));
-
-  format %{ "addss   $dst, [$src]" %}
+instruct addF_imm(regF dst, immF con) %{
+  match(Set dst (AddF dst con));
+  format %{ "addss   $dst, [$constantaddress]\t# load from constant table: float=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF3, 0x0F, 0x58);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+  ins_encode %{
+    __ addss($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10666,14 +10618,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct addD_imm(regD dst, immD src)
-%{
-  match(Set dst (AddD dst src));
-
-  format %{ "addsd   $dst, [$src]" %}
+instruct addD_imm(regD dst, immD con) %{
+  match(Set dst (AddD dst con));
+  format %{ "addsd   $dst, [$constantaddress]\t# load from constant table: double=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF2, 0x0F, 0x58);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+  ins_encode %{
+    __ addsd($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10699,14 +10650,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct subF_imm(regF dst, immF src)
-%{
-  match(Set dst (SubF dst src));
-
-  format %{ "subss   $dst, [$src]" %}
+instruct subF_imm(regF dst, immF con) %{
+  match(Set dst (SubF dst con));
+  format %{ "subss   $dst, [$constantaddress]\t# load from constant table: float=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF3, 0x0F, 0x5C);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+  ins_encode %{
+    __ subss($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10732,14 +10682,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct subD_imm(regD dst, immD src)
-%{
-  match(Set dst (SubD dst src));
-
-  format %{ "subsd   $dst, [$src]" %}
+instruct subD_imm(regD dst, immD con) %{
+  match(Set dst (SubD dst con));
+  format %{ "subsd   $dst, [$constantaddress]\t# load from constant table: double=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF2, 0x0F, 0x5C);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+  ins_encode %{
+    __ subsd($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10765,14 +10714,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct mulF_imm(regF dst, immF src)
-%{
-  match(Set dst (MulF dst src));
-
-  format %{ "mulss   $dst, [$src]" %}
+instruct mulF_imm(regF dst, immF con) %{
+  match(Set dst (MulF dst con));
+  format %{ "mulss   $dst, [$constantaddress]\t# load from constant table: float=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF3, 0x0F, 0x59);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+  ins_encode %{
+    __ mulss($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10798,14 +10746,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct mulD_imm(regD dst, immD src)
-%{
-  match(Set dst (MulD dst src));
-
-  format %{ "mulsd   $dst, [$src]" %}
+instruct mulD_imm(regD dst, immD con) %{
+  match(Set dst (MulD dst con));
+  format %{ "mulsd   $dst, [$constantaddress]\t# load from constant table: double=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF2, 0x0F, 0x59);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+  ins_encode %{
+    __ mulsd($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10831,14 +10778,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct divF_imm(regF dst, immF src)
-%{
-  match(Set dst (DivF dst src));
-
-  format %{ "divss   $dst, [$src]" %}
+instruct divF_imm(regF dst, immF con) %{
+  match(Set dst (DivF dst con));
+  format %{ "divss   $dst, [$constantaddress]\t# load from constant table: float=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF3, 0x0F, 0x5E);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+  ins_encode %{
+    __ divss($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10864,14 +10810,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct divD_imm(regD dst, immD src)
-%{
-  match(Set dst (DivD dst src));
-
-  format %{ "divsd   $dst, [$src]" %}
+instruct divD_imm(regD dst, immD con) %{
+  match(Set dst (DivD dst con));
+  format %{ "divsd   $dst, [$constantaddress]\t# load from constant table: double=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF2, 0x0F, 0x5E);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+  ins_encode %{
+    __ divsd($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10897,14 +10842,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct sqrtF_imm(regF dst, immF src)
-%{
-  match(Set dst (ConvD2F (SqrtD (ConvF2D src))));
-
-  format %{ "sqrtss  $dst, [$src]" %}
+instruct sqrtF_imm(regF dst, immF con) %{
+  match(Set dst (ConvD2F (SqrtD (ConvF2D con))));
+  format %{ "sqrtss  $dst, [$constantaddress]\t# load from constant table: float=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF3, 0x0F, 0x51);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immF(dst, src));
+  ins_encode %{
+    __ sqrtss($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -10930,14 +10874,13 @@
   ins_pipe(pipe_slow);
 %}
 
-instruct sqrtD_imm(regD dst, immD src)
-%{
-  match(Set dst (SqrtD src));
-
-  format %{ "sqrtsd  $dst, [$src]" %}
+instruct sqrtD_imm(regD dst, immD con) %{
+  match(Set dst (SqrtD con));
+  format %{ "sqrtsd  $dst, [$constantaddress]\t# load from constant table: double=$con" %}
   ins_cost(150); // XXX
-  opcode(0xF2, 0x0F, 0x51);
-  ins_encode(OpcP, REX_reg_mem(dst, src), OpcS, OpcT, load_immD(dst, src));
+  ins_encode %{
+    __ sqrtsd($dst$$XMMRegister, $constantaddress($con));
+  %}
   ins_pipe(pipe_slow);
 %}
 
--- a/src/os/linux/vm/vmError_linux.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/os/linux/vm/vmError_linux.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -44,11 +44,11 @@
     jio_snprintf(p, buflen - len,
                "\n\n"
                "Do you want to debug the problem?\n\n"
-               "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT "\n"
+               "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n"
                "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
                "Otherwise, press RETURN to abort...",
                os::current_process_id(), os::current_process_id(),
-               os::current_thread_id());
+               os::current_thread_id(), os::current_thread_id());
 
     yes = os::message_box("Unexpected Error", buf);
 
--- a/src/share/vm/adlc/adlparse.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/adlc/adlparse.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -95,7 +95,7 @@
     if (ident == NULL) {         // Empty line
       continue;                  // Get the next line
     }
-    if (!strcmp(ident, "instruct"))        instr_parse();
+         if (!strcmp(ident, "instruct"))   instr_parse();
     else if (!strcmp(ident, "operand"))    oper_parse();
     else if (!strcmp(ident, "opclass"))    opclass_parse();
     else if (!strcmp(ident, "ins_attrib")) ins_attr_parse();
@@ -216,24 +216,23 @@
     else if (!strcmp(ident, "encode"))  {
       parse_err(SYNERR, "Instructions specify ins_encode, not encode\n");
     }
-    else if (!strcmp(ident, "ins_encode"))
-      instr->_insencode = ins_encode_parse(*instr);
-    else if (!strcmp(ident, "opcode"))  instr->_opcode = opcode_parse(instr);
-    else if (!strcmp(ident, "size"))    instr->_size = size_parse(instr);
-    else if (!strcmp(ident, "effect"))  effect_parse(instr);
-    else if (!strcmp(ident, "expand"))  instr->_exprule = expand_parse(instr);
-    else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
+    else if (!strcmp(ident, "ins_encode"))     ins_encode_parse(*instr);
+    else if (!strcmp(ident, "opcode"))         instr->_opcode    = opcode_parse(instr);
+    else if (!strcmp(ident, "size"))           instr->_size      = size_parse(instr);
+    else if (!strcmp(ident, "effect"))         effect_parse(instr);
+    else if (!strcmp(ident, "expand"))         instr->_exprule   = expand_parse(instr);
+    else if (!strcmp(ident, "rewrite"))        instr->_rewrule   = rewrite_parse();
     else if (!strcmp(ident, "constraint")) {
       parse_err(SYNERR, "Instructions do not specify a constraint\n");
     }
     else if (!strcmp(ident, "construct")) {
       parse_err(SYNERR, "Instructions do not specify a construct\n");
     }
-    else if (!strcmp(ident, "format"))  instr->_format  = format_parse();
+    else if (!strcmp(ident, "format"))         instr->_format    = format_parse();
     else if (!strcmp(ident, "interface")) {
       parse_err(SYNERR, "Instructions do not specify an interface\n");
     }
-    else if (!strcmp(ident, "ins_pipe")) ins_pipe_parse(*instr);
+    else if (!strcmp(ident, "ins_pipe"))        ins_pipe_parse(*instr);
     else {  // Done with staticly defined parts of instruction definition
       // Check identifier to see if it is the name of an attribute
       const Form    *form = _globalNames[ident];
@@ -323,7 +322,8 @@
       const char *optype2  = NULL;
       // Can not have additional base operands in right side of match!
       if ( ! right->base_operand( position, _globalNames, result2, name2, optype2) ) {
-        assert( instr->_predicate == NULL, "ADLC does not support instruction chain rules with predicates");
+        if (instr->_predicate != NULL)
+          parse_err(SYNERR, "ADLC does not support instruction chain rules with predicates");
         // Chain from input  _ideal_operand_type_,
         // Needed for shared roots of match-trees
         ChainList *lst = (ChainList *)_AD._chainRules[optype];
@@ -935,9 +935,9 @@
     // (2)
     // If we are at a replacement variable,
     // copy it and record in EncClass
-    if ( _curchar == '$' ) {
+    if (_curchar == '$') {
       // Found replacement Variable
-      char *rep_var = get_rep_var_ident_dup();
+      char* rep_var = get_rep_var_ident_dup();
       // Add flag to _strings list indicating we should check _rep_vars
       encoding->add_rep_var(rep_var);
     }
@@ -2774,47 +2774,122 @@
 
 //------------------------------ins_encode_parse_block-------------------------
 // Parse the block form of ins_encode.  See ins_encode_parse for more details
-InsEncode *ADLParser::ins_encode_parse_block(InstructForm &inst) {
+void ADLParser::ins_encode_parse_block(InstructForm& inst) {
   // Create a new encoding name based on the name of the instruction
   // definition, which should be unique.
-  const char * prefix = "__enc_";
-  char* ec_name = (char*)malloc(strlen(inst._ident) + strlen(prefix) + 1);
+  const char* prefix = "__ins_encode_";
+  char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
   sprintf(ec_name, "%s%s", prefix, inst._ident);
 
   assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
-  EncClass  *encoding = _AD._encode->add_EncClass(ec_name);
+  EncClass* encoding = _AD._encode->add_EncClass(ec_name);
   encoding->_linenum = linenum();
 
   // synthesize the arguments list for the enc_class from the
   // arguments to the instruct definition.
-  const char * param = NULL;
+  const char* param = NULL;
   inst._parameters.reset();
   while ((param = inst._parameters.iter()) != NULL) {
-    OperandForm *opForm = (OperandForm*)inst._localNames[param];
+    OperandForm* opForm = (OperandForm*) inst._localNames[param];
     encoding->add_parameter(opForm->_ident, param);
   }
 
-  // Add the prologue to create the MacroAssembler
-  encoding->add_code("\n"
-  "    // Define a MacroAssembler instance for use by the encoding.  The\n"
-  "    // name is chosen to match the __ idiom used for assembly in other\n"
-  "    // parts of hotspot and assumes the existence of the standard\n"
-  "    // #define __ _masm.\n"
-  "    MacroAssembler _masm(&cbuf);\n");
+  // Define a MacroAssembler instance for use by the encoding.  The
+  // name is chosen to match the __ idiom used for assembly in other
+  // parts of hotspot and assumes the existence of the standard
+  // #define __ _masm.
+  encoding->add_code("    MacroAssembler _masm(&cbuf);\n");
 
   // Parse the following %{ }% block
-  enc_class_parse_block(encoding, ec_name);
+  ins_encode_parse_block_impl(inst, encoding, ec_name);
 
   // Build an encoding rule which invokes the encoding rule we just
   // created, passing all arguments that we received.
-  InsEncode *encrule  = new InsEncode(); // Encode class for instruction
-  NameAndList *params = encrule->add_encode(ec_name);
+  InsEncode*   encrule = new InsEncode(); // Encode class for instruction
+  NameAndList* params  = encrule->add_encode(ec_name);
   inst._parameters.reset();
   while ((param = inst._parameters.iter()) != NULL) {
     params->add_entry(param);
   }
 
-  return encrule;
+  // Set encode class of this instruction.
+  inst._insencode = encrule;
+}
+
+
+void ADLParser::ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name) {
+  skipws_no_preproc();              // Skip leading whitespace
+  // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
+  if (_AD._adlocation_debug) {
+    encoding->add_code(get_line_string());
+  }
+
+  // Collect the parts of the encode description
+  // (1) strings that are passed through to output
+  // (2) replacement/substitution variable, preceeded by a '$'
+  while ((_curchar != '%') && (*(_ptr+1) != '}')) {
+
+    // (1)
+    // Check if there is a string to pass through to output
+    char *start = _ptr;       // Record start of the next string
+    while ((_curchar != '$') && ((_curchar != '%') || (*(_ptr+1) != '}')) ) {
+      // If at the start of a comment, skip past it
+      if( (_curchar == '/') && ((*(_ptr+1) == '/') || (*(_ptr+1) == '*')) ) {
+        skipws_no_preproc();
+      } else {
+        // ELSE advance to the next character, or start of the next line
+        next_char_or_line();
+      }
+    }
+    // If a string was found, terminate it and record in EncClass
+    if (start != _ptr) {
+      *_ptr = '\0';          // Terminate the string
+      encoding->add_code(start);
+    }
+
+    // (2)
+    // If we are at a replacement variable,
+    // copy it and record in EncClass
+    if (_curchar == '$') {
+      // Found replacement Variable
+      char* rep_var = get_rep_var_ident_dup();
+
+      // Add flag to _strings list indicating we should check _rep_vars
+      encoding->add_rep_var(rep_var);
+
+      skipws();
+
+      // Check if this instruct is a MachConstantNode.
+      if (strcmp(rep_var, "constanttablebase") == 0) {
+        // This instruct is a MachConstantNode.
+        inst.set_is_mach_constant(true);
+
+        if (_curchar == '(')  {
+          parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument (only constantaddress and constantoffset)", ec_name);
+          return;
+        }
+      }
+      else if ((strcmp(rep_var, "constantaddress")   == 0) ||
+               (strcmp(rep_var, "constantoffset")    == 0)) {
+        // This instruct is a MachConstantNode.
+        inst.set_is_mach_constant(true);
+
+        // If the constant keyword has an argument, parse it.
+        if (_curchar == '(')  constant_parse(inst);
+      }
+    }
+  } // end while part of format description
+  next_char();                      // Skip '%'
+  next_char();                      // Skip '}'
+
+  skipws();
+
+  if (_AD._adlocation_debug) {
+    encoding->add_code(end_line_marker());
+  }
+
+  // Debug Stuff
+  if (_AD._adl_debug > 1)  fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
 }
 
 
@@ -2838,7 +2913,7 @@
 //
 //  making it more compact to take advantage of the MacroAssembler and
 //  placing the assembly closer to it's use by instructions.
-InsEncode *ADLParser::ins_encode_parse(InstructForm &inst) {
+void ADLParser::ins_encode_parse(InstructForm& inst) {
 
   // Parse encode class name
   skipws();                        // Skip whitespace
@@ -2849,11 +2924,12 @@
       next_char();                      // Skip '{'
 
       // Parse the block form of ins_encode
-      return ins_encode_parse_block(inst);
+      ins_encode_parse_block(inst);
+      return;
     }
 
     parse_err(SYNERR, "missing '%%{' or '(' in ins_encode definition\n");
-    return NULL;
+    return;
   }
   next_char();                     // move past '('
   skipws();
@@ -2866,7 +2942,7 @@
     ec_name = get_ident();
     if (ec_name == NULL) {
       parse_err(SYNERR, "Invalid encode class name after 'ins_encode('.\n");
-      return NULL;
+      return;
     }
     // Check that encoding is defined in the encode section
     EncClass *encode_class = _AD._encode->encClass(ec_name);
@@ -2898,7 +2974,7 @@
                (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
                ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
             parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
-            return NULL;
+            return;
           }
           params->add_entry(param);
 
@@ -2915,7 +2991,7 @@
             // Only ',' or ')' are valid after a parameter name
             parse_err(SYNERR, "expected ',' or ')' after parameter %s.\n",
                       ec_name);
-            return NULL;
+            return;
           }
 
         } else {
@@ -2923,11 +2999,11 @@
           // Did not find a parameter
           if (_curchar == ',') {
             parse_err(SYNERR, "Expected encode parameter before ',' in encoding %s.\n", ec_name);
-            return NULL;
+            return;
           }
           if (_curchar != ')') {
             parse_err(SYNERR, "Expected ')' after encode parameters.\n");
-            return NULL;
+            return;
           }
         }
       } // WHILE loop collecting parameters
@@ -2944,7 +3020,7 @@
     else if ( _curchar != ')' ) {
       // If not a ',' then only a ')' is allowed
       parse_err(SYNERR, "Expected ')' after encoding %s.\n", ec_name);
-      return NULL;
+      return;
     }
 
     // Check for ',' separating parameters
@@ -2956,14 +3032,14 @@
   } // done parsing ins_encode methods and their parameters
   if (_curchar != ')') {
     parse_err(SYNERR, "Missing ')' at end of ins_encode description.\n");
-    return NULL;
+    return;
   }
   next_char();                     // move past ')'
   skipws();                        // Skip leading whitespace
 
   if ( _curchar != ';' ) {
     parse_err(SYNERR, "Missing ';' at end of ins_encode.\n");
-    return NULL;
+    return;
   }
   next_char();                     // move past ';'
   skipws();                        // be friendly to oper_parse()
@@ -2971,7 +3047,113 @@
   // Debug Stuff
   if (_AD._adl_debug > 1) fprintf(stderr,"Instruction Encode: %s\n", ec_name);
 
-  return encrule;
+  // Set encode class of this instruction.
+  inst._insencode = encrule;
+}
+
+
+//------------------------------constant_parse---------------------------------
+// Parse a constant expression.
+void ADLParser::constant_parse(InstructForm& inst) {
+  // Create a new encoding name based on the name of the instruction
+  // definition, which should be unique.
+  const char* prefix = "__constant_";
+  char* ec_name = (char*) malloc(strlen(inst._ident) + strlen(prefix) + 1);
+  sprintf(ec_name, "%s%s", prefix, inst._ident);
+
+  assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist");
+  EncClass* encoding = _AD._encode->add_EncClass(ec_name);
+  encoding->_linenum = linenum();
+
+  // synthesize the arguments list for the enc_class from the
+  // arguments to the instruct definition.
+  const char* param = NULL;
+  inst._parameters.reset();
+  while ((param = inst._parameters.iter()) != NULL) {
+    OperandForm* opForm = (OperandForm*) inst._localNames[param];
+    encoding->add_parameter(opForm->_ident, param);
+  }
+
+  // Parse the following ( ) expression.
+  constant_parse_expression(encoding, ec_name);
+
+  // Build an encoding rule which invokes the encoding rule we just
+  // created, passing all arguments that we received.
+  InsEncode*   encrule = new InsEncode(); // Encode class for instruction
+  NameAndList* params  = encrule->add_encode(ec_name);
+  inst._parameters.reset();
+  while ((param = inst._parameters.iter()) != NULL) {
+    params->add_entry(param);
+  }
+
+  // Set encode class of this instruction.
+  inst._constant = encrule;
+}
+
+
+//------------------------------constant_parse_expression----------------------
+void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
+  skipws();
+
+  // Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
+  if (_AD._adlocation_debug) {
+    encoding->add_code(get_line_string());
+  }
+
+  // Start code line.
+  encoding->add_code("    _constant = C->constant_table().add");
+
+  // Parse everything in ( ) expression.
+  encoding->add_code("(");
+  next_char();  // Skip '('
+  int parens_depth = 1;
+
+  // Collect the parts of the constant expression.
+  // (1) strings that are passed through to output
+  // (2) replacement/substitution variable, preceeded by a '$'
+  while (parens_depth > 0) {
+    if (_curchar == '(') {
+      parens_depth++;
+      encoding->add_code("(");
+      next_char();
+    }
+    else if (_curchar == ')') {
+      parens_depth--;
+      encoding->add_code(")");
+      next_char();
+    }
+    else {
+      // (1)
+      // Check if there is a string to pass through to output
+      char *start = _ptr;  // Record start of the next string
+      while ((_curchar != '$') && (_curchar != '(') && (_curchar != ')')) {
+        next_char();
+      }
+      // If a string was found, terminate it and record in EncClass
+      if (start != _ptr) {
+        *_ptr = '\0';  // Terminate the string
+        encoding->add_code(start);
+      }
+
+      // (2)
+      // If we are at a replacement variable, copy it and record in EncClass.
+      if (_curchar == '$') {
+        // Found replacement Variable
+        char* rep_var = get_rep_var_ident_dup();
+        encoding->add_rep_var(rep_var);
+      }
+    }
+  }
+
+  // Finish code line.
+  encoding->add_code(";");
+
+  if (_AD._adlocation_debug) {
+    encoding->add_code(end_line_marker());
+  }
+
+  // Debug Stuff
+  if (_AD._adl_debug > 1)  fprintf(stderr, "EncodingClass Form: %s\n", ec_name);
 }
 
 
--- a/src/share/vm/adlc/adlparse.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/adlc/adlparse.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -156,8 +156,13 @@
 
   Attribute     *attr_parse(char *ident);// Parse instr/operand attribute rule
   // Parse instruction encode rule
-  InsEncode     *ins_encode_parse(InstructForm &inst);
-  InsEncode     *ins_encode_parse_block(InstructForm &inst);
+  void           ins_encode_parse(InstructForm &inst);
+  void           ins_encode_parse_block(InstructForm &inst);
+  void           ins_encode_parse_block_impl(InstructForm& inst, EncClass* encoding, char* ec_name);
+
+  void           constant_parse(InstructForm& inst);
+  void           constant_parse_expression(EncClass* encoding, char* ec_name);
+
   Opcode        *opcode_parse(InstructForm *insr); // Parse instruction opcode
   char          *size_parse(InstructForm *insr); // Parse instruction size
   Interface     *interface_parse();      // Parse operand interface rule
--- a/src/share/vm/adlc/archDesc.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/adlc/archDesc.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -126,7 +126,6 @@
   void chain_rule(FILE *fp, const char *indent, const char *ideal,
                   const Expr *icost, const char *irule,
                   Dict &operands_chained_from, ProductionState &status);
-  void chain_rule_c(FILE *fp, char *indent, char *ideal, char *irule);  // %%%%% TODO: remove this
   void expand_opclass(FILE *fp, const char *indent, const Expr *cost,
                       const char *result_type, ProductionState &status);
   Expr *calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status);
@@ -301,13 +300,18 @@
   void buildMachNodeGenerator(FILE *fp_cpp);
 
   // Generator for Expand methods for instructions with expand rules
-  void defineExpand(FILE *fp, InstructForm *node);
+  void defineExpand      (FILE *fp, InstructForm *node);
   // Generator for Peephole methods for instructions with peephole rules
-  void definePeephole(FILE *fp, InstructForm *node);
+  void definePeephole    (FILE *fp, InstructForm *node);
   // Generator for Size methods for instructions
-  void defineSize(FILE *fp, InstructForm &node);
+  void defineSize        (FILE *fp, InstructForm &node);
+
+public:
+  // Generator for EvalConstantValue methods for instructions
+  void defineEvalConstant(FILE *fp, InstructForm &node);
   // Generator for Emit methods for instructions
-  void defineEmit(FILE *fp, InstructForm &node);
+  void defineEmit        (FILE *fp, InstructForm &node);
+
   // Define a MachOper encode method
   void define_oper_interface(FILE *fp, OperandForm &oper, FormDict &globals,
                              const char *name, const char *encoding);
--- a/src/share/vm/adlc/formssel.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/adlc/formssel.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -30,11 +30,14 @@
 InstructForm::InstructForm(const char *id, bool ideal_only)
   : _ident(id), _ideal_only(ideal_only),
     _localNames(cmpstr, hashstr, Form::arena),
-    _effects(cmpstr, hashstr, Form::arena) {
+    _effects(cmpstr, hashstr, Form::arena),
+    _is_mach_constant(false)
+{
       _ftype = Form::INS;
 
       _matrule   = NULL;
       _insencode = NULL;
+      _constant  = NULL;
       _opcode    = NULL;
       _size      = NULL;
       _attribs   = NULL;
@@ -58,11 +61,14 @@
 InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule)
   : _ident(id), _ideal_only(false),
     _localNames(instr->_localNames),
-    _effects(instr->_effects) {
+    _effects(instr->_effects),
+    _is_mach_constant(false)
+{
       _ftype = Form::INS;
 
       _matrule   = rule;
       _insencode = instr->_insencode;
+      _constant  = instr->_constant;
       _opcode    = instr->_opcode;
       _size      = instr->_size;
       _attribs   = instr->_attribs;
@@ -1094,6 +1100,9 @@
   else if (is_ideal_nop()) {
     return "MachNopNode";
   }
+  else if (is_mach_constant()) {
+    return "MachConstantNode";
+  }
   else if (captures_bottom_type(globals)) {
     return "MachTypeNode";
   } else {
@@ -1190,6 +1199,21 @@
 //
 // Generate the format call for the replacement variable
 void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {
+  // Handle special constant table variables.
+  if (strcmp(rep_var, "constanttablebase") == 0) {
+    fprintf(fp, "char reg[128];  ra->dump_register(in(mach_constant_base_node_input()), reg);\n");
+    fprintf(fp, "st->print(\"%%s\");\n");
+    return;
+  }
+  if (strcmp(rep_var, "constantoffset") == 0) {
+    fprintf(fp, "st->print(\"#%%d\", constant_offset());\n");
+    return;
+  }
+  if (strcmp(rep_var, "constantaddress") == 0) {
+    fprintf(fp, "st->print(\"constant table base + #%%d\", constant_offset());\n");
+    return;
+  }
+
   // Find replacement variable's type
   const Form *form   = _localNames[rep_var];
   if (form == NULL) {
@@ -1348,6 +1372,7 @@
   fprintf(fp,"\nInstruction: %s\n", (_ident?_ident:""));
   if (_matrule)   _matrule->output(fp);
   if (_insencode) _insencode->output(fp);
+  if (_constant)  _constant->output(fp);
   if (_opcode)    _opcode->output(fp);
   if (_attribs)   _attribs->output(fp);
   if (_predicate) _predicate->output(fp);
--- a/src/share/vm/adlc/formssel.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/adlc/formssel.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -74,15 +74,16 @@
 //------------------------------InstructForm-----------------------------------
 class InstructForm : public Form {
 private:
-  bool          _ideal_only;       // Not a user-defined instruction
+  bool           _ideal_only;       // Not a user-defined instruction
   // Members used for tracking CISC-spilling
-  uint          _cisc_spill_operand;// Which operand may cisc-spill
+  uint           _cisc_spill_operand;// Which operand may cisc-spill
   void           set_cisc_spill_operand(uint op_index) { _cisc_spill_operand = op_index; }
-  bool          _is_cisc_alternate;
+  bool           _is_cisc_alternate;
   InstructForm  *_cisc_spill_alternate;// cisc possible replacement
   const char    *_cisc_reg_mask_name;
   InstructForm  *_short_branch_form;
   bool           _is_short_branch;
+  bool           _is_mach_constant;   // true if Node is a MachConstantNode
   uint           _alignment;
 
 public:
@@ -94,6 +95,7 @@
   Opcode        *_opcode;          // Encoding of the opcode for instruction
   char          *_size;            // Size of instruction
   InsEncode     *_insencode;       // Encoding class instruction belongs to
+  InsEncode     *_constant;        // Encoding class constant value belongs to
   Attribute     *_attribs;         // List of Attribute rules
   Predicate     *_predicate;       // Predicate test for this instruction
   FormDict       _effects;         // Dictionary of effect rules
@@ -251,6 +253,9 @@
   bool                is_short_branch() { return _is_short_branch; }
   void                set_short_branch(bool val) { _is_short_branch = val; }
 
+  bool                    is_mach_constant() const { return _is_mach_constant;     }
+  void                set_is_mach_constant(bool x) {        _is_mach_constant = x; }
+
   InstructForm       *short_branch_form() { return _short_branch_form; }
   bool                has_short_branch_form() { return _short_branch_form != NULL; }
   // Output short branch prototypes and method bodies
--- a/src/share/vm/adlc/output_c.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/adlc/output_c.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -1496,8 +1496,8 @@
   unsigned      i;
 
   // Generate Expand function header
-  fprintf(fp,"MachNode *%sNode::Expand(State *state, Node_List &proj_list, Node* mem) {\n", node->_ident);
-  fprintf(fp,"Compile* C = Compile::current();\n");
+  fprintf(fp, "MachNode* %sNode::Expand(State* state, Node_List& proj_list, Node* mem) {\n", node->_ident);
+  fprintf(fp, "  Compile* C = Compile::current();\n");
   // Generate expand code
   if( node->expands() ) {
     const char   *opid;
@@ -1818,6 +1818,12 @@
     }
   }
 
+  // If the node is a MachConstantNode, insert the MachConstantBaseNode edge.
+  // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input).
+  if (node->is_mach_constant()) {
+    fprintf(fp,"  add_req(C->mach_constant_base_node());\n");
+  }
+
   fprintf(fp,"\n");
   if( node->expands() ) {
     fprintf(fp,"  return result;\n");
@@ -1924,7 +1930,17 @@
         // No state needed.
         assert( _opclass == NULL,
                 "'primary', 'secondary' and 'tertiary' don't follow operand.");
-      } else {
+      }
+      else if ((strcmp(rep_var, "constanttablebase") == 0) ||
+               (strcmp(rep_var, "constantoffset")    == 0) ||
+               (strcmp(rep_var, "constantaddress")   == 0)) {
+        if (!_inst.is_mach_constant()) {
+          _AD.syntax_err(_encoding._linenum,
+                         "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n",
+                         rep_var, _encoding._name);
+        }
+      }
+      else {
         // Lookup its position in parameter list
         int   param_no  = _encoding.rep_var_index(rep_var);
         if ( param_no == -1 ) {
@@ -2380,6 +2396,15 @@
                         rep_var, _inst._ident, _encoding._name);
       }
     }
+    else if (strcmp(rep_var, "constanttablebase") == 0) {
+      fprintf(_fp, "as_Register(ra_->get_encode(in(mach_constant_base_node_input())))");
+    }
+    else if (strcmp(rep_var, "constantoffset") == 0) {
+      fprintf(_fp, "constant_offset()");
+    }
+    else if (strcmp(rep_var, "constantaddress") == 0) {
+      fprintf(_fp, "InternalAddress(__ code()->consts()->start() + constant_offset())");
+    }
     else {
       // Lookup its position in parameter list
       int   param_no  = _encoding.rep_var_index(rep_var);
@@ -2465,37 +2490,39 @@
   fprintf(fp,"}\n");
 }
 
-void ArchDesc::defineEmit(FILE *fp, InstructForm &inst) {
-  InsEncode *ins_encode = inst._insencode;
+// defineEmit -----------------------------------------------------------------
+void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
+  InsEncode* encode = inst._insencode;
 
   // (1)
   // Output instruction's emit prototype
-  fprintf(fp,"void  %sNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {\n",
-          inst._ident);
+  fprintf(fp, "void %sNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {\n", inst._ident);
 
   // If user did not define an encode section,
   // provide stub that does not generate any machine code.
-  if( (_encode == NULL) || (ins_encode == NULL) ) {
+  if( (_encode == NULL) || (encode == NULL) ) {
     fprintf(fp, "  // User did not define an encode section.\n");
-    fprintf(fp,"}\n");
+    fprintf(fp, "}\n");
     return;
   }
 
   // Save current instruction's starting address (helps with relocation).
-  fprintf(fp, "    cbuf.set_insts_mark();\n");
-
-  // // // idx0 is only needed for syntactic purposes and only by "storeSSI"
-  // fprintf( fp, "    unsigned idx0  = 0;\n");
+  fprintf(fp, "  cbuf.set_insts_mark();\n");
+
+  // For MachConstantNodes which are ideal jump nodes, fill the jump table.
+  if (inst.is_mach_constant() && inst.is_ideal_jump()) {
+    fprintf(fp, "  ra_->C->constant_table().fill_jump_table(cbuf, (MachConstantNode*) this, _index2label);\n");
+  }
 
   // Output each operand's offset into the array of registers.
-  inst.index_temps( fp, _globalNames );
+  inst.index_temps(fp, _globalNames);
 
   // Output this instruction's encodings
   const char *ec_name;
   bool        user_defined = false;
-  ins_encode->reset();
-  while ( (ec_name = ins_encode->encode_class_iter()) != NULL ) {
-    fprintf(fp, "  {");
+  encode->reset();
+  while ((ec_name = encode->encode_class_iter()) != NULL) {
+    fprintf(fp, "  {\n");
     // Output user-defined encoding
     user_defined           = true;
 
@@ -2507,25 +2534,25 @@
       abort();
     }
 
-    if (ins_encode->current_encoding_num_args() != encoding->num_args()) {
-      globalAD->syntax_err(ins_encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
-                           inst._ident, ins_encode->current_encoding_num_args(),
+    if (encode->current_encoding_num_args() != encoding->num_args()) {
+      globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+                           inst._ident, encode->current_encoding_num_args(),
                            ec_name, encoding->num_args());
     }
 
-    DefineEmitState  pending(fp, *this, *encoding, *ins_encode, inst );
+    DefineEmitState pending(fp, *this, *encoding, *encode, inst);
     encoding->_code.reset();
     encoding->_rep_vars.reset();
     // Process list of user-defined strings,
     // and occurrences of replacement variables.
     // Replacement Vars are pushed into a list and then output
-    while ( (ec_code = encoding->_code.iter()) != NULL ) {
-      if ( ! encoding->_code.is_signal( ec_code ) ) {
+    while ((ec_code = encoding->_code.iter()) != NULL) {
+      if (!encoding->_code.is_signal(ec_code)) {
         // Emit pending code
         pending.emit();
         pending.clear();
         // Emit this code section
-        fprintf(fp,"%s", ec_code);
+        fprintf(fp, "%s", ec_code);
       } else {
         // A replacement variable or one of its subfields
         // Obtain replacement variable from list
@@ -2536,7 +2563,7 @@
     // Emit pending code
     pending.emit();
     pending.clear();
-    fprintf(fp, "}\n");
+    fprintf(fp, "  }\n");
   } // end while instruction's encodings
 
   // Check if user stated which encoding to user
@@ -2545,7 +2572,86 @@
   }
 
   // (3) and (4)
-  fprintf(fp,"}\n");
+  fprintf(fp, "}\n");
+}
+
+// defineEvalConstant ---------------------------------------------------------
+void ArchDesc::defineEvalConstant(FILE* fp, InstructForm& inst) {
+  InsEncode* encode = inst._constant;
+
+  // (1)
+  // Output instruction's emit prototype
+  fprintf(fp, "void %sNode::eval_constant(Compile* C) {\n", inst._ident);
+
+  // For ideal jump nodes, allocate a jump table.
+  if (inst.is_ideal_jump()) {
+    fprintf(fp, "  _constant = C->constant_table().allocate_jump_table(this);\n");
+  }
+
+  // If user did not define an encode section,
+  // provide stub that does not generate any machine code.
+  if ((_encode == NULL) || (encode == NULL)) {
+    fprintf(fp, "  // User did not define an encode section.\n");
+    fprintf(fp, "}\n");
+    return;
+  }
+
+  // Output this instruction's encodings
+  const char *ec_name;
+  bool        user_defined = false;
+  encode->reset();
+  while ((ec_name = encode->encode_class_iter()) != NULL) {
+    fprintf(fp, "  {\n");
+    // Output user-defined encoding
+    user_defined           = true;
+
+    const char *ec_code    = NULL;
+    const char *ec_rep_var = NULL;
+    EncClass   *encoding   = _encode->encClass(ec_name);
+    if (encoding == NULL) {
+      fprintf(stderr, "User did not define contents of this encode_class: %s\n", ec_name);
+      abort();
+    }
+
+    if (encode->current_encoding_num_args() != encoding->num_args()) {
+      globalAD->syntax_err(encode->_linenum, "In %s: passing %d arguments to %s but expecting %d",
+                           inst._ident, encode->current_encoding_num_args(),
+                           ec_name, encoding->num_args());
+    }
+
+    DefineEmitState pending(fp, *this, *encoding, *encode, inst);
+    encoding->_code.reset();
+    encoding->_rep_vars.reset();
+    // Process list of user-defined strings,
+    // and occurrences of replacement variables.
+    // Replacement Vars are pushed into a list and then output
+    while ((ec_code = encoding->_code.iter()) != NULL) {
+      if (!encoding->_code.is_signal(ec_code)) {
+        // Emit pending code
+        pending.emit();
+        pending.clear();
+        // Emit this code section
+        fprintf(fp, "%s", ec_code);
+      } else {
+        // A replacement variable or one of its subfields
+        // Obtain replacement variable from list
+        ec_rep_var  = encoding->_rep_vars.iter();
+        pending.add_rep_var(ec_rep_var);
+      }
+    }
+    // Emit pending code
+    pending.emit();
+    pending.clear();
+    fprintf(fp, "  }\n");
+  } // end while instruction's encodings
+
+  // Check if user stated which encoding to user
+  if (user_defined == false) {
+    fprintf(fp, "  // User did not define which encode class to use.\n");
+  }
+
+  // (3) and (4)
+  fprintf(fp, "}\n");
 }
 
 // ---------------------------------------------------------------------------
@@ -2952,6 +3058,7 @@
     // If there are multiple defs/kills, or an explicit expand rule, build rule
     if( instr->expands() || instr->needs_projections() ||
         instr->has_temps() ||
+        instr->is_mach_constant() ||
         instr->_matrule != NULL &&
         instr->num_opnds() != instr->num_unique_opnds() )
       defineExpand(_CPP_EXPAND_file._fp, instr);
@@ -3032,8 +3139,9 @@
     // Ensure this is a machine-world instruction
     if ( instr->ideal_only() ) continue;
 
-    if (instr->_insencode) defineEmit(fp, *instr);
-    if (instr->_size)      defineSize(fp, *instr);
+    if (instr->_insencode)         defineEmit        (fp, *instr);
+    if (instr->is_mach_constant()) defineEvalConstant(fp, *instr);
+    if (instr->_size)              defineSize        (fp, *instr);
 
     // side-call to generate output that used to be in the header file:
     extern void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &oper, bool for_c_file);
--- a/src/share/vm/adlc/output_h.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/adlc/output_h.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -1550,7 +1550,12 @@
     }
 
     // virtual functions for encode and format
-    //
+
+    // Virtual function for evaluating the constant.
+    if (instr->is_mach_constant()) {
+      fprintf(fp,"  virtual void           eval_constant(Compile* C);\n");
+    }
+
     // Output the opcode function and the encode function here using the
     // encoding class information in the _insencode slot.
     if ( instr->_insencode ) {
@@ -1559,7 +1564,7 @@
 
     // virtual function for getting the size of an instruction
     if ( instr->_size ) {
-       fprintf(fp,"  virtual uint           size(PhaseRegAlloc *ra_) const;\n");
+      fprintf(fp,"  virtual uint           size(PhaseRegAlloc *ra_) const;\n");
     }
 
     // Return the top-level ideal opcode.
@@ -1752,6 +1757,7 @@
     // Virtual methods which are only generated to override base class
     if( instr->expands() || instr->needs_projections() ||
         instr->has_temps() ||
+        instr->is_mach_constant() ||
         instr->_matrule != NULL &&
         instr->num_opnds() != instr->num_unique_opnds() ) {
       fprintf(fp,"  virtual MachNode      *Expand(State *state, Node_List &proj_list, Node* mem);\n");
@@ -1780,24 +1786,6 @@
     // Declare short branch methods, if applicable
     instr->declare_short_branch_methods(fp);
 
-    // Instructions containing a constant that will be entered into the
-    // float/double table redefine the base virtual function
-#ifdef SPARC
-    // Sparc doubles entries in the constant table require more space for
-    // alignment. (expires 9/98)
-    int table_entries = (3 * instr->num_consts( _globalNames, Form::idealD ))
-      + instr->num_consts( _globalNames, Form::idealF );
-#else
-    int table_entries = instr->num_consts( _globalNames, Form::idealD )
-      + instr->num_consts( _globalNames, Form::idealF );
-#endif
-    if( table_entries != 0 ) {
-      fprintf(fp,"  virtual int            const_size() const {");
-      fprintf(fp,   " return %d;", table_entries);
-      fprintf(fp, " }\n");
-    }
-
-
     // See if there is an "ins_pipe" declaration for this instruction
     if (instr->_ins_pipe) {
       fprintf(fp,"  static  const Pipeline *pipeline_class();\n");
--- a/src/share/vm/asm/assembler.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/asm/assembler.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -292,7 +292,16 @@
   address    start_a_const(int required_space, int required_align = sizeof(double));
   void       end_a_const();
 
-  // fp constants support
+  // constants support
+  address long_constant(jlong c) {
+    address ptr = start_a_const(sizeof(c), sizeof(c));
+    if (ptr != NULL) {
+      *(jlong*)ptr = c;
+      _code_pos = ptr + sizeof(c);
+      end_a_const();
+    }
+    return ptr;
+  }
   address double_constant(jdouble c) {
     address ptr = start_a_const(sizeof(c), sizeof(c));
     if (ptr != NULL) {
@@ -311,6 +320,15 @@
     }
     return ptr;
   }
+  address address_constant(address c) {
+    address ptr = start_a_const(sizeof(c), sizeof(c));
+    if (ptr != NULL) {
+      *(address*)ptr = c;
+      _code_pos = ptr + sizeof(c);
+      end_a_const();
+    }
+    return ptr;
+  }
   address address_constant(address c, RelocationHolder const& rspec) {
     address ptr = start_a_const(sizeof(c), sizeof(c));
     if (ptr != NULL) {
@@ -321,8 +339,6 @@
     }
     return ptr;
   }
-  inline address address_constant(Label& L);
-  inline address address_table_constant(GrowableArray<Label*> label);
 
   // Bootstrapping aid to cope with delayed determination of constants.
   // Returns a static address which will eventually contain the constant.
--- a/src/share/vm/asm/assembler.inline.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/asm/assembler.inline.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -114,32 +114,4 @@
   bind_loc(CodeBuffer::locator(pos, sect));
 }
 
-address AbstractAssembler::address_constant(Label& L) {
-  address c = NULL;
-  address ptr = start_a_const(sizeof(c), sizeof(c));
-  if (ptr != NULL) {
-    relocate(Relocation::spec_simple(relocInfo::internal_word_type));
-    *(address*)ptr = c = code_section()->target(L, ptr);
-    _code_pos = ptr + sizeof(c);
-    end_a_const();
-  }
-  return ptr;
-}
-
-address AbstractAssembler::address_table_constant(GrowableArray<Label*> labels) {
-  int addressSize = sizeof(address);
-  int sizeLabel = addressSize * labels.length();
-  address ptr = start_a_const(sizeLabel, addressSize);
-
-  if (ptr != NULL) {
-    address *labelLoc = (address*)ptr;
-    for (int i=0; i < labels.length(); i++) {
-      emit_address(code_section()->target(*labels.at(i), (address)&labelLoc[i]));
-      code_section()->relocate((address)&labelLoc[i], relocInfo::internal_word_type);
-    }
-    end_a_const();
-  }
-  return ptr;
-}
-
 #endif // SHARE_VM_ASM_ASSEMBLER_INLINE_HPP
--- a/src/share/vm/compiler/disassembler.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/compiler/disassembler.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -467,5 +467,18 @@
     env.set_total_ticks(total_bucket_count);
   }
 
+  // Print constant table.
+  if (nm->consts_size() > 0) {
+    nm->print_nmethod_labels(env.output(), nm->consts_begin());
+    int offset = 0;
+    for (address p = nm->consts_begin(); p < nm->consts_end(); p += 4, offset += 4) {
+      if ((offset % 8) == 0) {
+        env.output()->print_cr("  " INTPTR_FORMAT " (offset: %4d): " PTR32_FORMAT "   " PTR64_FORMAT, (intptr_t) p, offset, *((int32_t*) p), *((int64_t*) p));
+      } else {
+        env.output()->print_cr("  " INTPTR_FORMAT " (offset: %4d): " PTR32_FORMAT,                    (intptr_t) p, offset, *((int32_t*) p));
+      }
+    }
+  }
+
   env.decode_instructions(p, end);
 }
--- a/src/share/vm/opto/c2_globals.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/c2_globals.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -284,6 +284,9 @@
   develop(bool, SparcV9RegsHiBitsZero, true,                                \
           "Assume Sparc V9 I&L registers on V8+ systems are zero-extended") \
                                                                             \
+  product(bool, UseRDPCForConstantTableBase, false,                         \
+          "Use Sparc RDPC instruction for the constant table base.")        \
+                                                                            \
   develop(intx, PrintIdealGraphLevel, 0,                                    \
           "Print ideal graph to XML file / network interface. "             \
           "By default attempts to connect to the visualizer on a socket.")  \
--- a/src/share/vm/opto/compile.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/compile.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -75,6 +75,18 @@
 # include "adfiles/ad_zero.hpp"
 #endif
 
+
+// -------------------- Compile::mach_constant_base_node -----------------------
+// Constant table base node singleton.
+MachConstantBaseNode* Compile::mach_constant_base_node() {
+  if (_mach_constant_base_node == NULL) {
+    _mach_constant_base_node = new (C) MachConstantBaseNode();
+    _mach_constant_base_node->add_req(C->root());
+  }
+  return _mach_constant_base_node;
+}
+
+
 /// Support for intrinsics.
 
 // Return the index at which m must be inserted (or already exists).
@@ -432,13 +444,14 @@
 }
 
 
-void Compile::init_scratch_buffer_blob() {
-  if( scratch_buffer_blob() != NULL )  return;
+void Compile::init_scratch_buffer_blob(int const_size) {
+  if (scratch_buffer_blob() != NULL)  return;
 
   // Construct a temporary CodeBuffer to have it construct a BufferBlob
   // Cache this BufferBlob for this compile.
   ResourceMark rm;
-  int size = (MAX_inst_size + MAX_stubs_size + MAX_const_size);
+  _scratch_const_size = const_size;
+  int size = (MAX_inst_size + MAX_stubs_size + _scratch_const_size);
   BufferBlob* blob = BufferBlob::create("Compile::scratch_buffer", size);
   // Record the buffer blob for next time.
   set_scratch_buffer_blob(blob);
@@ -455,9 +468,19 @@
 }
 
 
+void Compile::clear_scratch_buffer_blob() {
+  assert(scratch_buffer_blob(), "no BufferBlob set");
+  set_scratch_buffer_blob(NULL);
+  set_scratch_locs_memory(NULL);
+}
+
+
 //-----------------------scratch_emit_size-------------------------------------
 // Helper function that computes size by emitting code
 uint Compile::scratch_emit_size(const Node* n) {
+  // Start scratch_emit_size section.
+  set_in_scratch_emit_size(true);
+
   // Emit into a trash buffer and count bytes emitted.
   // This is a pretty expensive way to compute a size,
   // but it works well enough if seldom used.
@@ -476,13 +499,20 @@
   address blob_end   = (address)locs_buf;
   assert(blob->content_contains(blob_end), "sanity");
   CodeBuffer buf(blob_begin, blob_end - blob_begin);
-  buf.initialize_consts_size(MAX_const_size);
+  buf.initialize_consts_size(_scratch_const_size);
   buf.initialize_stubs_size(MAX_stubs_size);
   assert(locs_buf != NULL, "sanity");
-  int lsize = MAX_locs_size / 2;
-  buf.insts()->initialize_shared_locs(&locs_buf[0],     lsize);
-  buf.stubs()->initialize_shared_locs(&locs_buf[lsize], lsize);
+  int lsize = MAX_locs_size / 3;
+  buf.consts()->initialize_shared_locs(&locs_buf[lsize * 0], lsize);
+  buf.insts()->initialize_shared_locs( &locs_buf[lsize * 1], lsize);
+  buf.stubs()->initialize_shared_locs( &locs_buf[lsize * 2], lsize);
+
+  // Do the emission.
   n->emit(buf, this->regalloc());
+
+  // End scratch_emit_size section.
+  set_in_scratch_emit_size(false);
+
   return buf.insts_size();
 }
 
@@ -516,10 +546,13 @@
                   _orig_pc_slot(0),
                   _orig_pc_slot_offset_in_bytes(0),
                   _has_method_handle_invokes(false),
+                  _mach_constant_base_node(NULL),
                   _node_bundling_limit(0),
                   _node_bundling_base(NULL),
                   _java_calls(0),
                   _inner_loops(0),
+                  _scratch_const_size(-1),
+                  _in_scratch_emit_size(false),
 #ifndef PRODUCT
                   _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
                   _printer(IdealGraphPrinter::printer()),
@@ -783,6 +816,7 @@
     _failure_reason(NULL),
     _code_buffer("Compile::Fill_buffer"),
     _has_method_handle_invokes(false),
+    _mach_constant_base_node(NULL),
     _node_bundling_limit(0),
     _node_bundling_base(NULL),
     _java_calls(0),
@@ -2862,3 +2896,207 @@
     _log->done("phase nodes='%d'", C->unique());
   }
 }
+
+//=============================================================================
+// Two Constant's are equal when the type and the value are equal.
+bool Compile::Constant::operator==(const Constant& other) {
+  if (type()          != other.type()         )  return false;
+  if (can_be_reused() != other.can_be_reused())  return false;
+  // For floating point values we compare the bit pattern.
+  switch (type()) {
+  case T_FLOAT:   return (_value.i == other._value.i);
+  case T_LONG:
+  case T_DOUBLE:  return (_value.j == other._value.j);
+  case T_OBJECT:
+  case T_ADDRESS: return (_value.l == other._value.l);
+  case T_VOID:    return (_value.l == other._value.l);  // jump-table entries
+  default: ShouldNotReachHere();
+  }
+  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.
+  case T_VOID:
+  case T_ADDRESS:
+  case T_OBJECT:  return sizeof(jobject);
+  }
+
+  ShouldNotReachHere();
+  return -1;
+}
+
+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;
+    }
+  }
+
+  // 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);
+    }
+  }
+}
+
+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;
+      }
+      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()));
+    }
+  }
+}
+
+int Compile::ConstantTable::find_offset(Constant& con) const {
+  int idx = _constants.find(con);
+  assert(idx != -1, "constant must be in constant table");
+  int offset = _constants.at(idx).offset();
+  assert(offset != -1, "constant table not emitted yet?");
+  return offset;
+}
+
+void Compile::ConstantTable::add(Constant& con) {
+  if (con.can_be_reused()) {
+    int idx = _constants.find(con);
+    if (idx != -1 && _constants.at(idx).can_be_reused()) {
+      return;
+    }
+  }
+  (void) _constants.append(con);
+}
+
+Compile::Constant Compile::ConstantTable::add(BasicType type, jvalue value) {
+  Constant con(type, value);
+  add(con);
+  return con;
+}
+
+Compile::Constant Compile::ConstantTable::add(MachOper* oper) {
+  jvalue value;
+  BasicType type = oper->type()->basic_type();
+  switch (type) {
+  case T_LONG:    value.j = oper->constantL(); break;
+  case T_FLOAT:   value.f = oper->constantF(); break;
+  case T_DOUBLE:  value.d = oper->constantD(); break;
+  case T_OBJECT:
+  case T_ADDRESS: value.l = (jobject) oper->constant(); break;
+  default: ShouldNotReachHere();
+  }
+  return add(type, value);
+}
+
+Compile::Constant Compile::ConstantTable::allocate_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);
+  }
+  return con;
+}
+
+void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const {
+  // If called from Compile::scratch_emit_size do nothing.
+  if (Compile::current()->in_scratch_emit_size())  return;
+
+  assert(labels.is_nonempty(), "must be");
+  assert((uint) labels.length() == n->outcnt(), err_msg("must be equal: %d == %d", labels.length(), n->outcnt()));
+
+  // Since MachConstantNode::constant_offset() also contains
+  // table_base_offset() we need to subtract the table_base_offset()
+  // to get the plain offset into the constant table.
+  int offset = n->constant_offset() - table_base_offset();
+
+  MacroAssembler _masm(&cb);
+  address* jump_table_base = (address*) (_masm.code()->consts()->start() + offset);
+
+  for (int i = 0; i < labels.length(); i++) {
+    address* constant_addr = &jump_table_base[i];
+    assert(*constant_addr == (address) n, "all jump-table entries must contain node pointer");
+    *constant_addr = cb.consts()->target(*labels.at(i), (address) constant_addr);
+    cb.consts()->relocate((address) constant_addr, relocInfo::internal_word_type);
+  }
+}
--- a/src/share/vm/opto/compile.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/compile.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -48,7 +48,10 @@
 class InlineTree;
 class Int_Array;
 class Matcher;
+class MachConstantNode;
+class MachConstantBaseNode;
 class MachNode;
+class MachOper;
 class MachSafePointNode;
 class Node;
 class Node_Array;
@@ -139,6 +142,81 @@
     trapHistLength = methodDataOopDesc::_trap_hist_limit
   };
 
+  // Constant entry of the constant table.
+  class Constant {
+  private:
+    BasicType _type;
+    jvalue    _value;
+    int       _offset;         // offset of this constant (in bytes) relative to the constant table base.
+    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) :
+      _type(type),
+      _value(value),
+      _offset(-1),
+      _can_be_reused(can_be_reused)
+    {}
+
+    bool operator==(const Constant& other);
+
+    BasicType type()      const    { return _type; }
+
+    jlong   get_jlong()   const    { return _value.j; }
+    jfloat  get_jfloat()  const    { return _value.f; }
+    jdouble get_jdouble() const    { return _value.d; }
+    jobject get_jobject() const    { return _value.l; }
+
+    int         offset()  const    { return _offset; }
+    void    set_offset(int offset) {        _offset = offset; }
+
+    bool    can_be_reused() const  { return _can_be_reused; }
+  };
+
+  // Constant table.
+  class ConstantTable {
+  private:
+    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.
+
+  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).
+    {}
+
+    int size() const { assert(_size != -1, "size not yet calculated"); 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; }
+
+    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(); }
+
+    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) {
+      jvalue value; value.f = f;
+      return add(T_FLOAT, value);
+    }
+    Constant add(jdouble d) {
+      jvalue value; value.d = d;
+      return add(T_DOUBLE, value);
+    }
+
+    // Jump table
+    Constant allocate_jump_table(MachConstantNode* n);
+    void         fill_jump_table(CodeBuffer& cb, MachConstantNode* n, GrowableArray<Label*> labels) const;
+  };
+
  private:
   // Fixed parameters to this compilation.
   const int             _compile_id;
@@ -212,6 +290,11 @@
   Node*                 _recent_alloc_obj;
   Node*                 _recent_alloc_ctl;
 
+  // Constant table
+  ConstantTable         _constant_table;        // The constant table for this compile.
+  MachConstantBaseNode* _mach_constant_base_node;  // Constant table base node singleton.
+
+
   // Blocked array of debugging and profiling information,
   // tracked per node.
   enum { _log2_node_notes_block_size = 8,
@@ -272,6 +355,8 @@
   static int            _CompiledZap_count;     // counter compared against CompileZap[First/Last]
   BufferBlob*           _scratch_buffer_blob;   // For temporary code buffers.
   relocInfo*            _scratch_locs_memory;   // For temporary code buffers.
+  int                   _scratch_const_size;    // For temporary code buffers.
+  bool                  _in_scratch_emit_size;  // true when in scratch_emit_size.
 
  public:
   // Accessors
@@ -454,6 +539,12 @@
                                                   _recent_alloc_obj = obj;
                                                 }
 
+  // Constant table
+  ConstantTable&   constant_table() { return _constant_table; }
+
+  MachConstantBaseNode*     mach_constant_base_node();
+  bool                  has_mach_constant_base_node() const { return _mach_constant_base_node != NULL; }
+
   // Handy undefined Node
   Node*             top() const                 { return _top; }
 
@@ -605,13 +696,16 @@
   Dependencies*     dependencies()              { return env()->dependencies(); }
   static int        CompiledZap_count()         { return _CompiledZap_count; }
   BufferBlob*       scratch_buffer_blob()       { return _scratch_buffer_blob; }
-  void         init_scratch_buffer_blob();
+  void         init_scratch_buffer_blob(int const_size);
+  void        clear_scratch_buffer_blob();
   void          set_scratch_buffer_blob(BufferBlob* b) { _scratch_buffer_blob = b; }
   relocInfo*        scratch_locs_memory()       { return _scratch_locs_memory; }
   void          set_scratch_locs_memory(relocInfo* b)  { _scratch_locs_memory = b; }
 
   // emit to scratch blob, report resulting size
   uint              scratch_emit_size(const Node* n);
+  void       set_in_scratch_emit_size(bool x)   {        _in_scratch_emit_size = x; }
+  bool           in_scratch_emit_size() const   { return _in_scratch_emit_size;     }
 
   enum ScratchBufferBlob {
     MAX_inst_size       = 1024,
@@ -692,7 +786,7 @@
   void Fill_buffer();
 
   // Determine which variable sized branches can be shortened
-  void Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size, int& const_size);
+  void Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size);
 
   // Compute the size of first NumberOfLoopInstrToAlign instructions
   // at the head of a loop.
--- a/src/share/vm/opto/gcm.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/gcm.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -89,7 +89,7 @@
   assert(in0 != NULL, "Only control-dependent");
   const Node *p = in0->is_block_proj();
   if (p != NULL && p != n) {    // Control from a block projection?
-    assert(!n->pinned() || n->is_SafePointScalarObject(), "only SafePointScalarObject pinned node is expected here");
+    assert(!n->pinned() || n->is_MachConstantBase() || n->is_SafePointScalarObject(), "only pinned MachConstantBase or SafePointScalarObject node is expected here");
     // Find trailing Region
     Block *pb = _bbs[in0->_idx]; // Block-projection already has basic block
     uint j = 0;
--- a/src/share/vm/opto/machnode.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/machnode.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -489,6 +489,20 @@
 }
 #endif
 
+
+//=============================================================================
+int MachConstantNode::constant_offset() {
+  int offset = _constant.offset();
+  // Bind the offset lazily.
+  if (offset == -1) {
+    Compile::ConstantTable& constant_table = Compile::current()->constant_table();
+    offset = constant_table.table_base_offset() + constant_table.find_offset(_constant);
+    _constant.set_offset(offset);
+  }
+  return offset;
+}
+
+
 //=============================================================================
 #ifndef PRODUCT
 void MachNullCheckNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
--- a/src/share/vm/opto/machnode.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/machnode.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -231,9 +231,6 @@
   // Return number of relocatable values contained in this instruction
   virtual int   reloc() const { return 0; }
 
-  // Return number of words used for double constants in this instruction
-  virtual int   const_size() const { return 0; }
-
   // Hash and compare over operands.  Used to do GVN on machine Nodes.
   virtual uint  hash() const;
   virtual uint  cmp( const Node &n ) const;
@@ -348,6 +345,65 @@
 #endif
 };
 
+//------------------------------MachConstantBaseNode--------------------------
+// Machine node that represents the base address of the constant table.
+class MachConstantBaseNode : public MachIdealNode {
+public:
+  static const RegMask& _out_RegMask;  // We need the out_RegMask statically in MachConstantNode::in_RegMask().
+
+public:
+  MachConstantBaseNode() : MachIdealNode() {
+    init_class_id(Class_MachConstantBase);
+  }
+  virtual const class Type* bottom_type() const { return TypeRawPtr::NOTNULL; }
+  virtual uint ideal_reg() const { return Op_RegP; }
+  virtual uint oper_input_base() const { return 1; }
+
+  virtual void emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const;
+  virtual uint size(PhaseRegAlloc* ra_) const;
+  virtual bool pinned() const { return UseRDPCForConstantTableBase; }
+
+  static const RegMask& static_out_RegMask() { return _out_RegMask; }
+  virtual const RegMask& out_RegMask() const { return static_out_RegMask(); }
+
+#ifndef PRODUCT
+  virtual const char* Name() const { return "MachConstantBaseNode"; }
+  virtual void format(PhaseRegAlloc*, outputStream* st) const;
+#endif
+};
+
+//------------------------------MachConstantNode-------------------------------
+// Machine node that holds a constant which is stored in the constant table.
+class MachConstantNode : public MachNode {
+protected:
+  Compile::Constant _constant;  // This node's constant.
+
+public:
+  MachConstantNode() : MachNode() {
+    init_class_id(Class_MachConstant);
+  }
+
+  virtual void eval_constant(Compile* C) {
+#ifdef ASSERT
+    tty->print("missing MachConstantNode eval_constant function: ");
+    dump();
+#endif
+    ShouldNotCallThis();
+  }
+
+  virtual const RegMask &in_RegMask(uint idx) const {
+    if (idx == mach_constant_base_node_input())
+      return MachConstantBaseNode::static_out_RegMask();
+    return MachNode::in_RegMask(idx);
+  }
+
+  // Input edge of MachConstantBaseNode.
+  uint mach_constant_base_node_input() const { return req() - 1; }
+
+  int  constant_offset();
+  int  constant_offset() const { return ((MachConstantNode*) this)->constant_offset(); }
+};
+
 //------------------------------MachUEPNode-----------------------------------
 // Machine Unvalidated Entry Point Node
 class MachUEPNode : public MachIdealNode {
--- a/src/share/vm/opto/matcher.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/matcher.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -365,6 +365,10 @@
   // 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
--- a/src/share/vm/opto/node.hpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/node.hpp	Fri Dec 03 01:34:31 2010 -0800
@@ -81,6 +81,8 @@
 class MachCallNode;
 class MachCallRuntimeNode;
 class MachCallStaticJavaNode;
+class MachConstantBaseNode;
+class MachConstantNode;
 class MachIfNode;
 class MachNode;
 class MachNullCheckNode;
@@ -566,10 +568,12 @@
               DEFINE_CLASS_ID(MachCallDynamicJava,  MachCallJava, 1)
             DEFINE_CLASS_ID(MachCallRuntime,      MachCall, 1)
               DEFINE_CLASS_ID(MachCallLeaf,         MachCallRuntime, 0)
-      DEFINE_CLASS_ID(MachSpillCopy, Mach, 1)
-      DEFINE_CLASS_ID(MachNullCheck, Mach, 2)
-      DEFINE_CLASS_ID(MachIf,        Mach, 3)
-      DEFINE_CLASS_ID(MachTemp,      Mach, 4)
+      DEFINE_CLASS_ID(MachSpillCopy,    Mach, 1)
+      DEFINE_CLASS_ID(MachNullCheck,    Mach, 2)
+      DEFINE_CLASS_ID(MachIf,           Mach, 3)
+      DEFINE_CLASS_ID(MachTemp,         Mach, 4)
+      DEFINE_CLASS_ID(MachConstantBase, Mach, 5)
+      DEFINE_CLASS_ID(MachConstant,     Mach, 6)
 
     DEFINE_CLASS_ID(Proj,  Node, 2)
       DEFINE_CLASS_ID(CatchProj, Proj, 0)
@@ -734,6 +738,8 @@
   DEFINE_CLASS_QUERY(MachCallLeaf)
   DEFINE_CLASS_QUERY(MachCallRuntime)
   DEFINE_CLASS_QUERY(MachCallStaticJava)
+  DEFINE_CLASS_QUERY(MachConstantBase)
+  DEFINE_CLASS_QUERY(MachConstant)
   DEFINE_CLASS_QUERY(MachIf)
   DEFINE_CLASS_QUERY(MachNullCheck)
   DEFINE_CLASS_QUERY(MachReturn)
--- a/src/share/vm/opto/output.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/output.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -61,11 +61,6 @@
   // RootNode goes
   assert( _cfg->_broot->_nodes.size() == 0, "" );
 
-  // Initialize the space for the BufferBlob used to find and verify
-  // instruction size in MachNode::emit_size()
-  init_scratch_buffer_blob();
-  if (failing())  return; // Out of memory
-
   // The number of new nodes (mostly MachNop) is proportional to
   // the number of java calls and inner loops which are aligned.
   if ( C->check_node_count((NodeLimitFudgeFactor + C->java_calls()*3 +
@@ -333,7 +328,7 @@
 //----------------------Shorten_branches---------------------------------------
 // The architecture description provides short branch variants for some long
 // branch instructions. Replace eligible long branches with short branches.
-void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size, int& const_size) {
+void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, int& stub_size) {
 
   // fill in the nop array for bundling computations
   MachNode *_nop_list[Bundle::_nop_count];
@@ -353,12 +348,11 @@
   // Size in bytes of all relocation entries, including those in local stubs.
   // Start with 2-bytes of reloc info for the unvalidated entry point
   reloc_size = 1;          // Number of relocation entries
-  const_size = 0;          // size of fp constants in words
 
   // Make three passes.  The first computes pessimistic blk_starts,
-  // relative jmp_end, reloc_size and const_size information.
-  // The second performs short branch substitution using the pessimistic
-  // sizing. The third inserts nops where needed.
+  // relative jmp_end and reloc_size information.  The second performs
+  // short branch substitution using the pessimistic sizing.  The
+  // third inserts nops where needed.
 
   Node *nj; // tmp
 
@@ -381,7 +375,6 @@
         MachNode *mach = nj->as_Mach();
         blk_size += (mach->alignment_required() - 1) * relocInfo::addr_unit(); // assume worst case padding
         reloc_size += mach->reloc();
-        const_size += mach->const_size();
         if( mach->is_MachCall() ) {
           MachCallNode *mcall = mach->as_MachCall();
           // This destination address is NOT PC-relative
@@ -398,10 +391,6 @@
           if (min_offset_from_last_call == 0) {
             blk_size += nop_size;
           }
-        } else if (mach->ideal_Opcode() == Op_Jump) {
-          const_size += b->_num_succs; // Address table size
-          // The size is valid even for 64 bit since it is
-          // multiplied by 2*jintSize on this method exit.
         }
       }
       min_offset_from_last_call += inst_size;
@@ -562,10 +551,6 @@
   // a relocation index.
   // The CodeBuffer will expand the locs array if this estimate is too low.
   reloc_size   *= 10 / sizeof(relocInfo);
-
-  // Adjust const_size to number of bytes
-  const_size   *= 2*jintSize; // both float and double take two words per entry
-
 }
 
 //------------------------------FillLocArray-----------------------------------
@@ -1102,10 +1087,39 @@
     blk_labels[i].init();
   }
 
+  if (has_mach_constant_base_node()) {
+    // Fill the constant table.
+    // Note:  This must happen before Shorten_branches.
+    for (i = 0; i < _cfg->_num_blocks; i++) {
+      Block* b = _cfg->_blocks[i];
+
+      for (uint j = 0; j < b->_nodes.size(); j++) {
+        Node* n = b->_nodes[j];
+
+        // If the node is a MachConstantNode evaluate the constant
+        // value section.
+        if (n->is_MachConstant()) {
+          MachConstantNode* machcon = n->as_MachConstant();
+          machcon->eval_constant(C);
+        }
+      }
+    }
+
+    // Calculate the offsets of the constants and the size of the
+    // constant table (including the padding to the next section).
+    constant_table().calculate_offsets_and_size();
+    const_req = constant_table().size();
+  }
+
+  // Initialize the space for the BufferBlob used to find and verify
+  // instruction size in MachNode::emit_size()
+  init_scratch_buffer_blob(const_req);
+  if (failing())  return; // Out of memory
+
   // If this machine supports different size branch offsets, then pre-compute
   // the length of the blocks
   if( _matcher->is_short_branch_offset(-1, 0) ) {
-    Shorten_branches(blk_labels, code_req, locs_req, stub_req, const_req);
+    Shorten_branches(blk_labels, code_req, locs_req, stub_req);
     labels_not_set = false;
   }
 
@@ -1121,12 +1135,12 @@
     code_req = const_req = stub_req = exception_handler_req = deopt_handler_req = 0x10;  // force expansion
 
   int total_req =
+    const_req +
     code_req +
     pad_req +
     stub_req +
     exception_handler_req +
-    deopt_handler_req +              // deopt handler
-    const_req;
+    deopt_handler_req;               // deopt handler
 
   if (has_method_handle_invokes())
     total_req += deopt_handler_req;  // deopt MH handler
@@ -1180,6 +1194,11 @@
 
   NonSafepointEmitter non_safepoints(this);  // emit non-safepoints lazily
 
+  // Emit the constant table.
+  if (has_mach_constant_base_node()) {
+    constant_table().emit(*cb);
+  }
+
   // ------------------
   // Now fill in the code buffer
   Node *delay_slot = NULL;
@@ -1196,12 +1215,13 @@
       cb->flush_bundle(true);
 
     // Define the label at the beginning of the basic block
-    if( labels_not_set )
-      MacroAssembler(cb).bind( blk_labels[b->_pre_order] );
-
-    else
-      assert( blk_labels[b->_pre_order].loc_pos() == cb->insts_size(),
-              "label position does not match code offset" );
+    if (labels_not_set) {
+      MacroAssembler(cb).bind(blk_labels[b->_pre_order]);
+    } else {
+      assert(blk_labels[b->_pre_order].loc_pos() == cb->insts_size(),
+             err_msg("label position does not match code offset: %d != %d",
+                     blk_labels[b->_pre_order].loc_pos(), cb->insts_size()));
+    }
 
     uint last_inst = b->_nodes.size();
 
@@ -1718,9 +1738,17 @@
   // Create a data structure for all the scheduling information
   Scheduling scheduling(Thread::current()->resource_area(), *this);
 
+  // Initialize the space for the BufferBlob used to find and verify
+  // instruction size in MachNode::emit_size()
+  init_scratch_buffer_blob(MAX_const_size);
+  if (failing())  return;  // Out of memory
+
   // Walk backwards over each basic block, computing the needed alignment
   // Walk over all the basic blocks
   scheduling.DoScheduling();
+
+  // Clear the BufferBlob used for scheduling.
+  clear_scratch_buffer_blob();
 }
 
 //------------------------------ComputeLocalLatenciesForward-------------------
--- a/src/share/vm/opto/postaloc.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/opto/postaloc.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -200,6 +200,19 @@
   // then reloaded BUT survives in a register the whole way.
   Node *val = skip_copies(n->in(k));
 
+  if (val == x && nk_idx != 0 &&
+      regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
+      n2lidx(x) == n2lidx(regnd[nk_reg])) {
+    // When rematerialzing nodes and stretching lifetimes, the
+    // allocator will reuse the original def for multidef LRG instead
+    // of the current reaching def because it can't know it's safe to
+    // do so.  After allocation completes if they are in the same LRG
+    // then it should use the current reaching def instead.
+    n->set_req(k, regnd[nk_reg]);
+    blk_adjust += yank_if_dead(val, current_block, &value, &regnd);
+    val = skip_copies(n->in(k));
+  }
+
   if( val == x ) return blk_adjust; // No progress?
 
   bool single = is_single_register(val->ideal_reg());
--- a/src/share/vm/utilities/debug.cpp	Thu Dec 02 17:21:12 2010 -0800
+++ b/src/share/vm/utilities/debug.cpp	Fri Dec 03 01:34:31 2010 -0800
@@ -399,8 +399,14 @@
 extern "C" void disnm(intptr_t p) {
   Command c("disnm");
   CodeBlob* cb = CodeCache::find_blob((address) p);
-  cb->print();
-  Disassembler::decode(cb);
+  nmethod* nm = cb->as_nmethod_or_null();
+  if (nm) {
+    nm->print();
+    Disassembler::decode(nm);
+  } else {
+    cb->print();
+    Disassembler::decode(cb);
+  }
 }