JVM安全點輪詢匯編函數解析

OpenJDK 17 源碼的實現邏輯,handle_polling_page_exception?函數在方法返回時的調用流程如下:

調用流程分析:

  1. 棧水印檢查觸發跳轉

    • 當線程執行方法返回前的安全點輪詢時(MacroAssembler::safepoint_poll?中?at_return=true

    • 如果棧指針超出安全區域(cmpptr?比較結果為?above),會跳轉到關聯的?slow_path?標簽

    • 這個?slow_path?標簽由?C2SafepointPollStub?管理

  2. 樁代碼生成

    • C2SafepointPollStubTable::emit()?遍歷所有安全點條目

    • 為每個條目調用?emit_stub()?生成樁代碼

    cpp

    void emit_stub(MacroAssembler& masm, C2SafepointPollStub* entry) const {select_emit_stub<VM_Version::supports_stack_watermark_barrier()>(masm, entry);
    }
  3. 樁代碼核心邏輯

    • 在?emit_stub_impl()?中生成實際匯編代碼:

      cpp

      __ bind(entry->_stub_label);
      // 計算安全點返回地址
      InternalAddress safepoint_pc(...);// 保存返回地址到線程控制塊
      __ lea(rscratch1, safepoint_pc);
      __ movptr(Address(r15_thread, JavaThread::saved_exception_pc_offset()), rscratch1);// 跳轉到異常處理入口
      __ jump(callback_addr); // callback_addr = polling_page_return_handler_blob
  4. 處理函數綁定

    • polling_page_return_handler_blob?在 JVM 初始化時創建:

      cpp

      _polling_page_return_handler_blob = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception),POLL_AT_RETURN
      );
    • 該 blob 將?handle_polling_page_exception?函數地址嵌入到生成的機器代碼中

關鍵調用路徑:

text

執行線程 → 方法返回前的輪詢檢查│├─ 棧水印檢查失敗 → 跳轉到 slow_path (C2SafepointPollStub)│    ││    └─ 樁代碼執行:│        1. 保存返回地址到 JavaThread::saved_exception_pc_offset()│        2. 跳轉到 polling_page_return_handler_blob│             ││             └─ 執行 handle_polling_page_exception()│                  ││                  └─ 安全點同步處理│└─ 正常繼續執行

技術要點:

  1. 上下文保存

    • 樁代碼通過?saved_exception_pc_offset()?保存原始返回地址

    • 確保異常處理后能正確返回到原執行點

  2. 平臺適配

    • 使用?select_emit_stub?模板實現條件編譯

    • 僅當?VM_Version::supports_stack_watermark_barrier()?為 true 時生成樁代碼

  3. 異常處理機制

    cpp

    void SafepointSynchronize::handle_polling_page_exception(JavaThread* thread) {// 1. 檢查安全點狀態// 2. 阻塞線程直到安全點操作完成// 3. 恢復線程執行(通過 saved_exception_pc 返回)
    }
  4. 水印檢查優化

    • 在 nmethod 中使用?rsp?而非?rbp,因為:

      cpp

      // 當 in_nmethod 時,棧指針已在輪詢前遞增
      cmpptr(in_nmethod ? rsp : rbp, ...);

總結:

當線程在方法返回前檢測到棧水印越界時,會通過預先生成的樁代碼跳轉到?handle_polling_page_exception?函數。該函數負責將線程掛起直到安全點操作完成,然后通過保存的返回地址恢復執行。這種機制實現了高效的安全點協作,同時保證了棧收縮時的內存安全。

##源碼

