6964776: c2 should ensure the polling page is reachable on 64 bit
authoriveresov
Sun, 27 Mar 2011 13:17:37 -0700
changeset 8871 5c3b26c4119e
parent 8870 119881dc9d0b
child 8872 36680c58660e
6964776: c2 should ensure the polling page is reachable on 64 bit Summary: Materialize the pointer to the polling page in a register instead of using rip-relative addressing when the distance from the code cache is larger than disp32. Reviewed-by: never, kvn
hotspot/src/cpu/x86/vm/assembler_x86.cpp
hotspot/src/cpu/x86/vm/assembler_x86.hpp
hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
hotspot/src/cpu/x86/vm/nativeInst_x86.hpp
hotspot/src/cpu/x86/vm/relocInfo_x86.cpp
hotspot/src/cpu/x86/vm/x86_64.ad
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Sun Mar 27 00:00:14 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Sun Mar 27 13:17:37 2011 -0700
@@ -3510,7 +3510,6 @@
   // anywhere in the codeCache then we are always reachable.
   // This would have to change if we ever save/restore shared code
   // to be more pessimistic.
-
   disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int));
   if (!is_simm32(disp)) return false;
   disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int));
@@ -3534,6 +3533,14 @@
   return is_simm32(disp);
 }
 
+// Check if the polling page is not reachable from the code cache using rip-relative
+// addressing.
+bool Assembler::is_polling_page_far() {
+  intptr_t addr = (intptr_t)os::get_polling_page();
+  return !is_simm32(addr - (intptr_t)CodeCache::low_bound()) ||
+         !is_simm32(addr - (intptr_t)CodeCache::high_bound());
+}
+
 void Assembler::emit_data64(jlong data,
                             relocInfo::relocType rtype,
                             int format) {
@@ -6886,6 +6893,11 @@
   }
 }
 
+void MacroAssembler::testl(Register dst, AddressLiteral src) {
+  assert(reachable(src), "Address should be reachable");
+  testl(dst, as_Address(src));
+}
+
 //////////////////////////////////////////////////////////////////////////////////
 #ifndef SERIALGC
 
@@ -7121,17 +7133,6 @@
   LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src));
 }
 
-void MacroAssembler::test32(Register src1, AddressLiteral src2) {
-  // src2 must be rval
-
-  if (reachable(src2)) {
-    testl(src1, as_Address(src2));
-  } else {
-    lea(rscratch1, src2);
-    testl(src1, Address(rscratch1, 0));
-  }
-}
-
 // C++ bool manipulation
 void MacroAssembler::testbool(Register dst) {
   if(sizeof(bool) == 1)
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Sun Mar 27 00:00:14 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Sun Mar 27 13:17:37 2011 -0700
@@ -580,7 +580,6 @@
   void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
   void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);
 
-
   bool reachable(AddressLiteral adr) NOT_LP64({ return true;});
 
   // These are all easily abused and hence protected
@@ -683,6 +682,8 @@
  static bool is_simm32(int32_t x) { return true; }
 #endif // _LP64
 
+  static bool is_polling_page_far() NOT_LP64({ return false;});
+
   // Generic instructions
   // Does 32bit or 64bit as needed for the platform. In some sense these
   // belong in macro assembler but there is no need for both varieties to exist
@@ -2094,7 +2095,10 @@
 
   void leal32(Register dst, Address src) { leal(dst, src); }
 
-  void test32(Register src1, AddressLiteral src2);
+  // Import other testl() methods from the parent class or else
+  // they will be hidden by the following overriding declaration.
+  using Assembler::testl;
+  void testl(Register dst, AddressLiteral src);
 
   void orptr(Register dst, Address src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); }
   void orptr(Register dst, Register src) { LP64_ONLY(orq(dst, src)) NOT_LP64(orl(dst, src)); }
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Sun Mar 27 00:00:14 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Sun Mar 27 13:17:37 2011 -0700
@@ -648,12 +648,13 @@
   AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
                               relocInfo::poll_return_type);
 
