Thu, 07 Apr 2011 09:53:20 -0700
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) 2002, 2006, 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 <stdio.h>
26 #include <string.h>
28 static const int R_O0_num = 1000;
29 static const int R_I0_num = 2000;
30 static const int R_F0_num = 3000;
31 static const int R_F1_num = R_F0_num + 1;
32 static const int R_F2_num = R_F0_num + 2;
33 static const int STACK_num= 4000;
35 static bool LP64 = false;
36 static bool LONGS_IN_ONE_ENTRY = false;
38 static const int Op_RegI = 'I';
39 static const int Op_RegP = 'P';
40 static const int Op_RegF = 'F';
41 static const int Op_RegD = 'D';
42 static const int Op_RegL = 'L';
43 static const int SPARC_ARGS_IN_REGS_NUM=6;
45 static void print_reg( int reg ) {
46 if( reg == 0 )
47 printf("__"); // halve's
48 else if( reg >= STACK_num && reg < STACK_num+100 )
49 printf("S%d_",reg - STACK_num);
50 else if( reg >= R_F0_num && reg < R_F0_num+100 )
51 printf("F%d_",reg - R_F0_num);
52 else if( reg >= R_O0_num && reg < R_O0_num+100 ) {
53 if( LONGS_IN_ONE_ENTRY ) {
54 reg -= R_O0_num;
55 printf("O%d",reg>>1);
56 printf(reg&1 ? "H" : "L");
57 } else
58 printf("O%d_",reg - R_O0_num);
59 } else
60 printf("Wretched: %d\n", reg);
61 }
63 static void print_convention( int *sig, const char *s, int length ) {
64 // Print it out
65 for( int i = 0; i < length; i++) {
66 if( sig[i] == 0 ) continue; // do not print 'halves'
67 print_reg( sig[i] & 0xFFFF );
68 int reg = sig[i] >> 16;
69 if( reg ) {
70 printf(":");
71 print_reg( reg );
72 } else {
73 printf(" ");
74 }
75 printf(" ");
76 }
77 printf("\n");
78 }
80 static int INT_SCALE( int x ) {
81 return LONGS_IN_ONE_ENTRY ? (x<<1) : x;
82 }
84 static void java_convention( int *sig, const char *s, int length ) {
85 if( LP64 && !LONGS_IN_ONE_ENTRY ) {
86 printf("LP64 and 2-reg longs not supported\n");
87 return;
88 }
89 for( int i = 0; i < length; i++ )
90 sig[i] = s[i]; // Reset sig array
91 bool is_outgoing = true;
93 int int_base = (is_outgoing ? R_O0_num : R_I0_num);
95 // Convention is to pack the first 6 int/oop args into the first 6
96 // registers (I0-I5), extras spill to the stack. Then pack the first
97 // 32 float args into F0-F31, extras spill to the stack. Then pad
98 // all register sets to align. Then put longs and doubles into the
99 // same registers as they fit, else spill to the stack.
100 int int_reg_max = SPARC_ARGS_IN_REGS_NUM;
101 int flt_reg_max = 32;
103 // Count int/oop and float args. See how many stack slots we'll need
104 // and where the longs & doubles will go.
105 int int_reg_cnt = 0;
106 int flt_reg_cnt = 0;
107 int stk_reg_pairs = 0;
108 for( int i = 0; i < length; i++) {
109 switch( sig[i] ) {
110 case Op_RegL: // Longs-in-1-reg compete with int args
111 if( LONGS_IN_ONE_ENTRY ) {
112 if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
113 }
114 break;
115 case Op_RegP:
116 if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
117 else if( !LP64 ) stk_reg_pairs++;
118 break;
119 case Op_RegI:
120 if( int_reg_cnt < int_reg_max ) int_reg_cnt++;
121 else stk_reg_pairs++;
122 break;
123 case Op_RegF:
124 if( flt_reg_cnt < flt_reg_max ) flt_reg_cnt++;
125 else stk_reg_pairs++;
126 break;
127 }
128 }
130 // This is where the longs/doubles start on the stack.
131 stk_reg_pairs = (stk_reg_pairs+1) & ~1; // Round
133 int int_reg_pairs = (int_reg_cnt+1) & ~1; // 32-bit 2-reg longs only
134 int flt_reg_pairs = (flt_reg_cnt+1) & ~1;
136 int stk_reg = 0;
137 int int_reg = 0;
138 int flt_reg = 0;
140 // Now do the signature layout
141 for( int i = 0; i < length; i++) {
142 int tmp = sig[i];
143 if( tmp == Op_RegP )
144 tmp = LP64 ? Op_RegL : Op_RegI; // Treat ptrs and ints or long accordingly
145 switch( tmp ) {
146 case Op_RegI:
147 // case Op_RegP:
148 if( int_reg < int_reg_max) tmp = INT_SCALE(int_reg++) + int_base;
149 else tmp = STACK_num + stk_reg++;
150 sig[i] = tmp;
151 break;
153 case Op_RegL:
154 if( sig[i] != Op_RegP && sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
155 // case Op_RegP:
156 if( LONGS_IN_ONE_ENTRY ) {
157 if( int_reg < int_reg_max ) {
158 tmp = INT_SCALE(int_reg++) + int_base;
159 } else {
160 tmp = STACK_num + stk_reg_pairs;
161 stk_reg_pairs += 2;
162 }
163 } else {
164 if( int_reg_pairs < int_reg_max ) {
165 tmp = int_reg_pairs + int_base;
166 int_reg_pairs += 2;
167 } else {
168 tmp = STACK_num + stk_reg_pairs;
169 stk_reg_pairs += 2;
170 }
171 }
172 sig[i] = tmp | (tmp+1)<<16; // Smear to pair
173 break;
175 case Op_RegF:
176 sig[i] = (flt_reg < flt_reg_max) ? (R_F0_num + flt_reg++) : STACK_num + stk_reg++;
177 break;
178 case Op_RegD:
179 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
180 if( flt_reg_pairs < flt_reg_max ) {
181 tmp = R_F0_num + flt_reg_pairs;
182 flt_reg_pairs += 2;
183 } else {
184 tmp = STACK_num + stk_reg_pairs;
185 stk_reg_pairs += 2;
186 }
187 sig[i] = tmp | (tmp+1)<<16; // Smear to pair
188 break;
189 case 'h': sig[i] = 0; break;
190 default:
191 printf("Bad character: %c\n", sig[i] );
192 return;
193 }
194 }
196 printf("java ");
197 printf(LP64 ? "LP64 " : "LP32 ");
198 printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: ");
199 print_convention(sig,s,length);
200 }
202 static int int_stk_helper( int i ) {
203 if( i < 6 ) return R_O0_num + (LONGS_IN_ONE_ENTRY ? i<<1 : i);
204 else return STACK_num + (LP64 ? i<<1 : i);
205 }
207 static void native_convention( int *sig, const char *s, int length ) {
208 if( LP64 && !LONGS_IN_ONE_ENTRY ) {
209 printf("LP64 and 2-reg longs not supported\n");
210 return;
211 }
212 for( int i = 0; i < length; i++ )
213 sig[i] = s[i]; // Reset sig array
215 // The native convention is V8 if !LP64, which means the V8 convention is
216 // used both with and without LONGS_IN_ONE_ENTRY, an unfortunate split. The
217 // same actual machine registers are used, but they are named differently in
218 // the LONGS_IN_ONE_ENTRY mode. The LP64 convention is the V9 convention
219 // which is slightly more sane.
221 if( LP64 ) {
222 // V9 convention: All things "as-if" on double-wide stack slots.
223 // Hoist any int/ptr/long's in the first 6 to int regs.
224 // Hoist any flt/dbl's in the first 16 dbl regs.
225 int j = 0; // Count of actual args, not HALVES
226 for( int i=0; i<length; i++, j++ ) {
227 int tmp;
228 switch( sig[i] ) {
229 case Op_RegI:
230 sig[i] = int_stk_helper( j );
231 break;
232 case Op_RegL:
233 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
234 case Op_RegP:
235 tmp = int_stk_helper( j );
236 sig[i] = tmp | ((tmp+1) << 16); // Smear to pair
237 break;
238 case Op_RegF: // V9ism: floats go in ODD registers
239 sig[i] = ((j < 16) ? R_F1_num : (STACK_num + 1)) + (j<<1);
240 break;
241 case Op_RegD: // V9ism: doubles go in EVEN/ODD regs
242 tmp = ((j < 16) ? R_F0_num : STACK_num) + (j<<1);
243 sig[i] = tmp | ((tmp+1) << 16); // Smear to pair
244 break;
245 case 'h': sig[i] = 0; j--; break; // Do not count HALVES
246 default:
247 printf("Bad character: %c\n", sig[i] );
248 return;
249 }
250 }
252 } else {
253 // V8 convention: first 6 things in O-regs, rest on stack.
254 // Alignment is willy-nilly.
255 for( int i=0; i<length; i++ ) {
256 int tmp;
257 switch( sig[i] ) {
258 case Op_RegI:
259 case Op_RegP:
260 case Op_RegF:
261 sig[i] = int_stk_helper( i );
262 break;
263 case Op_RegL:
264 case Op_RegD:
265 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; }
266 tmp = int_stk_helper( i );
267 sig[i] = tmp | (int_stk_helper( i+1 ) << 16);
268 break;
269 case 'h': sig[i] = 0; break;
270 default:
271 printf("Bad character: %c\n", sig[i] );
272 return;
273 }
274 }
275 }
277 printf("natv ");
278 printf(LP64 ? "LP64 " : "LP32 ");
279 printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: ");
280 print_convention(sig,s,length);
281 }
283 int main( int argc, char **argv ) {
285 if( argc != 2 ) {
286 printf("Usage: args IPFLhDh... (Java argument string)\n");
287 printf("Returns argument layout\n");
288 return -1;
289 }
291 const char *s = argv[1];
292 int length = strlen(s);
293 int sig[1000];
295 LP64 = false; LONGS_IN_ONE_ENTRY = false;
296 java_convention( sig, s, length );
297 LP64 = false; LONGS_IN_ONE_ENTRY = true;
298 java_convention( sig, s, length );
299 LP64 = true ; LONGS_IN_ONE_ENTRY = true;
300 java_convention( sig, s, length );
302 LP64 = false; LONGS_IN_ONE_ENTRY = false;
303 native_convention( sig, s, length );
304 LP64 = false; LONGS_IN_ONE_ENTRY = true;
305 native_convention( sig, s, length );
306 LP64 = true ; LONGS_IN_ONE_ENTRY = true;
307 native_convention( sig, s, length );
308 }