HGraphBuilder方法分析一

来源:互联网 发布:sql server 权限管理 编辑:程序博客网 时间:2024/06/05 09:21

在~/android-6.0.1_r62/art/compiler/optimizing/builder.cc中为类HGraphBuilder的具体信息:
1/首要分析的方法为:
bool AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_pc);
该方法的主要功能是分析dex instruction,将HInstruction添加到graph中以可以执行该dex instruction。返回值意为,该dex instruction是否能被处理。
具体实现:
A.
1317 if (current_block_ == nullptr) {
1318 return true; // Dead code
1319 }

先检查current_block_ == nullptr,若相等,则直接返回真。
B. switch (instruction.Opcode())
根据Opcode的不同进行不同的处理,类instruction中定义了dex instruction,Opcode()方法返回的是instruction的opcode field,也就是instruction的前16位。
下面以CONST_4为例,总共只有三行代码。

1322     case Instruction::CONST_4: {1323       int32_t register_index = instruction.VRegA();1324       HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n());//HIntConstant类包含的是int类型的常量。1325       UpdateLocal(register_index, constant);1326       break;1327     }

其中CONST_4为dalvik指令const/4:
const/4 vA,#+B 将数值符号扩展为32位后赋值给寄存器vA。
关于dalvik指令更详细的介绍在~/android-6.0.1_r62/art/runtime/dex_instruction_list.h中,例如对于CONST_4:

#define DEX_INSTRUCTION_LIST(V) \V(0x12, CONST_4, "const/4", k11n, true, kNone, kContinue | kRegBFieldOrConstant, kVerifyRegA)

