src/cpu/sparc/vm/jniFastGetField_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 2314
f95d63e2154a
child 4323
f0c2369fda5a
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) 2004, 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 "assembler_sparc.inline.hpp"
    27 #include "memory/resourceArea.hpp"
    28 #include "prims/jniFastGetField.hpp"
    29 #include "prims/jvm_misc.hpp"
    30 #include "runtime/safepoint.hpp"
    32 // TSO ensures that loads are blocking and ordered with respect to
    33 // to earlier loads, so we don't need LoadLoad membars.
    35 #define __ masm->
    37 #define BUFFER_SIZE 30*sizeof(jint)
    39 // Common register usage:
    40 // O0: env
    41 // O1: obj
    42 // O2: jfieldID
    43 // O4: offset (O2 >> 2)
    44 // G4: old safepoint counter
    46 address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
    47   const char *name;
    48   switch (type) {
    49     case T_BOOLEAN: name = "jni_fast_GetBooleanField"; break;
    50     case T_BYTE:    name = "jni_fast_GetByteField";    break;
    51     case T_CHAR:    name = "jni_fast_GetCharField";    break;
    52     case T_SHORT:   name = "jni_fast_GetShortField";   break;
    53     case T_INT:     name = "jni_fast_GetIntField";     break;
    54     default:        ShouldNotReachHere();
    55   }
    56   ResourceMark rm;
    57   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
    58   CodeBuffer cbuf(blob);
    59   MacroAssembler* masm = new MacroAssembler(&cbuf);
    60   address fast_entry = __ pc();
    62   Label label1, label2;
    64   AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
    65   __ sethi (cnt_addrlit, O3);
    66   Address cnt_addr(O3, cnt_addrlit.low10());
    67   __ ld (cnt_addr, G4);
    68   __ andcc (G4, 1, G0);
    69   __ br (Assembler::notZero, false, Assembler::pn, label1);
    70   __ delayed()->srl (O2, 2, O4);
    71   __ ld_ptr (O1, 0, O5);
    73   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
    74   speculative_load_pclist[count] = __ pc();
    75   switch (type) {
    76     case T_BOOLEAN: __ ldub (O5, O4, G3);  break;
    77     case T_BYTE:    __ ldsb (O5, O4, G3);  break;
    78     case T_CHAR:    __ lduh (O5, O4, G3);  break;
    79     case T_SHORT:   __ ldsh (O5, O4, G3);  break;
    80     case T_INT:     __ ld (O5, O4, G3);    break;
    81     default:        ShouldNotReachHere();
    82   }
    84   __ ld (cnt_addr, O5);
    85   __ cmp (O5, G4);
    86   __ br (Assembler::notEqual, false, Assembler::pn, label2);
    87   __ delayed()->mov (O7, G1);
    88   __ retl ();
    89   __ delayed()->mov (G3, O0);
    91   slowcase_entry_pclist[count++] = __ pc();
    92   __ bind (label1);
    93   __ mov (O7, G1);
    95   address slow_case_addr;
    96   switch (type) {
    97     case T_BOOLEAN: slow_case_addr = jni_GetBooleanField_addr(); break;
    98     case T_BYTE:    slow_case_addr = jni_GetByteField_addr();    break;
    99     case T_CHAR:    slow_case_addr = jni_GetCharField_addr();    break;
   100     case T_SHORT:   slow_case_addr = jni_GetShortField_addr();   break;
   101     case T_INT:     slow_case_addr = jni_GetIntField_addr();     break;
   102     default:        ShouldNotReachHere();
   103   }
   104   __ bind (label2);
   105   __ call (slow_case_addr, relocInfo::none);
   106   __ delayed()->mov (G1, O7);
   108   __ flush ();
   110   return fast_entry;
   111 }
   113 address JNI_FastGetField::generate_fast_get_boolean_field() {
   114   return generate_fast_get_int_field0(T_BOOLEAN);
   115 }
   117 address JNI_FastGetField::generate_fast_get_byte_field() {
   118   return generate_fast_get_int_field0(T_BYTE);
   119 }
   121 address JNI_FastGetField::generate_fast_get_char_field() {
   122   return generate_fast_get_int_field0(T_CHAR);
   123 }
   125 address JNI_FastGetField::generate_fast_get_short_field() {
   126   return generate_fast_get_int_field0(T_SHORT);
   127 }
   129 address JNI_FastGetField::generate_fast_get_int_field() {
   130   return generate_fast_get_int_field0(T_INT);
   131 }
   133 address JNI_FastGetField::generate_fast_get_long_field() {
   134   const char *name = "jni_fast_GetLongField";
   135   ResourceMark rm;
   136   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
   137   CodeBuffer cbuf(blob);
   138   MacroAssembler* masm = new MacroAssembler(&cbuf);
   139   address fast_entry = __ pc();
   141   Label label1, label2;
   143   AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
   144   __ sethi (cnt_addrlit, G3);
   145   Address cnt_addr(G3, cnt_addrlit.low10());
   146   __ ld (cnt_addr, G4);
   147   __ andcc (G4, 1, G0);
   148   __ br (Assembler::notZero, false, Assembler::pn, label1);
   149   __ delayed()->srl (O2, 2, O4);
   150   __ ld_ptr (O1, 0, O5);
   151   __ add (O5, O4, O5);
   153 #ifndef _LP64
   154   assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small");
   155   speculative_load_pclist[count++] = __ pc();
   156   __ ld (O5, 0, G2);
   158   speculative_load_pclist[count] = __ pc();
   159   __ ld (O5, 4, O3);
   160 #else
   161   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
   162   speculative_load_pclist[count] = __ pc();
   163   __ ldx (O5, 0, O3);
   164 #endif
   166   __ ld (cnt_addr, G1);
   167   __ cmp (G1, G4);
   168   __ br (Assembler::notEqual, false, Assembler::pn, label2);
   169   __ delayed()->mov (O7, G1);
   171 #ifndef _LP64
   172   __ mov (G2, O0);
   173   __ retl ();
   174   __ delayed()->mov (O3, O1);
   175 #else
   176   __ retl ();
   177   __ delayed()->mov (O3, O0);
   178 #endif
   180 #ifndef _LP64
   181   slowcase_entry_pclist[count-1] = __ pc();
   182   slowcase_entry_pclist[count++] = __ pc() ;
   183 #else
   184   slowcase_entry_pclist[count++] = __ pc();
   185 #endif
   187   __ bind (label1);
   188   __ mov (O7, G1);
   190   address slow_case_addr = jni_GetLongField_addr();
   191   __ bind (label2);
   192   __ call (slow_case_addr, relocInfo::none);
   193   __ delayed()->mov (G1, O7);
   195   __ flush ();
   197   return fast_entry;
   198 }
   200 address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
   201   const char *name;
   202   switch (type) {
   203     case T_FLOAT:  name = "jni_fast_GetFloatField";  break;
   204     case T_DOUBLE: name = "jni_fast_GetDoubleField"; break;
   205     default:       ShouldNotReachHere();
   206   }
   207   ResourceMark rm;
   208   BufferBlob* blob = BufferBlob::create(name, BUFFER_SIZE*wordSize);
   209   CodeBuffer cbuf(blob);
   210   MacroAssembler* masm = new MacroAssembler(&cbuf);
   211   address fast_entry = __ pc();
   213   Label label1, label2;
   215   AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
   216   __ sethi (cnt_addrlit, O3);
   217   Address cnt_addr(O3, cnt_addrlit.low10());
   218   __ ld (cnt_addr, G4);
   219   __ andcc (G4, 1, G0);
   220   __ br (Assembler::notZero, false, Assembler::pn, label1);
   221   __ delayed()->srl (O2, 2, O4);
   222   __ ld_ptr (O1, 0, O5);
   224   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
   225   speculative_load_pclist[count] = __ pc();
   226   switch (type) {
   227     case T_FLOAT:  __ ldf (FloatRegisterImpl::S, O5, O4, F0); break;
   228     case T_DOUBLE: __ ldf (FloatRegisterImpl::D, O5, O4, F0); break;
   229     default:       ShouldNotReachHere();
   230   }
   232   __ ld (cnt_addr, O5);
   233   __ cmp (O5, G4);
   234   __ br (Assembler::notEqual, false, Assembler::pn, label2);
   235   __ delayed()->mov (O7, G1);
   237   __ retl ();
   238   __ delayed()-> nop ();
   240   slowcase_entry_pclist[count++] = __ pc();
   241   __ bind (label1);
   242   __ mov (O7, G1);
   244   address slow_case_addr;
   245   switch (type) {
   246     case T_FLOAT:  slow_case_addr = jni_GetFloatField_addr();  break;
   247     case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break;
   248     default:       ShouldNotReachHere();
   249   }
   250   __ bind (label2);
   251   __ call (slow_case_addr, relocInfo::none);
   252   __ delayed()->mov (G1, O7);
   254   __ flush ();
   256   return fast_entry;
   257 }
   259 address JNI_FastGetField::generate_fast_get_float_field() {
   260   return generate_fast_get_float_field0(T_FLOAT);
   261 }
   263 address JNI_FastGetField::generate_fast_get_double_field() {
   264   return generate_fast_get_float_field0(T_DOUBLE);
   265 }

mercurial