Hotspot JVM 底层C/C++ 源码 入门--3 _call_stub_entry

回顾之前

static CallStub call_stub(){
	return (CallStub)(castable_address(_call_stub_entry));
}

JVM 通过call_stub()函数返回一个CallStub类型函数指针,即_call_stub_entry,再通过_call_stub_entry指向某个函数地址从而调用函数

StubRoutines::_call_stub_entry = generate_call_stub(StubRoutines::_call_stub_return_address)

_call_stub_entry初始化由generate_call_stub(),顾名思义就是产生函数首地址

address generate_call_stub(address& return_address) {
	StubCodeMark mark(this, "StubRoutines", "call_stub");
	address start = __ pc();//获取当前入口的内存地址,因为后续会继续向代码空间在写入汇编指令,后面返回start即可

	// stub code parameters / addresses
	assert(frame::entry_frame_call_wrapper_offset == 2, "adjust this code");
	bool  sse_save = false;
	const Address rsp_after_call(rbp, -4 * wordSize); // same as in generate_catch_exception()!
	const int     locals_count_in_bytes  (4*wordSize);
	//...
	const Address result        (rbp,  3 * wordSize);
	const Address result_type   (rbp,  4 * wordSize);
	const Address method        (rbp,  5 * wordSize);
	const Address entry_point   (rbp,  6 * wordSize);
	const Address parameters    (rbp,  7 * wordSize);
	const Address parameter_size(rbp,  8 * wordSize);
	const Address thread        (rbp,  9 * wordSize); // same as in generate_catch_exception()!
	sse_save =  UseSSE > 0;

	// stub code
	__ enter();//实现:push(rbp);mov(rbp,rsp);均调用emit()写入机器码
	__ movptr(rcx, parameter_size);//类似          // parameter counter
	__ shlptr(rcx, Interpreter::logStackElementSize); // convert parameter count to bytes
	__ addptr(rcx, locals_count_in_bytes);       // reserve space for register saves
	__ subptr(rsp, rcx);
	__ andptr(rsp, -(StackAlignmentInBytes));    // Align stack

	// save rdi, rsi, & rbx, according to C calling conventions
	__ movptr(saved_rdi, rdi);
	__ movptr(saved_rsi, rsi);
	__ movptr(saved_rbx, rbx);
	// save and initialize %mxcsr
	//...
	// interpreter uses xmm0 for return values
	if (UseSSE >= 1) {
	  __ movflt(Address(rdi, 0), xmm0);
	} else {
	  __ fstp_s(Address(rdi, 0));
	}
	__ jmp(exit);

	__ BIND(is_double);
	// interpreter uses xmm0 for return values
	if (UseSSE >= 2) {
	  __ movdbl(Address(rdi, 0), xmm0);
	} else {
	  __ fstp_d(Address(rdi, 0));
	}
	__ jmp(exit);

	return start;
}

pc()

第一行代码 address start = ___pc();保存当前例程所写入对应的机器码的起始位置

address pc() const {
    return _code_pos;
}

JVM启动过程中会生成很多机器码(例程)如函数调用,字节码例程,异常处理等

每一个例程都在一段连续的内存中,生成第一个例程时pc()返回0,生成了长度为20字节的机器码,而当生成第二个例程时,pc()返回20

JVM中每一个例程都对应一个generate()来生成机器码,通过全局的_code_pos来记录例程的相应信息

参数

// stub code parameters / addresses
	assert(frame::entry_frame_call_wrapper_offset == 2, "adjust this code");
	bool  sse_save = false;
	const Address rsp_after_call(rbp, -4 * wordSize); // same as in generate_catch_exception()!
	const int     locals_count_in_bytes  (4*wordSize);
	//...
	const Address result        (rbp,  3 * wordSize);
	const Address result_type   (rbp,  4 * wordSize);
	const Address method        (rbp,  5 * wordSize);
	const Address entry_point   (rbp,  6 * wordSize);

先回顾汇编调用call时堆栈模型(基础)

JVM在调用CallStub时传递8个参数,推断一下入参根据ebp的相对位置

参数位置
(address)&link8(%ebp)
result_val_address12(%ebp)
result_type16(%ebp)
......