-  // NOTE: the requires that the polling page be reachable else the reloc
-  // goes to the movq that loads the address and not the faulting instruction
-  // which breaks the signal handler code
-
-  __ test32(rax, polling_page);
-
+  if (Assembler::is_polling_page_far()) {
+    __ lea(rscratch1, polling_page);
+    __ relocate(relocInfo::poll_return_type);
+    __ testl(rax, Address(rscratch1, 0));
+  } else {
+    __ testl(rax, polling_page);
+  }
   __ ret(0);
 }
 
@@ -661,20 +662,17 @@
 int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
   AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()),
                               relocInfo::poll_type);
-
-  if (info != NULL) {
+  guarantee(info != NULL, "Shouldn't be NULL");
+  int offset = __ offset();
+  if (Assembler::is_polling_page_far()) {
+    __ lea(rscratch1, polling_page);
+    offset = __ offset();
     add_debug_info_for_branch(info);
+    __ testl(rax, Address(rscratch1, 0));
   } else {
-    ShouldNotReachHere();
+    add_debug_info_for_branch(info);
+    __ testl(rax, polling_page);
   }
-
-  int offset = __ offset();
-
-  // NOTE: the requires that the polling page be reachable else the reloc
-  // goes to the movq that loads the address and not the faulting instruction
-  // which breaks the signal handler code
-
-  __ test32(rax, polling_page);
   return offset;
 }
 
--- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp	Sun Mar 27 00:00:14 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp	Sun Mar 27 13:17:37 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -519,7 +519,11 @@
 class NativeTstRegMem: public NativeInstruction {
  public:
   enum Intel_specific_constants {
-    instruction_code_memXregl   = 0x85
+    instruction_rex_prefix_mask = 0xF0,
+    instruction_rex_prefix      = Assembler::REX,
+    instruction_code_memXregl   = 0x85,
+    modrm_mask                  = 0x38, // select reg from the ModRM byte
+    modrm_reg                   = 0x00  // rax
   };
 };
 
@@ -533,12 +537,25 @@
                                                           (ubyte_at(0) & 0xF0) == 0x70;  /* short jump */ }
 inline bool NativeInstruction::is_safepoint_poll() {
 #ifdef AMD64
-  if ( ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
-       ubyte_at(1) == 0x05 ) { // 00 rax 101
-     address fault = addr_at(6) + int_at(2);
-     return os::is_poll_address(fault);
+  if (Assembler::is_polling_page_far()) {
+    // two cases, depending on the choice of the base register in the address.
+    if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
+         ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
+         (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
+        ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+        (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
+      return true;
+    } else {
+      return false;
+    }
   } else {
-    return false;
+    if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+        ubyte_at(1) == 0x05) { // 00 rax 101
+      address fault = addr_at(6) + int_at(2);
+      return os::is_poll_address(fault);
+    } else {
+      return false;
+    }
   }
 #else
   return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
--- a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp	Sun Mar 27 00:00:14 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp	Sun Mar 27 13:17:37 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -198,41 +198,44 @@
 
 void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
 #ifdef _LP64
-  typedef Assembler::WhichOperand WhichOperand;
-  WhichOperand which = (WhichOperand) format();
-  // This format is imm but it is really disp32
-  which = Assembler::disp32_operand;
-  address orig_addr = old_addr_for(addr(), src, dest);
-  NativeInstruction* oni = nativeInstruction_at(orig_addr);
-  int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
-  // This poll_addr is incorrect by the size of the instruction it is irrelevant
-  intptr_t poll_addr = (intptr_t)oni + *orig_disp;
+  if (!Assembler::is_polling_page_far()) {
+    typedef Assembler::WhichOperand WhichOperand;
+    WhichOperand which = (WhichOperand) format();
+    // This format is imm but it is really disp32
+    which = Assembler::disp32_operand;
+    address orig_addr = old_addr_for(addr(), src, dest);
+    NativeInstruction* oni = nativeInstruction_at(orig_addr);
+    int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
+    // This poll_addr is incorrect by the size of the instruction it is irrelevant
+    intptr_t poll_addr = (intptr_t)oni + *orig_disp;
 
-  NativeInstruction* ni = nativeInstruction_at(addr());
-  intptr_t new_disp = poll_addr - (intptr_t) ni;
+    NativeInstruction* ni = nativeInstruction_at(addr());
+    intptr_t new_disp = poll_addr - (intptr_t) ni;
 
-  int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
-  * disp = (int32_t)new_disp;
-
+    int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
+    * disp = (int32_t)new_disp;
+  }
 #endif // _LP64
 }
 
 void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
 #ifdef _LP64
-  typedef Assembler::WhichOperand WhichOperand;
-  WhichOperand which = (WhichOperand) format();
-  // This format is imm but it is really disp32
-  which = Assembler::disp32_operand;
-  address orig_addr = old_addr_for(addr(), src, dest);
-  NativeInstruction* oni = nativeInstruction_at(orig_addr);
-  int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
-  // This poll_addr is incorrect by the size of the instruction it is irrelevant
-  intptr_t poll_addr = (intptr_t)oni + *orig_disp;
+  if (!Assembler::is_polling_page_far()) {
+    typedef Assembler::WhichOperand WhichOperand;
+    WhichOperand which = (WhichOperand) format();
+    // This format is imm but it is really disp32
+    which = Assembler::disp32_operand;
+    address orig_addr = old_addr_for(addr(), src, dest);
+    NativeInstruction* oni = nativeInstruction_at(orig_addr);
+    int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
+    // This poll_addr is incorrect by the size of the instruction it is irrelevant
+    intptr_t poll_addr = (intptr_t)oni + *orig_disp;
 
-  NativeInstruction* ni = nativeInstruction_at(addr());
-  intptr_t new_disp = poll_addr - (intptr_t) ni;
+    NativeInstruction* ni = nativeInstruction_at(addr());
+    intptr_t new_disp = poll_addr - (intptr_t) ni;
 
-  int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
-  * disp = (int32_t)new_disp;
+    int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
+    * disp = (int32_t)new_disp;
+  }
 #endif // _LP64
 }
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Sun Mar 27 00:00:14 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Sun Mar 27 13:17:37 2011 -0700
@@ -574,12 +574,11 @@
 // In os_cpu .ad file
 // int MachCallRuntimeNode::ret_addr_offset()
 
