上一篇主要分析了HotSpot模板解释器和汇编器的实现,相比于c解释器,通过汇编器和模板解释器将字节码指令编译成汇编指令,显著提升了HotSpot的性能。除此之外HotSpot更进一步实现了C1,C2编译器用于在服务端选择性的进一步编译优化指令。提供了Tiered分层编译,内置LLVM,AOT编译等,此外基于Java语言实现的 GraalVm 全栈编译器也势头强劲。

一.初始化C1编译器

hotspot/src/share/vm/runtime/thread.cpp
创建HotSpot虚拟机时会初始化编译器

jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {CompileBroker::compilation_init(CHECK_JNI_ERR);
}

hotspot/src/share/vm/compiler/compileBroker.cpp

void CompileBroker::compilation_init(TRAPS) {init_compiler_sweeper_threads(c1_count, c2_count);
}

hotspot/src/share/vm/compiler/compileBroker.cpp
按c1_compiler_count值创建多个编译线程,线程持有编译任务队列

void CompileBroker::init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count) {_c1_compile_queue  = new CompileQueue("C1 compile queue");for (int i = 0; i < c1_compiler_count; i++) {CompilerCounters* counters = new CompilerCounters();make_thread(name_buffer, _c1_compile_queue, counters, _compilers[1], compiler_thread, CHECK);}
}

hotspot/src/share/vm/compiler/compileBroker.cpp

JavaThread* CompileBroker::make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters,AbstractCompiler* comp, bool compiler_thread, TRAPS) {thread = new CompilerThread(queue, counters);Thread::start(thread);
}

hotspot/src/share/vm/runtime/thread.cpp
初始化编译线程时挂载一个执行函数compiler_thread_entry

CompilerThread::CompilerThread(CompileQueue* queue,CompilerCounters* counters): JavaThread(&compiler_thread_entry) {_queue = queue;_counters = counters;_buffer_blob = NULL;_compiler = NULL;
}

hotspot/src/share/vm/runtime/thread.cpp
执行函数会在线程创建完成之后调用compiler_thread_loop,通知编译器开始线程循环

static void compiler_thread_entry(JavaThread* thread, TRAPS) {CompileBroker::compiler_thread_loop();
}

hotspot/src/share/vm/compiler/compileBroker.cpp
while循环执行,从任务队列中取出已提交的编译任务,调用invoke_compiler_on_method派发编译

void CompileBroker::compiler_thread_loop() {CompilerThread* thread = CompilerThread::current();CompileQueue* queue = thread->queue();//初始化编译环境init_compiler_runtime()//循环从编译任务队列里取编译任务并执行while (!is_compilation_disabled_forever()) {CompileTask* task = queue->get();// Assign the task to the current thread.  Mark this compilation// thread as active for the profiler.CompileTaskWrapper ctw(task);nmethodLocker result_handle;  // (handle for the nmethod produced by this task)task->set_code_handle(&result_handle);methodHandle method(thread, task->method());//......//编译任务invoke_compiler_on_method(task);//......// Shut down compiler runtimeshutdown_compiler_runtime(thread->compiler(), thread);
}

hotspot/src/share/vm/compiler/compileBroker.cpp
收到编译任务后,从task取出对应需要使用的编译器,调用compile_method

void CompileBroker::invoke_compiler_on_method(CompileTask* task) {CompilerThread* thread = CompilerThread::current();uint compile_id = task->compile_id();int osr_bci = task->osr_bci();bool is_osr = (osr_bci != standard_entry_bci);const int task_level = task->comp_level();AbstractCompiler* comp = task->compiler();methodHandle method(thread, task->method());// Allocate a new set of JNI handles.push_jni_handle_block();Method* target_handle = task->method();int compilable = ciEnv::MethodCompilable;{ciEnv ci_env(task, system_dictionary_modification_counter);//执行编译comp->compile_method(&ci_env, target, osr_bci, directive);// Copy this bit to the enclosing block:compilable = ci_env.compilable();post_compile(thread, task, event, !ci_env.failing(), &ci_env);}// Remove the JNI handle block after the ciEnv destructor has run in// the previous block.pop_jni_handle_block();// Disable compilation, if required.switch (compilable) {case ciEnv::MethodCompilable_never:if (is_osr)method->set_not_osr_compilable_quietly();elsemethod->set_not_compilable_quietly();break;case ciEnv::MethodCompilable_not_at_tier:if (is_osr)method->set_not_osr_compilable_quietly(task_level);elsemethod->set_not_compilable_quietly(task_level);break;}
}

