src/cpu/sparc/vm/args.cc

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

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 1907
c18cbe5936b8
child 6876
710a3c8b516e
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

duke@435 1 /*
trims@1907 2 * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 #include <stdio.h>
duke@435 26 #include <string.h>
duke@435 27
duke@435 28 static const int R_O0_num = 1000;
duke@435 29 static const int R_I0_num = 2000;
duke@435 30 static const int R_F0_num = 3000;
duke@435 31 static const int R_F1_num = R_F0_num + 1;
duke@435 32 static const int R_F2_num = R_F0_num + 2;
duke@435 33 static const int STACK_num= 4000;
duke@435 34
duke@435 35 static bool LP64 = false;
duke@435 36 static bool LONGS_IN_ONE_ENTRY = false;
duke@435 37
duke@435 38 static const int Op_RegI = 'I';
duke@435 39 static const int Op_RegP = 'P';
duke@435 40 static const int Op_RegF = 'F';
duke@435 41 static const int Op_RegD = 'D';
duke@435 42 static const int Op_RegL = 'L';
duke@435 43 static const int SPARC_ARGS_IN_REGS_NUM=6;
duke@435 44
duke@435 45 static void print_reg( int reg ) {
duke@435 46 if( reg == 0 )
duke@435 47 printf("__"); // halve's
duke@435 48 else if( reg >= STACK_num && reg < STACK_num+100 )
duke@435 49 printf("S%d_",reg - STACK_num);
duke@435 50 else if( reg >= R_F0_num && reg < R_F0_num+100 )
duke@435 51 printf("F%d_",reg - R_F0_num);
duke@435 52 else if( reg >= R_O0_num && reg < R_O0_num+100 ) {
duke@435 53 if( LONGS_IN_ONE_ENTRY ) {
duke@435 54 reg -= R_O0_num;
duke@435 55 printf("O%d",reg>>1);
duke@435 56 printf(reg&1 ? "H" : "L");
duke@435 57 } else
duke@435 58 printf("O%d_",reg - R_O0_num);
duke@435 59 } else
duke@435 60 printf("Wretched: %d\n", reg);
duke@435 61 }
duke@435 62
duke@435 63 static void print_convention( int *sig, const char *s, int length ) {
duke@435 64 // Print it out
duke@435 65 for( int i = 0; i < length; i++) {
duke@435 66 if( sig[i] == 0 ) continue; // do not print 'halves'
duke@435 67 print_reg( sig[i] & 0xFFFF );
duke@435 68 int reg = sig[i] >> 16;
duke@435 69 if( reg ) {
duke@435 70 printf(":");
duke@435 71 print_reg( reg );
duke@435 72 } else {
duke@435 73 printf(" ");
duke@435 74 }
duke@435 75 printf(" ");
duke@435 76 }
duke@435 77 printf("\n");
duke@435 78 }
duke@435 79
duke@435 80 static int INT_SCALE( int x ) {
duke@435 81 return LONGS_IN_ONE_ENTRY ? (x<<1) : x;
duke@435 82 }
duke@435 83
duke@435 84 static void java_convention( int *sig, const char *s, int length ) {
duke@435 85 if( LP64 && !LONGS_IN_ONE_ENTRY ) {
duke@435 86 printf("LP64 and 2-reg longs not supported\n");
duke@435 87 return;
duke@435 88 }
duke@435 89 for( int i = 0; i < length; i++ )
duke@435 90 sig[i] = s[i]; // Reset sig array
duke@435 91 bool is_outgoing = true;
duke@435 92
duke@435 93 int int_base = (is_outgoing ? R_O0_num : R_I0_num);
duke@435 94
duke@435 95 // Convention is to pack the first 6 int/oop args into the first 6
duke@435 96 // registers (I0-I5), extras spill to the stack. Then pack the first
duke@435 97 // 32 float args into F0-F31, extras spill to the stack. Then pad
duke@435 98 // all register sets to align. Then put longs and doubles into the
duke@435 99 // same registers as they fit, else spill to the stack.
duke@435 100 int int_reg_max = SPARC_ARGS_IN_REGS_NUM;
duke@435 101 int flt_reg_max = 32;
duke@435 102
duke@435 103 // Count int/oop and float args. See how many stack slots we'll need
duke@435 104 // and where the longs & doubles will go.
duke@435 105 int int_reg_cnt = 0;
duke@435 106 int flt_reg_cnt = 0;
duke@435 107 int stk_reg_pairs = 0;
duke@435 108 for( int i = 0; i < length; i++) {
duke@435 109 switch( sig[i] ) {
duke@435 110 case Op_RegL: // Longs-in-1-reg compete with int args
duke@435 111 if( LONGS_IN_ONE_ENTRY ) {
duke@435 112 if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
duke@435 113 }
duke@435 114 break;
duke@435 115 case Op_RegP:
duke@435 116 if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
duke@435 117 else if( !LP64 ) stk_reg_pairs++;
duke@435 118 break;
duke@435 119 case Op_RegI:
duke@435 120 if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
duke@435 121 else stk_reg_pairs++;
duke@435 122 break;
duke@435 123 case Op_RegF:
duke@435 124 if( flt_reg_cnt < flt_reg_max ) flt_reg_cnt++;
duke@435 125 else stk_reg_pairs++;
duke@435 126 break;
duke@435 127 }
duke@435 128 }
duke@435 129
duke@435 130 // This is where the longs/doubles start on the stack.
duke@435 131 stk_reg_pairs = (stk_reg_pairs+1) & ~1; // Round
duke@435 132
duke@435 133 int int_reg_pairs = (int_reg_cnt+1) & ~1; // 32-bit 2-reg longs only
duke@435 134 int flt_reg_pairs = (flt_reg_cnt+1) & ~1;
duke@435 135
duke@435 136 int stk_reg = 0;
duke@435 137 int int_reg = 0;
duke@435 138 int flt_reg = 0;
duke@435 139
duke@435 140 // Now do the signature layout
duke@435 141 for( int i = 0; i < length; i++) {
duke@435 142 int tmp = sig[i];
duke@435 143 if( tmp == Op_RegP )
duke@435 144 tmp = LP64 ? Op_RegL : Op_RegI; // Treat ptrs and ints or long accordingly
duke@435 145 switch( tmp ) {
duke@435 146 case Op_RegI:
duke@435 147 // case Op_RegP:
duke@435 148 if( int_reg < int_reg_max) tmp = INT_SCALE(int_reg++) + int_base;
duke@435 149 else tmp = STACK_num + stk_reg++;
duke@435 150 sig[i] = tmp;
duke@435 151 break;
duke@435 152
duke@435 153 case Op_RegL:
duke@435 154 if( sig[i] != Op_RegP && sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
duke@435 155 // case Op_RegP:
duke@435 156 if( LONGS_IN_ONE_ENTRY ) {
duke@435 157 if( int_reg < int_reg_max ) {
duke@435 158 tmp = INT_SCALE(int_reg++) + int_base;
duke@435 159 } else {
duke@435 160 tmp = STACK_num + stk_reg_pairs;
duke@435 161 stk_reg_pairs += 2;
duke@435 162 }
duke@435 163 } else {
duke@435 164 if( int_reg_pairs < int_reg_max ) {
duke@435 165 tmp = int_reg_pairs + int_base;
duke@435 166 int_reg_pairs += 2;
duke@435 167 } else {
duke@435 168 tmp = STACK_num + stk_reg_pairs;
duke@435 169 stk_reg_pairs += 2;
duke@435 170 }
duke@435 171 }
duke@435 172 sig[i] = tmp | (tmp+1)<<16; // Smear to pair
duke@435 173 break;
duke@435 174
duke@435 175 case Op_RegF:
duke@435 176 sig[i] = (flt_reg < flt_reg_max) ? (R_F0_num + flt_reg++) : STACK_num + stk_reg++;
duke@435 177 break;
duke@435 178 case Op_RegD:
duke@435 179 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
duke@435 180 if( flt_reg_pairs < flt_reg_max ) {
duke@435 181 tmp = R_F0_num + flt_reg_pairs;
duke@435 182 flt_reg_pairs += 2;
duke@435 183 } else {
duke@435 184 tmp = STACK_num + stk_reg_pairs;
duke@435 185 stk_reg_pairs += 2;
duke@435 186 }
duke@435 187 sig[i] = tmp | (tmp+1)<<16; // Smear to pair
duke@435 188 break;
duke@435 189 case 'h': sig[i] = 0; break;
duke@435 190 default:
duke@435 191 printf("Bad character: %c\n", sig[i] );
duke@435 192 return;
duke@435 193 }
duke@435 194 }
duke@435 195
duke@435 196 printf("java ");
duke@435 197 printf(LP64 ? "LP64 " : "LP32 ");
duke@435 198 printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: ");
duke@435 199 print_convention(sig,s,length);
duke@435 200 }
duke@435 201
duke@435 202 static int int_stk_helper( int i ) {
duke@435 203 if( i < 6 ) return R_O0_num + (LONGS_IN_ONE_ENTRY ? i<<1 : i);
duke@435 204 else return STACK_num + (LP64 ? i<<1 : i);
duke@435 205 }
duke@435 206
duke@435 207 static void native_convention( int *sig, const char *s, int length ) {
duke@435 208 if( LP64 && !LONGS_IN_ONE_ENTRY ) {
duke@435 209 printf("LP64 and 2-reg longs not supported\n");
duke@435 210 return;
duke@435 211 }
duke@435 212 for( int i = 0; i < length; i++ )
duke@435 213 sig[i] = s[i]; // Reset sig array
duke@435 214
duke@435 215 // The native convention is V8 if !LP64, which means the V8 convention is
duke@435 216 // used both with and without LONGS_IN_ONE_ENTRY, an unfortunate split. The
duke@435 217 // same actual machine registers are used, but they are named differently in
duke@435 218 // the LONGS_IN_ONE_ENTRY mode. The LP64 convention is the V9 convention
duke@435 219 // which is slightly more sane.
duke@435 220
duke@435 221 if( LP64 ) {
duke@435 222 // V9 convention: All things "as-if" on double-wide stack slots.
duke@435 223 // Hoist any int/ptr/long's in the first 6 to int regs.
duke@435 224 // Hoist any flt/dbl's in the first 16 dbl regs.
duke@435 225 int j = 0; // Count of actual args, not HALVES
duke@435 226 for( int i=0; i<length; i++, j++ ) {
duke@435 227 int tmp;
duke@435 228 switch( sig[i] ) {
duke@435 229 case Op_RegI:
duke@435 230 sig[i] = int_stk_helper( j );
duke@435 231 break;
duke@435 232 case Op_RegL:
duke@435 233 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
duke@435 234 case Op_RegP:
duke@435 235 tmp = int_stk_helper( j );
duke@435 236 sig[i] = tmp | ((tmp+1) << 16); // Smear to pair
duke@435 237 break;
duke@435 238 case Op_RegF: // V9ism: floats go in ODD registers
duke@435 239 sig[i] = ((j < 16) ? R_F1_num : (STACK_num + 1)) + (j<<1);
duke@435 240 break;
duke@435 241 case Op_RegD: // V9ism: doubles go in EVEN/ODD regs
duke@435 242 tmp = ((j < 16) ? R_F0_num : STACK_num) + (j<<1);
duke@435 243 sig[i] = tmp | ((tmp+1) << 16); // Smear to pair
duke@435 244 break;
duke@435 245 case 'h': sig[i] = 0; j--; break; // Do not count HALVES
duke@435 246 default:
duke@435 247 printf("Bad character: %c\n", sig[i] );
duke@435 248 return;
duke@435 249 }
duke@435 250 }
duke@435 251
duke@435 252 } else {
duke@435 253 // V8 convention: first 6 things in O-regs, rest on stack.
duke@435 254 // Alignment is willy-nilly.
duke@435 255 for( int i=0; i<length; i++ ) {
duke@435 256 int tmp;
duke@435 257 switch( sig[i] ) {
duke@435 258 case Op_RegI:
duke@435 259 case Op_RegP:
duke@435 260 case Op_RegF:
duke@435 261 sig[i] = int_stk_helper( i );
duke@435 262 break;
duke@435 263 case Op_RegL:
duke@435 264 case Op_RegD:
duke@435 265 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
duke@435 266 tmp = int_stk_helper( i );
duke@435 267 sig[i] = tmp | (int_stk_helper( i+1 ) << 16);
duke@435 268 break;
duke@435 269 case 'h': sig[i] = 0; break;
duke@435 270 default:
duke@435 271 printf("Bad character: %c\n", sig[i] );
duke@435 272 return;
duke@435 273 }
duke@435 274 }
duke@435 275 }
duke@435 276
duke@435 277 printf("natv ");
duke@435 278 printf(LP64 ? "LP64 " : "LP32 ");
duke@435 279 printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: ");
duke@435 280 print_convention(sig,s,length);
duke@435 281 }
duke@435 282
duke@435 283 int main( int argc, char **argv ) {
duke@435 284
duke@435 285 if( argc != 2 ) {
duke@435 286 printf("Usage: args IPFLhDh... (Java argument string)\n");
duke@435 287 printf("Returns argument layout\n");
duke@435 288 return -1;
duke@435 289 }
duke@435 290
duke@435 291 const char *s = argv[1];
duke@435 292 int length = strlen(s);
duke@435 293 int sig[1000];
duke@435 294
duke@435 295 LP64 = false; LONGS_IN_ONE_ENTRY = false;
duke@435 296 java_convention( sig, s, length );
duke@435 297 LP64 = false; LONGS_IN_ONE_ENTRY = true;
duke@435 298 java_convention( sig, s, length );
duke@435 299 LP64 = true ; LONGS_IN_ONE_ENTRY = true;
duke@435 300 java_convention( sig, s, length );
duke@435 301
duke@435 302 LP64 = false; LONGS_IN_ONE_ENTRY = false;
duke@435 303 native_convention( sig, s, length );
duke@435 304 LP64 = false; LONGS_IN_ONE_ENTRY = true;
duke@435 305 native_convention( sig, s, length );
duke@435 306 LP64 = true ; LONGS_IN_ONE_ENTRY = true;
duke@435 307 native_convention( sig, s, length );
duke@435 308 }
duke@435 309

mercurial