-// Indicate if the safepoint node needs the polling page as an input.
-// Since amd64 does not have absolute addressing but RIP-relative
-// addressing and the polling page is within 2G, it doesn't.
+// Indicate if the safepoint node needs the polling page as an input,
+// it does if the polling page is more than disp32 away.
 bool SafePointNode::needs_polling_address_input()
 {
-  return false;
+  return Assembler::is_polling_page_far();
 }
 
 //
@@ -992,15 +991,21 @@
   framesize -= 2*wordSize;
 
   if (framesize) {
-    st->print_cr("addq\trsp, %d\t# Destroy frame", framesize);
+    st->print_cr("addq    rsp, %d\t# Destroy frame", framesize);
     st->print("\t");
   }
 
-  st->print_cr("popq\trbp");
+  st->print_cr("popq   rbp");
   if (do_polling() && C->is_method_compilation()) {
-    st->print_cr("\ttestl\trax, [rip + #offset_to_poll_page]\t"
-                  "# Safepoint: poll for GC");
     st->print("\t");
+    if (Assembler::is_polling_page_far()) {
+      st->print_cr("movq   rscratch1, #polling_page_address\n\t"
+                   "testl  rax, [rscratch1]\t"
+                   "# Safepoint: poll for GC");
+    } else {
+      st->print_cr("testl  rax, [rip + #offset_to_poll_page]\t"
+                   "# Safepoint: poll for GC");
+    }
   }
 }
 #endif
