谁能解释一下这个 C++代码(来自 OpenJDK6)转换成简单的英语?

发布于 2024-12-01 05:52:00 字数 2258 浏览 7 评论 0 原文

这是 OpenJDK6的hotspot/src/share/vm/prims/unsafe.cpp(从线上开始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

还添加了关键方法oopDesc::atomic_compare_exchange_oop

 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);
      }
    }

这段代码在 JVM 上下文中的用途是什么?我没有 C++ 经验。

原子::cmpxchg & Atomic::cmpxchg_ptr 成为 OS &中央处理器和32 位/64 位相关。所以这里对JVM进行了拆分。

编辑

正如 steve-O 指出的,CAS 有其弱点(如 ABA 问题),因此这里需要内存屏障来确保 CAS 在多线程环境中仍然正确。另外,由于 CAS 需要三个参数:地址、旧值和新值,因此该过程需要现代 CPU。

编辑

使用新的C++0x标准(不是现在正式发布了?),那是不是说明JVM就不需要拆分了呢?至少,在源代码级别。二进制文件仍然可以被分割,但它将由 C++ 编译器处理。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦中的蝴蝶 2024-12-08 05:52:00

它是 CAS API 的 JNI 包装器,具有 >IA64架构。

编辑:对于 CAS 的描述:

dest比较值进行比较,如果它们匹配,则将交换值分配给< em>目的地。

这是一个原子操作,这意味着没有其他处理器可以更改dest的值当操作执行时。

这里列出了在没有原子操作的情况下可能发生的典型问题,“ABA 问题”

http://en.wikipedia。 org/wiki/ABA_problem

为什么要使用 CAS 函数?

简单的例子是计数器,如果您有多个线程递增计数器,请考虑递增过程的作用:

int i;
read the value of i
add one to the current value
save the value back to i.

当另一个处理器时会发生什么读取值i 并在此处理器完成之前保存 i + 1

最终得到的是 i + 1 而不是 i + 2

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.

妳是的陽光 2024-12-08 05:52:00

一些解释

  • 以下是关于什么是 oop 以及为什么要压缩它们的


HotSpot 术语中的“oop”或“普通对象指针”是指向对象的托管指针。它通常与本机机器指针大小相同,这意味着 LP64 系统上为 64 位。在 ILP32 系统上,最大堆大小略小于 4Gb,这对于许多应用程序来说是不够的。

  • 哪些oops被压缩了?

在 ILP32 模式 JVM 中,或者如果在 LP64 模式下关闭 UseCompressedOops 标志,则所有 oop 都是本机机器字大小。

如果 UseCompressedOops 为 true,则堆中的以下 oops 将被压缩:

• 每个对象的 klass 字段
•每个oop实例字段
• oop 数组 (objArray) 的每个元素

有关详细信息,请查看此 sun wiki

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文