hotspot/src/share/vm/c1/c1_Compiler.cpp
执行Compilation初始化,Compilation构造函数将调用compile_method

void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();Compilation c(this, env, method, entry_bci, buffer_blob, directive);
}

二.触发和提交编译任务

hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp
编译器环境初始化好以后循环等待编译任务到来,HosSpot中在generate_normal_entry这个entry_point会埋点统计当前方法的执行次数,当方法执行次数超过指定阀值时会触发JIT

address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {......// Handle overflow of counter and compile method__ bind(invocation_counter_overflow);generate_counter_overflow(continue_after_compile);
}

hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp

void TemplateInterpreterGenerator::generate_counter_overflow(Label& do_continue) {__ call_VM(noreg,CAST_FROM_FN_PTR(address,InterpreterRuntime::frequency_counter_overflow),rarg);__ movptr(rbx, Address(rbp, method_offset));   // restore Method*__ jmp(do_continue, relocInfo::none);
}

hotspot/src/share/vm/interpreter/interpreterRuntime.cpp

nmethod* InterpreterRuntime::frequency_counter_overflow(JavaThread* thread, address branch_bcp) {nmethod* nm = frequency_counter_overflow_inner(thread, branch_bcp);
}

hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
触发编译执行策略

IRT_ENTRY(nmethod*,InterpreterRuntime::frequency_counter_overflow_inner(JavaThread* thread, address branch_bcp))nmethod* osr_nm = CompilationPolicy::policy()->event(method, method, branch_bci, bci, CompLevel_none, NULL, thread);

hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp

nmethod* SimpleThresholdPolicy::event(const methodHandle& method, const methodHandle& inlinee,int branch_bci, int bci, CompLevel comp_level, CompiledMethod* nm, JavaThread* thread) {method_back_branch_event(method, inlinee, bci, comp_level, nm, thread);
}

hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp

void AdvancedThresholdPolicy::method_back_branch_event(const methodHandle& mh, const methodHandle& imh,int bci, CompLevel level, CompiledMethod* nm, JavaThread* thread) {compile(mh, InvocationEntryBci, next_level, thread);
}

hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
提交编译

void SimpleThresholdPolicy::compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) {submit_compile(mh, bci, level, thread);
}

hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp

void AdvancedThresholdPolicy::submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) {int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count();update_rate(os::javaTimeMillis(), mh());CompileBroker::compile_method(mh, bci, level, mh, hot_count, CompileTask::Reason_Tiered, thread);
}

hotspot/src/share/vm/compiler/compileBroker.cpp

nmethod* CompileBroker::compile_method(const methodHandle& method, ...) {compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, compile_reason, is_blocking, THREAD);
}

hotspot/src/share/vm/compiler/compileBroker.cpp
创建编译任务

void CompileBroker::compile_method_base(const methodHandle& method,int osr_bci,...) {task = create_compile_task(queue,compile_id, method,osr_bci, comp_level,hot_method, hot_count, compile_reason,blocking);
}

hotspot/src/share/vm/compiler/compileBroker.cpp
创建任务并将编译任务加入到任务队列

CompileTask* CompileBroker::create_compile_task(CompileQueue*       queue, ...) {CompileTask* new_task = CompileTask::allocate();new_task->initialize(compile_id, method, osr_bci, comp_level,hot_method, hot_count, compile_reason,blocking);queue->add(new_task);return new_task;
}

三.C1编译流程

hotspot/src/share/vm/c1/c1_Compilation.cpp
当编译线程循环从任务队列拿到一个编译任务时,会构造Compilation并执行compile_method

Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive){compile_method();
}

