Mercurial > hg > truffle
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. |