原创文章,转载请注明: 转载自慢慢的回味
本文链接地址: Hotspot JIT编译(C1)
上一篇文章介绍了JVM怎么用template interpreter来完成字节码到机器码的映射,但是频繁的取指,译指,然后执行,性能会有所损耗。所以hotspot对频繁执行的方法进行编译优化能大大缩短代码执行时间。
这儿以编译器C1来说明JIT编译,过程主要包括生成BlockList,生成HIR,发射LIR,寄存器分配,生成机器码,代码安装。对应的代码位置为jdk8\hotspot\src\share\vm\c1。
1 字节码
以String.indexOf(int,int)方法的编译为例:
//LineNo SourceCode 1545 public int indexOf(int ch, int fromIndex) { 1546 final int max = value.length; 1547 if (fromIndex < 0) { 1548 fromIndex = 0; 1549 } else if (fromIndex >= max) { 1550 // Note: fromIndex might be near -1>>>1. 1551 return -1; 1552 } 1553 1554 if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { 1555 // handle most cases here (ch is a BMP code point or a 1556 // negative value (invalid code point)) 1557 final char[] value = this.value; 1558 for (int i = fromIndex; i < max; i++) { 1559 if (value[i] == ch) { 1560 return i; 1561 } 1562 } 1563 return -1; 1564 } else { 1565 return indexOfSupplementary(ch, fromIndex); 1566 } 1567 } //BCI(Byte Code Index): ByteCode 0: aload_0 1: getfield #423 // Field value:[C 4: arraylength 5: istore_3 6: iload_2 7: ifge 15 10: iconst_0 11: istore_2 12: goto 22 15: iload_2 16: iload_3 17: if_icmplt 22 20: iconst_m1 21: ireturn 22: iload_1 23: ldc #4 // int 65536 25: if_icmpge 63 28: aload_0 29: getfield #423 // Field value:[C 32: astore 4 34: iload_2 35: istore 5 37: iload 5 39: iload_3 40: if_icmpge 61 43: aload 4 45: iload 5 47: caload 48: iload_1 49: if_icmpne 55 52: iload 5 54: ireturn 55: iinc 5, 1 58: goto 37 61: iconst_m1 62: ireturn 63: aload_0 64: iload_1 65: iload_2 66: invokespecial #465 // Method indexOfSupplementary:(II)I 69: ireturn |
2 Block List生成
Call stack to build block list:
int Compilation::compile_java_method() void Compilation::build_hir() IR::IR(Compilation* compilation, ciMethod* method, int osr_bci) IRScope::IRScope(Compilation* compilation, IRScope* caller, int caller_bci, ciMethod* method, int osr_bci, bool create_graph) BlockBegin* IRScope::build_graph(Compilation* compilation, int osr_bci) GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) BlockListBuilder::BlockListBuilder(Compilation* compilation, IRScope* scope, int osr_bci) BlockListBuilder::set_leaders() //代码文件c1_GraphBuilder.cpp //通过此方法对所有的字节码进行分析,然后划分并生成Block,从下面代码可以看到所有的跳转命令,比较命令,switch语句会生成新的block。 void BlockListBuilder::set_leaders() { bool has_xhandlers = xhandlers()->has_handlers(); BlockBegin* current = NULL; // The information which bci starts a new block simplifies the analysis // Without it, backward branches could jump to a bci where no block was created // during bytecode iteration. This would require the creation of a new block at the // branch target and a modification of the successor lists. BitMap bci_block_start = method()->bci_block_start(); ciBytecodeStream s(method()); while (s.next() != ciBytecodeStream::EOBC()) { int cur_bci = s.cur_bci(); if (bci_block_start.at(cur_bci)) { current = make_block_at(cur_bci, current); } assert(current != NULL, "must have current block"); if (has_xhandlers && GraphBuilder::can_trap(method(), s.cur_bc())) { handle_exceptions(current, cur_bci); } switch (s.cur_bc()) { // track stores to local variables for selective creation of phi functions //在桢栈中标记局部变量 case Bytecodes::_iinc: store_one(current, s.get_index()); break; case Bytecodes::_istore: store_one(current, s.get_index()); break; case Bytecodes::_lstore: store_two(current, s.get_index()); break; case Bytecodes::_fstore: store_one(current, s.get_index()); break; case Bytecodes::_dstore: store_two(current, s.get_index()); break; case Bytecodes::_astore: store_one(current, s.get_index()); break; case Bytecodes::_istore_0: store_one(current, 0); break; case Bytecodes::_istore_1: store_one(current, 1); break; case Bytecodes::_istore_2: store_one(current, 2); break; case Bytecodes::_istore_3: store_one(current, 3); break; case Bytecodes::_lstore_0: store_two(current, 0); break; case Bytecodes::_lstore_1: store_two(current, 1); break; case Bytecodes::_lstore_2: store_two(current, 2); break; case Bytecodes::_lstore_3: store_two(current, 3); break; case Bytecodes::_fstore_0: store_one(current, 0); break; case Bytecodes::_fstore_1: store_one(current, 1); break; case Bytecodes::_fstore_2: store_one(current, 2); break; case Bytecodes::_fstore_3: store_one(current, 3); break; case Bytecodes::_dstore_0: store_two(current, 0); break; case Bytecodes::_dstore_1: store_two(current, 1); break; case Bytecodes::_dstore_2: store_two(current, 2); break; case Bytecodes::_dstore_3: store_two(current, 3); break; case Bytecodes::_astore_0: store_one(current, 0); break; case Bytecodes::_astore_1: store_one(current, 1); break; case Bytecodes::_astore_2: store_one(current, 2); break; case Bytecodes::_astore_3: store_one(current, 3); break; // track bytecodes that affect the control flow case Bytecodes::_athrow: // fall through case Bytecodes::_ret: // fall through case Bytecodes::_ireturn: // fall through case Bytecodes::_lreturn: // fall through case Bytecodes::_freturn: // fall through case Bytecodes::_dreturn: // fall through case Bytecodes::_areturn: // fall through case Bytecodes::_return: current = NULL; break; case Bytecodes::_ifeq: // fall through case Bytecodes::_ifne: // fall through case Bytecodes::_iflt: // fall through case Bytecodes::_ifge: // fall through case Bytecodes::_ifgt: // fall through case Bytecodes::_ifle: // fall through case Bytecodes::_if_icmpeq: // fall through case Bytecodes::_if_icmpne: // fall through case Bytecodes::_if_icmplt: // fall through case Bytecodes::_if_icmpge: // fall through case Bytecodes::_if_icmpgt: // fall through case Bytecodes::_if_icmple: // fall through case Bytecodes::_if_acmpeq: // fall through case Bytecodes::_if_acmpne: // fall through case Bytecodes::_ifnull: // fall through case Bytecodes::_ifnonnull: make_block_at(s.next_bci(), current);//条件成功时,下一个字节码开始下一个block make_block_at(s.get_dest(), current);//条件不成功时,跳转到的字节码地方开始下一个block current = NULL; break; case Bytecodes::_goto: make_block_at(s.get_dest(), current); current = NULL; break; case Bytecodes::_goto_w: make_block_at(s.get_far_dest(), current); current = NULL; break; case Bytecodes::_jsr: handle_jsr(current, s.get_dest(), s.next_bci()); current = NULL; break; case Bytecodes::_jsr_w: handle_jsr(current, s.get_far_dest(), s.next_bci()); current = NULL; break; case Bytecodes::_tableswitch: { // set block for each case Bytecode_tableswitch sw(&s); int l = sw.length(); for (int i = 0; i < l; i++) { make_block_at(cur_bci + sw.dest_offset_at(i), current); } make_block_at(cur_bci + sw.default_offset(), current); current = NULL; break; } case Bytecodes::_lookupswitch: { // set block for each case Bytecode_lookupswitch sw(&s); int l = sw.number_of_pairs(); for (int i = 0; i < l; i++) { make_block_at(cur_bci + sw.pair_at(i).offset(), current); } make_block_at(cur_bci + sw.default_offset(), current); current = NULL; break; } } } } |
最后,Block List生成如下:
begin_compilation name " java.lang.String::indexOf" method "virtual jint java.lang.String.indexOf(jint, jint)" date 1527264031403 end_compilation begin_cfg name "BlockListBuilder virtual jint java.lang.String.indexOf(jint, jint)" begin_block name "B0" //Block名称 from_bci 0 //Block开始的字节码索引 to_bci -1 //Block的结束字节码索引 predecessors //前置Block successors "B1" "B2" //此Block会跳转到的Block名称 xhandlers flags "std" end_block begin_block name "B1" from_bci 10 to_bci -1 predecessors successors "B3" xhandlers flags end_block begin_block name "B2" from_bci 15 to_bci -1 predecessors successors "B4" "B3" xhandlers flags end_block begin_block name "B4" from_bci 20 to_bci -1 predecessors successors xhandlers flags end_block begin_block name "B3" from_bci 22 to_bci -1 predecessors successors "B5" "B6" xhandlers flags end_block begin_block name "B5" from_bci 28 to_bci -1 predecessors successors "B7" xhandlers flags end_block begin_block name "B7" from_bci 37 to_bci -1 predecessors successors "B8" "B9" xhandlers flags "plh" end_block begin_block name "B8" from_bci 43 to_bci -1 predecessors successors "B10" "B11" xhandlers flags end_block begin_block name "B10" from_bci 52 to_bci -1 predecessors successors xhandlers flags end_block begin_block name "B11" from_bci 55 to_bci -1 predecessors successors "B7" xhandlers flags end_block begin_block name "B9" from_bci 61 to_bci -1 predecessors successors xhandlers flags end_block begin_block name "B6" from_bci 63 to_bci -1 predecessors successors xhandlers flags end_block end_cfg |
生成高级中间表示(HIR)
Block List生成完后,接下来就需要为每个Block生成HIR了。
Call stack to create HIR:
int Compilation::compile_java_method() void Compilation::build_hir() IR::IR(Compilation* compilation, ciMethod* method, int osr_bci) IRScope::IRScope(Compilation* compilation, IRScope* caller, int caller_bci, ciMethod* method, int osr_bci, bool create_graph) BlockBegin* IRScope::build_graph(Compilation* compilation, int osr_bci) GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) void GraphBuilder::iterate_all_blocks(bool start_in_current_block_for_inlining) void GraphBuilder::connect_to_end(BlockBegin* beg) BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) //代码文件c1_GraphBuilder.cpp //循环每个字节码,生成对应的Instruction,所以的Instruction声明都在c1_Instruction.hpp中。 BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) { ...... _skip_block = false; assert(state() != NULL, "ValueStack missing!"); CompileLog* log = compilation()->log(); ciBytecodeStream s(method()); s.reset_to_bci(bci); int prev_bci = bci; scope_data()->set_stream(&s); // iterate Bytecodes::Code code = Bytecodes::_illegal; bool push_exception = false; if (block()->is_set(BlockBegin::exception_entry_flag) && block()->next() == NULL) { // first thing in the exception entry block should be the exception object. push_exception = true; } while (!bailed_out() && last()->as_BlockEnd() == NULL && (code = stream()->next()) != ciBytecodeStream::EOBC() && (block_at(s.cur_bci()) == NULL || block_at(s.cur_bci()) == block())) { ...... // handle bytecode switch (code) { case Bytecodes::_nop : /* nothing to do */ break; ...... case Bytecodes::_tableswitch : table_switch(); break; case Bytecodes::_lookupswitch : lookup_switch(); break; case Bytecodes::_ireturn : method_return(ipop()); break; case Bytecodes::_lreturn : method_return(lpop()); break; case Bytecodes::_freturn : method_return(fpop()); break; case Bytecodes::_dreturn : method_return(dpop()); break; case Bytecodes::_areturn : method_return(apop()); break; case Bytecodes::_return : method_return(NULL ); break; case Bytecodes::_getstatic : // fall through case Bytecodes::_putstatic : // fall through case Bytecodes::_getfield : // fall through case Bytecodes::_putfield : access_field(code); break; case Bytecodes::_invokevirtual : // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through case Bytecodes::_invokedynamic : // fall through case Bytecodes::_invokeinterface: invoke(code); break; ...... default : ShouldNotReachHere(); break; } if (log != NULL) log->clear_context(); // skip marker if nothing was printed // save current bci to setup Goto at the end prev_bci = s.cur_bci(); } ...... // done return end; } |
以字节码“ 1: getfield #423 // Field value:[C”为例,
上面的代码就会生成对应的LoadField Instruction(LoadField* load = new LoadField(obj, offset, field, false, state_before, needs_patching))。
LoadField的定义为:
//通过宏定义,为LoadField添加了as_LoadField(), LoadField()和visit(InstructionVisitor)方法。 //这儿的LoadField.visit方法会调用do_LoadField(this)方法,此方法会在两个类中进行实现。 LEAF(LoadField, AccessField) BASE(AccessField, Instruction) #define BASE(class_name, super_class_name) \ class class_name: public super_class_name { \ public: \ virtual class_name* as_##class_name() { return this; } \ #define LEAF(class_name, super_class_name) \ BASE(class_name, super_class_name) \ public: \ virtual const char* name() const { return #class_name; } \ virtual void visit(InstructionVisitor* v) { v->do_##class_name(this); } \ //代码在c1_InstructionPrinter.cpp中,在打印HIR的指令到output.cfg中时会调用。 void InstructionPrinter::do_LoadField(LoadField* x) { print_field(x); output()->print(" (%c)", type2char(x->field()->type()->basic_type())); output()->print(" %s", x->field()->name()->as_utf8()); } //代码在c1_LIRGenerator.cpp中,在生成LIR代码时调用。 void LIRGenerator::do_LoadField(LoadField* x) { bool needs_patching = x->needs_patching(); bool is_volatile = x->field()->is_volatile(); BasicType field_type = x->field_type(); CodeEmitInfo* info = NULL; if (needs_patching) { assert(x->explicit_null_check() == NULL, "can't fold null check into patching field access"); info = state_for(x, x->state_before()); } else if (x->needs_null_check()) { NullCheck* nc = x->explicit_null_check(); if (nc == NULL) { info = state_for(x); } else { info = state_for(nc); } } LIRItem object(x->obj(), this); object.load_item(); #ifndef PRODUCT if (PrintNotLoaded && needs_patching) { tty->print_cr(" ###class not loaded at load_%s bci %d", x->is_static() ? "static" : "field", x->printable_bci()); } #endif bool stress_deopt = StressLoopInvariantCodeMotion && info && info->deoptimize_on_exception(); if (x->needs_null_check() && (needs_patching || MacroAssembler::needs_explicit_null_check(x->offset()) || stress_deopt)) { LIR_Opr obj = object.result(); if (stress_deopt) { obj = new_register(T_OBJECT); __ move(LIR_OprFact::oopConst(NULL), obj); } // emit an explicit null check because the offset is too large __ null_check(obj, new CodeEmitInfo(info)); } LIR_Opr reg = rlock_result(x, field_type); LIR_Address* address; if (needs_patching) { // we need to patch the offset in the instruction so don't allow // generate_address to try to be smart about emitting the -1. // Otherwise the patching code won't know how to find the // instruction to patch. address = new LIR_Address(object.result(), PATCHED_ADDR, field_type); } else { address = generate_address(object.result(), x->offset(), field_type); } if (is_volatile && !needs_patching) { volatile_field_load(address, reg, info); } else { LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; __ load(address, reg, info, patch_code); } if (is_volatile && os::is_MP()) { __ membar_acquire(); } } |
最后,生成的高级中间表示(HIR)为:
begin_cfg name "After Generation of HIR" begin_block name "B12" from_bci 0 to_bci 0 predecessors successors "B13" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 end_locals end_states begin_HIR .0 0 47 std entry B13 <|@ end_HIR end_block begin_block name "B13" from_bci 0 to_bci 0 predecessors "B12" successors "B0" xhandlers flags "std" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 end_locals end_states begin_HIR .0 0 46 goto B0 <|@ end_HIR end_block begin_block name "B0" from_bci 0 to_bci 7 predecessors "B13" successors "B2" "B1" xhandlers flags "std" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" //格式为index value SSA(静态单一赋值,即每个变量只会赋值一次) 0 a12 1 i13 2 i14 end_locals end_states begin_HIR //格式为pin.bci usecnt SSA type+id do_LoadField(obj.field type name) .1 0 a15 a12._12 ([) value <|@ // 1: getfield对应的HIR .4 0 i16 a15.length <|@ //bci usecnt type+id do_Constant(Int0) 7 0 i17 0 <|@ //pin.bci usecnt id do_If(if x cond y then block0 else block1) .7 0 18 if i14 >= i17 then B2 else B1 <|@ end_HIR end_block begin_block name "B1" from_bci 10 to_bci 12 predecessors "B0" successors "B3" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 3 i16 end_locals end_states begin_HIR 10 0 i19 0 <|@ .12 0 20 goto B3 <|@ end_HIR end_block begin_block name "B3" from_bci 22 to_bci 25 predecessors "B1" "B2" successors "B6" "B5" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i22 [ i19 i14] 3 i16 end_locals end_states begin_HIR 23 0 i25 65536 <|@ .25 0 26 if i13 >= i25 then B6 else B5 <|@ end_HIR end_block begin_block name "B5" from_bci 28 to_bci 37 predecessors "B3" successors "B7" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i22 3 i16 end_locals end_states begin_HIR .29 0 a27 a12._12 ([) value <|@ .37 0 28 goto B7 <|@ end_HIR end_block begin_block name "B7" from_bci 37 to_bci 40 predecessors "B5" "B11" successors "B9" "B8" xhandlers flags "plh" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 3 i16 4 a27 5 i29 [ i22 i35] end_locals end_states begin_HIR .40 0 30 if i29 >= i16 then B9 else B8 <|@ end_HIR end_block begin_block name "B8" from_bci 43 to_bci 49 predecessors "B7" successors "B11" "B10" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 3 i16 4 a27 5 i29 end_locals end_states begin_HIR .47 0 i31 a27[i29] (C) [rc] <|@ .49 0 32 if i31 != i13 then B11 else B10 <|@ end_HIR end_block begin_block name "B10" from_bci 52 to_bci 54 predecessors "B8" successors xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 5 i29 end_locals end_states begin_HIR .54 0 i33 ireturn i29 <|@ end_HIR end_block begin_block name "B11" from_bci 55 to_bci 58 predecessors "B8" successors "B7" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 3 i16 4 a27 5 i29 end_locals end_states begin_HIR 55 0 i34 1 <|@ 55 0 i35 i29 + i34 <|@ .58 0 36 goto B7 (safepoint) <|@ end_HIR end_block begin_block name "B9" from_bci 61 to_bci 62 predecessors "B7" successors xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" end_locals end_states begin_HIR 61 0 i37 -1 <|@ .62 0 i38 ireturn i37 <|@ end_HIR end_block begin_block name "B6" from_bci 63 to_bci 69 predecessors "B3" successors xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i22 end_locals end_states begin_HIR .66 0 a39 null_check(a12) <|@ .66 0 v41 profile a12 java/lang/String.indexOf) <|@ .66 0 i42 a12.invokespecial(i13, i22) java/lang/String.indexOfSupplementary(II)I <|@ .69 0 i43 ireturn i42 <|@ end_HIR end_block begin_block name "B2" from_bci 15 to_bci 17 predecessors "B0" successors "B3" "B4" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 3 i16 end_locals end_states begin_HIR .17 0 21 if i14 < i16 then B3 else B4 <|@ end_HIR end_block begin_block name "B4" from_bci 20 to_bci 21 predecessors "B2" successors xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" end_locals end_states begin_HIR 20 0 i23 -1 <|@ .21 0 i24 ireturn i23 <|@ end_HIR end_block end_cfg begin_cfg name "Before RangeCheckElimination" begin_block name "B12" from_bci 0 to_bci 0 predecessors successors "B13" xhandlers flags begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 end_locals end_states begin_HIR .0 0 47 std entry B13 <|@ end_HIR end_block begin_block name "B13" from_bci 0 to_bci 0 predecessors "B12" successors "B0" xhandlers flags "std" dominator "B12" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 end_locals end_states begin_HIR .0 0 46 goto B0 <|@ end_HIR end_block begin_block name "B0" from_bci 0 to_bci 7 predecessors "B13" successors "B2" "B1" xhandlers flags "std" dominator "B13" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 end_locals end_states begin_HIR .1 0 a15 a12._12 ([) value <|@ .4 0 i16 a15.length <|@ 7 0 i17 0 <|@ .7 0 18 if i14 >= i17 then B2 else B1 <|@ end_HIR end_block begin_block name "B1" from_bci 10 to_bci 12 predecessors "B0" successors "B3" xhandlers flags dominator "B0" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 3 i16 end_locals end_states begin_HIR .12 0 20 goto B3 <|@ end_HIR end_block begin_block name "B3" from_bci 22 to_bci 25 predecessors "B1" "B14" successors "B6" "B5" xhandlers flags dominator "B0" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i22 [ i17 i14] 3 i16 end_locals end_states begin_HIR 23 0 i25 65536 <|@ .25 0 26 if i13 >= i25 then B6 else B5 <|@ end_HIR end_block begin_block name "B5" from_bci 28 to_bci 37 predecessors "B3" successors "B7" xhandlers flags dominator "B3" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i22 3 i16 end_locals end_states begin_HIR .37 0 28 goto B7 <|@ end_HIR end_block begin_block name "B7" from_bci 37 to_bci 40 predecessors "B5" "B11" successors "B9" "B8" xhandlers flags "bb" "plh" "llh" dominator "B5" loop_index 0 loop_depth 1 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 3 i16 4 a15 5 i29 [ i22 i35] end_locals end_states begin_HIR .40 0 30 if i29 >= i16 then B9 else B8 <|@ end_HIR end_block begin_block name "B8" from_bci 43 to_bci 49 predecessors "B7" successors "B11" "B10" xhandlers flags dominator "B7" loop_index 0 loop_depth 1 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 3 i16 4 a15 5 i29 end_locals end_states begin_HIR .47 0 i31 a15[i29] (C) [rc] <|@ .49 0 32 if i31 != i13 then B11 else B10 <|@ end_HIR end_block begin_block name "B10" from_bci 52 to_bci 54 predecessors "B8" successors xhandlers flags dominator "B8" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 5 i29 end_locals end_states begin_HIR .54 0 i33 ireturn i29 <|@ end_HIR end_block begin_block name "B11" from_bci 55 to_bci 58 predecessors "B8" successors "B7" xhandlers flags "lle" dominator "B8" loop_index 0 loop_depth 1 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 3 i16 4 a15 5 i29 end_locals end_states begin_HIR 55 0 i34 1 <|@ 55 0 i35 i29 + i34 <|@ .58 0 36 goto B7 (safepoint) <|@ end_HIR end_block begin_block name "B9" from_bci 61 to_bci 62 predecessors "B7" successors xhandlers flags dominator "B7" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" end_locals end_states begin_HIR 61 0 i37 -1 <|@ .62 0 i38 ireturn i37 <|@ end_HIR end_block begin_block name "B6" from_bci 63 to_bci 69 predecessors "B3" successors xhandlers flags dominator "B3" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i22 end_locals end_states begin_HIR .66 0 a39 null_check(a12) <|@ .66 0 v41 profile a12 java/lang/String.indexOf) <|@ .66 0 i42 a12.invokespecial(i13, i22) java/lang/String.indexOfSupplementary(II)I <|@ .69 0 i43 ireturn i42 <|@ end_HIR end_block begin_block name "B2" from_bci 15 to_bci 17 predecessors "B0" successors "B14" "B4" xhandlers flags dominator "B0" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 3 i16 end_locals end_states begin_HIR .17 0 21 if i14 < i16 then B14 else B4 <|@ end_HIR end_block begin_block name "B4" from_bci 20 to_bci 21 predecessors "B2" successors xhandlers flags dominator "B2" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" end_locals end_states begin_HIR 20 0 i23 -1 <|@ .21 0 i24 ireturn i23 <|@ end_HIR end_block begin_block name "B14" from_bci 22 to_bci 22 predecessors "B2" successors "B3" xhandlers flags "ces" dominator "B2" begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 1 i13 2 i14 3 i16 end_locals end_states begin_HIR .22 0 49 goto B3 <|@ end_HIR end_block end_cfg |
生成LIR
现在,需要根据HIR生成对应的LIR。
Call stack to create LIR:
int Compilation::compile_java_method() void Compilation::emit_lir() void IR::iterate_linear_scan_order(BlockClosure* closure) //closure为LIRGenerator gen(this, method()) void LIRGenerator::block_do(BlockBegin* block) //通过如下的方法,对每个block里的每个instruction调用visit。 //前面生成生成HIR时,说到过的方法void LIRGenerator::do_LoadField(LoadField* x) 就在此调用并生成LIR。 void LIRGenerator::block_do(BlockBegin* block) { CHECK_BAILOUT(); block_do_prolog(block); set_block(block); for (Instruction* instr = block; instr != NULL; instr = instr->next()) { if (instr->is_pinned()) do_root(instr); } set_block(NULL); block_do_epilog(block); } // This is where the tree-walk starts; instr must be root; void LIRGenerator::do_root(Value instr) { CHECK_BAILOUT(); InstructionMark im(compilation(), instr); assert(instr->is_pinned(), "use only with roots"); assert(instr->subst() == instr, "shouldn't have missed substitution"); instr->visit(this); assert(!instr->has_uses() || instr->operand()->is_valid() || instr->as_Constant() != NULL || bailed_out(), "invalid item set"); } //代码在c1_LIR.cpp中 //do_LoadField方法调用下面方法生成LIR_Op1:lir_move。 void LIR_List::load(LIR_Address* addr, LIR_Opr src, CodeEmitInfo* info, LIR_PatchCode patch_code) { append(new LIR_Op1( lir_move, LIR_OprFact::address(addr), src, addr->type(), patch_code, info)); } //代码在c1_LIR.cpp中 //此方法会在后面的线性扫描方法中调用,它对每个LIR_Op会做一些标记。 //比如,lir_move它有输入和输出,所以有do_input和do_output。 //在线性扫描中,如果有input,那么就会标记对应寄存器的使用区间(Interval),有output就会定义一个寄存器开始使用的位置。 void LIR_OpVisitState::visit(LIR_Op* op) { // copy information from the LIR_Op reset(); set_op(op); switch (op->code()) { ...... case lir_move: // input and result always valid, may have info case lir_pack64: // input and result always valid case lir_unpack64: // input and result always valid case lir_prefetchr: // input always valid, result and info always invalid case lir_prefetchw: // input always valid, result and info always invalid { assert(op->as_Op1() != NULL, "must be"); LIR_Op1* op1 = (LIR_Op1*)op; if (op1->_info) do_info(op1->_info); if (op1->_opr->is_valid()) do_input(op1->_opr); if (op1->_result->is_valid()) do_output(op1->_result); break; } ...... } |
最后,生成的LIR为:
begin_cfg name "Before Register Allocation" begin_block name "B12" from_bci 0 to_bci 0 predecessors successors "B13" xhandlers flags first_lir_id 0 last_lir_id 28 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i14 "[R179|I]" end_locals end_states begin_HIR .0 0 47 std entry B13 <|@ end_HIR begin_LIR 0 label [label:0xfc0043b8] <|@ 2 std_entry <|@ 4 move [rsi|L] [R177|L] <|@ 6 move [rdx|I] [R178|I] <|@ 8 move [rcx|I] [R179|I] <|@ 10 move [metadata:0x3301c100|M] [R180|M] <|@ 12 move [Base:[R180|M] Disp: 108|I] [R181|I] <|@ 14 add [R181|I] [int:8|I] [R181|I] <|@ 16 move [R181|I] [Base:[R180|M] Disp: 108|I] <|@ 18 move [metadata:0x32dd2238|M] [R182|M] <|@ 20 logic_and [R181|I] [int:8184|I] [R181|I] <|@ 22 cmp [R181|I] [int:0|I] <|@ 24 branch [EQ] [CounterOverflowStub: 0xf8025908] <|@ 26 label [label:0xf8025930] <|@ 28 branch [AL] [B13] <|@ end_LIR end_block begin_block name "B13" from_bci 0 to_bci 0 predecessors "B12" successors "B0" xhandlers flags "std" dominator "B12" first_lir_id 30 last_lir_id 32 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i14 "[R179|I]" end_locals end_states begin_HIR .0 0 46 goto B0 <|@ end_HIR begin_LIR 30 label [label:0xfc0046c8] <|@ 32 branch [AL] [B0] <|@ end_LIR end_block begin_block name "B0" from_bci 0 to_bci 7 predecessors "B13" successors "B2" "B1" xhandlers flags "std" dominator "B13" first_lir_id 34 last_lir_id 54 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" #index value SSA 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i14 "[R179|I]" end_locals end_states begin_HIR #pin.bci usecnt SSA type+id do_LoadField(obj.field type name) .1 6 "[R183|L]" a15 a12._12 ([) value <|@ .4 11 "[R184|I]" i16 a15.length <|@ #bci usecnt type+id do_Constant(Int0) 7 2 i17 0 <|@ #pin.bci usecnt id do_If(if x cond y then block0 else block1) .7 0 18 if i14 >= i17 then B2 else B1 <|@ end_HIR begin_LIR 34 label [label:0xf801ee78] <|@ 36 move [Base:[R177|L] Disp: 12|L] [R183|L] <|@ //对应的HIR为 .1 6 "[R183|L]" a15 a12._12 ([) value <|@ 38 move [Base:[R183|L] Disp: 12|I] [R184|I] [bci:4] <|@ //对应的HIR为 .4 11 "[R184|I]" i16 a15.length <|@ 40 cmp [R179|I] [int:0|I] <|@ 42 move [metadata:0x3301c100|M] [R185|M] <|@ 44 cmove [GE] [lng:152|J] [lng:168|J] [R186|J] <|@ 46 move [Base:[R185|M] Index:[R186|J] Disp: 0|J] [R187|J] <|@ 48 leal [Base:[R187|J] Disp: 1|I] [R187|J] <|@ 50 move [R187|J] [Base:[R185|M] Index:[R186|J] Disp: 0|J] <|@ 52 branch [GE] [B2] <|@ 54 branch [AL] [B1] <|@ end_LIR end_block begin_block name "B1" from_bci 10 to_bci 12 predecessors "B0" successors "B3" xhandlers flags dominator "B0" first_lir_id 56 last_lir_id 64 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 3 i16 "[R184|I]" end_locals end_states begin_HIR .12 0 20 goto B3 <|@ end_HIR begin_LIR 56 label [label:0xf801f198] <|@ 58 move [metadata:0x3301c100|M] [R188|M] <|@ 60 add [Base:[R188|M] Disp: 184|J] [int:1|I] [Base:[R188|M] Disp: 184|J] <|@ 62 move [int:0|I] [R189|I] <|@ 64 branch [AL] [B3] <|@ end_LIR end_block begin_block name "B2" from_bci 15 to_bci 17 predecessors "B0" successors "B14" "B4" xhandlers flags dominator "B0" first_lir_id 66 last_lir_id 82 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i14 "[R179|I]" 3 i16 "[R184|I]" end_locals end_states begin_HIR .17 0 21 if i14 < i16 then B14 else B4 <|@ end_HIR begin_LIR 66 label [label:0xf801f4b8] <|@ 68 cmp [R179|I] [R184|I] <|@ 70 move [metadata:0x3301c100|M] [R190|M] <|@ 72 cmove [LT] [lng:208|J] [lng:224|J] [R191|J] <|@ 74 move [Base:[R190|M] Index:[R191|J] Disp: 0|J] [R192|J] <|@ 76 leal [Base:[R192|J] Disp: 1|I] [R192|J] <|@ 78 move [R192|J] [Base:[R190|M] Index:[R191|J] Disp: 0|J] <|@ 80 branch [LT] [B14] <|@ 82 branch [AL] [B4] <|@ end_LIR end_block begin_block name "B14" from_bci 22 to_bci 22 predecessors "B2" successors "B3" xhandlers flags "ces" dominator "B2" first_lir_id 84 last_lir_id 88 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i14 "[R179|I]" 3 i16 "[R184|I]" end_locals end_states begin_HIR .22 0 49 goto B3 <|@ end_HIR begin_LIR 84 label [label:0xfc0062c8] <|@ 86 move [R179|I] [R189|I] <|@ 88 branch [AL] [B3] <|@ end_LIR end_block begin_block name "B3" from_bci 22 to_bci 25 predecessors "B1" "B14" successors "B6" "B5" xhandlers flags dominator "B0" first_lir_id 90 last_lir_id 106 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i22 [ i17 i14] "[R189|I]" 3 i16 "[R184|I]" end_locals end_states begin_HIR 23 1 i25 65536 <|@ .25 0 26 if i13 >= i25 then B6 else B5 <|@ end_HIR begin_LIR 90 label [label:0xf801f7d8] <|@ 92 cmp [R178|I] [int:65536|I] <|@ 94 move [metadata:0x3301c100|M] [R193|M] <|@ 96 cmove [GE] [lng:240|J] [lng:256|J] [R194|J] <|@ 98 move [Base:[R193|M] Index:[R194|J] Disp: 0|J] [R195|J] <|@ 100 leal [Base:[R195|J] Disp: 1|I] [R195|J] <|@ 102 move [R195|J] [Base:[R193|M] Index:[R194|J] Disp: 0|J] <|@ 104 branch [GE] [B6] <|@ 106 branch [AL] [B5] <|@ end_LIR end_block begin_block name "B5" from_bci 28 to_bci 37 predecessors "B3" successors "B7" xhandlers flags dominator "B3" first_lir_id 108 last_lir_id 112 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i22 "[R189|I]" 3 i16 "[R184|I]" end_locals end_states begin_HIR .37 0 28 goto B7 <|@ end_HIR begin_LIR 108 label [label:0xf801fe18] <|@ 110 move [R189|I] [R196|I] <|@ 112 branch [AL] [B7] <|@ end_LIR end_block begin_block name "B7" from_bci 37 to_bci 40 predecessors "B5" "B11" successors "B9" "B8" xhandlers flags "bb" "plh" "llh" dominator "B5" loop_index 0 loop_depth 1 first_lir_id 114 last_lir_id 130 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 "[R178|I]" 3 i16 "[R184|I]" 4 a15 "[R183|L]" 5 i29 [ i22 i35] "[R196|I]" end_locals end_states begin_HIR .40 0 30 if i29 >= i16 then B9 else B8 <|@ end_HIR begin_LIR 114 label [label:0xf8020458] <|@ 116 cmp [R196|I] [R184|I] <|@ 118 move [metadata:0x3301c100|M] [R197|M] <|@ 120 cmove [GE] [lng:272|J] [lng:288|J] [R198|J] <|@ 122 move [Base:[R197|M] Index:[R198|J] Disp: 0|J] [R199|J] <|@ 124 leal [Base:[R199|J] Disp: 1|I] [R199|J] <|@ 126 move [R199|J] [Base:[R197|M] Index:[R198|J] Disp: 0|J] <|@ 128 branch [GE] [B9] <|@ 130 branch [AL] [B8] <|@ end_LIR end_block begin_block name "B8" from_bci 43 to_bci 49 predecessors "B7" successors "B11" "B10" xhandlers flags dominator "B7" loop_index 0 loop_depth 1 first_lir_id 132 last_lir_id 156 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 "[R178|I]" 3 i16 "[R184|I]" 4 a15 "[R183|L]" 5 i29 "[R196|I]" end_locals end_states begin_HIR .47 1 "[R201|I]" i31 a15[i29] (C) [rc] <|@ .49 0 32 if i31 != i13 then B11 else B10 <|@ end_HIR begin_LIR 132 label [label:0xf8020778] <|@ 134 convert [i2l] [R196|I] [R200|J] <|@ 136 cmp [R196|I] [Base:[R183|L] Disp: 12|I] <|@ 138 branch [AE] [RangeCheckStub: 0xf80296d8] [bci:47] <|@ 140 move [Base:[R183|L] Index:[R200|J] * 2 Disp: 16|C] [R201|I] <|@ 142 cmp [R201|I] [R178|I] <|@ 144 move [metadata:0x3301c100|M] [R202|M] <|@ 146 cmove [NE] [lng:304|J] [lng:320|J] [R203|J] <|@ 148 move [Base:[R202|M] Index:[R203|J] Disp: 0|J] [R204|J] <|@ 150 leal [Base:[R204|J] Disp: 1|I] [R204|J] <|@ 152 move [R204|J] [Base:[R202|M] Index:[R203|J] Disp: 0|J] <|@ 154 branch [NE] [B11] <|@ 156 branch [AL] [B10] <|@ end_LIR end_block begin_block name "B11" from_bci 55 to_bci 58 predecessors "B8" successors "B7" xhandlers flags "lle" dominator "B8" loop_index 0 loop_depth 1 first_lir_id 158 last_lir_id 190 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 1 i13 "[R178|I]" 3 i16 "[R184|I]" 4 a15 "[R183|L]" 5 i29 "[R196|I]" end_locals end_states begin_HIR 55 1 i34 1 <|@ .55 1 "[R205|I]" i35 i29 + i34 <|@ .58 0 36 goto B7 (safepoint) <|@ end_HIR begin_LIR 158 label [label:0xf80210d8] <|@ 160 move [R196|I] [R205|I] <|@ 162 add [R205|I] [int:1|I] [R205|I] <|@ 164 move [metadata:0x3301c100|M] [R206|M] <|@ 166 move [Base:[R206|M] Disp: 112|I] [R207|I] <|@ 168 add [R207|I] [int:8|I] [R207|I] <|@ 170 move [R207|I] [Base:[R206|M] Disp: 112|I] <|@ 172 move [metadata:0x32dd2238|M] [R208|M] <|@ 174 logic_and [R207|I] [int:65528|I] [R207|I] <|@ 176 cmp [R207|I] [int:0|I] <|@ 178 branch [EQ] [CounterOverflowStub: 0xf802a488] <|@ 180 label [label:0xf802a4b0] <|@ 182 safepoint [bci:58] <|@ 184 move [metadata:0x3301c100|M] [R209|M] <|@ 186 add [Base:[R209|M] Disp: 336|J] [int:1|I] [Base:[R209|M] Disp: 336|J] <|@ 188 move [R205|I] [R196|I] <|@ 190 branch [AL] [B7] <|@ end_LIR end_block begin_block name "B10" from_bci 52 to_bci 54 predecessors "B8" successors xhandlers flags dominator "B8" first_lir_id 192 last_lir_id 196 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 5 i29 "[R196|I]" end_locals end_states begin_HIR .54 0 i33 ireturn i29 <|@ end_HIR begin_LIR 192 label [label:0xf8020db8] <|@ 194 move [R196|I] [rax|I] <|@ 196 return [rax|I] <|@ end_LIR end_block begin_block name "B9" from_bci 61 to_bci 62 predecessors "B7" successors xhandlers flags dominator "B7" first_lir_id 198 last_lir_id 202 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" end_locals end_states begin_HIR 61 1 i37 -1 <|@ .62 0 i38 ireturn i37 <|@ end_HIR begin_LIR 198 label [label:0xf8020a98] <|@ 200 move [int:-1|I] [rax|I] <|@ 202 return [rax|I] <|@ end_LIR end_block begin_block name "B6" from_bci 63 to_bci 69 predecessors "B3" successors xhandlers flags dominator "B3" first_lir_id 204 last_lir_id 222 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" 0 a12 "[R177|L]" 1 i13 "[R178|I]" 2 i22 "[R189|I]" end_locals end_states begin_HIR .66 0 a39 null_check(a12) (eliminated) <|@ .66 0 v41 profile a12 java/lang/String.indexOf) <|@ .66 1 "[R213|I]" i42 a12.invokespecial(i13, i22) java/lang/String.indexOfSupplementary(II)I <|@ .69 0 i43 ireturn i42 <|@ end_HIR begin_LIR 204 label [label:0xf8020138] <|@ 206 move [R177|L] [R212|L] <|@ 208 profile_call indexOf.java/lang/String @ 66 [R210|L] [R212|L] [R211|J] <|@ 210 move [R178|I] [rdx|I] <|@ 212 move [R189|I] [rcx|I] <|@ 214 move [R177|L] [rsi|L] <|@ 216 optvirtual call: [addr: 0x0] [recv: [rsi|L]] [result: [rax|I]] [bci:66] <|@ 218 move [rax|I] [R213|I] <|@ 220 move [R213|I] [rax|I] <|@ 222 return [rax|I] <|@ end_LIR end_block begin_block name "B4" from_bci 20 to_bci 21 predecessors "B2" successors xhandlers flags dominator "B2" first_lir_id 224 last_lir_id 228 begin_states begin_locals size 6 method "virtual jint java.lang.String.indexOf(jint, jint)" end_locals end_states begin_HIR 20 1 i23 -1 <|@ .21 0 i24 ireturn i23 <|@ end_HIR begin_LIR 224 label [label:0xf801faf8] <|@ 226 move [int:-1|I] [rax|I] <|@ 228 return [rax|I] <|@ end_LIR end_block end_cfg |
分配物理寄存器
LIR生成后,因为LIR目前使用的是虚拟寄存器,所以需要通过线性扫描算法分配物理寄存器。
Call stack to create register allocation:
int Compilation::compile_java_method() void Compilation::emit_lir() LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map) void LinearScan::do_linear_scan() //代码在c1_LinearScan.cpp中。 //方法先调用build_intervals()生成所有寄存器的活动区间,然后调用allocate_registers()为所以的虚拟寄存器分配物理寄存器。 void LinearScan::do_linear_scan() { NOT_PRODUCT(_total_timer.begin_method()); number_instructions(); ...... CHECK_BAILOUT(); build_intervals(); CHECK_BAILOUT(); sort_intervals_before_allocation(); NOT_PRODUCT(print_intervals("Before Register Allocation")); NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_before_alloc)); allocate_registers(); CHECK_BAILOUT(); resolve_data_flow(); ...... } //循环每个block的每个instruction,生成每个寄存器的活动区间(interval) void LinearScan::build_intervals() { TIME_LINEAR_SCAN(timer_build_intervals); ...... LIR_OpVisitState visitor; // iterate all blocks in reverse order for (i = block_count() - 1; i >= 0; i--) { BlockBegin* block = block_at(i); LIR_OpList* instructions = block->lir()->instructions_list(); int block_from = block->first_lir_instruction_id(); int block_to = block->last_lir_instruction_id(); ...... // iterate all instructions of the block in reverse order. // skip the first instruction because it is always a label // definitions of intervals are processed before uses assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label"); for (int j = instructions->length() - 1; j >= 1; j--) { LIR_Op* op = instructions->at(j); int op_id = op->id(); ...... // visit definitions (output and temp operands) //如果此instruction有output,则生成寄存器使用定义,默认为当前instruction位置到+1。 int k, n; n = visitor.opr_count(LIR_OpVisitState::outputMode); for (k = 0; k < n; k++) { LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k); assert(opr->is_register(), "visitor should only return register operands"); add_def(opr, op_id, use_kind_of_output_operand(op, opr)); } n = visitor.opr_count(LIR_OpVisitState::tempMode); for (k = 0; k < n; k++) { LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k); assert(opr->is_register(), "visitor should only return register operands"); add_temp(opr, op_id, mustHaveRegister); } // visit uses (input operands) //如果此instruction有intput,则添加寄存器的使用区间,默认从block开始到当前instruction位置。 n = visitor.opr_count(LIR_OpVisitState::inputMode); for (k = 0; k < n; k++) { LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k); assert(opr->is_register(), "visitor should only return register operands"); add_use(opr, block_from, op_id, use_kind_of_input_operand(op, opr)); } // Add uses of live locals from interpreter's point of view for proper // debug information generation // Treat these operands as temp values (if the life range is extended // to a call site, the value would be in a register at the call otherwise) n = visitor.info_count(); for (k = 0; k < n; k++) { CodeEmitInfo* info = visitor.info_at(k); ValueStack* stack = info->stack(); for_each_state_value(stack, value, add_use(value, block_from, op_id + 1, noUse); ); } // special steps for some instructions (especially moves) handle_method_arguments(op); handle_doubleword_moves(op); add_register_hints(op); } // end of instruction iteration } // end of block iteration ...... } |
最后,列出寄存器分配前后的对比。
begin_intervals name "Before Register Allocation" //格式为: regNum type opr parentRegNum regHintRegNum (rngStart_rngEnd)+ (usePosAndKind)* spillState 0 fixed "[rsi|I]" 0 177 [0, 4[ [214, 217[ "no spill store" 1 fixed "[rdi|I]" 1 -1 [0, 1[ [216, 217[ "no definition" 2 fixed "[rbx|I]" 2 -1 [0, 1[ [216, 217[ "no definition" 3 fixed "[rax|I]" 3 196 [0, 1[ [194, 196[ [200, 202[ [216, 218[ [220, 222[ [226, 228[ "no optimization" 4 fixed "[rdx|I]" 4 178 [0, 6[ [210, 217[ "no spill store" 5 fixed "[rcx|I]" 5 189 [0, 8[ [212, 217[ "no spill store" 6 fixed "[r8|I]" 6 -1 [0, 1[ [216, 217[ "no definition" 7 fixed "[r9|I]" 7 -1 [0, 1[ [216, 217[ "no definition" 8 fixed "[r11|I]" 8 -1 [0, 1[ [216, 217[ "no definition" 9 fixed "[r13|I]" 9 -1 [0, 1[ [216, 217[ "no definition" 10 fixed "[r14|I]" 10 -1 [0, 1[ [216, 217[ "no definition" 177 object 177 0 [4, 108[ [204, 214[ 4 M 36 M 206 S 214 S "no spill store" 178 int 178 4 [6, 192[ [204, 210[ 6 M 92 M 142 S 191 L 210 S "no spill store" 179 int 179 5 [8, 56[ [66, 86[ 8 M 40 M 68 M 86 S "no spill store" 180 *metadata* 180 -1 [10, 16[ 10 M 12 M 16 M "no spill store" 181 int 181 -1 [12, 22[ 12 M 14 M 16 M 20 M 22 M "no optimization" 182 *metadata* 182 -1 [18, 24[ 18 M 24 M "no spill store" 183 object 183 -1 [36, 192[ 36 M 38 M 136 M 140 M 191 L "no spill store" 184 int 184 -1 [38, 192[ 38 M 68 S 116 S 191 L "no spill store" 185 *metadata* 185 -1 [42, 50[ 42 M 46 M 50 M "no spill store" 186 long 186 -1 [44, 50[ 44 M 46 M 50 M "no spill store" 187 long 187 -1 [46, 50[ 46 M 48 M 50 M "no spill store" 188 *metadata* 188 -1 [58, 60[ 58 M 60 M "no spill store" 189 int 189 179 [62, 66[ [86, 110[ [204, 212[ 62 M 86 M 110 S 212 S "no optimization" 190 *metadata* 190 -1 [70, 78[ 70 M 74 M 78 M "no spill store" 191 long 191 -1 [72, 78[ 72 M 74 M 78 M "no spill store" 192 long 192 -1 [74, 78[ 74 M 76 M 78 M "no spill store" 193 *metadata* 193 -1 [94, 102[ 94 M 98 M 102 M "no spill store" 194 long 194 -1 [96, 102[ 96 M 98 M 102 M "no spill store" 195 long 195 -1 [98, 102[ 98 M 100 M 102 M "no spill store" 196 int 196 189 [110, 160[ [188, 194[ 110 M 116 M 134 M 136 M 138 M 160 S 188 M 191 L 194 S "no optimization" 197 *metadata* 197 -1 [118, 126[ 118 M 122 M 126 M "no spill store" 198 long 198 -1 [120, 126[ 120 M 122 M 126 M "no spill store" 199 long 199 -1 [122, 126[ 122 M 124 M 126 M "no spill store" 200 long 200 196 [134, 140[ 134 M 140 M "no spill store" 201 int 201 -1 [140, 142[ 140 M 142 M "no spill store" 202 *metadata* 202 -1 [144, 152[ 144 M 148 M 152 M "no spill store" 203 long 203 -1 [146, 152[ 146 M 148 M 152 M "no spill store" 204 long 204 -1 [148, 152[ 148 M 150 M 152 M "no spill store" 205 int 205 196 [160, 188[ 160 M 162 M 188 S "no spill store" 206 *metadata* 206 -1 [164, 170[ 164 M 166 M 170 M "no spill store" 207 int 207 -1 [166, 176[ 166 M 168 M 170 M 174 M 176 M "no optimization" 208 *metadata* 208 -1 [172, 178[ 172 M 178 M "no spill store" 209 *metadata* 209 -1 [184, 186[ 184 M 186 M "no spill store" 210 object 210 -1 [208, 209[ 208 M "no definition" 211 long 211 -1 [208, 209[ 208 M "no definition" 212 object 212 177 [206, 207[ [208, 209[ 206 M 208 M "no spill store" 213 int 213 3 [218, 220[ 218 M 220 S "no spill store" end_intervals begin_intervals name "After Register Allocation" 0 fixed "[rsi|I]" 0 177 [0, 4[ [214, 217[ "no spill store" 1 fixed "[rdi|I]" 1 -1 [0, 1[ [216, 217[ "no definition" 2 fixed "[rbx|I]" 2 -1 [0, 1[ [216, 217[ "no definition" 3 fixed "[rax|I]" 3 196 [0, 1[ [194, 196[ [200, 202[ [216, 218[ [220, 222[ [226, 228[ "no optimization" 4 fixed "[rdx|I]" 4 178 [0, 6[ [210, 217[ "no spill store" 5 fixed "[rcx|I]" 5 189 [0, 8[ [212, 217[ "no spill store" 6 fixed "[r8|I]" 6 -1 [0, 1[ [216, 217[ "no definition" 7 fixed "[r9|I]" 7 -1 [0, 1[ [216, 217[ "no definition" 8 fixed "[r11|I]" 8 -1 [0, 1[ [216, 217[ "no definition" 9 fixed "[r13|I]" 9 -1 [0, 1[ [216, 217[ "no definition" 10 fixed "[r14|I]" 10 -1 [0, 1[ [216, 217[ "no definition" //寄存器177分配后,使用物理寄存器rsi。 177 object "[rsi|L]" 177 0 [4, 108[ [204, 214[ 4 M 36 M 206 S 214 S "no spill store" 178 int "[rdx|I]" 178 4 [6, 192[ [204, 210[ 6 M 92 M 142 S 191 L 210 S "no spill store" 179 int "[rcx|I]" 179 5 [8, 56[ [66, 86[ 8 M 40 M 68 M 86 S "no spill store" 180 *metadata* "[rax|M]" 180 -1 [10, 16[ 10 M 12 M 16 M "no spill store" 181 int "[rdi|I]" 181 -1 [12, 22[ 12 M 14 M 16 M 20 M 22 M "no optimization" 182 *metadata* "[rax|M]" 182 -1 [18, 24[ 18 M 24 M "no spill store" 183 object "[rax|L]" 183 -1 [36, 192[ 36 M 38 M 136 M 140 M 191 L "no spill store" 184 int "[rdi|I]" 184 -1 [38, 192[ 38 M 68 S 116 S 191 L "no spill store" 185 *metadata* "[rbx|M]" 185 -1 [42, 50[ 42 M 46 M 50 M "no spill store" 186 long "[r8r8|J]" 186 -1 [44, 50[ 44 M 46 M 50 M "no spill store" 187 long "[r9r9|J]" 187 -1 [46, 50[ 46 M 48 M 50 M "no spill store" 188 *metadata* "[rcx|M]" 188 -1 [58, 60[ 58 M 60 M "no spill store" 189 int "[rcx|I]" 189 179 [62, 66[ [86, 110[ [204, 212[ 62 M 86 M 110 S 212 S "no optimization" 190 *metadata* "[rbx|M]" 190 -1 [70, 78[ 70 M 74 M 78 M "no spill store" 191 long "[r8r8|J]" 191 -1 [72, 78[ 72 M 74 M 78 M "no spill store" 192 long "[r9r9|J]" 192 -1 [74, 78[ 74 M 76 M 78 M "no spill store" 193 *metadata* "[rbx|M]" 193 -1 [94, 102[ 94 M 98 M 102 M "no spill store" 194 long "[r8r8|J]" 194 -1 [96, 102[ 96 M 98 M 102 M "no spill store" 195 long "[r9r9|J]" 195 -1 [98, 102[ 98 M 100 M 102 M "no spill store" 196 int "[rcx|I]" 196 189 [110, 160[ [188, 194[ 110 M 116 M 134 M 136 M 138 M 160 S 188 M 191 L 194 S "no optimization" 197 *metadata* "[rsi|M]" 197 -1 [118, 126[ 118 M 122 M 126 M "no spill store" 198 long "[rbxrbx|J]" 198 -1 [120, 126[ 120 M 122 M 126 M "no spill store" 199 long "[r8r8|J]" 199 -1 [122, 126[ 122 M 124 M 126 M "no spill store" 200 long "[rsirsi|J]" 200 196 [134, 140[ 134 M 140 M "no spill store" 201 int "[rsi|I]" 201 -1 [140, 142[ 140 M 142 M "no spill store" 202 *metadata* "[rsi|M]" 202 -1 [144, 152[ 144 M 148 M 152 M "no spill store" 203 long "[rbxrbx|J]" 203 -1 [146, 152[ 146 M 148 M 152 M "no spill store" 204 long "[r8r8|J]" 204 -1 [148, 152[ 148 M 150 M 152 M "no spill store" 205 int "[rcx|I]" 205 196 [160, 188[ 160 M 162 M 188 S "no spill store" 206 *metadata* "[rsi|M]" 206 -1 [164, 170[ 164 M 166 M 170 M "no spill store" 207 int "[rbx|I]" 207 -1 [166, 176[ 166 M 168 M 170 M 174 M 176 M "no optimization" 208 *metadata* "[rsi|M]" 208 -1 [172, 178[ 172 M 178 M "no spill store" 209 *metadata* "[rsi|M]" 209 -1 [184, 186[ 184 M 186 M "no spill store" 210 object "[rbx|L]" 210 -1 [208, 209[ 208 M "no definition" 211 long "[raxrax|J]" 211 -1 [208, 209[ 208 M "no definition" 212 object "[rdi|L]" 212 177 [206, 207[ [208, 209[ 206 M 208 M "no spill store" 213 int "[rax|I]" 213 3 [218, 220[ 218 M 220 S "no spill store" end_intervals |
这个例子的物理寄存器刚好都够用,不需要split interval。下面给一个需要分割区间的例子。
虚拟寄存器194的120-250区间就无法找到一个完整的物理寄存器。
寄存器分配完后,区间分配为120-190, 190-201, 201-230, 230-250。
其中,190-201, 201-230使用了桢栈空间,230以后又回到了rdi寄存器的使用。
总之,算法是尽可能使用物理寄存器来加速程序执行。
begin_intervals name "Before Register Allocation" 0 fixed "[rsi|I]" 0 179 [0, 4[ [200, 203[ [356, 359[ [466, 469[ "no optimization" 1 fixed "[rdi|I]" 1 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 2 fixed "[rbx|I]" 2 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 3 fixed "[rax|I]" 3 227 [0, 1[ [202, 204[ [358, 360[ [442, 444[ [448, 450[ [468, 470[ [472, 474[ [478, 480[ "no optimization" 4 fixed "[rdx|I]" 4 202 [0, 6[ [198, 203[ [354, 359[ [462, 469[ "no optimization" 5 fixed "[rcx|I]" 5 179 [0, 8[ [202, 203[ [358, 359[ [464, 469[ "no spill store" 6 fixed "[r8|I]" 6 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 7 fixed "[r9|I]" 7 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 8 fixed "[r11|I]" 8 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 9 fixed "[r13|I]" 9 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 10 fixed "[r14|I]" 10 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" ...... 194 object 194 -1 [98, 116[ [120, 250[ [254, 274[ [452, 454[ [476, 478[ 98 M 100 M 122 M 146 M 232 M 256 M 454 M 478 S "no spill store" ...... end_intervals begin_intervals name "After Register Allocation" 0 fixed "[rsi|I]" 0 179 [0, 4[ [200, 203[ [356, 359[ [466, 469[ "no optimization" 1 fixed "[rdi|I]" 1 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 2 fixed "[rbx|I]" 2 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 3 fixed "[rax|I]" 3 227 [0, 1[ [202, 204[ [358, 360[ [442, 444[ [448, 450[ [468, 470[ [472, 474[ [478, 480[ "no optimization" 4 fixed "[rdx|I]" 4 202 [0, 6[ [198, 203[ [354, 359[ [462, 469[ "no optimization" 5 fixed "[rcx|I]" 5 179 [0, 8[ [202, 203[ [358, 359[ [464, 469[ "no spill store" 6 fixed "[r8|I]" 6 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 7 fixed "[r9|I]" 7 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 8 fixed "[r11|I]" 8 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 9 fixed "[r13|I]" 9 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" 10 fixed "[r14|I]" 10 -1 [0, 1[ [202, 203[ [358, 359[ [468, 469[ "no definition" ...... 194 object "[rdi|L]" 194 -1 [98, 116[ [120, 190[ 98 M 100 M 122 M 146 M "one spill store" ...... 263 object "[stack:3|L]" 194 194 [190, 201[ "one spill store" 264 object "[stack:3|L]" 194 194 [201, 230[ "one spill store" ...... 267 object "[rdi|L]" 194 194 [230, 250[ [254, 274[ [452, 454[ [476, 478[ 232 M 256 M 454 M 478 S "one spill store" ...... end_intervals |
生成代码
最后,LIR分配物理寄存器后如下:
begin_cfg name "Before Code Generation" begin_block name "B12" from_bci 0 to_bci 0 predecessors successors "B13" xhandlers flags first_lir_id 0 last_lir_id 28 begin_LIR 0 label [label:0xfc0043b8] <|@ 2 std_entry <|@ 10 move [metadata:0x3301c100|M] [rax|M] <|@ 12 move [Base:[rax|M] Disp: 108|I] [rdi|I] <|@ 14 add [rdi|I] [int:8|I] [rdi|I] <|@ 16 move [rdi|I] [Base:[rax|M] Disp: 108|I] <|@ 18 move [metadata:0x32dd2238|M] [rax|M] <|@ 20 logic_and [rdi|I] [int:8184|I] [rdi|I] <|@ 22 cmp [rdi|I] [int:0|I] <|@ 24 branch [EQ] [CounterOverflowStub: 0xf8025908] <|@ 26 label [label:0xf8025930] <|@ end_LIR end_block begin_block name "B13" from_bci 0 to_bci 0 predecessors "B12" successors "B0" xhandlers flags "std" dominator "B12" first_lir_id 30 last_lir_id 32 begin_LIR 30 label [label:0xfc0046c8] <|@ end_LIR end_block begin_block name "B0" from_bci 0 to_bci 7 predecessors "B13" successors "B2" "B1" xhandlers flags "std" dominator "B13" first_lir_id 34 last_lir_id 54 begin_LIR 34 label [label:0xf801ee78] <|@ 36 move [Base:[rsi|L] Disp: 12|L] [rax|L] <|@ 38 move [Base:[rax|L] Disp: 12|I] [rdi|I] [bci:4] <|@ 40 cmp [rcx|I] [int:0|I] <|@ 42 move [metadata:0x3301c100|M] [rbx|M] <|@ 44 cmove [GE] [lng:152|J] [lng:168|J] [r8r8|J] <|@ 46 move [Base:[rbx|M] Index:[r8r8|J] Disp: 0|J] [r9r9|J] <|@ 48 leal [Base:[r9r9|J] Disp: 1|I] [r9r9|J] <|@ 50 move [r9r9|J] [Base:[rbx|M] Index:[r8r8|J] Disp: 0|J] <|@ 52 branch [GE] [B2] <|@ end_LIR end_block begin_block name "B1" from_bci 10 to_bci 12 predecessors "B0" successors "B3" xhandlers flags dominator "B0" first_lir_id 56 last_lir_id 64 begin_LIR 56 label [label:0xf801f198] <|@ 58 move [metadata:0x3301c100|M] [rcx|M] <|@ 60 add [Base:[rcx|M] Disp: 184|J] [int:1|I] [Base:[rcx|M] Disp: 184|J] <|@ 62 move [int:0|I] [rcx|I] <|@ 64 branch [AL] [B3] <|@ end_LIR end_block begin_block name "B2" from_bci 15 to_bci 17 predecessors "B0" successors "B3" "B4" xhandlers flags dominator "B0" first_lir_id 66 last_lir_id 82 begin_LIR 66 label [label:0xf801f4b8] <|@ 68 cmp [rcx|I] [rdi|I] <|@ 70 move [metadata:0x3301c100|M] [rbx|M] <|@ 72 cmove [LT] [lng:208|J] [lng:224|J] [r8r8|J] <|@ 74 move [Base:[rbx|M] Index:[r8r8|J] Disp: 0|J] [r9r9|J] <|@ 76 leal [Base:[r9r9|J] Disp: 1|I] [r9r9|J] <|@ 78 move [r9r9|J] [Base:[rbx|M] Index:[r8r8|J] Disp: 0|J] <|@ 80 branch [GE] [B4] <|@ end_LIR end_block begin_block name "B3" from_bci 22 to_bci 25 predecessors "B1" "B2" successors "B6" "B7" xhandlers flags dominator "B0" first_lir_id 90 last_lir_id 106 begin_LIR 90 label [label:0xf801f7d8] <|@ 92 cmp [rdx|I] [int:65536|I] <|@ 94 move [metadata:0x3301c100|M] [rbx|M] <|@ 96 cmove [GE] [lng:240|J] [lng:256|J] [r8r8|J] <|@ 98 move [Base:[rbx|M] Index:[r8r8|J] Disp: 0|J] [r9r9|J] <|@ 100 leal [Base:[r9r9|J] Disp: 1|I] [r9r9|J] <|@ 102 move [r9r9|J] [Base:[rbx|M] Index:[r8r8|J] Disp: 0|J] <|@ 104 branch [GE] [B6] <|@ 106 branch [AL] [B7] <|@ end_LIR end_block begin_block name "B8" from_bci 43 to_bci 49 predecessors "B7" successors "B11" "B10" xhandlers flags "bb" dominator "B7" loop_index 0 loop_depth 1 first_lir_id 132 last_lir_id 156 begin_LIR 132 label [label:0xf8020778] <|@ 134 convert [i2l] [rcx|I] [rsirsi|J] <|@ 136 cmp [rcx|I] [Base:[rax|L] Disp: 12|I] <|@ 138 branch [AE] [RangeCheckStub: 0xf80296d8] [bci:47] <|@ 140 move [Base:[rax|L] Index:[rsirsi|J] * 2 Disp: 16|C] [rsi|I] <|@ 142 cmp [rsi|I] [rdx|I] <|@ 144 move [metadata:0x3301c100|M] [rsi|M] <|@ 146 cmove [NE] [lng:304|J] [lng:320|J] [rbxrbx|J] <|@ 148 move [Base:[rsi|M] Index:[rbxrbx|J] Disp: 0|J] [r8r8|J] <|@ 150 leal [Base:[r8r8|J] Disp: 1|I] [r8r8|J] <|@ 152 move [r8r8|J] [Base:[rsi|M] Index:[rbxrbx|J] Disp: 0|J] <|@ 154 branch [EQ] [B10] <|@ end_LIR end_block begin_block name "B11" from_bci 55 to_bci 58 predecessors "B8" successors "B7" xhandlers flags "lle" dominator "B8" loop_index 0 loop_depth 1 first_lir_id 158 last_lir_id 190 begin_LIR 158 label [label:0xf80210d8] <|@ 162 add [rcx|I] [int:1|I] [rcx|I] <|@ 164 move [metadata:0x3301c100|M] [rsi|M] <|@ 166 move [Base:[rsi|M] Disp: 112|I] [rbx|I] <|@ 168 add [rbx|I] [int:8|I] [rbx|I] <|@ 170 move [rbx|I] [Base:[rsi|M] Disp: 112|I] <|@ 172 move [metadata:0x32dd2238|M] [rsi|M] <|@ 174 logic_and [rbx|I] [int:65528|I] [rbx|I] <|@ 176 cmp [rbx|I] [int:0|I] <|@ 178 branch [EQ] [CounterOverflowStub: 0xf802a488] <|@ 180 label [label:0xf802a4b0] <|@ 182 safepoint [bci:58] <|@ 184 move [metadata:0x3301c100|M] [rsi|M] <|@ 186 add [Base:[rsi|M] Disp: 336|J] [int:1|I] [Base:[rsi|M] Disp: 336|J] <|@ end_LIR end_block begin_block name "B7" from_bci 37 to_bci 40 predecessors "B11" "B3" successors "B9" "B8" xhandlers flags "plh" "llh" dominator "B5" loop_index 0 loop_depth 1 first_lir_id 114 last_lir_id 130 begin_LIR 114 label [label:0xf8020458] <|@ 116 cmp [rcx|I] [rdi|I] <|@ 118 move [metadata:0x3301c100|M] [rsi|M] <|@ 120 cmove [GE] [lng:272|J] [lng:288|J] [rbxrbx|J] <|@ 122 move [Base:[rsi|M] Index:[rbxrbx|J] Disp: 0|J] [r8r8|J] <|@ 124 leal [Base:[r8r8|J] Disp: 1|I] [r8r8|J] <|@ 126 move [r8r8|J] [Base:[rsi|M] Index:[rbxrbx|J] Disp: 0|J] <|@ 128 branch [GE] [B9] <|@ 130 branch [AL] [B8] <|@ end_LIR end_block begin_block name "B10" from_bci 52 to_bci 54 predecessors "B8" successors xhandlers flags dominator "B8" first_lir_id 192 last_lir_id 196 begin_LIR 192 label [label:0xf8020db8] <|@ 194 move [rcx|I] [rax|I] <|@ 196 return [rax|I] <|@ end_LIR end_block begin_block name "B9" from_bci 61 to_bci 62 predecessors "B7" successors xhandlers flags dominator "B7" first_lir_id 198 last_lir_id 202 begin_LIR 198 label [label:0xf8020a98] <|@ 200 move [int:-1|I] [rax|I] <|@ 202 return [rax|I] <|@ end_LIR end_block begin_block name "B6" from_bci 63 to_bci 69 predecessors "B3" successors xhandlers flags dominator "B3" first_lir_id 204 last_lir_id 222 begin_LIR 204 label [label:0xf8020138] <|@ 206 move [rsi|L] [rdi|L] <|@ 208 profile_call indexOf.java/lang/String @ 66 [rbx|L] [rdi|L] [raxrax|J] <|@ 216 optvirtual call: [addr: 0x0] [recv: [rsi|L]] [result: [rax|I]] [bci:66] <|@ 222 return [rax|I] <|@ end_LIR end_block begin_block name "B4" from_bci 20 to_bci 21 predecessors "B2" successors xhandlers flags dominator "B2" first_lir_id 224 last_lir_id 228 begin_LIR 224 label [label:0xf801faf8] <|@ 226 move [int:-1|I] [rax|I] <|@ 228 return [rax|I] <|@ end_LIR end_block end_cfg |
发射汇编代码的过程如:
int Compilation::compile_java_method() int Compilation::emit_code_body() void LIR_Assembler::emit_code(BlockList* hir) void LIR_Assembler::emit_block(BlockBegin* block) void LIR_Assembler::emit_lir_list(LIR_List* list) virtual void emit_code(LIR_Assembler* masm) void LIR_Op1::emit_code(LIR_Assembler* masm) //比如前面的lir_move void LIR_Assembler::emit_op1(LIR_Op1* op) { switch (op->code()) { case lir_move: if (op->move_kind() == lir_move_volatile) { assert(op->patch_code() == lir_patch_none, "can't patch volatiles"); volatile_move_op(op->in_opr(), op->result_opr(), op->type(), op->info()); } else { move_op(op->in_opr(), op->result_opr(), op->type(), op->patch_code(), op->info(), op->pop_fpu_stack(), op->move_kind() == lir_move_unaligned, op->move_kind() == lir_move_wide); } break; ...... } void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned, bool wide) { if (src->is_register()) { if (dest->is_register()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); reg2reg(src, dest); } else if (dest->is_stack()) { ...... } void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { ...... // move between cpu-registers if (dest->is_single_cpu()) { ...... move_regs(src->as_register(), dest->as_register()); } else if (dest->is_double_cpu()) { ...... } void LIR_Assembler::move_regs(Register from_reg, Register to_reg) { if (from_reg != to_reg) __ mov(to_reg, from_reg); } //Code in assembler_x86.cpp void Assembler::mov(Register dst, Register src) { LP64_ONLY(movq(dst, src)) NOT_LP64(movl(dst, src)); } |
本作品采用知识共享署名 4.0 国际许可协议进行许可。