Ceragon 的个人空间 Help

Continuation 涉及的各种结构体

Continuation

Continuation java 结构体

package jdk.internal.vm; public class Continuation { private final Runnable target; private final ContinuationScope scope; private Continuation parent; private Continuation child; private StackChunk tail; private boolean done; private volatile boolean mounted; private Object yieldInfo; private boolean preempted; private Object[] scopedValueCache; }

Continuation vm 结构体

class jdk_internal_vm_Continuation: AllStatic { oop* target; ContinuationScope* scope; Continuation* parent; Continuation* tail; bool done; bool mounted; oop* yieldInfo; bool preempted; }

StackChunk

分为 java 里的结构体和 jvm 中 C++ 结构体

StackChunk java 结构体

package jdk.internal.vm; public final class StackChunk { private StackChunk parent; private int size; private int sp; private int argsize; }

jvm 结构体

由于 vm 并没有实际定义这样一个结构体,所以还原了一下

class jdk_internal_vm_StackChunk: AllStatic { private: //--------- klass 部分 ---------- StackChunk* parent; int size; int sp; int argsize; Continuation* count; uint8_t flags; address pc; int maxThawingSize; //----------- 存储栈上数据 -------- byte stack[]; //------------ gc 所需的数据 ----- byte gc_data[]; }

size 字段的赋值

通过查询 size 的引用,找到了如下赋值的位置

class StackChunkAllocator : public MemAllocator { const size_t _stack_size; virtual oop initialize(HeapWord* mem) const override { // hs 的值是 2 const size_t hs = oopDesc::header_size(); // 将 mem + 2 后面的字节全部置0 Copy::fill_to_aligned_words(mem + hs, vmClasses::StackChunk_klass()->size_helper() - hs); // size 和 sp 都是栈大小。 // 结合下文,栈大小是需要存储的栈的大小,单位是 word_size(8字节) jdk_internal_vm_StackChunk::set_size(mem, (int)_stack_size); jdk_internal_vm_StackChunk::set_sp(mem, (int)_stack_size); } public: StackChunkAllocator(Klass* klass, size_t word_size, Thread* thread, size_t stack_size, ContinuationWrapper& continuation_wrapper, JvmtiSampledObjectAllocEventCollector* jvmti_event_collector) : MemAllocator(klass, word_size, thread), // 设置栈大小 _stack_size(stack_size), _continuation_wrapper(continuation_wrapper), _jvmti_event_collector(jvmti_event_collector), _took_slow_path(false) {} }

由于 size 的赋值和成员变量 _stack_size 有关,而该变量通过构造函数传入,所以查看构造函数的调用。查到了下面的方法。

template <typename ConfigT> stackChunkOop Freeze<ConfigT>::allocate_chunk(size_t stack_size) { InstanceStackChunkKlass* klass = InstanceStackChunkKlass::cast(vmClasses::StackChunk_klass()); // 计算出 StackChunk 的总大小 size_t size_in_words = klass->instance_size(stack_size); //............. // 创建一个分配器 StackChunkAllocator allocator(klass, size_in_words, current, stack_size, _cont, _jvmti_event_collector); // 分配一个块 stackChunkOop chunk = allocator.allocate(); return chunk; }

stack_size 是被 size_in_words 变量传递赋值的,继续查看 size_in_words 赋值方法,就是 instance_size() 这个方法

inline size_t InstanceStackChunkKlass::instance_size(size_t stack_size_in_words) const { // StackChunk 由三部分组成 // - StackChunk 的本体 // - 存储栈上的内容 // - gc 数据 return align_object_size(size_helper() + stack_size_in_words + gc_data_size(stack_size_in_words)); }

可以看到实际的 stack_size 由三部分组成,StackChunk 的基础成员变量、存储栈上内容、gc数据

oopDesc::header_size
class oopDesc { volatile markWord _mark; union _metadata { Klass* _klass; narrowKlass _compressed_klass; } _metadata; static constexpr int header_size() { // sizeof(oopDesc): 由两部分组成,mark 和 _metadata指针。不考虑压缩指针的情况,值是 8 + 8 = 16 字节。 // HeapWordSize: vm 中指针的字节数。不开启压缩指针是 8 字节 // 最终值是 2 return sizeof(oopDesc)/HeapWordSize; } }

argsize 字段的赋值

该字段的赋值和 freeze 有关. 详情

Last modified: 27 December 2023