comparison src/share/vm/prims/unsafe.cpp @ 2114:4fc084dac61e

7009756: volatile variables could be broken throw reflection API Summary: Use Atomic::load() and Atomic::store() to access a volatile long. Reviewed-by: iveresov, jrose, dholmes, never
author kvn
date Fri, 07 Jan 2011 10:16:57 -0800
parents f95d63e2154a
children 3582bf76420e
comparison
equal deleted inserted replaced
2113:0e52ef6e94d3 2114:4fc084dac61e
1 /* 1 /*
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
152 oop p = JNIHandles::resolve(obj); \ 152 oop p = JNIHandles::resolve(obj); \
153 *(type_name*)index_oop_from_field_offset_long(p, offset) = x 153 *(type_name*)index_oop_from_field_offset_long(p, offset) = x
154 154
155 #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ 155 #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
156 oop p = JNIHandles::resolve(obj); \ 156 oop p = JNIHandles::resolve(obj); \
157 volatile type_name v = *(volatile type_name*)index_oop_from_field_offset_long(p, offset) 157 volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset));
158 158
159 #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \ 159 #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
160 oop p = JNIHandles::resolve(obj); \ 160 oop p = JNIHandles::resolve(obj); \
161 *(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \ 161 OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
162 OrderAccess::fence();
163 162
164 // Macros for oops that check UseCompressedOops 163 // Macros for oops that check UseCompressedOops
165 164
166 #define GET_OOP_FIELD(obj, offset, v) \ 165 #define GET_OOP_FIELD(obj, offset, v) \
167 oop p = JNIHandles::resolve(obj); \ 166 oop p = JNIHandles::resolve(obj); \
179 if (UseCompressedOops) { \ 178 if (UseCompressedOops) { \
180 volatile narrowOop n = *(volatile narrowOop*)index_oop_from_field_offset_long(p, offset); \ 179 volatile narrowOop n = *(volatile narrowOop*)index_oop_from_field_offset_long(p, offset); \
181 v = oopDesc::decode_heap_oop(n); \ 180 v = oopDesc::decode_heap_oop(n); \
182 } else { \ 181 } else { \
183 v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \ 182 v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \
184 } 183 } \
184 OrderAccess::acquire();
185 185
186 186
187 // Get/SetObject must be special-cased, since it works with handles. 187 // Get/SetObject must be special-cased, since it works with handles.
188 188
189 // The xxx140 variants for backward compatibility do not allow a full-width offset. 189 // The xxx140 variants for backward compatibility do not allow a full-width offset.
246 246
247 UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) 247 UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
248 UnsafeWrapper("Unsafe_SetObjectVolatile"); 248 UnsafeWrapper("Unsafe_SetObjectVolatile");
249 oop x = JNIHandles::resolve(x_h); 249 oop x = JNIHandles::resolve(x_h);
250 oop p = JNIHandles::resolve(obj); 250 oop p = JNIHandles::resolve(obj);
251 void* addr = index_oop_from_field_offset_long(p, offset);
252 OrderAccess::release();
251 if (UseCompressedOops) { 253 if (UseCompressedOops) {
252 oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); 254 oop_store((narrowOop*)addr, x);
253 } else { 255 } else {
254 oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); 256 oop_store((oop*)addr, x);
255 } 257 }
256 OrderAccess::fence(); 258 OrderAccess::fence();
257 UNSAFE_END 259 UNSAFE_END
260
261 #if defined(SPARC) || defined(X86)
262 // Sparc and X86 have atomic jlong (8 bytes) instructions
263
264 #else
265 // Keep old code for platforms which may not have atomic jlong (8 bytes) instructions
258 266
259 // Volatile long versions must use locks if !VM_Version::supports_cx8(). 267 // Volatile long versions must use locks if !VM_Version::supports_cx8().
260 // support_cx8 is a surrogate for 'supports atomic long memory ops'. 268 // support_cx8 is a surrogate for 'supports atomic long memory ops'.
261 269
262 UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) 270 UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
289 *addr = x; 297 *addr = x;
290 } 298 }
291 } 299 }
292 UNSAFE_END 300 UNSAFE_END
293 301
302 #endif // not SPARC and not X86
294 303
295 #define DEFINE_GETSETOOP(jboolean, Boolean) \ 304 #define DEFINE_GETSETOOP(jboolean, Boolean) \
296 \ 305 \
297 UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \ 306 UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \
298 UnsafeWrapper("Unsafe_Get"#Boolean); \ 307 UnsafeWrapper("Unsafe_Get"#Boolean); \
318 SET_FIELD(obj, offset, jboolean, x); \ 327 SET_FIELD(obj, offset, jboolean, x); \
319 UNSAFE_END \ 328 UNSAFE_END \
320 \ 329 \
321 // END DEFINE_GETSETOOP. 330 // END DEFINE_GETSETOOP.
322 331
332 DEFINE_GETSETOOP(jboolean, Boolean)
333 DEFINE_GETSETOOP(jbyte, Byte)
334 DEFINE_GETSETOOP(jshort, Short);
335 DEFINE_GETSETOOP(jchar, Char);
336 DEFINE_GETSETOOP(jint, Int);
337 DEFINE_GETSETOOP(jlong, Long);
338 DEFINE_GETSETOOP(jfloat, Float);
339 DEFINE_GETSETOOP(jdouble, Double);
340
341 #undef DEFINE_GETSETOOP
323 342
324 #define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \ 343 #define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \
325 \ 344 \
326 UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \ 345 UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \
327 UnsafeWrapper("Unsafe_Get"#Boolean); \ 346 UnsafeWrapper("Unsafe_Get"#Boolean); \
334 SET_FIELD_VOLATILE(obj, offset, jboolean, x); \ 353 SET_FIELD_VOLATILE(obj, offset, jboolean, x); \
335 UNSAFE_END \ 354 UNSAFE_END \
336 \ 355 \
337 // END DEFINE_GETSETOOP_VOLATILE. 356 // END DEFINE_GETSETOOP_VOLATILE.
338 357
339 DEFINE_GETSETOOP(jboolean, Boolean)
340 DEFINE_GETSETOOP(jbyte, Byte)
341 DEFINE_GETSETOOP(jshort, Short);
342 DEFINE_GETSETOOP(jchar, Char);
343 DEFINE_GETSETOOP(jint, Int);
344 DEFINE_GETSETOOP(jlong, Long);
345 DEFINE_GETSETOOP(jfloat, Float);
346 DEFINE_GETSETOOP(jdouble, Double);
347
348 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) 358 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
349 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte) 359 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
350 DEFINE_GETSETOOP_VOLATILE(jshort, Short); 360 DEFINE_GETSETOOP_VOLATILE(jshort, Short);
351 DEFINE_GETSETOOP_VOLATILE(jchar, Char); 361 DEFINE_GETSETOOP_VOLATILE(jchar, Char);
352 DEFINE_GETSETOOP_VOLATILE(jint, Int); 362 DEFINE_GETSETOOP_VOLATILE(jint, Int);
353 // no long -- handled specially
354 DEFINE_GETSETOOP_VOLATILE(jfloat, Float); 363 DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
355 DEFINE_GETSETOOP_VOLATILE(jdouble, Double); 364 DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
356 365
357 #undef DEFINE_GETSETOOP 366 #if defined(SPARC) || defined(X86)
367 // Sparc and X86 have atomic jlong (8 bytes) instructions
368 DEFINE_GETSETOOP_VOLATILE(jlong, Long);
369 #endif
370
371 #undef DEFINE_GETSETOOP_VOLATILE
358 372
359 // The non-intrinsified versions of setOrdered just use setVolatile 373 // The non-intrinsified versions of setOrdered just use setVolatile
360 374
361 UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) \ 375 UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x))
362 UnsafeWrapper("Unsafe_SetOrderedInt"); \ 376 UnsafeWrapper("Unsafe_SetOrderedInt");
363 SET_FIELD_VOLATILE(obj, offset, jint, x); \ 377 SET_FIELD_VOLATILE(obj, offset, jint, x);
364 UNSAFE_END 378 UNSAFE_END
365 379
366 UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) 380 UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
367 UnsafeWrapper("Unsafe_SetOrderedObject"); 381 UnsafeWrapper("Unsafe_SetOrderedObject");
368 oop x = JNIHandles::resolve(x_h); 382 oop x = JNIHandles::resolve(x_h);
369 oop p = JNIHandles::resolve(obj); 383 oop p = JNIHandles::resolve(obj);
384 void* addr = index_oop_from_field_offset_long(p, offset);
385 OrderAccess::release();
370 if (UseCompressedOops) { 386 if (UseCompressedOops) {
371 oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); 387 oop_store((narrowOop*)addr, x);
372 } else { 388 } else {
373 oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); 389 oop_store((oop*)addr, x);
374 } 390 }
375 OrderAccess::fence(); 391 OrderAccess::fence();
376 UNSAFE_END 392 UNSAFE_END
377 393
378 UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) 394 UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
379 UnsafeWrapper("Unsafe_SetOrderedLong"); 395 UnsafeWrapper("Unsafe_SetOrderedLong");
396 #if defined(SPARC) || defined(X86)
397 // Sparc and X86 have atomic jlong (8 bytes) instructions
398 SET_FIELD_VOLATILE(obj, offset, jlong, x);
399 #else
400 // Keep old code for platforms which may not have atomic long (8 bytes) instructions
380 { 401 {
381 if (VM_Version::supports_cx8()) { 402 if (VM_Version::supports_cx8()) {
382 SET_FIELD_VOLATILE(obj, offset, jlong, x); 403 SET_FIELD_VOLATILE(obj, offset, jlong, x);
383 } 404 }
384 else { 405 else {
386 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); 407 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
387 ObjectLocker ol(p, THREAD); 408 ObjectLocker ol(p, THREAD);
388 *addr = x; 409 *addr = x;
389 } 410 }
390 } 411 }
412 #endif
391 UNSAFE_END 413 UNSAFE_END
392 414
393 ////// Data in the C heap. 415 ////// Data in the C heap.
394 416
395 // Note: These do not throw NullPointerException for bad pointers. 417 // Note: These do not throw NullPointerException for bad pointers.