builder.cc revision f12feb8e0e857f2832545b3f28d31bad5a9d3903
1/* 2 * 3 * Copyright (C) 2014 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18#include "builder.h" 19 20#include "class_linker.h" 21#include "dex_file.h" 22#include "dex_file-inl.h" 23#include "dex_instruction.h" 24#include "dex_instruction-inl.h" 25#include "driver/compiler_driver-inl.h" 26#include "mirror/art_field.h" 27#include "mirror/art_field-inl.h" 28#include "mirror/class_loader.h" 29#include "mirror/dex_cache.h" 30#include "nodes.h" 31#include "primitive.h" 32#include "scoped_thread_state_change.h" 33#include "thread.h" 34 35namespace art { 36 37/** 38 * Helper class to add HTemporary instructions. This class is used when 39 * converting a DEX instruction to multiple HInstruction, and where those 40 * instructions do not die at the following instruction, but instead spans 41 * multiple instructions. 42 */ 43class Temporaries : public ValueObject { 44 public: 45 Temporaries(HGraph* graph, size_t count) : graph_(graph), count_(count), index_(0) { 46 graph_->UpdateNumberOfTemporaries(count_); 47 } 48 49 void Add(HInstruction* instruction) { 50 // We currently only support vreg size temps. 51 DCHECK(instruction->GetType() != Primitive::kPrimLong 52 && instruction->GetType() != Primitive::kPrimDouble); 53 HInstruction* temp = new (graph_->GetArena()) HTemporary(index_++); 54 instruction->GetBlock()->AddInstruction(temp); 55 DCHECK(temp->GetPrevious() == instruction); 56 } 57 58 private: 59 HGraph* const graph_; 60 61 // The total number of temporaries that will be used. 62 const size_t count_; 63 64 // Current index in the temporary stack, updated by `Add`. 65 size_t index_; 66}; 67 68static bool IsTypeSupported(Primitive::Type type) { 69 return type != Primitive::kPrimFloat && type != Primitive::kPrimDouble; 70} 71 72void HGraphBuilder::InitializeLocals(uint16_t count) { 73 graph_->SetNumberOfVRegs(count); 74 locals_.SetSize(count); 75 for (int i = 0; i < count; i++) { 76 HLocal* local = new (arena_) HLocal(i); 77 entry_block_->AddInstruction(local); 78 locals_.Put(i, local); 79 } 80} 81 82bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { 83 // dex_compilation_unit_ is null only when unit testing. 84 if (dex_compilation_unit_ == nullptr) { 85 return true; 86 } 87 88 graph_->SetNumberOfInVRegs(number_of_parameters); 89 const char* shorty = dex_compilation_unit_->GetShorty(); 90 int locals_index = locals_.Size() - number_of_parameters; 91 int parameter_index = 0; 92 93 if (!dex_compilation_unit_->IsStatic()) { 94 // Add the implicit 'this' argument, not expressed in the signature. 95 HParameterValue* parameter = 96 new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot); 97 entry_block_->AddInstruction(parameter); 98 HLocal* local = GetLocalAt(locals_index++); 99 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter)); 100 number_of_parameters--; 101 } 102 103 uint32_t pos = 1; 104 for (int i = 0; i < number_of_parameters; i++) { 105 switch (shorty[pos++]) { 106 case 'F': 107 case 'D': { 108 return false; 109 } 110 111 default: { 112 // integer and reference parameters. 113 HParameterValue* parameter = 114 new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos - 1])); 115 entry_block_->AddInstruction(parameter); 116 HLocal* local = GetLocalAt(locals_index++); 117 // Store the parameter value in the local that the dex code will use 118 // to reference that parameter. 119 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter)); 120 if (parameter->GetType() == Primitive::kPrimLong) { 121 i++; 122 locals_index++; 123 parameter_index++; 124 } 125 break; 126 } 127 } 128 } 129 return true; 130} 131 132static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) { 133 if (code_item.tries_size_ > 0) { 134 return false; 135 } 136 return true; 137} 138 139template<typename T> 140void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_offset) { 141 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); 142 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 143 T* comparison = new (arena_) T(first, second); 144 current_block_->AddInstruction(comparison); 145 HInstruction* ifinst = new (arena_) HIf(comparison); 146 current_block_->AddInstruction(ifinst); 147 HBasicBlock* target = FindBlockStartingAt(dex_offset + instruction.GetTargetOffset()); 148 DCHECK(target != nullptr); 149 current_block_->AddSuccessor(target); 150 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits()); 151 DCHECK(target != nullptr); 152 current_block_->AddSuccessor(target); 153 current_block_ = nullptr; 154} 155 156template<typename T> 157void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_offset) { 158 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); 159 T* comparison = new (arena_) T(value, GetIntConstant(0)); 160 current_block_->AddInstruction(comparison); 161 HInstruction* ifinst = new (arena_) HIf(comparison); 162 current_block_->AddInstruction(ifinst); 163 HBasicBlock* target = FindBlockStartingAt(dex_offset + instruction.GetTargetOffset()); 164 DCHECK(target != nullptr); 165 current_block_->AddSuccessor(target); 166 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits()); 167 DCHECK(target != nullptr); 168 current_block_->AddSuccessor(target); 169 current_block_ = nullptr; 170} 171 172HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { 173 if (!CanHandleCodeItem(code_item)) { 174 return nullptr; 175 } 176 177 const uint16_t* code_ptr = code_item.insns_; 178 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_; 179 180 // Setup the graph with the entry block and exit block. 181 graph_ = new (arena_) HGraph(arena_); 182 entry_block_ = new (arena_) HBasicBlock(graph_); 183 graph_->AddBlock(entry_block_); 184 exit_block_ = new (arena_) HBasicBlock(graph_); 185 graph_->SetEntryBlock(entry_block_); 186 graph_->SetExitBlock(exit_block_); 187 188 InitializeLocals(code_item.registers_size_); 189 graph_->UpdateMaximumNumberOfOutVRegs(code_item.outs_size_); 190 191 // To avoid splitting blocks, we compute ahead of time the instructions that 192 // start a new block, and create these blocks. 193 ComputeBranchTargets(code_ptr, code_end); 194 195 if (!InitializeParameters(code_item.ins_size_)) { 196 return nullptr; 197 } 198 199 size_t dex_offset = 0; 200 while (code_ptr < code_end) { 201 // Update the current block if dex_offset starts a new block. 202 MaybeUpdateCurrentBlock(dex_offset); 203 const Instruction& instruction = *Instruction::At(code_ptr); 204 if (!AnalyzeDexInstruction(instruction, dex_offset)) return nullptr; 205 dex_offset += instruction.SizeInCodeUnits(); 206 code_ptr += instruction.SizeInCodeUnits(); 207 } 208 209 // Add the exit block at the end to give it the highest id. 210 graph_->AddBlock(exit_block_); 211 exit_block_->AddInstruction(new (arena_) HExit()); 212 entry_block_->AddInstruction(new (arena_) HGoto()); 213 return graph_; 214} 215 216void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) { 217 HBasicBlock* block = FindBlockStartingAt(index); 218 if (block == nullptr) { 219 return; 220 } 221 222 if (current_block_ != nullptr) { 223 // Branching instructions clear current_block, so we know 224 // the last instruction of the current block is not a branching 225 // instruction. We add an unconditional goto to the found block. 226 current_block_->AddInstruction(new (arena_) HGoto()); 227 current_block_->AddSuccessor(block); 228 } 229 graph_->AddBlock(block); 230 current_block_ = block; 231} 232 233void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, const uint16_t* code_end) { 234 // TODO: Support switch instructions. 235 branch_targets_.SetSize(code_end - code_ptr); 236 237 // Create the first block for the dex instructions, single successor of the entry block. 238 HBasicBlock* block = new (arena_) HBasicBlock(graph_); 239 branch_targets_.Put(0, block); 240 entry_block_->AddSuccessor(block); 241 242 // Iterate over all instructions and find branching instructions. Create blocks for 243 // the locations these instructions branch to. 244 size_t dex_offset = 0; 245 while (code_ptr < code_end) { 246 const Instruction& instruction = *Instruction::At(code_ptr); 247 if (instruction.IsBranch()) { 248 int32_t target = instruction.GetTargetOffset() + dex_offset; 249 // Create a block for the target instruction. 250 if (FindBlockStartingAt(target) == nullptr) { 251 block = new (arena_) HBasicBlock(graph_); 252 branch_targets_.Put(target, block); 253 } 254 dex_offset += instruction.SizeInCodeUnits(); 255 code_ptr += instruction.SizeInCodeUnits(); 256 if ((code_ptr < code_end) && (FindBlockStartingAt(dex_offset) == nullptr)) { 257 block = new (arena_) HBasicBlock(graph_); 258 branch_targets_.Put(dex_offset, block); 259 } 260 } else { 261 code_ptr += instruction.SizeInCodeUnits(); 262 dex_offset += instruction.SizeInCodeUnits(); 263 } 264 } 265} 266 267HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const { 268 DCHECK_GE(index, 0); 269 return branch_targets_.Get(index); 270} 271 272template<typename T> 273void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) { 274 HInstruction* first = LoadLocal(instruction.VRegB(), type); 275 HInstruction* second = LoadLocal(instruction.VRegC(), type); 276 current_block_->AddInstruction(new (arena_) T(type, first, second)); 277 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 278} 279 280template<typename T> 281void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) { 282 HInstruction* first = LoadLocal(instruction.VRegA(), type); 283 HInstruction* second = LoadLocal(instruction.VRegB(), type); 284 current_block_->AddInstruction(new (arena_) T(type, first, second)); 285 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 286} 287 288template<typename T> 289void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) { 290 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 291 HInstruction* second = GetIntConstant(instruction.VRegC_22s()); 292 if (reverse) { 293 std::swap(first, second); 294 } 295 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); 296 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 297} 298 299template<typename T> 300void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) { 301 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 302 HInstruction* second = GetIntConstant(instruction.VRegC_22b()); 303 if (reverse) { 304 std::swap(first, second); 305 } 306 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); 307 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 308} 309 310void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) { 311 if (type == Primitive::kPrimVoid) { 312 current_block_->AddInstruction(new (arena_) HReturnVoid()); 313 } else { 314 HInstruction* value = LoadLocal(instruction.VRegA(), type); 315 current_block_->AddInstruction(new (arena_) HReturn(value)); 316 } 317 current_block_->AddSuccessor(exit_block_); 318 current_block_ = nullptr; 319} 320 321bool HGraphBuilder::BuildInvoke(const Instruction& instruction, 322 uint32_t dex_offset, 323 uint32_t method_idx, 324 uint32_t number_of_vreg_arguments, 325 bool is_range, 326 uint32_t* args, 327 uint32_t register_index) { 328 const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx); 329 const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_); 330 const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_); 331 Primitive::Type return_type = Primitive::GetType(descriptor[0]); 332 bool is_instance_call = 333 instruction.Opcode() != Instruction::INVOKE_STATIC 334 && instruction.Opcode() != Instruction::INVOKE_STATIC_RANGE; 335 const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1); 336 337 // Treat invoke-direct like static calls for now. 338 HInvoke* invoke = new (arena_) HInvokeStatic( 339 arena_, number_of_arguments, return_type, dex_offset, method_idx); 340 341 size_t start_index = 0; 342 Temporaries temps(graph_, is_instance_call ? 1 : 0); 343 if (is_instance_call) { 344 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot); 345 HNullCheck* null_check = new (arena_) HNullCheck(arg, dex_offset); 346 current_block_->AddInstruction(null_check); 347 temps.Add(null_check); 348 invoke->SetArgumentAt(0, null_check); 349 start_index = 1; 350 } 351 352 uint32_t descriptor_index = 1; 353 uint32_t argument_index = start_index; 354 for (size_t i = start_index; i < number_of_vreg_arguments; i++, argument_index++) { 355 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]); 356 if (!IsTypeSupported(type)) { 357 return false; 358 } 359 if (!is_range && type == Primitive::kPrimLong && args[i] + 1 != args[i + 1]) { 360 LOG(WARNING) << "Non sequential register pair in " << dex_compilation_unit_->GetSymbol() 361 << " at " << dex_offset; 362 // We do not implement non sequential register pair. 363 return false; 364 } 365 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type); 366 invoke->SetArgumentAt(argument_index, arg); 367 if (type == Primitive::kPrimLong) { 368 i++; 369 } 370 } 371 372 if (!IsTypeSupported(return_type)) { 373 return false; 374 } 375 376 DCHECK_EQ(argument_index, number_of_arguments); 377 current_block_->AddInstruction(invoke); 378 return true; 379} 380 381bool HGraphBuilder::BuildFieldAccess(const Instruction& instruction, 382 uint32_t dex_offset, 383 bool is_put) { 384 uint32_t source_or_dest_reg = instruction.VRegA_22c(); 385 uint32_t obj_reg = instruction.VRegB_22c(); 386 uint16_t field_index = instruction.VRegC_22c(); 387 388 ScopedObjectAccess soa(Thread::Current()); 389 StackHandleScope<1> hs(soa.Self()); 390 Handle<mirror::ArtField> resolved_field(hs.NewHandle( 391 compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa))); 392 393 if (resolved_field.Get() == nullptr) { 394 return false; 395 } 396 if (resolved_field->IsVolatile()) { 397 return false; 398 } 399 400 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); 401 if (!IsTypeSupported(field_type)) { 402 return false; 403 } 404 405 HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot); 406 current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_offset)); 407 if (is_put) { 408 Temporaries temps(graph_, 1); 409 HInstruction* null_check = current_block_->GetLastInstruction(); 410 // We need one temporary for the null check. 411 temps.Add(null_check); 412 HInstruction* value = LoadLocal(source_or_dest_reg, field_type); 413 current_block_->AddInstruction(new (arena_) HInstanceFieldSet( 414 null_check, 415 value, 416 resolved_field->GetOffset())); 417 } else { 418 current_block_->AddInstruction(new (arena_) HInstanceFieldGet( 419 current_block_->GetLastInstruction(), 420 field_type, 421 resolved_field->GetOffset())); 422 423 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction()); 424 } 425 return true; 426} 427 428bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) { 429 if (current_block_ == nullptr) { 430 return true; // Dead code 431 } 432 433 switch (instruction.Opcode()) { 434 case Instruction::CONST_4: { 435 int32_t register_index = instruction.VRegA(); 436 HIntConstant* constant = GetIntConstant(instruction.VRegB_11n()); 437 UpdateLocal(register_index, constant); 438 break; 439 } 440 441 case Instruction::CONST_16: { 442 int32_t register_index = instruction.VRegA(); 443 HIntConstant* constant = GetIntConstant(instruction.VRegB_21s()); 444 UpdateLocal(register_index, constant); 445 break; 446 } 447 448 case Instruction::CONST: { 449 int32_t register_index = instruction.VRegA(); 450 HIntConstant* constant = GetIntConstant(instruction.VRegB_31i()); 451 UpdateLocal(register_index, constant); 452 break; 453 } 454 455 case Instruction::CONST_HIGH16: { 456 int32_t register_index = instruction.VRegA(); 457 HIntConstant* constant = GetIntConstant(instruction.VRegB_21h() << 16); 458 UpdateLocal(register_index, constant); 459 break; 460 } 461 462 case Instruction::CONST_WIDE_16: { 463 int32_t register_index = instruction.VRegA(); 464 // Get 16 bits of constant value, sign extended to 64 bits. 465 int64_t value = instruction.VRegB_21s(); 466 value <<= 48; 467 value >>= 48; 468 HLongConstant* constant = GetLongConstant(value); 469 UpdateLocal(register_index, constant); 470 break; 471 } 472 473 case Instruction::CONST_WIDE_32: { 474 int32_t register_index = instruction.VRegA(); 475 // Get 32 bits of constant value, sign extended to 64 bits. 476 int64_t value = instruction.VRegB_31i(); 477 value <<= 32; 478 value >>= 32; 479 HLongConstant* constant = GetLongConstant(value); 480 UpdateLocal(register_index, constant); 481 break; 482 } 483 484 case Instruction::CONST_WIDE: { 485 int32_t register_index = instruction.VRegA(); 486 HLongConstant* constant = GetLongConstant(instruction.VRegB_51l()); 487 UpdateLocal(register_index, constant); 488 break; 489 } 490 491 case Instruction::CONST_WIDE_HIGH16: { 492 int32_t register_index = instruction.VRegA(); 493 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48; 494 HLongConstant* constant = GetLongConstant(value); 495 UpdateLocal(register_index, constant); 496 break; 497 } 498 499 // TODO: these instructions are also used to move floating point values, so what is 500 // the type (int or float)? 501 case Instruction::MOVE: 502 case Instruction::MOVE_FROM16: 503 case Instruction::MOVE_16: { 504 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 505 UpdateLocal(instruction.VRegA(), value); 506 break; 507 } 508 509 // TODO: these instructions are also used to move floating point values, so what is 510 // the type (long or double)? 511 case Instruction::MOVE_WIDE: 512 case Instruction::MOVE_WIDE_FROM16: 513 case Instruction::MOVE_WIDE_16: { 514 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong); 515 UpdateLocal(instruction.VRegA(), value); 516 break; 517 } 518 519 case Instruction::MOVE_OBJECT: 520 case Instruction::MOVE_OBJECT_16: 521 case Instruction::MOVE_OBJECT_FROM16: { 522 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot); 523 UpdateLocal(instruction.VRegA(), value); 524 break; 525 } 526 527 case Instruction::RETURN_VOID: { 528 BuildReturn(instruction, Primitive::kPrimVoid); 529 break; 530 } 531 532#define IF_XX(comparison, cond) \ 533 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_offset); break; \ 534 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_offset); break 535 536 IF_XX(HEqual, EQ); 537 IF_XX(HNotEqual, NE); 538 IF_XX(HLessThan, LT); 539 IF_XX(HLessThanOrEqual, LE); 540 IF_XX(HGreaterThan, GT); 541 IF_XX(HGreaterThanOrEqual, GE); 542 543 case Instruction::GOTO: 544 case Instruction::GOTO_16: 545 case Instruction::GOTO_32: { 546 HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset); 547 DCHECK(target != nullptr); 548 current_block_->AddInstruction(new (arena_) HGoto()); 549 current_block_->AddSuccessor(target); 550 current_block_ = nullptr; 551 break; 552 } 553 554 case Instruction::RETURN: { 555 BuildReturn(instruction, Primitive::kPrimInt); 556 break; 557 } 558 559 case Instruction::RETURN_OBJECT: { 560 BuildReturn(instruction, Primitive::kPrimNot); 561 break; 562 } 563 564 case Instruction::RETURN_WIDE: { 565 BuildReturn(instruction, Primitive::kPrimLong); 566 break; 567 } 568 569 case Instruction::INVOKE_STATIC: 570 case Instruction::INVOKE_DIRECT: { 571 uint32_t method_idx = instruction.VRegB_35c(); 572 uint32_t number_of_vreg_arguments = instruction.VRegA_35c(); 573 uint32_t args[5]; 574 instruction.GetVarArgs(args); 575 if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) { 576 return false; 577 } 578 break; 579 } 580 581 case Instruction::INVOKE_STATIC_RANGE: 582 case Instruction::INVOKE_DIRECT_RANGE: { 583 uint32_t method_idx = instruction.VRegB_3rc(); 584 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc(); 585 uint32_t register_index = instruction.VRegC(); 586 if (!BuildInvoke(instruction, dex_offset, method_idx, 587 number_of_vreg_arguments, true, nullptr, register_index)) { 588 return false; 589 } 590 break; 591 } 592 593 case Instruction::ADD_INT: { 594 Binop_23x<HAdd>(instruction, Primitive::kPrimInt); 595 break; 596 } 597 598 case Instruction::ADD_LONG: { 599 Binop_23x<HAdd>(instruction, Primitive::kPrimLong); 600 break; 601 } 602 603 case Instruction::SUB_INT: { 604 Binop_23x<HSub>(instruction, Primitive::kPrimInt); 605 break; 606 } 607 608 case Instruction::SUB_LONG: { 609 Binop_23x<HSub>(instruction, Primitive::kPrimLong); 610 break; 611 } 612 613 case Instruction::ADD_INT_2ADDR: { 614 Binop_12x<HAdd>(instruction, Primitive::kPrimInt); 615 break; 616 } 617 618 case Instruction::ADD_LONG_2ADDR: { 619 Binop_12x<HAdd>(instruction, Primitive::kPrimLong); 620 break; 621 } 622 623 case Instruction::SUB_INT_2ADDR: { 624 Binop_12x<HSub>(instruction, Primitive::kPrimInt); 625 break; 626 } 627 628 case Instruction::SUB_LONG_2ADDR: { 629 Binop_12x<HSub>(instruction, Primitive::kPrimLong); 630 break; 631 } 632 633 case Instruction::ADD_INT_LIT16: { 634 Binop_22s<HAdd>(instruction, false); 635 break; 636 } 637 638 case Instruction::RSUB_INT: { 639 Binop_22s<HSub>(instruction, true); 640 break; 641 } 642 643 case Instruction::ADD_INT_LIT8: { 644 Binop_22b<HAdd>(instruction, false); 645 break; 646 } 647 648 case Instruction::RSUB_INT_LIT8: { 649 Binop_22b<HSub>(instruction, true); 650 break; 651 } 652 653 case Instruction::NEW_INSTANCE: { 654 current_block_->AddInstruction( 655 new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c())); 656 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 657 break; 658 } 659 660 case Instruction::MOVE_RESULT: 661 case Instruction::MOVE_RESULT_WIDE: 662 case Instruction::MOVE_RESULT_OBJECT: 663 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 664 break; 665 666 case Instruction::CMP_LONG: { 667 Binop_23x<HCompare>(instruction, Primitive::kPrimLong); 668 break; 669 } 670 671 case Instruction::NOP: 672 break; 673 674 case Instruction::IGET: 675 case Instruction::IGET_WIDE: 676 case Instruction::IGET_OBJECT: 677 case Instruction::IGET_BOOLEAN: 678 case Instruction::IGET_BYTE: 679 case Instruction::IGET_CHAR: 680 case Instruction::IGET_SHORT: { 681 if (!BuildFieldAccess(instruction, dex_offset, false)) { 682 return false; 683 } 684 break; 685 } 686 687 case Instruction::IPUT: 688 case Instruction::IPUT_WIDE: 689 case Instruction::IPUT_OBJECT: 690 case Instruction::IPUT_BOOLEAN: 691 case Instruction::IPUT_BYTE: 692 case Instruction::IPUT_CHAR: 693 case Instruction::IPUT_SHORT: { 694 if (!BuildFieldAccess(instruction, dex_offset, true)) { 695 return false; 696 } 697 break; 698 } 699 700 default: 701 return false; 702 } 703 return true; 704} 705 706HIntConstant* HGraphBuilder::GetIntConstant0() { 707 if (constant0_ != nullptr) { 708 return constant0_; 709 } 710 constant0_ = new(arena_) HIntConstant(0); 711 entry_block_->AddInstruction(constant0_); 712 return constant0_; 713} 714 715HIntConstant* HGraphBuilder::GetIntConstant1() { 716 if (constant1_ != nullptr) { 717 return constant1_; 718 } 719 constant1_ = new(arena_) HIntConstant(1); 720 entry_block_->AddInstruction(constant1_); 721 return constant1_; 722} 723 724HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) { 725 switch (constant) { 726 case 0: return GetIntConstant0(); 727 case 1: return GetIntConstant1(); 728 default: { 729 HIntConstant* instruction = new (arena_) HIntConstant(constant); 730 entry_block_->AddInstruction(instruction); 731 return instruction; 732 } 733 } 734} 735 736HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) { 737 HLongConstant* instruction = new (arena_) HLongConstant(constant); 738 entry_block_->AddInstruction(instruction); 739 return instruction; 740} 741 742HLocal* HGraphBuilder::GetLocalAt(int register_index) const { 743 return locals_.Get(register_index); 744} 745 746void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const { 747 HLocal* local = GetLocalAt(register_index); 748 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction)); 749} 750 751HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const { 752 HLocal* local = GetLocalAt(register_index); 753 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type)); 754 return current_block_->GetLastInstruction(); 755} 756 757} // namespace art 758