@@ -1033,45 +1038,22 @@
   emit_opcode(cbuf, 0x58 | RBP_enc);
 
   if (do_polling() && C->is_method_compilation()) {
-    // testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes
-    // XXX reg_mem doesn't support RIP-relative addressing yet
-    cbuf.set_insts_mark();
-    cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_return_type, 0); // XXX
-    emit_opcode(cbuf, 0x85); // testl
-    emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5
-    // cbuf.insts_mark() is beginning of instruction
-    emit_d32_reloc(cbuf, os::get_polling_page());
-//                    relocInfo::poll_return_type,
+    MacroAssembler _masm(&cbuf);
+    AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type);
+    if (Assembler::is_polling_page_far()) {
+      __ lea(rscratch1, polling_page);
+      __ relocate(relocInfo::poll_return_type);
+      __ testl(rax, Address(rscratch1, 0));
+    } else {
+      __ testl(rax, polling_page);
+    }
   }
 }
 
 uint MachEpilogNode::size(PhaseRegAlloc* ra_) const
 {
-  Compile* C = ra_->C;
-  int framesize = C->frame_slots() << LogBytesPerInt;
-  assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned");
-  // Remove word for return adr already pushed
-  // and RBP
-  framesize -= 2*wordSize;
-
-  uint size = 0;
-
-  if (do_polling() && C->is_method_compilation()) {
-    size += 6;
-  }
-
-  // count popq rbp
-  size++;
-
-  if (framesize) {
-    if (framesize < 0x80) {
-      size += 4;
-    } else if (framesize) {
-      size += 7;
-    }
-  }
-
-  return size;
+  return MachNode::size(ra_); // too many variables; just compute it
+                              // the hard way
 }
 
 int MachEpilogNode::reloc() const