#define __ masm.
void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const {assert(SharedRuntime::polling_page_return_handler_blob() != NULL,"polling page return stub not created yet");address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point();RuntimeAddress callback_addr(stub);__ bind(entry->_stub_label);InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset);
#ifdef _LP64__ lea(rscratch1, safepoint_pc);__ movptr(Address(r15_thread, JavaThread::saved_exception_pc_offset()), rscratch1);
#elseconst Register tmp1 = rcx;const Register tmp2 = rdx;__ push(tmp1);__ push(tmp2);__ lea(tmp1, safepoint_pc);__ get_thread(tmp2);__ movptr(Address(tmp2, JavaThread::saved_exception_pc_offset()), tmp1);__ pop(tmp2);__ pop(tmp1);
#endif__ jump(callback_addr);
}
#undef __void C2SafepointPollStubTable::emit(CodeBuffer& cb) {MacroAssembler masm(&cb);for (int i = _safepoints.length() - 1; i >= 0; i--) {// Make sure there is enough space in the code bufferif (cb.insts()->maybe_expand_to_ensure_remaining(PhaseOutput::MAX_inst_size) && cb.blob() == NULL) {ciEnv::current()->record_failure("CodeCache is full");return;}C2SafepointPollStub* entry = _safepoints.at(i);emit_stub(masm, entry);}
}// The selection logic below relieves the need to add dummy files to unsupported platforms.template <bool enabled>typename EnableIf<enabled>::typeselect_emit_stub(MacroAssembler& masm, C2SafepointPollStub* entry) const {emit_stub_impl(masm, entry);}template <bool enabled>typename EnableIf<!enabled>::typeselect_emit_stub(MacroAssembler& masm, C2SafepointPollStub* entry) const {}void emit_stub(MacroAssembler& masm, C2SafepointPollStub* entry) const {select_emit_stub<VM_Version::supports_stack_watermark_barrier()>(masm, entry);}_polling_page_return_handler_blob    = generate_handler_blob(CAST_FROM_FN_PTR(address, SafepointSynchronize::handle_polling_page_exception), POLL_AT_RETURN);static SafepointBlob* polling_page_return_handler_blob()     { return _polling_page_return_handler_blob; }

##gdb堆棧

(gdb) bt
#0  C2SafepointPollStubTable::emit (this=0x7fffd0bfbb98, cb=...) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/output.cpp:237
#1  0x00007ffff6896363 in PhaseOutput::fill_buffer (this=0x7fffd0bfb950, cb=0x7fffd0bfb970, blk_starts=0x7fffb002a750)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/output.cpp:1824
#2  0x00007ffff6890444 in PhaseOutput::Output (this=0x7fffd0bfb950) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/output.cpp:432
#3  0x00007ffff602fe6b in Compile::Code_Gen (this=0x7fffd0bfde90) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/compile.cpp:2775
#4  0x00007ffff6027214 in Compile::Compile (this=0x7fffd0bfde90, ci_env=0x7fffd0bfeac0, generator=0x7ffff6959ff0 <OptoRuntime::new_instance_Type()>,stub_function=0x7ffff6958c68 <OptoRuntime::new_instance_C(Klass*, JavaThread*)> "\363\017\036\372UH\211\345H\203\354`H\211}\250H\211u\240H\213U\240H\215E\320H\211\326H\211\307\350\067\204N\377H\213M\240H\215E\340\272\001", stub_name=0x7ffff72815ea "_new_instance_Java", is_fancy_jump=0, pass_tls=true, return_pc=false, directive=0x7ffff01b1f90)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/compile.cpp:925
#5  0x00007ffff6958b70 in OptoRuntime::generate_stub (env=0x7fffd0bfeac0, gen=0x7ffff6959ff0 <OptoRuntime::new_instance_Type()>,C_function=0x7ffff6958c68 <OptoRuntime::new_instance_C(Klass*, JavaThread*)> "\363\017\036\372UH\211\345H\203\354`H\211}\250H\211u\240H\213U\240H\215E\320H\211\326H\211\307\350\067\204N\377H\213M\240H\215E\340\272\001", name=0x7ffff72815ea "_new_instance_Java", is_fancy_jump=0, pass_tls=true, return_pc=false)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/runtime.cpp:171
#6  0x00007ffff6958625 in OptoRuntime::generate (env=0x7fffd0bfeac0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/runtime.cpp:139
#7  0x00007ffff5f07753 in C2Compiler::init_c2_runtime () at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/c2compiler.cpp:78
#8  0x00007ffff5f077d7 in C2Compiler::initialize (this=0x7ffff02c01f0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/opto/c2compiler.cpp:91
#9  0x00007ffff6043287 in CompileBroker::init_compiler_runtime () at /home/yym/openjdk17/jdk17-master/src/hotspot/share/compiler/compileBroker.cpp:1801
#10 0x00007ffff6043806 in CompileBroker::compiler_thread_loop () at /home/yym/openjdk17/jdk17-master/src/hotspot/share/compiler/compileBroker.cpp:1938
#11 0x00007ffff6065c02 in CompilerThread::thread_entry (thread=0x7ffff02c08c0, __the_thread__=0x7ffff02c08c0)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/compiler/compilerThread.cpp:59
#12 0x00007ffff6b5e498 in JavaThread::thread_main_inner (this=0x7ffff02c08c0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:1305
#13 0x00007ffff6b5e32e in JavaThread::run (this=0x7ffff02c08c0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:1288
#14 0x00007ffff6b5ba31 in Thread::call_run (this=0x7ffff02c08c0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:394
#15 0x00007ffff68752bb in thread_native_entry (thread=0x7ffff02c08c0) at /home/yym/openjdk17/jdk17-master/src/hotspot/os/linux/os_linux.cpp:720
#16 0x00007ffff7c94ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#17 0x00007ffff7d26850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