__ enter();//实现:push(rbp);mov(rbp,rsp);均调用emit()写入机器码
	__ movptr(rcx, parameter_size);//类似          // parameter counter
	__ shlptr(rcx, Interpreter::logStackElementSize); // convert parameter count to bytes
	__ addptr(rcx, locals_count_in_bytes);       // reserve space for register saves
	__ subptr(rsp, rcx);
	__ andptr(rsp, -(StackAlignmentInBytes));    // Align stack

JVM在对被调用的java函数的堆栈大小计算,最终如下

根据parameters开始将参数压栈(汇编基础)

经过堆栈之间的处理,函数调用的资源已经准备充足,正式通过entry_point开始调用函数

// call Java function
    __ BIND(parameters_done);
    __ movptr(rbx, method);           // get Method*
    __ movptr(rax, entry_point);      // get entry_point
    __ mov(rsi, rsp);                 // set sender sp
    BLOCK_COMMENT("call Java function");
    __ call(rax);

    BLOCK_COMMENT("call_stub_return_address:");
    return_address = __ pc();

简单,将java函数的method对象首地址保存在ebx,entry_point到eax中,总体如下

开始call entry_point.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用GATK的combinegvcf模块合并gvcf文件,可是到了这一步Using GATK jar /stor9000/apps/users/NWSUAF/2022050434/biosoft/gatk4.3/gatk-4.3.0.0/gatk-package-4.3.0.0-local.jar Running: java -Dsamjdk.use_async_io_read_samtools=false -Dsamjdk.use_async_io_write_samtools=true -Dsamjdk.use_async_io_write_tribble=false -Dsamjdk.compression_level=2 -jar /stor9000/apps/users/NWSUAF/2022050434/biosoft/gatk4.3/gatk-4.3.0.0/gatk-package-4.3.0.0-local.jar CombineGVCFs -R /stor9000/apps/users/NWSUAF/2008115251/genomes/ARS-UCD1.2_Btau5.0.1Y.fa --variant /stor9000/apps/users/NWSUAF/2020055419/home/xncattle/03.GVCF/01_out_GVCF/XN_22/1_XN_22.g.vcf.gz --variant /stor9000/apps/users/NWSUAF/2020055419/home/xncattle/03.GVCF/01_out_GVCF/XN_18/1_XN_18.g.vcf.gz -O /stor9000/apps/users/NWSUAF/2022050469/candy/bwa/gatk/Combine/chr1.g.vcf.gz 09:10:40.524 INFO NativeLibraryLoader - Loading libgkl_compression.so from jar:file:/stor9000/apps/users/NWSUAF/2022050434/biosoft/gatk4.3/gatk-4.3.0.0/gatk-package-4.3.0.0-local.jar!/com/intel/gkl/native/libgkl_compression.so 09:10:50.696 INFO CombineGVCFs - ------------------------------------------------------------ 09:10:50.697 INFO CombineGVCFs - The Genome Analysis Toolkit (GATK) v4.3.0.0 09:10:50.697 INFO CombineGVCFs - For support and documentation go to https://software.broadinstitute.org/gatk/ 09:10:50.698 INFO CombineGVCFs - Executing as 2022050469@node54 on Linux v3.10.0-1127.el7.x86_64 amd64 09:10:50.698 INFO CombineGVCFs - Java runtime: Java HotSpot(TM) 64-Bit Server VM v1.8.0_72-b15 09:10:50.698 INFO CombineGVCFs - Start Date/Time: July 21, 2023 9:10:40 AM CST 09:10:50.698 INFO CombineGVCFs - ------------------------------------------------------------ 09:10:50.698 INFO CombineGVCFs - ------------------------------------------------------------ 09:10:50.698 INFO CombineGVCFs - HTSJDK Version: 3.0.1 09:10:50.699 INFO CombineGVCFs - Picard Version: 2.27.5 09:10:50.699 INFO CombineGVCFs - Built for Spark Version: 2.4.5 09:10:50.699 INFO CombineGVCFs - HTSJDK Defaults.COMPRESSION_LEVEL : 2 09:10:50.699 INFO CombineGVCFs - HTSJDK Defa就停止了,没有输出文件,也没有报错文件
最新发布
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值