@@ -3410,8 +3392,8 @@
     }
     if (EmitSync & 1) {
         // Without cast to int32_t a movptr will destroy r10 which is typically obj
-        masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; 
-        masm.cmpptr(rsp, (int32_t)NULL_WORD) ; 
+        masm.movptr (Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
+        masm.cmpptr(rsp, (int32_t)NULL_WORD) ;
     } else
     if (EmitSync & 2) {
         Label DONE_LABEL;
@@ -3439,10 +3421,10 @@
     } else {
         Label DONE_LABEL, IsInflated, Egress;
 
-        masm.movptr(tmpReg, Address(objReg, 0)) ; 
+        masm.movptr(tmpReg, Address(objReg, 0)) ;
         masm.testl (tmpReg, 0x02) ;         // inflated vs stack-locked|neutral|biased
-        masm.jcc   (Assembler::notZero, IsInflated) ; 
-         
+        masm.jcc   (Assembler::notZero, IsInflated) ;
+
         // it's stack-locked, biased or neutral
         // TODO: optimize markword triage order to reduce the number of
         // conditional branches in the most common cases.
@@ -3456,9 +3438,9 @@
         }
 
         // was q will it destroy high?
-        masm.orl   (tmpReg, 1) ; 
-        masm.movptr(Address(boxReg, 0), tmpReg) ;  
-        if (os::is_MP()) { masm.lock(); } 
+        masm.orl   (tmpReg, 1) ;
+        masm.movptr(Address(boxReg, 0), tmpReg) ;
+        if (os::is_MP()) { masm.lock(); }
         masm.cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg
         if (_counters != NULL) {
            masm.cond_inc32(Assembler::equal,
@@ -3485,16 +3467,16 @@
         // fetched _owner.  If the CAS is successful we may
         // avoid an RTO->RTS upgrade on the $line.
         // Without cast to int32_t a movptr will destroy r10 which is typically obj
-        masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ; 
-
-        masm.mov    (boxReg, tmpReg) ; 
-        masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; 
-        masm.testptr(tmpReg, tmpReg) ;   
-        masm.jcc    (Assembler::notZero, DONE_LABEL) ; 
+        masm.movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())) ;
+
+        masm.mov    (boxReg, tmpReg) ;
+        masm.movptr (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
+        masm.testptr(tmpReg, tmpReg) ;
+        masm.jcc    (Assembler::notZero, DONE_LABEL) ;
 
         // It's inflated and appears unlocked
-        if (os::is_MP()) { masm.lock(); } 
-        masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; 
+        if (os::is_MP()) { masm.lock(); }
+        masm.cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
         // Intentional fall-through into DONE_LABEL ...
 
         masm.bind  (DONE_LABEL) ;
@@ -3513,8 +3495,8 @@
     Register tmpReg = as_Register($tmp$$reg);
     MacroAssembler masm(&cbuf);
 
-    if (EmitSync & 4) { 
-       masm.cmpptr(rsp, 0) ; 
+    if (EmitSync & 4) {
+       masm.cmpptr(rsp, 0) ;
     } else
     if (EmitSync & 8) {
        Label DONE_LABEL;
@@ -3541,25 +3523,25 @@
        if (UseBiasedLocking && !UseOptoBiasInlining) {
          masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL);
        }
-        
-       masm.movptr(tmpReg, Address(objReg, 0)) ; 
-       masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ; 
-       masm.jcc   (Assembler::zero, DONE_LABEL) ; 
-       masm.testl (tmpReg, 0x02) ; 
-       masm.jcc   (Assembler::zero, Stacked) ; 
-        
+
+       masm.movptr(tmpReg, Address(objReg, 0)) ;
+       masm.cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD) ;
+       masm.jcc   (Assembler::zero, DONE_LABEL) ;
+       masm.testl (tmpReg, 0x02) ;
+       masm.jcc   (Assembler::zero, Stacked) ;
+
        // It's inflated
-       masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; 
-       masm.xorptr(boxReg, r15_thread) ; 
-       masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ; 
-       masm.jcc   (Assembler::notZero, DONE_LABEL) ; 
-       masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; 
-       masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; 
-       masm.jcc   (Assembler::notZero, CheckSucc) ; 
-       masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ; 
-       masm.jmp   (DONE_LABEL) ; 
-        
-       if ((EmitSync & 65536) == 0) { 
+       masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ;
+       masm.xorptr(boxReg, r15_thread) ;
+       masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::recursions_offset_in_bytes()-2)) ;
+       masm.jcc   (Assembler::notZero, DONE_LABEL) ;
+       masm.movptr(boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ;
+       masm.orptr (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ;
+       masm.jcc   (Assembler::notZero, CheckSucc) ;
+       masm.movptr(Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
+       masm.jmp   (DONE_LABEL) ;
+
+       if ((EmitSync & 65536) == 0) {
          Label LSuccess, LGoSlowPath ;
          masm.bind  (CheckSucc) ;
          masm.cmpptr(Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int32_t)NULL_WORD) ;
@@ -3591,9 +3573,9 @@
          masm.jmp   (DONE_LABEL) ;
        }
 
-       masm.bind  (Stacked) ; 
+       masm.bind  (Stacked) ;
        masm.movptr(tmpReg, Address (boxReg, 0)) ;      // re-fetch
-       if (os::is_MP()) { masm.lock(); } 
+       if (os::is_MP()) { masm.lock(); }
        masm.cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box
 
        if (EmitSync & 65536) {
@@ -3914,22 +3896,6 @@
 
     // done:
   %}
-
-  // Safepoint Poll.  This polls the safepoint page, and causes an
-  // exception if it is not readable. Unfortunately, it kills
-  // RFLAGS in the process.
-  enc_class enc_safepoint_poll
-  %{
-    // testl %rax, off(%rip) // Opcode + ModRM + Disp32 == 6 bytes
-    // XXX reg_mem doesn't support RIP-relative addressing yet
-    cbuf.set_insts_mark();
-    cbuf.relocate(cbuf.insts_mark(), relocInfo::poll_type, 0); // XXX
-    emit_opcode(cbuf, 0x85); // testl
-    emit_rm(cbuf, 0x0, RAX_enc, 0x5); // 00 rax 101 == 0x5
-    // cbuf.insts_mark() is beginning of instruction
-    emit_d32_reloc(cbuf, os::get_polling_page());
-//                    relocInfo::poll_type,
-  %}
 %}
 
 
@@ -4233,6 +4199,15 @@
   interface(CONST_INTER);
 %}
 
+operand immP_poll() %{
+  predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
+  match(ConP);
+
+  // formats are generated automatically for constants and base registers
+  format %{ %}
+  interface(CONST_INTER);
+%}
+
 // Pointer Immediate
 operand immN() %{
   match(ConN);
@@ -4840,7 +4815,7 @@
 %}
 
 // Double register operands
-operand regD() 
+operand regD()
 %{
   constraint(ALLOC_IN_RC(double_reg));
   match(RegD);
@@ -6568,6 +6543,16 @@
   ins_pipe(ialu_reg);
 %}
 
+instruct loadConP_poll(rRegP dst, immP_poll src) %{
+  match(Set dst src);
+  format %{ "movq    $dst, $src\t!ptr" %}
+  ins_encode %{
+    AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type);
+    __ lea($dst$$Register, polling_page);
+  %}
+  ins_pipe(ialu_reg_fat);
+%}
+
 instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
 %{
   match(Set dst src);
@@ -7241,11 +7226,11 @@
 instruct bytes_reverse_unsigned_short(rRegI dst) %{
   match(Set dst (ReverseBytesUS dst));
 
-  format %{ "bswapl  $dst\n\t" 
+  format %{ "bswapl  $dst\n\t"
             "shrl    $dst,16\n\t" %}
   ins_encode %{
     __ bswapl($dst$$Register);
-    __ shrl($dst$$Register, 16); 
+    __ shrl($dst$$Register, 16);
   %}
   ins_pipe( ialu_reg );
 %}
@@ -7253,11 +7238,11 @@
 instruct bytes_reverse_short(rRegI dst) %{
   match(Set dst (ReverseBytesS dst));
 
-  format %{ "bswapl  $dst\n\t" 
+  format %{ "bswapl  $dst\n\t"
             "sar     $dst,16\n\t" %}
   ins_encode %{
     __ bswapl($dst$$Register);
-    __ sarl($dst$$Register, 16); 
+    __ sarl($dst$$Register, 16);
   %}
   ins_pipe( ialu_reg );
 %}
@@ -7480,7 +7465,7 @@
   effect(KILL cr);
   ins_cost(400);
 
-  format %{ 
+  format %{
     $$template
     if (os::is_MP()) {
       $$emit$$"lock addl [rsp + #0], 0\t! membar_volatile"
@@ -8291,7 +8276,7 @@
                            rFlagsReg cr)
 %{
   match(Set cr (StorePConditional heap_top_ptr (Binary oldval newval)));
- 
+
   format %{ "cmpxchgq $heap_top_ptr, $newval\t# (ptr) "
             "If rax == $heap_top_ptr then store $newval into $heap_top_ptr" %}
   opcode(0x0F, 0xB1);
@@ -9854,9 +9839,9 @@
 
 // Xor Register with Immediate -1
 instruct xorI_rReg_im1(rRegI dst, immI_M1 imm) %{
-  match(Set dst (XorI dst imm));  
-
-  format %{ "not    $dst" %}  
+  match(Set dst (XorI dst imm));
+
+  format %{ "not    $dst" %}
   ins_encode %{
      __ notl($dst$$Register);
   %}
@@ -10097,9 +10082,9 @@
 
 // Xor Register with Immediate -1
 instruct xorL_rReg_im1(rRegL dst, immL_M1 imm) %{
-  match(Set dst (XorL dst imm));  
-
-  format %{ "notq   $dst" %}  
+  match(Set dst (XorL dst imm));
+
+  format %{ "notq   $dst" %}
   ins_encode %{
      __ notq($dst$$Register);
   %}
@@ -12473,14 +12458,33 @@
 // Safepoint Instructions
 instruct safePoint_poll(rFlagsReg cr)
 %{
+  predicate(!Assembler::is_polling_page_far());
   match(SafePoint);
   effect(KILL cr);
 
-  format %{ "testl   rax, [rip + #offset_to_poll_page]\t"
+  format %{ "testl  rax, [rip + #offset_to_poll_page]\t"
             "# Safepoint: poll for GC" %}
-  size(6); // Opcode + ModRM + Disp32 == 6 bytes
   ins_cost(125);
-  ins_encode(enc_safepoint_poll);
+  ins_encode %{
+    AddressLiteral addr(os::get_polling_page(), relocInfo::poll_type);
+    __ testl(rax, addr);
+  %}
+  ins_pipe(ialu_reg_mem);
+%}
+
+instruct safePoint_poll_far(rFlagsReg cr, rRegP poll)
+%{
+  predicate(Assembler::is_polling_page_far());
+  match(SafePoint poll);
+  effect(KILL cr, USE poll);
+
+  format %{ "testl  rax, [$poll]\t"
+            "# Safepoint: poll for GC" %}
+  ins_cost(125);
+  ins_encode %{
+    __ relocate(relocInfo::poll_type);
+    __ testl(rax, Address($poll$$Register, 0));
+  %}
   ins_pipe(ialu_reg_mem);
 %}