##gdb堆棧

Thread 15 "C1 CompilerThre" hit Breakpoint 1, SharedRuntime::polling_page_return_handler_blob () at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/sharedRuntime.hpp:250
250       static SafepointBlob* polling_page_return_handler_blob()     { return _polling_page_return_handler_blob; }
(gdb) bt
#0  SharedRuntime::polling_page_return_handler_blob () at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/sharedRuntime.hpp:250
#1  0x00007ffff5e14d46 in C1SafepointPollStub::emit_code (this=0x7ffff0385490, ce=0x7fffd0afe0f0) at /home/yym/openjdk17/jdk17-master/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp:104
#2  0x00007ffff5e64987 in LIR_Assembler::emit_stubs (this=0x7fffd0afe0f0, stub_list=0x7fffa409c5f0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_LIRAssembler.cpp:150
#3  0x00007ffff5e649ff in LIR_Assembler::emit_slow_case_stubs (this=0x7fffd0afe0f0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_LIRAssembler.cpp:159
#4  0x00007ffff5e19a9d in Compilation::emit_code_epilog (this=0x7fffd0afe4d0, assembler=0x7fffd0afe0f0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_Compilation.cpp:291
#5  0x00007ffff5e19e18 in Compilation::emit_code_body (this=0x7fffd0afe4d0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_Compilation.cpp:355
#6  0x00007ffff5e1a12a in Compilation::compile_java_method (this=0x7fffd0afe4d0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_Compilation.cpp:404
#7  0x00007ffff5e1a470 in Compilation::compile_method (this=0x7fffd0afe4d0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_Compilation.cpp:460
#8  0x00007ffff5e1ac88 in Compilation::Compilation (this=0x7fffd0afe4d0, compiler=0x7ffff0231910, env=0x7fffd0afe9f0, method=0x7fffa40922b0, osr_bci=-1, buffer_blob=0x7fffe111cf90,install_code=true, directive=0x7ffff01b56b0) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_Compilation.cpp:584
#9  0x00007ffff5e1f184 in Compiler::compile_method (this=0x7ffff0231910, env=0x7fffd0afe9f0, method=0x7fffa40922b0, entry_bci=-1, install_code=true, directive=0x7ffff01b56b0)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/c1/c1_Compiler.cpp:247
#10 0x00007ffff6044f06 in CompileBroker::invoke_compiler_on_method (task=0x7ffff030e790) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/compiler/compileBroker.cpp:2312
#11 0x00007ffff6043a81 in CompileBroker::compiler_thread_loop () at /home/yym/openjdk17/jdk17-master/src/hotspot/share/compiler/compileBroker.cpp:1985
#12 0x00007ffff6065c02 in CompilerThread::thread_entry (thread=0x7ffff02c2340, __the_thread__=0x7ffff02c2340)at /home/yym/openjdk17/jdk17-master/src/hotspot/share/compiler/compilerThread.cpp:59
#13 0x00007ffff6b5e498 in JavaThread::thread_main_inner (this=0x7ffff02c2340) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:1305
#14 0x00007ffff6b5e32e in JavaThread::run (this=0x7ffff02c2340) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:1288
#15 0x00007ffff6b5ba31 in Thread::call_run (this=0x7ffff02c2340) at /home/yym/openjdk17/jdk17-master/src/hotspot/share/runtime/thread.cpp:394
#16 0x00007ffff68752bb in thread_native_entry (thread=0x7ffff02c2340) at /home/yym/openjdk17/jdk17-master/src/hotspot/os/linux/os_linux.cpp:720
#17 0x00007ffff7c94ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#18 0x00007ffff7d26850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/95893.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/95893.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/95893.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux怎么查看服務器開放和啟用的端口