①int32_t register_index = instruction.VRegA();

 57 inline int32_t Instruction::VRegA() const { 58   switch (FormatOf(Opcode())) { 59     case k10t: return VRegA_10t(); 60     case k10x: return VRegA_10x(); 61     case k11n: return VRegA_11n(); 62     case k11x: return VRegA_11x(); 63     case k12x: return VRegA_12x(); 64     case k20t: return VRegA_20t(); 65     case k21c: return VRegA_21c(); 66     case k21h: return VRegA_21h(); 67     case k21s: return VRegA_21s(); 68     case k21t: return VRegA_21t(); 69     case k22b: return VRegA_22b(); 70     case k22c: return VRegA_22c(); 71     case k22s: return VRegA_22s(); 72     case k22t: return VRegA_22t(); 73     case k22x: return VRegA_22x(); 74     case k23x: return VRegA_23x(); 75     case k30t: return VRegA_30t(); 76     case k31c: return VRegA_31c(); 77     case k31i: return VRegA_31i(); 78     case k31t: return VRegA_31t(); 79     case k32x: return VRegA_32x(); 80     case k35c: return VRegA_35c(); 81     case k3rc: return VRegA_3rc(); 82     case k51l: return VRegA_51l(); 83     default: 84       LOG(FATAL) << "Tried to access vA of instruction " << Name() << " which has no A operand."; 85       exit(EXIT_FAILURE); 86   }

关于dalvik指令的一些知识:
寄存器有两种不同的命名方法:v字命名法和p字命名法;以小写字母v开头的方式表示方法中使用的局部变量和参数;以小写字母p开头的方式表示参数,参数名称从p0开始,依次增大.局部变量能够使用的寄存器仍然是以v开头.
以指令格式“A|G|op BBBB F|E|D|C”为例:
指令中间有两个空格,每个分开的部分大小为16位,所以这条指令由三个16位的字组成。第一个16位是“A|G|op”,高8位由A与G组成,低字节由操作码op组成。第二个16位由BBBB组成,它表示一个16位的偏移值。第三个16位分别由F,E,D,C共四个4位组成,在这里它们表示寄存器参数。
11n有特殊的含义:
1:指令有多少个16位的字组成
1:指令最多使用寄存器的个数
n:4位的立即数
以指令 “op vAA, string@BBBB” 为例:指令用到了1个寄存器参数 vAA,并且还附加了一个字符串常量池索引 string@BBBB,其实这条指令格式代表着 const-string 指令。
指令格式标示等的参考文献:https://my.oschina.net/fhd/blog/365337

根据DEX_ INSTRUCTION_ LIST中的定义可知:CONST_ 4属于k11n,所以返回的是VRegA_11n(),该函数的具体实现如下:

244   uint4_t VRegA_11n() const {245     return VRegA_11n(Fetch16(0));246   }532   uint16_t Fetch16(size_t offset) const {533     const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);534     return insns[offset];//返回insns的第一个16位字的值。535   }556   uint4_t InstA(uint16_t inst_data) const {557     DCHECK_EQ(inst_data, Fetch16(0));//检查inst_data是否与Fetch16(0)相等558     return static_cast<uint4_t>((inst_data >> 8) & 0x0f);//inst_data右移8位后与00001111进行与运算。559   }

②HIntConstant* constant = graph_ ->GetIntConstant(instruction.VRegB_11n());
GetIntConstant函数的具体实现为:
(在~/android-6.0.1_r62/art/compiler/optimizing/nodes.h的class:art::HGraph中)

 266   HIntConstant* GetIntConstant(int32_t value) { 267     return CreateConstant(value, &cached_int_constants_); 268   } //首先试着在cache中寻找给定value的已有的常量,如果没有找到,或者已经被删掉了,那么就创建并cache一个新的指令,最后返回常量。 301   InstructionType* CreateConstant(ValueType value, 302                                   ArenaSafeMap<ValueType, InstructionType*>* cache) { 303     // Try to find an existing constant of the given value. 304     InstructionType* constant = nullptr; 305     auto cached_constant = cache->find(value); 306     if (cached_constant != cache->end()) { 307       constant = cached_constant->second; 308     } 309  310     // If not found or previously deleted, create and cache a new instruction. 311     if (constant == nullptr || constant->GetBlock() == nullptr) { 312       constant = new (arena_) InstructionType(value); 313       cache->Overwrite(value, constant); 314       InsertConstant(constant); 315     } 316     return constant; 317   }

③UpdateLocal(register_index, constant);
(在~/android-6.0.1_r62/art/compiler/optimizing/builder.cc中)

2295 void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {2296   HLocal* local = GetLocalAt(register_index);//HLocal类内是graph中的一个local,也就是方法内的局部变量,与一个dex register相关。2297   current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));//HStoreLocal类是将一个value存放(store)在一个给定的local里。该指令有两个输入:value和local。这里是new了一个该类的实例,即将HStoreLocal指令存入了指令序列中。传入的参数中instruction为对应的value。2298 } 2291 HLocal* HGraphBuilder::GetLocalAt(int register_index) const {2292   return locals_.Get(register_index);//locals_的定义为:GrowableArray<HLocal*> locals_;返回的是HLocal*队列中的第register_index个元素。2293 }//HStoreLocal的构造函数2190   HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {2191     SetRawInputAt(0, local);2192     SetRawInputAt(1, value);2193   }//~/android-6.0.1_r62/art/compiler/optimizing/nodes.cc中实现: 483 void HBasicBlock::AddInstruction(HInstruction* instruction) { 484   Add(&instructions_, this, instruction);//instruction_的定义为:HInstructionList instructions_; 485 } 472 static void Add(HInstructionList* instruction_list, 473                 HBasicBlock* block, 474                 HInstruction* instruction) { 475   DCHECK(instruction->GetBlock() == nullptr); 476   DCHECK_EQ(instruction->GetId(), -1); 477   instruction->SetBlock(block); 478   instruction->SetId(block->GetGraph()->GetNextInstructionId()); 479   UpdateInputsUsers(instruction); 480   instruction_list->AddInstruction(instruction); 481 }
原创粉丝点击