执行C1编译,安装编译好的代码
hotspot/src/share/vm/c1/c1_Compilation.cpp

void Compilation::compile_method() {//初始化编译环境initialize();//这里开始真正执行java方法的编译int frame_size = compile_java_method();//编译完成以后进行原方法替换install_code(frame_size);totalInstructionNodes += Instruction::number_of_instructions();
}

hotspot/src/share/vm/c1/c1_Compilation.cpp

编译流程分三步:

  1. HIR阶段:构建CFG流程图,根据流程图进行数据流优化
  2. LIR阶段:为指令操作数分配虚拟寄存器,根据变量存活周期采用线性扫描算法分配物理寄存器
  3. 发射阶段:LIR宏汇编器优化,存储编译好的机器码到内存缓冲区
int Compilation::compile_java_method() {//编译字节码为中间表示HIRbuild_hir();//编译HIR为低级表示LIRemit_lir();//编译结果存贮return emit_code_body();
}

1.HIR阶段

hotspot/src/share/vm/c1/c1_Compilation.cpp

void Compilation::build_hir() { //构建HIR_hir = new IR(this, method(), osr_bci());//各种编译优化_hir->optimize_blocks();_hir->split_critical_edges();_hir->compute_code();//访问越界优化RangeCheckElimination::eliminate(_hir);//null检查优化_hir->eliminate_null_checks();_hir->compute_use_counts();
}

hotspot/src/share/vm/c1/c1_IR.cpp
构建IR

IR::IR(Compilation* compilation, ciMethod* method, int osr_bci) :_num_loops(0) {// setup IR fields_compilation = compilation;_top_scope   = new IRScope(compilation, NULL, -1, method, osr_bci, true);_code        = NULL;
}

hotspot/src/share/vm/c1/c1_IR.cpp
构建IRScope

IRScope::IRScope(Compilation* compilation, IRScope* caller, int caller_bci, ciMethod* method, int osr_bci, bool create_graph)
: _callees(2)
, _compilation(compilation)
, _requires_phi_function(method->max_locals())
{......//构建CFG流程图if (create_graph && monitor_pairing_ok()) _start = build_graph(compilation, osr_bci);
}

hotspot/src/share/vm/c1/c1_IR.cpp
构建CFG图

BlockBegin* IRScope::build_graph(Compilation* compilation, int osr_bci) {GraphBuilder gm(compilation, this);return gm.start();
}

hotspot/src/share/vm/c1/c1_GraphBuilder.cpp

GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
{int osr_bci = compilation->osr_bci();//构建所有块BlockListBuilder blm(compilation, scope, osr_bci);//字节码到块的映射BlockList* bci2block = blm.bci2block();BlockBegin* start_block = bci2block->at(0);push_root_scope(scope, bci2block, start_block);//块合并_initial_state = state_at_entry();start_block->merge(_initial_state);//完成图构建_vmap        = new ValueMap();switch (scope->method()->intrinsic_id()) {//......// Otherwise, fall thru}default:scope_data()->add_to_work_list(start_block);iterate_all_blocks();break;}//块图入口_start = setup_start_block(osr_bci, start_block, _osr_entry, _initial_state);}

hotspot/src/share/vm/c1/c1_GraphBuilder.cpp

BlockListBuilder::BlockListBuilder(Compilation* compilation, IRScope* scope, int osr_bci)
{//生成起始块set_entries(osr_bci);//根据指令数量构建所有块,存储在_bci2block(字节码和块映射)和_blocks(块列表),并为当前块构建前驱和后驱set_leaders();//处理块循环mark_loops();}

2.LIR阶段

hotspot/src/share/vm/c1/c1_Compilation.cpp

void Compilation::emit_lir() {LIRGenerator gen(this, method());hir()->iterate_linear_scan_order(&gen);{LinearScan* allocator = new LinearScan(hir(), &gen, frame_map());set_allocator(allocator);//线性扫描算法,赋值物理寄存器给LIR操作数allocator->do_linear_scan();_max_spills = allocator->max_spills();}
}

3.发射阶段

hotspot/src/share/vm/c1/c1_Compilation.cpp
C1_MacroAssembler继承自MacroAssembler

int Compilation::emit_code_body() {// emit code_masm = new C1_MacroAssembler(code());LIR_Assembler lir_asm(this);//发射代码lir_asm.emit_code(hir()->code());//CodeStubemit_code_epilog(&lir_asm);generate_exception_handler_table();return frame_map()->framesize();
}

hotspot/src/share/vm/c1/c1_LIRAssembler.cpp

void LIR_Assembler::emit_code(BlockList* hir) {int n = hir->length();for (int i = 0; i < n; i++) {emit_block(hir->at(i));}
}

hotspot/src/share/vm/c1/c1_LIRAssembler.cpp

void LIR_Assembler::emit_block(BlockBegin* block) {......emit_lir_list(block->lir());......
}

hotspot/src/share/vm/c1/c1_LIRAssembler.cpp

void LIR_Assembler::emit_lir_list(LIR_List* list) {int n = list->length();for (int i = 0; i < n; i++) {LIR_Op* op = list->at(i);check_codespace();op->emit_code(this);
}

hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp

#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"

4.代码安装

hotspot/src/share/vm/c1/c1_Compilation.cpp

void Compilation::install_code(int frame_size) {_env->register_method(method(),osr_bci(),...));
}

hotspot/src/share/vm/ci/ciEnv.cpp

void ciEnv::register_method(ciMethod* target,...) {nm =  nmethod::new_nmethod(method,compile_id(),...);// Free codeBlobscode_buffer->free_blob();task()->set_code(nm);if (entry_bci == InvocationEntryBci) {//栈上替换method->set_code(method, nm);}
}

hotspot/src/share/vm/oops/method.cpp
替换栈上方法,同时修改entry_point,实时替换可被立即执行

void Method::set_code(methodHandle mh, CompiledMethod *code) {mh->_code = code; OrderAccess::storestore();
#ifdef SHARKmh->_from_interpreted_entry = code->insts_begin();
#else //!SHARKmh->_from_compiled_entry = code->verified_entry_point();OrderAccess::storestore();// Instantly compiled code can execute.if (!mh->is_method_handle_intrinsic())mh->_from_interpreted_entry = mh->get_i2c_entry();
#endif //!SHARK
}

四.CFG图分析

修改之前的Hello类,添加add方法,循环一万次触发阈值编译

public class Hello{public static void main(String[] args){int index = 0;for(int i = 0; i < 10000; i++){index = add(i);}System.out.println("hello world !" + index);}public static int add(int i) {i++;return i;}}

执行命令追加 -XX:+PrintCFGToFile 将编译CFG流程输出到本地 .cfg文件,查找Hello的add控制流段取出。

begin_block --> end_block 代表控制流图中的一个节点,节点与节点之间通过sucessors和predecessors来链接。

begin_blockname "B0"from_bci 0to_bci -1predecessors successors xhandlersflags "std" end_block

add 对应的字节码

0:iinc 1,1
3:iload_1
4:ireturn

HIR后得到的中间表示,HIR通过SSA每个变量分配一个编号

0 0 i2 1 <|@
0 0 i3 i1 + i2 <|@
.4 0 i4 ireturn i3 <|@

begin_intervals -->end_intervals之间表示线性扫描算法得到的寄存器生命周期

begin_intervalsname "Before Register Allocation"
0 fixed "[rsi|I]" 0 -1 [0, 4[  "no definition"
3 fixed "[rax|I]" 3 572 [0, 1[ [34, 36[  "no spill store"
569 int 569 0 [4, 30[ 4 M 30 S  "no spill store"
570 long 570 -1 [6, 12[ 6 M 8 M 12 M  "no spill store"
571 int 571 -1 [8, 16[ 8 M 10 M 12 M 14 M 16 M  "no optimization"
572 int 572 569 [30, 34[ 30 M 32 M 34 S  "no spill store"
end_intervals

经过LIR阶段后

  begin_LIR28 label [label:0x00007f93643ae400] <|@ 32 add [rsi|I] [int:1|I] [rsi|I] <|@ 34 move [rsi|I] [rax|I]  <|@ 36 return [rax|I]   <|@ end_LIR

add方法完整的CFG

begin_compilationname " Hello::add"method "static jint Hello.add(jint)"date 1599640056921
end_compilation
begin_cfgbegin_blockname "B0"from_bci 0to_bci -1predecessors successors xhandlersflags "std" end_block
end_cfg
begin_cfgname "After Generation of HIR"begin_blockname "B1"from_bci 0to_bci 0predecessors successors "B2" xhandlersflags begin_statesbegin_localssize 1method "static jint Hello.add(jint)"0  i1end_localsend_statesbegin_HIR
.0 0  8 std entry B2 <|@end_HIRend_blockbegin_blockname "B2"from_bci 0to_bci 0predecessors "B1" successors "B0" xhandlersflags "std" begin_statesbegin_localssize 1method "static jint Hello.add(jint)"0  i1end_localsend_statesbegin_HIR
.0 0  7 goto B0 <|@end_HIRend_blockbegin_blockname "B0"from_bci 0to_bci 4predecessors "B2" successors xhandlersflags "std" begin_statesbegin_localssize 1method "static jint Hello.add(jint)"0  i1end_localsend_statesbegin_HIR
0 0 i2 1 <|@
0 0 i3 i1 + i2 <|@
.4 0 i4 ireturn i3 <|@end_HIRend_block
end_cfg
//掐掉了一些优化流程
begin_cfgname "Before Register Allocation"begin_blockname "B1"from_bci 0to_bci 0predecessors successors "B2" xhandlersflags first_lir_id 0last_lir_id 22begin_statesbegin_localssize 1method "static jint Hello.add(jint)"0  i1 "[R569|I]" end_localsend_statesbegin_HIR
.0 0  8 std entry B2 <|@end_HIRbegin_LIR0 label [label:0x00007f93643af030] <|@ 2 std_entry  <|@ 4 move [rsi|I] [R569|I]  <|@ 6 move [lng:140270052721192|J] [R570|J]  <|@ 8 move [Base:[R570|J] Disp: 32|I] [R571|I]  <|@ 10 add [R571|I] [int:8|I] [R571|I] <|@ 12 move [R571|I] [Base:[R570|J] Disp: 32|I]  <|@ 14 logic_and [R571|I] [int:16376|I] [R571|I] <|@ 16 cmp [EQ] [R571|I] [int:0|I]  <|@ 18 branch [EQ] [CounterOverflowStub: 0x00007f92f403d290] <|@ 20 label [label:0x00007f92f403d2b8] <|@ 22 branch [AL] [B2]  <|@ end_LIRend_blockbegin_blockname "B2"from_bci 0to_bci 0predecessors "B1" successors "B0" xhandlersflags "std" dominator "B1"first_lir_id 24last_lir_id 26begin_statesbegin_localssize 1method "static jint Hello.add(jint)"0  i1 "[R569|I]" end_localsend_statesbegin_HIR
.0 0  7 goto B0 <|@end_HIRbegin_LIR24 label [label:0x00007f93643af2a0] <|@ 26 branch [AL] [B0]  <|@ end_LIRend_blockbegin_blockname "B0"from_bci 0to_bci 4predecessors "B2" successors xhandlersflags "std" dominator "B2"first_lir_id 28last_lir_id 36begin_statesbegin_localssize 1method "static jint Hello.add(jint)"0  i1 "[R569|I]" end_localsend_statesbegin_HIR
0 1 i2 1 <|@
.0 2  "[R572|I]" i3 i1 + i2 <|@
.4 0 i4 ireturn i3 <|@end_HIRbegin_LIR28 label [label:0x00007f93643ae400] <|@ 30 move [R569|I] [R572|I]  <|@ 32 add [R572|I] [int:1|I] [R572|I] <|@ 34 move [R572|I] [rax|I]  <|@ 36 return [rax|I]   <|@ end_LIRend_block
end_cfg
begin_intervalsname "Before Register Allocation"
0 fixed "[rsi|I]" 0 -1 [0, 4[  "no definition"
3 fixed "[rax|I]" 3 572 [0, 1[ [34, 36[  "no spill store"
569 int 569 0 [4, 30[ 4 M 30 S  "no spill store"
570 long 570 -1 [6, 12[ 6 M 8 M 12 M  "no spill store"
571 int 571 -1 [8, 16[ 8 M 10 M 12 M 14 M 16 M  "no optimization"
572 int 572 569 [30, 34[ 30 M 32 M 34 S  "no spill store"
end_intervals
begin_intervalsname "After Register Allocation"
0 fixed "[rsi|I]" 0 -1 [0, 4[  "no definition"
3 fixed "[rax|I]" 3 572 [0, 1[ [34, 36[  "no spill store"
569 int "[rsi|I]" 569 0 [4, 30[ 4 M 30 S  "no spill store"
570 long "[raxrax|J]" 570 -1 [6, 12[ 6 M 8 M 12 M  "no spill store"
571 int "[rdi|I]" 571 -1 [8, 16[ 8 M 10 M 12 M 14 M 16 M  "no optimization"
572 int "[rsi|I]" 572 569 [30, 34[ 30 M 32 M 34 S  "no spill store"
end_intervals
begin_cfgname "Before Code Generation"begin_blockname "B1"from_bci 0to_bci 0predecessors successors "B2" xhandlersflags first_lir_id 0last_lir_id 22begin_LIR0 label [label:0x00007f93643af030] <|@ 2 std_entry  <|@ 6 move [lng:140270052721192|J] [raxrax|J]  <|@ 8 move [Base:[raxrax|J] Disp: 32|I] [rdi|I]  <|@ 10 add [rdi|I] [int:8|I] [rdi|I] <|@ 12 move [rdi|I] [Base:[raxrax|J] Disp: 32|I]  <|@ 14 logic_and [rdi|I] [int:16376|I] [rdi|I] <|@ 16 cmp [EQ] [rdi|I] [int:0|I]  <|@ 18 branch [EQ] [CounterOverflowStub: 0x00007f92f403d290] <|@ 20 label [label:0x00007f92f403d2b8] <|@ end_LIRend_blockbegin_blockname "B2"from_bci 0to_bci 0predecessors "B1" successors "B0" xhandlersflags "std" dominator "B1"first_lir_id 24last_lir_id 26begin_LIR24 label [label:0x00007f93643af2a0] <|@ end_LIRend_blockbegin_blockname "B0"from_bci 0to_bci 4predecessors "B2" successors xhandlersflags "std" dominator "B2"first_lir_id 28last_lir_id 36begin_LIR28 label [label:0x00007f93643ae400] <|@ 32 add [rsi|I] [int:1|I] [rsi|I] <|@ 34 move [rsi|I] [rax|I]  <|@ 36 return [rax|I]   <|@ end_LIRend_block
end_cfg

C1编译器的优化相比C2要弱,所以编译速度较C2快,代码产出质量较C2低一些。JIT通过调用计数和回边计数触发方法编译,被编译的方法将封装到一个编译Task中,然后将这个Task放到任务队列中。C1随虚拟机启动后,运行一个编译线程从任务队列中循环取任务执行编译。编译器将字节码取出经过HIR,LIR两个阶段的编译优化生成优化后的代码。优化后的代码存储到CodeBuffer中。编译完成以后的代码对应着一个nmethod。在最后阶段install_code将进行栈上替换。

HotSpot C1编译器与栈上替换相关推荐

  1. [Inside HotSpot] C1编译器HIR的构造

    1. 简介 这篇文章可以说是Christian Wimmer硕士论文Linear Scan Register Allocation for the Java HotSpot™ Client Compi ...

  2. 一文带你学明白java虚拟机:C1编译器,HIR代码优化

    HIR代码优化 为了减少编译时间,C1在抽象解释生成HIR期间,每生成一条SSA指令,都会调用append_with_bci努力尝试若干局部优化.除此之外,HIR构造完成之后,C1还会执行若干轻量级全 ...

  3. HotSpot C2编译器

     可以先看看前同事Vladimir Ivanov讲解JIT编译器: JIT-compiler in JVM seen by a Java developer, Vladimir Ivanov, J ...

  4. 只能在堆或只能在栈上分配内存的类

    只能在堆上分配内存的类 方法:将析构函数设置为私有 原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性.若析构函数不可访问,则不能在 ...

  5. c++如何定义一个只能在堆上(栈上)生成对象的类?

    只能在堆上 方法:将析构函数设置为私有 原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性.若析构函数不可访问,则不能在栈上创建对象 ...

  6. java让对象分配在栈上_java – Hotspot何时可以在堆栈上分配对象?

    我做了一些实验,以便了解Hotspot何时可以进行堆栈分配.事实证明,它的堆栈分配比基于available documentation的预期要有限得多.Choi"Escape Analysi ...

  7. GC分类、TLAB、逃逸分析、栈上分配、同步消除、标量替换

    GC分类 JVM的调优的一个环节,也就是垃圾收集,我们需要尽量的避免垃圾回收,因为在垃圾回收的过程中,容易出现STW(Stop the World)的问题,而 Major GC 和 Full GC出现 ...

  8. JVM逃逸分析(同步省略、标量替换、栈上分配)

    在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件.第二段编译是把.class转换成机器指令的过程. ...

  9. java标量替换_JAVA逃逸分析、栈上分配、标量替换、同步消除

    一.逃逸分析 逃逸分析是编译语言中的一种优化分析,而不是一种优化的手段.通过对象的作用范围的分析,为其他优化手段提供分析数据从而进行优化. 逃逸分析包括: 全局变量赋值逃逸 方法返回值逃逸 实例引用发 ...

最新文章

  1. 【坑爹升级】更新NVIDIA GeForce GTX Ti最新驱动,突然屏幕亮瞎我24K钛合金双眼。导致Fn+F2/F3、win+x无法控制笔记本电脑显示器亮度调整, 电源选项屏幕亮度也不见了!
  2. SpringBoot第十三篇:springboot集成spring cache
  3. java jni调用dll文件_Java通过jni调用动态链接库
  4. Android中五种常用的menu
  5. #1300 : 展胜地的鲤鱼旗(dp)
  6. Spring Boot和Spring数据JPA集成
  7. OGEngine教程:声音载入
  8. 来,一起“八卦”一下数据湖
  9. 把java复制到e_编写一个程序,将e:\java目录下的所有.java文件复制到e:\jad目录下...
  10. Python 协程gevent
  11. 20050405:什么都要会啊
  12. 天正双击墙体不能编辑_入门必备!20个超实用天正CAD技巧,设计院高手都在收藏...
  13. 电力系统稳定与控制_风电场柔性直流系统组网型控制关键技术
  14. NVME格式硬盘SSD安装WIN7蓝屏(0x000007B)解决方法
  15. 浏览器漏洞种类复杂多样
  16. 微信公众号图灵机器人开发php,使用图灵机器人api搭建微信聊天机器人php实现,图灵微信聊天机器人...
  17. Redis RU101课程 Introduction to Redis Data Structures 第5周学习笔记
  18. 索引的使用以及常见索引类型,组合索引的具体使用方法。
  19. qt android png透明,Qt处理照片实现白色背景转透明
  20. 网易白帽子黑客训练营笔记(1)

热门文章

  1. 如何成长为优秀的架构师?架构师成长的4大必经之路
  2. 活动|苏宁撒钱送你30元,先到先得!千万别错过
  3. Html.Partial()与Html.RenderPartial()区别
  4. ubuntu 12.04 安装深度影音播放器(deepin-music-player)+百度音乐插件
  5. 云计算平台对于智慧防雷事业的重要性
  6. 2019有的图纸打印出来看不清楚_CAD图纸转成PDF四周空白多,利用这一招轻松解决空白多的问题...
  7. 关于CommandTimeOut
  8. DBeaver,杀出重围!
  9. freedownloadmanager 下载工具,代替 讯雷
  10. 濒临倒闭的瑜伽馆,只用20天时间就实现逆转,并收入100万!