src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2447
5577848f5923
child 2708
1d1603768966
child 2746
d86923d96dca
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

     1 /*
     2  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "c1/c1_MacroAssembler.hpp"
    27 #include "c1/c1_Runtime1.hpp"
    28 #include "classfile/systemDictionary.hpp"
    29 #include "gc_interface/collectedHeap.hpp"
    30 #include "interpreter/interpreter.hpp"
    31 #include "oops/arrayOop.hpp"
    32 #include "oops/markOop.hpp"
    33 #include "runtime/basicLock.hpp"
    34 #include "runtime/biasedLocking.hpp"
    35 #include "runtime/os.hpp"
    36 #include "runtime/stubRoutines.hpp"
    38 void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
    39   Label L;
    40   const Register temp_reg = G3_scratch;
    41   // Note: needs more testing of out-of-line vs. inline slow case
    42   verify_oop(receiver);
    43   load_klass(receiver, temp_reg);
    44   cmp(temp_reg, iCache);
    45   brx(Assembler::equal, true, Assembler::pt, L);
    46   delayed()->nop();
    47   AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub());
    48   jump_to(ic_miss, temp_reg);
    49   delayed()->nop();
    50   align(CodeEntryAlignment);
    51   bind(L);
    52 }
    55 void C1_MacroAssembler::explicit_null_check(Register base) {
    56   Unimplemented();
    57 }
    60 void C1_MacroAssembler::build_frame(int frame_size_in_bytes) {
    62   generate_stack_overflow_check(frame_size_in_bytes);
    63   // Create the frame.
    64   save_frame_c1(frame_size_in_bytes);
    65 }
    68 void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) {
    69   if (C1Breakpoint) breakpoint_trap();
    70   inline_cache_check(receiver, ic_klass);
    71 }
    74 void C1_MacroAssembler::verified_entry() {
    75   if (C1Breakpoint) breakpoint_trap();
    76   // build frame
    77   verify_FPU(0, "method_entry");
    78 }
    81 void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox, Register Rscratch, Label& slow_case) {
    82   assert_different_registers(Rmark, Roop, Rbox, Rscratch);
    84   Label done;
    86   Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
    88   // The following move must be the first instruction of emitted since debug
    89   // information may be generated for it.
    90   // Load object header
    91   ld_ptr(mark_addr, Rmark);
    93   verify_oop(Roop);
    95   // save object being locked into the BasicObjectLock
    96   st_ptr(Roop, Rbox, BasicObjectLock::obj_offset_in_bytes());
    98   if (UseBiasedLocking) {
    99     biased_locking_enter(Roop, Rmark, Rscratch, done, &slow_case);
   100   }
   102   // Save Rbox in Rscratch to be used for the cas operation
   103   mov(Rbox, Rscratch);
   105   // and mark it unlocked
   106   or3(Rmark, markOopDesc::unlocked_value, Rmark);
   108   // save unlocked object header into the displaced header location on the stack
   109   st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes());
   111   // compare object markOop with Rmark and if equal exchange Rscratch with object markOop
   112   assert(mark_addr.disp() == 0, "cas must take a zero displacement");
   113   casx_under_lock(mark_addr.base(), Rmark, Rscratch, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
   114   // if compare/exchange succeeded we found an unlocked object and we now have locked it
   115   // hence we are done
   116   cmp(Rmark, Rscratch);
   117   brx(Assembler::equal, false, Assembler::pt, done);
   118   delayed()->sub(Rscratch, SP, Rscratch);  //pull next instruction into delay slot
   119   // we did not find an unlocked object so see if this is a recursive case
   120   // sub(Rscratch, SP, Rscratch);
   121   assert(os::vm_page_size() > 0xfff, "page size too small - change the constant");
   122   andcc(Rscratch, 0xfffff003, Rscratch);
   123   brx(Assembler::notZero, false, Assembler::pn, slow_case);
   124   delayed()->st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes());
   125   bind(done);
   126 }
   129 void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rbox, Label& slow_case) {
   130   assert_different_registers(Rmark, Roop, Rbox);
   132   Label done;
   134   Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
   135   assert(mark_addr.disp() == 0, "cas must take a zero displacement");
   137   if (UseBiasedLocking) {
   138     // load the object out of the BasicObjectLock
   139     ld_ptr(Rbox, BasicObjectLock::obj_offset_in_bytes(), Roop);
   140     verify_oop(Roop);
   141     biased_locking_exit(mark_addr, Rmark, done);
   142   }
   143   // Test first it it is a fast recursive unlock
   144   ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rmark);
   145   br_null(Rmark, false, Assembler::pt, done);
   146   delayed()->nop();
   147   if (!UseBiasedLocking) {
   148     // load object
   149     ld_ptr(Rbox, BasicObjectLock::obj_offset_in_bytes(), Roop);
   150     verify_oop(Roop);
   151   }
   153   // Check if it is still a light weight lock, this is is true if we see
   154   // the stack address of the basicLock in the markOop of the object
   155   casx_under_lock(mark_addr.base(), Rbox, Rmark, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
   156   cmp(Rbox, Rmark);
   158   brx(Assembler::notEqual, false, Assembler::pn, slow_case);
   159   delayed()->nop();
   160   // Done
   161   bind(done);
   162 }
   165 void C1_MacroAssembler::try_allocate(
   166   Register obj,                        // result: pointer to object after successful allocation
   167   Register var_size_in_bytes,          // object size in bytes if unknown at compile time; invalid otherwise
   168   int      con_size_in_bytes,          // object size in bytes if   known at compile time
   169   Register t1,                         // temp register, must be global register for incr_allocated_bytes
   170   Register t2,                         // temp register
   171   Label&   slow_case                   // continuation point if fast allocation fails
   172 ) {
   173   RegisterOrConstant size_in_bytes = var_size_in_bytes->is_valid()
   174     ? RegisterOrConstant(var_size_in_bytes) : RegisterOrConstant(con_size_in_bytes);
   175   if (UseTLAB) {
   176     tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
   177   } else {
   178     eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
   179     incr_allocated_bytes(size_in_bytes, t1, t2);
   180   }
   181 }
   184 void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
   185   assert_different_registers(obj, klass, len, t1, t2);
   186   if (UseBiasedLocking && !len->is_valid()) {
   187     ld_ptr(klass, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes(), t1);
   188   } else {
   189     set((intx)markOopDesc::prototype(), t1);
   190   }
   191   st_ptr(t1, obj, oopDesc::mark_offset_in_bytes());
   192   if (UseCompressedOops) {
   193     // Save klass
   194     mov(klass, t1);
   195     encode_heap_oop_not_null(t1);
   196     stw(t1, obj, oopDesc::klass_offset_in_bytes());
   197   } else {
   198     st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());
   199   }
   200   if (len->is_valid()) st(len, obj, arrayOopDesc::length_offset_in_bytes());
   201   else if (UseCompressedOops) {
   202     store_klass_gap(G0, obj);
   203   }
   204 }
   207 void C1_MacroAssembler::initialize_body(Register base, Register index) {
   208   assert_different_registers(base, index);
   209   Label loop;
   210   bind(loop);
   211   subcc(index, HeapWordSize, index);
   212   brx(Assembler::greaterEqual, true, Assembler::pt, loop);
   213   delayed()->st_ptr(G0, base, index);
   214 }
   217 void C1_MacroAssembler::allocate_object(
   218   Register obj,                        // result: pointer to object after successful allocation
   219   Register t1,                         // temp register
   220   Register t2,                         // temp register, must be a global register for try_allocate
   221   Register t3,                         // temp register
   222   int      hdr_size,                   // object header size in words
   223   int      obj_size,                   // object size in words
   224   Register klass,                      // object klass
   225   Label&   slow_case                   // continuation point if fast allocation fails
   226 ) {
   227   assert_different_registers(obj, t1, t2, t3, klass);
   228   assert(klass == G5, "must be G5");
   230   // allocate space & initialize header
   231   if (!is_simm13(obj_size * wordSize)) {
   232     // would need to use extra register to load
   233     // object size => go the slow case for now
   234     br(Assembler::always, false, Assembler::pt, slow_case);
   235     delayed()->nop();
   236     return;
   237   }
   238   try_allocate(obj, noreg, obj_size * wordSize, t2, t3, slow_case);
   240   initialize_object(obj, klass, noreg, obj_size * HeapWordSize, t1, t2);
   241 }
   243 void C1_MacroAssembler::initialize_object(
   244   Register obj,                        // result: pointer to object after successful allocation
   245   Register klass,                      // object klass
   246   Register var_size_in_bytes,          // object size in bytes if unknown at compile time; invalid otherwise
   247   int      con_size_in_bytes,          // object size in bytes if   known at compile time
   248   Register t1,                         // temp register
   249   Register t2                          // temp register
   250   ) {
   251   const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
   253   initialize_header(obj, klass, noreg, t1, t2);
   255 #ifdef ASSERT
   256   {
   257     Label ok;
   258     ld(klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), t1);
   259     if (var_size_in_bytes != noreg) {
   260       cmp(t1, var_size_in_bytes);
   261     } else {
   262       cmp(t1, con_size_in_bytes);
   263     }
   264     brx(Assembler::equal, false, Assembler::pt, ok);
   265     delayed()->nop();
   266     stop("bad size in initialize_object");
   267     should_not_reach_here();
   269     bind(ok);
   270   }
   272 #endif
   274   // initialize body
   275   const int threshold = 5 * HeapWordSize;              // approximate break even point for code size
   276   if (var_size_in_bytes != noreg) {
   277     // use a loop
   278     add(obj, hdr_size_in_bytes, t1);               // compute address of first element
   279     sub(var_size_in_bytes, hdr_size_in_bytes, t2); // compute size of body
   280     initialize_body(t1, t2);
   281 #ifndef _LP64
   282   } else if (VM_Version::v9_instructions_work() && con_size_in_bytes < threshold * 2) {
   283     // on v9 we can do double word stores to fill twice as much space.
   284     assert(hdr_size_in_bytes % 8 == 0, "double word aligned");
   285     assert(con_size_in_bytes % 8 == 0, "double word aligned");
   286     for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += 2 * HeapWordSize) stx(G0, obj, i);
   287 #endif
   288   } else if (con_size_in_bytes <= threshold) {
   289     // use explicit NULL stores
   290     for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += HeapWordSize)     st_ptr(G0, obj, i);
   291   } else if (con_size_in_bytes > hdr_size_in_bytes) {
   292     // use a loop
   293     const Register base  = t1;
   294     const Register index = t2;
   295     add(obj, hdr_size_in_bytes, base);               // compute address of first element
   296     // compute index = number of words to clear
   297     set(con_size_in_bytes - hdr_size_in_bytes, index);
   298     initialize_body(base, index);
   299   }
   301   if (CURRENT_ENV->dtrace_alloc_probes()) {
   302     assert(obj == O0, "must be");
   303     call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
   304          relocInfo::runtime_call_type);
   305     delayed()->nop();
   306   }
   308   verify_oop(obj);
   309 }
   312 void C1_MacroAssembler::allocate_array(
   313   Register obj,                        // result: pointer to array after successful allocation
   314   Register len,                        // array length
   315   Register t1,                         // temp register
   316   Register t2,                         // temp register
   317   Register t3,                         // temp register
   318   int      hdr_size,                   // object header size in words
   319   int      elt_size,                   // element size in bytes
   320   Register klass,                      // object klass
   321   Label&   slow_case                   // continuation point if fast allocation fails
   322 ) {
   323   assert_different_registers(obj, len, t1, t2, t3, klass);
   324   assert(klass == G5, "must be G5");
   325   assert(t1 == G1, "must be G1");
   327   // determine alignment mask
   328   assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work");
   330   // check for negative or excessive length
   331   // note: the maximum length allowed is chosen so that arrays of any
   332   //       element size with this length are always smaller or equal
   333   //       to the largest integer (i.e., array size computation will
   334   //       not overflow)
   335   set(max_array_allocation_length, t1);
   336   cmp(len, t1);
   337   br(Assembler::greaterUnsigned, false, Assembler::pn, slow_case);
   339   // compute array size
   340   // note: if 0 <= len <= max_length, len*elt_size + header + alignment is
   341   //       smaller or equal to the largest integer; also, since top is always
   342   //       aligned, we can do the alignment here instead of at the end address
   343   //       computation
   344   const Register arr_size = t1;
   345   switch (elt_size) {
   346     case  1: delayed()->mov(len,    arr_size); break;
   347     case  2: delayed()->sll(len, 1, arr_size); break;
   348     case  4: delayed()->sll(len, 2, arr_size); break;
   349     case  8: delayed()->sll(len, 3, arr_size); break;
   350     default: ShouldNotReachHere();
   351   }
   352   add(arr_size, hdr_size * wordSize + MinObjAlignmentInBytesMask, arr_size); // add space for header & alignment
   353   and3(arr_size, ~MinObjAlignmentInBytesMask, arr_size);                     // align array size
   355   // allocate space & initialize header
   356   if (UseTLAB) {
   357     tlab_allocate(obj, arr_size, 0, t2, slow_case);
   358   } else {
   359     eden_allocate(obj, arr_size, 0, t2, t3, slow_case);
   360   }
   361   initialize_header(obj, klass, len, t2, t3);
   363   // initialize body
   364   const Register base  = t2;
   365   const Register index = t3;
   366   add(obj, hdr_size * wordSize, base);               // compute address of first element
   367   sub(arr_size, hdr_size * wordSize, index);         // compute index = number of words to clear
   368   initialize_body(base, index);
   370   if (CURRENT_ENV->dtrace_alloc_probes()) {
   371     assert(obj == O0, "must be");
   372     call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
   373          relocInfo::runtime_call_type);
   374     delayed()->nop();
   375   }
   377   verify_oop(obj);
   378 }
   381 #ifndef PRODUCT
   383 void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
   384   if (!VerifyOops) return;
   385   verify_oop_addr(Address(SP, stack_offset + STACK_BIAS));
   386 }
   388 void C1_MacroAssembler::verify_not_null_oop(Register r) {
   389   Label not_null;
   390   br_zero(Assembler::notEqual, false, Assembler::pt, r, not_null);
   391   delayed()->nop();
   392   stop("non-null oop required");
   393   bind(not_null);
   394   if (!VerifyOops) return;
   395   verify_oop(r);
   396 }
   398 void C1_MacroAssembler::invalidate_registers(bool iregisters, bool lregisters, bool oregisters,
   399                                              Register preserve1, Register preserve2) {
   400   if (iregisters) {
   401     for (int i = 0; i < 6; i++) {
   402       Register r = as_iRegister(i);
   403       if (r != preserve1 && r != preserve2)  set(0xdead, r);
   404     }
   405   }
   406   if (oregisters) {
   407     for (int i = 0; i < 6; i++) {
   408       Register r = as_oRegister(i);
   409       if (r != preserve1 && r != preserve2)  set(0xdead, r);
   410     }
   411   }
   412   if (lregisters) {
   413     for (int i = 0; i < 8; i++) {
   414       Register r = as_lRegister(i);
   415       if (r != preserve1 && r != preserve2)  set(0xdead, r);
   416     }
   417   }
   418 }
   421 #endif

mercurial