src/cpu/sparc/vm/relocInfo_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 2657
d673ef06fe96
child 2708
1d1603768966
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) 1998, 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 "asm/assembler.inline.hpp"
    27 #include "assembler_sparc.inline.hpp"
    28 #include "code/relocInfo.hpp"
    29 #include "nativeInst_sparc.hpp"
    30 #include "oops/oop.inline.hpp"
    31 #include "runtime/safepoint.hpp"
    33 void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
    34   NativeInstruction* ip = nativeInstruction_at(addr());
    35   jint inst = ip->long_at(0);
    36   assert(inst != NativeInstruction::illegal_instruction(), "no breakpoint");
    37   switch (Assembler::inv_op(inst)) {
    39   case Assembler::ldst_op:
    40     #ifdef ASSERT
    41       switch (Assembler::inv_op3(inst)) {
    42         case Assembler::lduw_op3:
    43         case Assembler::ldub_op3:
    44         case Assembler::lduh_op3:
    45         case Assembler::ldd_op3:
    46         case Assembler::ldsw_op3:
    47         case Assembler::ldsb_op3:
    48         case Assembler::ldsh_op3:
    49         case Assembler::ldx_op3:
    50         case Assembler::ldf_op3:
    51         case Assembler::lddf_op3:
    52         case Assembler::stw_op3:
    53         case Assembler::stb_op3:
    54         case Assembler::sth_op3:
    55         case Assembler::std_op3:
    56         case Assembler::stx_op3:
    57         case Assembler::stf_op3:
    58         case Assembler::stdf_op3:
    59         case Assembler::casa_op3:
    60         case Assembler::casxa_op3:
    61           break;
    62         default:
    63           ShouldNotReachHere();
    64       }
    65       goto do_non_sethi;
    66     #endif
    68   case Assembler::arith_op:
    69     #ifdef ASSERT
    70       switch (Assembler::inv_op3(inst)) {
    71         case Assembler::or_op3:
    72         case Assembler::add_op3:
    73         case Assembler::jmpl_op3:
    74           break;
    75         default:
    76           ShouldNotReachHere();
    77       }
    78     do_non_sethi:;
    79     #endif
    80     {
    81     guarantee(Assembler::inv_immed(inst), "must have a simm13 field");
    82     int simm13 = Assembler::low10((intptr_t)x) + o;
    83     guarantee(Assembler::is_simm13(simm13), "offset can't overflow simm13");
    84     inst &= ~Assembler::simm(    -1, 13);
    85     inst |=  Assembler::simm(simm13, 13);
    86     if (verify_only) {
    87       assert(ip->long_at(0) == inst, "instructions must match");
    88     } else {
    89       ip->set_long_at(0, inst);
    90     }
    91     }
    92     break;
    94   case Assembler::branch_op:
    95     {
    96 #ifdef _LP64
    97     jint inst2;
    98     guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi");
    99     if (format() != 0) {
   100       assert(type() == relocInfo::oop_type, "only narrow oops case");
   101       jint np = oopDesc::encode_heap_oop((oop)x);
   102       inst &= ~Assembler::hi22(-1);
   103       inst |=  Assembler::hi22((intptr_t)np);
   104       if (verify_only) {
   105         assert(ip->long_at(0) == inst, "instructions must match");
   106       } else {
   107         ip->set_long_at(0, inst);
   108       }
   109       inst2 = ip->long_at( NativeInstruction::nop_instruction_size );
   110       guarantee(Assembler::inv_op(inst2)==Assembler::arith_op, "arith op");
   111       if (verify_only) {
   112         assert(ip->long_at(NativeInstruction::nop_instruction_size) == NativeInstruction::set_data32_simm13( inst2, (intptr_t)np),
   113                "instructions must match");
   114       } else {
   115         ip->set_long_at(NativeInstruction::nop_instruction_size, NativeInstruction::set_data32_simm13( inst2, (intptr_t)np));
   116       }
   117       break;
   118     }
   119     if (verify_only) {
   120       ip->verify_data64_sethi( ip->addr_at(0), (intptr_t)x );
   121     } else {
   122       ip->set_data64_sethi( ip->addr_at(0), (intptr_t)x );
   123     }
   124 #else
   125     guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi");
   126     inst &= ~Assembler::hi22(     -1);
   127     inst |=  Assembler::hi22((intptr_t)x);
   128     // (ignore offset; it doesn't play into the sethi)
   129     if (verify_only) {
   130       assert(ip->long_at(0) == inst, "instructions must match");
   131     } else {
   132       ip->set_long_at(0, inst);
   133     }
   134 #endif
   135     }
   136     break;
   138   default:
   139     guarantee(false, "instruction must perform arithmetic or memory access");
   140   }
   141 }
   144 address Relocation::pd_call_destination(address orig_addr) {
   145   intptr_t adj = 0;
   146   if (orig_addr != NULL) {
   147     // We just moved this call instruction from orig_addr to addr().
   148     // This means its target will appear to have grown by addr() - orig_addr.
   149     adj = -( addr() - orig_addr );
   150   }
   151   if (NativeCall::is_call_at(addr())) {
   152     NativeCall* call = nativeCall_at(addr());
   153     return call->destination() + adj;
   154   }
   155   if (NativeFarCall::is_call_at(addr())) {
   156     NativeFarCall* call = nativeFarCall_at(addr());
   157     return call->destination() + adj;
   158   }
   159   // Special case:  Patchable branch local to the code cache.
   160   // This will break badly if the code cache grows larger than a few Mb.
   161   NativeGeneralJump* br = nativeGeneralJump_at(addr());
   162   return br->jump_destination() + adj;
   163 }
   166 void Relocation::pd_set_call_destination(address x) {
   167   if (NativeCall::is_call_at(addr())) {
   168     NativeCall* call = nativeCall_at(addr());
   169     call->set_destination(x);
   170     return;
   171   }
   172   if (NativeFarCall::is_call_at(addr())) {
   173     NativeFarCall* call = nativeFarCall_at(addr());
   174     call->set_destination(x);
   175     return;
   176   }
   177   // Special case:  Patchable branch local to the code cache.
   178   // This will break badly if the code cache grows larger than a few Mb.
   179   NativeGeneralJump* br = nativeGeneralJump_at(addr());
   180   br->set_jump_destination(x);
   181 }
   184 address* Relocation::pd_address_in_code() {
   185   // SPARC never embeds addresses in code, at present.
   186   //assert(type() == relocInfo::oop_type, "only oops are inlined at present");
   187   return (address*)addr();
   188 }
   191 address Relocation::pd_get_address_from_code() {
   192   // SPARC never embeds addresses in code, at present.
   193   //assert(type() == relocInfo::oop_type, "only oops are inlined at present");
   194   return *(address*)addr();
   195 }
   198 int Relocation::pd_breakpoint_size() {
   199   // minimum breakpoint size, in short words
   200   return NativeIllegalInstruction::instruction_size / sizeof(short);
   201 }
   203 void Relocation::pd_swap_in_breakpoint(address x, short* instrs, int instrlen) {
   204   Untested("pd_swap_in_breakpoint");
   205   // %%% probably do not need a general instrlen; just use the trap size
   206   if (instrs != NULL) {
   207     assert(instrlen * sizeof(short) == NativeIllegalInstruction::instruction_size, "enough instrlen in reloc. data");
   208     for (int i = 0; i < instrlen; i++) {
   209       instrs[i] = ((short*)x)[i];
   210     }
   211   }
   212   NativeIllegalInstruction::insert(x);
   213 }
   216 void Relocation::pd_swap_out_breakpoint(address x, short* instrs, int instrlen) {
   217   Untested("pd_swap_out_breakpoint");
   218   assert(instrlen * sizeof(short) == sizeof(int), "enough buf");
   219   union { int l; short s[1]; } u;
   220   for (int i = 0; i < instrlen; i++) {
   221     u.s[i] = instrs[i];
   222   }
   223   NativeInstruction* ni = nativeInstruction_at(x);
   224   ni->set_long_at(0, u.l);
   225 }
   227 void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
   228 }
   230 void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
   231 }

mercurial