在 Linux 系統中&#xff0c;可以通過以下方法查看 服務器開放和啟用的端口。以下是詳細的步驟和工具&#xff0c;適用于不同場景。1. 使用 ss 查看開放的端口ss 是一個現代化工具&#xff0c;用于顯示網絡連接和監聽的端口。1.1 查看正在監聽的端口運行以下命令&#xff1a;ba…

XF 306-2025 阻燃耐火電線電纜檢測

近幾年隨著我國經濟快速的發展&#xff0c;電氣火災呈現高發趨勢&#xff0c;鑒于電線電纜火災的危險性&#xff0c;國家制定了阻燃&#xff0c;耐火電線電纜的標準&#xff0c;為企業&#xff0c;建設方&#xff0c;施工方等的生產&#xff0c;選材提供了指引。XF 306-2025 阻…

【Java|第二十篇】面向對象(十)——枚舉類

目錄 &#xff08;四&#xff09;面向對象&#xff1a; 12、枚舉類&#xff1a; &#xff08;1&#xff09;概述&#xff1a; &#xff08;2&#xff09;枚舉類的定義格式&#xff1a; &#xff08;3&#xff09;編譯與反編譯&#xff1a; &#xff08;4&#xff09;Enum類…

第二十一天-OLED顯示實驗

一、OLED顯示原理1、OLED名詞解釋OLED可以自發光&#xff0c;無需背光光源。2、正點原子OLED模塊模塊總體概述模塊接口模式選擇MCU與模塊外部連接8080并口讀寫過程OLED顯存因為要進行顯示&#xff0c;所以需要有顯存。顯存容量為128 x 8 byte&#xff0c;一個點用一位表示。SSD…

會議系統核心流程詳解:創建、加入與消息交互

一、系統架構概覽 會議系統采用"主進程線程池進程池"的分層架構&#xff0c;實現高并發與業務隔離&#xff1a; #mermaid-svg-fDJ5Ja5L3rqPkby0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fDJ5Ja5L3r…

Spring 創建 Bean 的 8 種主要方式

Spring&#xff08;尤其是 Spring Boot&#xff09;提供了多種方式來讓容器創建和管理 Bean。Component、Configuration Bean、EnableConfigurationProperties 都是常見方式。 下面我為你系統地梳理 Spring 創建 Bean 的所有主要方式&#xff0c;并說明它們的使用場景和區別。…

React 第七十節 Router中matchRoutes的使用詳解及注意事項

前言 matchRoutes 是 React Router v6 提供的一個核心工具函數&#xff0c;主要用于匹配路由配置與當前路徑。它在服務端渲染&#xff08;SSR&#xff09;、數據預加載、權限校驗等場景中非常實用。下面詳細解析其用法、注意事項和案例分析&#xff1a; 1、基本用法 import { m…

iSCSI服務配置全指南(含服務器與客戶端)

iSCSI服務配置全指南&#xff08;含服務器與客戶端&#xff09;一、iSCSI簡介 1. 概念 互聯網小型計算機系統接口&#xff08;Internet Small Computer System Interface&#xff0c;簡稱iSCSI&#xff09;是一種基于TCP/IP的協議&#xff0c;其核心功能是通過IP網絡仿真SCSI高…

堆(Heap):高效的優先級隊列實現

什么是堆&#xff1f;堆是一種特殊的完全二叉樹&#xff0c;滿足以下性質&#xff1a;堆序性&#xff1a;每個節點的值與其子節點滿足特定關系最小堆&#xff1a;父節點 ≤ 子節點&#xff08;根最小&#xff09;最大堆&#xff1a;父節點 ≥ 子節點&#xff08;根最大&#xf…

朝花夕拾(四) --------python中的os庫全指南

目錄 Python os模塊完全指南&#xff1a;從基礎到高階文件操作 1. 引言&#xff1a;為什么需要os模塊&#xff1f; 1.1 os模塊的重要性 1.2 適用場景 1.3 os模塊的"瑞士軍刀"特性 2. os模塊基礎功能 2.1 文件與目錄操作 2.1.1 核心方法介紹 2.1.2 避坑指南 …

