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 35 namespace 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 */ 43 class 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 68 static bool IsTypeSupported(Primitive::Type type) { 69 return type != Primitive::kPrimFloat && type != Primitive::kPrimDouble; 70 } 71 72 void 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 82 bool 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 132 static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) { 133 if (code_item.tries_size_ > 0) { 134 return false; 135 } 136 return true; 137 } 138 139 template<typename T> 140 void 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 156 template<typename T> 157 void 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 172 HGraph* 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 216 void 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 233 void 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 267 HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const { 268 DCHECK_GE(index, 0); 269 return branch_targets_.Get(index); 270 } 271 272 template<typename T> 273 void 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 280 template<typename T> 281 void 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 288 template<typename T> 289 void 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 299 template<typename T> 300 void 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 310 void 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 321 bool 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 381 bool 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 428 void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, 429 uint32_t dex_offset, 430 bool is_put, 431 Primitive::Type anticipated_type) { 432 uint8_t source_or_dest_reg = instruction.VRegA_23x(); 433 uint8_t array_reg = instruction.VRegB_23x(); 434 uint8_t index_reg = instruction.VRegC_23x(); 435 436 DCHECK(IsTypeSupported(anticipated_type)); 437 438 // We need one temporary for the null check, one for the index, and one for the length. 439 Temporaries temps(graph_, 3); 440 441 HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot); 442 object = new (arena_) HNullCheck(object, dex_offset); 443 current_block_->AddInstruction(object); 444 temps.Add(object); 445 446 HInstruction* length = new (arena_) HArrayLength(object); 447 current_block_->AddInstruction(length); 448 temps.Add(length); 449 HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt); 450 index = new (arena_) HBoundsCheck(index, length, dex_offset); 451 current_block_->AddInstruction(index); 452 temps.Add(index); 453 if (is_put) { 454 HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type); 455 // TODO: Insert a type check node if the type is Object. 456 current_block_->AddInstruction(new (arena_) HArraySet(object, index, value, dex_offset)); 457 } else { 458 current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type)); 459 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction()); 460 } 461 } 462 463 bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_t dex_offset) { 464 if (current_block_ == nullptr) { 465 return true; // Dead code 466 } 467 468 switch (instruction.Opcode()) { 469 case Instruction::CONST_4: { 470 int32_t register_index = instruction.VRegA(); 471 HIntConstant* constant = GetIntConstant(instruction.VRegB_11n()); 472 UpdateLocal(register_index, constant); 473 break; 474 } 475 476 case Instruction::CONST_16: { 477 int32_t register_index = instruction.VRegA(); 478 HIntConstant* constant = GetIntConstant(instruction.VRegB_21s()); 479 UpdateLocal(register_index, constant); 480 break; 481 } 482 483 case Instruction::CONST: { 484 int32_t register_index = instruction.VRegA(); 485 HIntConstant* constant = GetIntConstant(instruction.VRegB_31i()); 486 UpdateLocal(register_index, constant); 487 break; 488 } 489 490 case Instruction::CONST_HIGH16: { 491 int32_t register_index = instruction.VRegA(); 492 HIntConstant* constant = GetIntConstant(instruction.VRegB_21h() << 16); 493 UpdateLocal(register_index, constant); 494 break; 495 } 496 497 case Instruction::CONST_WIDE_16: { 498 int32_t register_index = instruction.VRegA(); 499 // Get 16 bits of constant value, sign extended to 64 bits. 500 int64_t value = instruction.VRegB_21s(); 501 value <<= 48; 502 value >>= 48; 503 HLongConstant* constant = GetLongConstant(value); 504 UpdateLocal(register_index, constant); 505 break; 506 } 507 508 case Instruction::CONST_WIDE_32: { 509 int32_t register_index = instruction.VRegA(); 510 // Get 32 bits of constant value, sign extended to 64 bits. 511 int64_t value = instruction.VRegB_31i(); 512 value <<= 32; 513 value >>= 32; 514 HLongConstant* constant = GetLongConstant(value); 515 UpdateLocal(register_index, constant); 516 break; 517 } 518 519 case Instruction::CONST_WIDE: { 520 int32_t register_index = instruction.VRegA(); 521 HLongConstant* constant = GetLongConstant(instruction.VRegB_51l()); 522 UpdateLocal(register_index, constant); 523 break; 524 } 525 526 case Instruction::CONST_WIDE_HIGH16: { 527 int32_t register_index = instruction.VRegA(); 528 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48; 529 HLongConstant* constant = GetLongConstant(value); 530 UpdateLocal(register_index, constant); 531 break; 532 } 533 534 // TODO: these instructions are also used to move floating point values, so what is 535 // the type (int or float)? 536 case Instruction::MOVE: 537 case Instruction::MOVE_FROM16: 538 case Instruction::MOVE_16: { 539 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 540 UpdateLocal(instruction.VRegA(), value); 541 break; 542 } 543 544 // TODO: these instructions are also used to move floating point values, so what is 545 // the type (long or double)? 546 case Instruction::MOVE_WIDE: 547 case Instruction::MOVE_WIDE_FROM16: 548 case Instruction::MOVE_WIDE_16: { 549 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong); 550 UpdateLocal(instruction.VRegA(), value); 551 break; 552 } 553 554 case Instruction::MOVE_OBJECT: 555 case Instruction::MOVE_OBJECT_16: 556 case Instruction::MOVE_OBJECT_FROM16: { 557 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot); 558 UpdateLocal(instruction.VRegA(), value); 559 break; 560 } 561 562 case Instruction::RETURN_VOID: { 563 BuildReturn(instruction, Primitive::kPrimVoid); 564 break; 565 } 566 567 #define IF_XX(comparison, cond) \ 568 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_offset); break; \ 569 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_offset); break 570 571 IF_XX(HEqual, EQ); 572 IF_XX(HNotEqual, NE); 573 IF_XX(HLessThan, LT); 574 IF_XX(HLessThanOrEqual, LE); 575 IF_XX(HGreaterThan, GT); 576 IF_XX(HGreaterThanOrEqual, GE); 577 578 case Instruction::GOTO: 579 case Instruction::GOTO_16: 580 case Instruction::GOTO_32: { 581 HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset); 582 DCHECK(target != nullptr); 583 current_block_->AddInstruction(new (arena_) HGoto()); 584 current_block_->AddSuccessor(target); 585 current_block_ = nullptr; 586 break; 587 } 588 589 case Instruction::RETURN: { 590 BuildReturn(instruction, Primitive::kPrimInt); 591 break; 592 } 593 594 case Instruction::RETURN_OBJECT: { 595 BuildReturn(instruction, Primitive::kPrimNot); 596 break; 597 } 598 599 case Instruction::RETURN_WIDE: { 600 BuildReturn(instruction, Primitive::kPrimLong); 601 break; 602 } 603 604 case Instruction::INVOKE_STATIC: 605 case Instruction::INVOKE_DIRECT: { 606 uint32_t method_idx = instruction.VRegB_35c(); 607 uint32_t number_of_vreg_arguments = instruction.VRegA_35c(); 608 uint32_t args[5]; 609 instruction.GetVarArgs(args); 610 if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) { 611 return false; 612 } 613 break; 614 } 615 616 case Instruction::INVOKE_STATIC_RANGE: 617 case Instruction::INVOKE_DIRECT_RANGE: { 618 uint32_t method_idx = instruction.VRegB_3rc(); 619 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc(); 620 uint32_t register_index = instruction.VRegC(); 621 if (!BuildInvoke(instruction, dex_offset, method_idx, 622 number_of_vreg_arguments, true, nullptr, register_index)) { 623 return false; 624 } 625 break; 626 } 627 628 case Instruction::ADD_INT: { 629 Binop_23x<HAdd>(instruction, Primitive::kPrimInt); 630 break; 631 } 632 633 case Instruction::ADD_LONG: { 634 Binop_23x<HAdd>(instruction, Primitive::kPrimLong); 635 break; 636 } 637 638 case Instruction::SUB_INT: { 639 Binop_23x<HSub>(instruction, Primitive::kPrimInt); 640 break; 641 } 642 643 case Instruction::SUB_LONG: { 644 Binop_23x<HSub>(instruction, Primitive::kPrimLong); 645 break; 646 } 647 648 case Instruction::ADD_INT_2ADDR: { 649 Binop_12x<HAdd>(instruction, Primitive::kPrimInt); 650 break; 651 } 652 653 case Instruction::ADD_LONG_2ADDR: { 654 Binop_12x<HAdd>(instruction, Primitive::kPrimLong); 655 break; 656 } 657 658 case Instruction::SUB_INT_2ADDR: { 659 Binop_12x<HSub>(instruction, Primitive::kPrimInt); 660 break; 661 } 662 663 case Instruction::SUB_LONG_2ADDR: { 664 Binop_12x<HSub>(instruction, Primitive::kPrimLong); 665 break; 666 } 667 668 case Instruction::ADD_INT_LIT16: { 669 Binop_22s<HAdd>(instruction, false); 670 break; 671 } 672 673 case Instruction::RSUB_INT: { 674 Binop_22s<HSub>(instruction, true); 675 break; 676 } 677 678 case Instruction::ADD_INT_LIT8: { 679 Binop_22b<HAdd>(instruction, false); 680 break; 681 } 682 683 case Instruction::RSUB_INT_LIT8: { 684 Binop_22b<HSub>(instruction, true); 685 break; 686 } 687 688 case Instruction::NEW_INSTANCE: { 689 current_block_->AddInstruction( 690 new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c())); 691 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 692 break; 693 } 694 695 case Instruction::MOVE_RESULT: 696 case Instruction::MOVE_RESULT_WIDE: 697 case Instruction::MOVE_RESULT_OBJECT: 698 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 699 break; 700 701 case Instruction::CMP_LONG: { 702 Binop_23x<HCompare>(instruction, Primitive::kPrimLong); 703 break; 704 } 705 706 case Instruction::NOP: 707 break; 708 709 case Instruction::IGET: 710 case Instruction::IGET_WIDE: 711 case Instruction::IGET_OBJECT: 712 case Instruction::IGET_BOOLEAN: 713 case Instruction::IGET_BYTE: 714 case Instruction::IGET_CHAR: 715 case Instruction::IGET_SHORT: { 716 if (!BuildFieldAccess(instruction, dex_offset, false)) { 717 return false; 718 } 719 break; 720 } 721 722 case Instruction::IPUT: 723 case Instruction::IPUT_WIDE: 724 case Instruction::IPUT_OBJECT: 725 case Instruction::IPUT_BOOLEAN: 726 case Instruction::IPUT_BYTE: 727 case Instruction::IPUT_CHAR: 728 case Instruction::IPUT_SHORT: { 729 if (!BuildFieldAccess(instruction, dex_offset, true)) { 730 return false; 731 } 732 break; 733 } 734 735 #define ARRAY_XX(kind, anticipated_type) \ 736 case Instruction::AGET##kind: { \ 737 BuildArrayAccess(instruction, dex_offset, false, anticipated_type); \ 738 break; \ 739 } \ 740 case Instruction::APUT##kind: { \ 741 BuildArrayAccess(instruction, dex_offset, true, anticipated_type); \ 742 break; \ 743 } 744 745 ARRAY_XX(, Primitive::kPrimInt); 746 ARRAY_XX(_WIDE, Primitive::kPrimLong); 747 ARRAY_XX(_OBJECT, Primitive::kPrimNot); 748 ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean); 749 ARRAY_XX(_BYTE, Primitive::kPrimByte); 750 ARRAY_XX(_CHAR, Primitive::kPrimChar); 751 ARRAY_XX(_SHORT, Primitive::kPrimShort); 752 753 default: 754 return false; 755 } 756 return true; 757 } 758 759 HIntConstant* HGraphBuilder::GetIntConstant0() { 760 if (constant0_ != nullptr) { 761 return constant0_; 762 } 763 constant0_ = new(arena_) HIntConstant(0); 764 entry_block_->AddInstruction(constant0_); 765 return constant0_; 766 } 767 768 HIntConstant* HGraphBuilder::GetIntConstant1() { 769 if (constant1_ != nullptr) { 770 return constant1_; 771 } 772 constant1_ = new(arena_) HIntConstant(1); 773 entry_block_->AddInstruction(constant1_); 774 return constant1_; 775 } 776 777 HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) { 778 switch (constant) { 779 case 0: return GetIntConstant0(); 780 case 1: return GetIntConstant1(); 781 default: { 782 HIntConstant* instruction = new (arena_) HIntConstant(constant); 783 entry_block_->AddInstruction(instruction); 784 return instruction; 785 } 786 } 787 } 788 789 HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) { 790 HLongConstant* instruction = new (arena_) HLongConstant(constant); 791 entry_block_->AddInstruction(instruction); 792 return instruction; 793 } 794 795 HLocal* HGraphBuilder::GetLocalAt(int register_index) const { 796 return locals_.Get(register_index); 797 } 798 799 void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const { 800 HLocal* local = GetLocalAt(register_index); 801 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction)); 802 } 803 804 HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const { 805 HLocal* local = GetLocalAt(register_index); 806 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type)); 807 return current_block_->GetLastInstruction(); 808 } 809 810 } // namespace art 811