Here's a code snippet from OpenJDK6's hotspot/src/share/vm/prims/unsafe.cpp
(starting on line 1082):
// JSR166 ------------------------------------------------------------------
UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
UnsafeWrapper("Unsafe_CompareAndSwapObject");
oop x = JNIHandles::resolve(x_h);
oop e = JNIHandles::resolve(e_h);
oop p = JNIHandles::resolve(obj);
HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
if (UseCompressedOops) {
update_barrier_set_pre((narrowOop*)addr, e);
} else {
update_barrier_set_pre((oop*)addr, e);
}
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);
jboolean success = (res == e);
if (success)
update_barrier_set((void*)addr, x);
return success;
UNSAFE_END
The key method oopDesc::atomic_compare_exchange_oop is added also.
inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value,
volatile HeapWord *dest,
oop compare_value) {
if (UseCompressedOops) {
// encode exchange and compare value from oop to T
narrowOop val = encode_heap_oop(exchange_value);
narrowOop cmp = encode_heap_oop(compare_value);
narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp);
// decode old from T to oop
return decode_heap_oop(old);
} else {
return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value);
}
}
What is the purpose of this code in the context of the JVM? I'm not experienced in C++.
Atomic::cmpxchg & Atomic::cmpxchg_ptr becomes OS & CPU & 32bit/64bit dependent. So JVMs are splitted here.
EDIT
As steve-O pointed out, CAS has its weakness as ABA problem, so memory barrier is necessary here to ensure the CAS is still correct in multithread environment. Also as CAS would need three paramter the address,old value and new value,so modern CPU is required for this process.
EDIT
With the new C++0x standard (not formal published now?) , does it mean that JVM don't need to be spliited then? At least, in the source code level. The binary could be still splitted but it will be handled by the C++ compiler.
It is a JNI wrapper for the CAS API, with memory barriers for IA64 architecture.
edit: for a description of CAS:
Compare dest with compare value and if they match assign exchange value to dest.
It is an atomic operation which means no other processor can change the value of dest whilst the operation executes.
Typical problems that can occur without atomic operations are listed here, the "ABA problem"
http://en.wikipedia.org/wiki/ABA_problem
Why would you use a CAS function?
Easy example is a counter, if you have multiple threads incrementing a counter consider what the increment process does:
int i;
read the value of i
add one to the current value
save the value back to i.
What happens when another processor reads the value of i and saves i + 1 before this processor has completed?
You end up with i + 1 instead of i + 2.
Here are some interprets about
- What's an oop, and why should they be compressed?
An "oop", or "ordinary object pointer" in HotSpot parlance is a managed pointer to an object. It is normally the same size as a native machine pointer, which means 64 bits on an LP64 system. On an ILP32 system, there is a maximum heap size of somewhat less than 4Gb, which is not enough for many applications.
- Which oops are compressed?
In an ILP32-mode JVM, or if the UseCompressedOops flag is turned off in LP64 mode, all oops are the native machine word size.
If UseCompressedOops is true, the following oops in the heap will be compressed:
•the klass field of every object •every oop instance field •every element of an oop array (objArray)
For details, looks into this sun wiki
来源:https://stackoverflow.com/questions/7169961/can-anyone-interpret-this-c-code-from-openjdk6-into-plain-english