uniappx 安卓端本地打包的一些總結

本人之前沒用過android studio&#xff0c;因為有打包到安卓端的需求&#xff0c;所以有了這篇文章。下面一些內容不正常工作&#xff0c;也不報錯&#xff0c;是很煩的&#xff0c;根本不知道是哪里出了問題。比如對應的aar包沒有引入。或者沒有注冊信息。 在實現過程中我遇到…

AUTOSAR進階圖解==>AUTOSAR_SWS_UDPNetworkManagement

AUTOSAR UDP網絡管理詳解 基于AUTOSAR標準的UDP網絡管理模塊架構分析與實現指南目錄 1. 概述2. UDP網絡管理架構 2.1 整體架構圖2.2 架構組件詳解 3. UDP網絡管理狀態機 3.1 狀態機圖3.2 狀態詳解 4. UDP網絡管理操作序列 4.1 序列圖4.2 操作流程詳解 5. UDP網絡管理配置模型 …

AI搜索引擎下的內容優化新范式:GEO的關鍵技術解析

摘要&#xff1a; 生成式AI搜索引擎的崛起&#xff0c;催生了GEO&#xff08;Generative Engine Optimization&#xff09;這一新的優化領域。本文將深入剖析GEO背后的關鍵技術&#xff0c;包括深度語義理解、結構化內容生成、以及AI算法的適配性&#xff0c;旨在為品牌在AI時代…

Java Lambda表達式是什么,怎么用

這種代碼是什么&#xff0c;怎么閱讀/*** 批量插入** param entityList ignore* param batchSize ignore* return ignore*/Transactional(rollbackFor Exception.class)Overridepublic boolean saveBatch(Collection<T> entityList, int batchSize) {String sqlStateme…

集成運算放大器(反向加法,減法)

反向加法電路原理&#xff1a;示波器顯示&#xff1a;結論&#xff1a;輸出電壓-&#xff08;R4/R1*V1R4/R2*V2R4/R3*V3&#xff09;。平衡電阻R4等于R1和R2和R3的并聯電壓。減法運算電路原理&#xff1a;結論&#xff1a;減法運算電路分為三種不同情況&#xff0c;第一種情況為…

Maven入門到精通

目錄 一&#xff0c;Maven概述 1.1介紹 1.2安裝 1.3Maven生命周期和插件 1.4Maven的坐標的本地倉庫的存儲地址 二&#xff0c;依賴管理 2.1依賴管理——依賴范圍 2.2依賴管理——添加依賴 獲取依賴坐標 依賴添加后的操作 2.3依賴管理——依賴傳遞 2.4依賴管理——依…

計算機網絡 TCP 延遲確認機制

TCP 延遲確認&#xff08;Delayed Acknowledgments&#xff0c;簡稱 Delayed ACK&#xff09;是 TCP 協議中一項旨在減少網絡中小數據包數量、提升傳輸效率的優化機制。其核心思想是&#xff1a;不立即回復 ACK&#xff0c;而是等待一段時間&#xff08;通常 40ms&#xff09;&…

【visual studio】visual studio配置環境opencv和onnxruntime

下載opencv https://opencv.org/releases/?spma2ty_o01.29997173.0.0.57f4c921RELipW配置環境變量visual studio配置opencv 新建c項目選中文件后右鍵選擇屬性添加include文件夾庫文件添加lib添加lib文件 將上一步的lib文件夾下的兩個文件復制到這里以下兩者區別在于&#xff0…

【Java】多線程Thread類

1. 進程與線程進程與線程的基本認識進程&#xff08;Process&#xff09;&#xff1a;進程是程序的一次動態執行過程&#xff0c;它經歷了從代碼加載、執行、到執行完畢的一個完整過程&#xff1b;同時也是并發執行的程序在執行過程中分配和管理資源的基本單位&#xff0c;競爭…

C/C++復習(四)

一.模版 模版涉及的是泛型編程&#xff0c;即通過編譯器去確定類型的編程方式&#xff0c;模版分為&#xff1a;類模板和函數模版&#xff0c;下面我們一一復習&#xff1a; 函數模版&#xff1a; 格式&#xff1a; template<typename T1, typename T2,......,typename Tn&g…