builder.cc revision 3dbcb38a8b2237b0da290ae35dc0caab3cb47b3d
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "builder.h" 18 19#include "class_linker.h" 20#include "dex_file.h" 21#include "dex_file-inl.h" 22#include "dex_instruction.h" 23#include "dex_instruction-inl.h" 24#include "driver/compiler_driver-inl.h" 25#include "mirror/art_field.h" 26#include "mirror/art_field-inl.h" 27#include "mirror/class_loader.h" 28#include "mirror/dex_cache.h" 29#include "nodes.h" 30#include "primitive.h" 31#include "scoped_thread_state_change.h" 32#include "thread.h" 33 34namespace art { 35 36/** 37 * Helper class to add HTemporary instructions. This class is used when 38 * converting a DEX instruction to multiple HInstruction, and where those 39 * instructions do not die at the following instruction, but instead spans 40 * multiple instructions. 41 */ 42class Temporaries : public ValueObject { 43 public: 44 Temporaries(HGraph* graph, size_t count) : graph_(graph), count_(count), index_(0) { 45 graph_->UpdateNumberOfTemporaries(count_); 46 } 47 48 void Add(HInstruction* instruction) { 49 // We currently only support vreg size temps. 50 DCHECK(instruction->GetType() != Primitive::kPrimLong 51 && instruction->GetType() != Primitive::kPrimDouble); 52 HInstruction* temp = new (graph_->GetArena()) HTemporary(index_++); 53 instruction->GetBlock()->AddInstruction(temp); 54 DCHECK(temp->GetPrevious() == instruction); 55 } 56 57 private: 58 HGraph* const graph_; 59 60 // The total number of temporaries that will be used. 61 const size_t count_; 62 63 // Current index in the temporary stack, updated by `Add`. 64 size_t index_; 65}; 66 67static bool IsTypeSupported(Primitive::Type type) { 68 return type != Primitive::kPrimFloat && type != Primitive::kPrimDouble; 69} 70 71void HGraphBuilder::InitializeLocals(uint16_t count) { 72 graph_->SetNumberOfVRegs(count); 73 locals_.SetSize(count); 74 for (int i = 0; i < count; i++) { 75 HLocal* local = new (arena_) HLocal(i); 76 entry_block_->AddInstruction(local); 77 locals_.Put(i, local); 78 } 79} 80 81bool HGraphBuilder::InitializeParameters(uint16_t number_of_parameters) { 82 // dex_compilation_unit_ is null only when unit testing. 83 if (dex_compilation_unit_ == nullptr) { 84 return true; 85 } 86 87 graph_->SetNumberOfInVRegs(number_of_parameters); 88 const char* shorty = dex_compilation_unit_->GetShorty(); 89 int locals_index = locals_.Size() - number_of_parameters; 90 int parameter_index = 0; 91 92 if (!dex_compilation_unit_->IsStatic()) { 93 // Add the implicit 'this' argument, not expressed in the signature. 94 HParameterValue* parameter = 95 new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot); 96 entry_block_->AddInstruction(parameter); 97 HLocal* local = GetLocalAt(locals_index++); 98 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter)); 99 number_of_parameters--; 100 } 101 102 uint32_t pos = 1; 103 for (int i = 0; i < number_of_parameters; i++) { 104 HParameterValue* parameter = 105 new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos++])); 106 entry_block_->AddInstruction(parameter); 107 HLocal* local = GetLocalAt(locals_index++); 108 // Store the parameter value in the local that the dex code will use 109 // to reference that parameter. 110 entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter)); 111 bool is_wide = (parameter->GetType() == Primitive::kPrimLong) 112 || (parameter->GetType() == Primitive::kPrimDouble); 113 if (is_wide) { 114 i++; 115 locals_index++; 116 parameter_index++; 117 } 118 } 119 return true; 120} 121 122static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) { 123 if (code_item.tries_size_ > 0) { 124 return false; 125 } 126 return true; 127} 128 129template<typename T> 130void HGraphBuilder::If_22t(const Instruction& instruction, uint32_t dex_offset) { 131 int32_t target_offset = instruction.GetTargetOffset(); 132 PotentiallyAddSuspendCheck(target_offset, dex_offset); 133 HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); 134 HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 135 T* comparison = new (arena_) T(first, second); 136 current_block_->AddInstruction(comparison); 137 HInstruction* ifinst = new (arena_) HIf(comparison); 138 current_block_->AddInstruction(ifinst); 139 HBasicBlock* target = FindBlockStartingAt(dex_offset + target_offset); 140 DCHECK(target != nullptr); 141 current_block_->AddSuccessor(target); 142 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits()); 143 DCHECK(target != nullptr); 144 current_block_->AddSuccessor(target); 145 current_block_ = nullptr; 146} 147 148template<typename T> 149void HGraphBuilder::If_21t(const Instruction& instruction, uint32_t dex_offset) { 150 int32_t target_offset = instruction.GetTargetOffset(); 151 PotentiallyAddSuspendCheck(target_offset, dex_offset); 152 HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt); 153 T* comparison = new (arena_) T(value, GetIntConstant(0)); 154 current_block_->AddInstruction(comparison); 155 HInstruction* ifinst = new (arena_) HIf(comparison); 156 current_block_->AddInstruction(ifinst); 157 HBasicBlock* target = FindBlockStartingAt(dex_offset + target_offset); 158 DCHECK(target != nullptr); 159 current_block_->AddSuccessor(target); 160 target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits()); 161 DCHECK(target != nullptr); 162 current_block_->AddSuccessor(target); 163 current_block_ = nullptr; 164} 165 166HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { 167 if (!CanHandleCodeItem(code_item)) { 168 return nullptr; 169 } 170 171 const uint16_t* code_ptr = code_item.insns_; 172 const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_; 173 code_start_ = code_ptr; 174 175 // Setup the graph with the entry block and exit block. 176 graph_ = new (arena_) HGraph(arena_); 177 entry_block_ = new (arena_) HBasicBlock(graph_, 0); 178 graph_->AddBlock(entry_block_); 179 exit_block_ = new (arena_) HBasicBlock(graph_, kNoDexPc); 180 graph_->SetEntryBlock(entry_block_); 181 graph_->SetExitBlock(exit_block_); 182 183 InitializeLocals(code_item.registers_size_); 184 graph_->UpdateMaximumNumberOfOutVRegs(code_item.outs_size_); 185 186 // To avoid splitting blocks, we compute ahead of time the instructions that 187 // start a new block, and create these blocks. 188 ComputeBranchTargets(code_ptr, code_end); 189 190 if (!InitializeParameters(code_item.ins_size_)) { 191 return nullptr; 192 } 193 194 size_t dex_offset = 0; 195 while (code_ptr < code_end) { 196 // Update the current block if dex_offset starts a new block. 197 MaybeUpdateCurrentBlock(dex_offset); 198 const Instruction& instruction = *Instruction::At(code_ptr); 199 if (!AnalyzeDexInstruction(instruction, dex_offset)) return nullptr; 200 dex_offset += instruction.SizeInCodeUnits(); 201 code_ptr += instruction.SizeInCodeUnits(); 202 } 203 204 // Add the exit block at the end to give it the highest id. 205 graph_->AddBlock(exit_block_); 206 exit_block_->AddInstruction(new (arena_) HExit()); 207 // Add the suspend check to the entry block. 208 entry_block_->AddInstruction(new (arena_) HSuspendCheck(0)); 209 entry_block_->AddInstruction(new (arena_) HGoto()); 210 return graph_; 211} 212 213void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) { 214 HBasicBlock* block = FindBlockStartingAt(index); 215 if (block == nullptr) { 216 return; 217 } 218 219 if (current_block_ != nullptr) { 220 // Branching instructions clear current_block, so we know 221 // the last instruction of the current block is not a branching 222 // instruction. We add an unconditional goto to the found block. 223 current_block_->AddInstruction(new (arena_) HGoto()); 224 current_block_->AddSuccessor(block); 225 } 226 graph_->AddBlock(block); 227 current_block_ = block; 228} 229 230void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr, const uint16_t* code_end) { 231 // TODO: Support switch instructions. 232 branch_targets_.SetSize(code_end - code_ptr); 233 234 // Create the first block for the dex instructions, single successor of the entry block. 235 HBasicBlock* block = new (arena_) HBasicBlock(graph_, 0); 236 branch_targets_.Put(0, block); 237 entry_block_->AddSuccessor(block); 238 239 // Iterate over all instructions and find branching instructions. Create blocks for 240 // the locations these instructions branch to. 241 size_t dex_offset = 0; 242 while (code_ptr < code_end) { 243 const Instruction& instruction = *Instruction::At(code_ptr); 244 if (instruction.IsBranch()) { 245 int32_t target = instruction.GetTargetOffset() + dex_offset; 246 // Create a block for the target instruction. 247 if (FindBlockStartingAt(target) == nullptr) { 248 block = new (arena_) HBasicBlock(graph_, target); 249 branch_targets_.Put(target, block); 250 } 251 dex_offset += instruction.SizeInCodeUnits(); 252 code_ptr += instruction.SizeInCodeUnits(); 253 if ((code_ptr < code_end) && (FindBlockStartingAt(dex_offset) == nullptr)) { 254 block = new (arena_) HBasicBlock(graph_, dex_offset); 255 branch_targets_.Put(dex_offset, block); 256 } 257 } else { 258 code_ptr += instruction.SizeInCodeUnits(); 259 dex_offset += instruction.SizeInCodeUnits(); 260 } 261 } 262} 263 264HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const { 265 DCHECK_GE(index, 0); 266 return branch_targets_.Get(index); 267} 268 269template<typename T> 270void HGraphBuilder::Unop_12x(const Instruction& instruction, Primitive::Type type) { 271 HInstruction* first = LoadLocal(instruction.VRegB(), type); 272 current_block_->AddInstruction(new (arena_) T(type, first)); 273 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 274} 275 276void HGraphBuilder::Conversion_12x(const Instruction& instruction, 277 Primitive::Type input_type, 278 Primitive::Type result_type) { 279 HInstruction* first = LoadLocal(instruction.VRegB(), input_type); 280 current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first)); 281 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 282} 283 284template<typename T> 285void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) { 286 HInstruction* first = LoadLocal(instruction.VRegB(), type); 287 HInstruction* second = LoadLocal(instruction.VRegC(), type); 288 current_block_->AddInstruction(new (arena_) T(type, first, second)); 289 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 290} 291 292template<typename T> 293void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) { 294 HInstruction* first = LoadLocal(instruction.VRegA(), type); 295 HInstruction* second = LoadLocal(instruction.VRegB(), type); 296 current_block_->AddInstruction(new (arena_) T(type, first, second)); 297 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 298} 299 300template<typename T> 301void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) { 302 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 303 HInstruction* second = GetIntConstant(instruction.VRegC_22s()); 304 if (reverse) { 305 std::swap(first, second); 306 } 307 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); 308 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 309} 310 311template<typename T> 312void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) { 313 HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 314 HInstruction* second = GetIntConstant(instruction.VRegC_22b()); 315 if (reverse) { 316 std::swap(first, second); 317 } 318 current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second)); 319 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 320} 321 322void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) { 323 if (type == Primitive::kPrimVoid) { 324 current_block_->AddInstruction(new (arena_) HReturnVoid()); 325 } else { 326 HInstruction* value = LoadLocal(instruction.VRegA(), type); 327 current_block_->AddInstruction(new (arena_) HReturn(value)); 328 } 329 current_block_->AddSuccessor(exit_block_); 330 current_block_ = nullptr; 331} 332 333bool HGraphBuilder::BuildInvoke(const Instruction& instruction, 334 uint32_t dex_offset, 335 uint32_t method_idx, 336 uint32_t number_of_vreg_arguments, 337 bool is_range, 338 uint32_t* args, 339 uint32_t register_index) { 340 Instruction::Code opcode = instruction.Opcode(); 341 InvokeType invoke_type; 342 switch (opcode) { 343 case Instruction::INVOKE_STATIC: 344 case Instruction::INVOKE_STATIC_RANGE: 345 invoke_type = kStatic; 346 break; 347 case Instruction::INVOKE_DIRECT: 348 case Instruction::INVOKE_DIRECT_RANGE: 349 invoke_type = kDirect; 350 break; 351 case Instruction::INVOKE_VIRTUAL: 352 case Instruction::INVOKE_VIRTUAL_RANGE: 353 invoke_type = kVirtual; 354 break; 355 case Instruction::INVOKE_INTERFACE: 356 case Instruction::INVOKE_INTERFACE_RANGE: 357 invoke_type = kInterface; 358 break; 359 case Instruction::INVOKE_SUPER_RANGE: 360 case Instruction::INVOKE_SUPER: 361 invoke_type = kSuper; 362 break; 363 default: 364 LOG(FATAL) << "Unexpected invoke op: " << opcode; 365 return false; 366 } 367 368 const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx); 369 const DexFile::ProtoId& proto_id = dex_file_->GetProtoId(method_id.proto_idx_); 370 const char* descriptor = dex_file_->StringDataByIdx(proto_id.shorty_idx_); 371 Primitive::Type return_type = Primitive::GetType(descriptor[0]); 372 bool is_instance_call = invoke_type != kStatic; 373 const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1); 374 375 HInvoke* invoke = nullptr; 376 if (invoke_type == kVirtual) { 377 MethodReference target_method(dex_file_, method_idx); 378 uintptr_t direct_code; 379 uintptr_t direct_method; 380 int vtable_index; 381 // TODO: Add devirtualization support. 382 compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_offset, true, true, 383 &invoke_type, &target_method, &vtable_index, 384 &direct_code, &direct_method); 385 if (vtable_index == -1) { 386 return false; 387 } 388 invoke = new (arena_) HInvokeVirtual( 389 arena_, number_of_arguments, return_type, dex_offset, vtable_index); 390 } else { 391 // Treat invoke-direct like static calls for now. 392 invoke = new (arena_) HInvokeStatic( 393 arena_, number_of_arguments, return_type, dex_offset, method_idx); 394 } 395 396 size_t start_index = 0; 397 Temporaries temps(graph_, is_instance_call ? 1 : 0); 398 if (is_instance_call) { 399 HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot); 400 HNullCheck* null_check = new (arena_) HNullCheck(arg, dex_offset); 401 current_block_->AddInstruction(null_check); 402 temps.Add(null_check); 403 invoke->SetArgumentAt(0, null_check); 404 start_index = 1; 405 } 406 407 uint32_t descriptor_index = 1; 408 uint32_t argument_index = start_index; 409 for (size_t i = start_index; i < number_of_vreg_arguments; i++, argument_index++) { 410 Primitive::Type type = Primitive::GetType(descriptor[descriptor_index++]); 411 bool is_wide = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble); 412 if (!is_range && is_wide && args[i] + 1 != args[i + 1]) { 413 LOG(WARNING) << "Non sequential register pair in " << dex_compilation_unit_->GetSymbol() 414 << " at " << dex_offset; 415 // We do not implement non sequential register pair. 416 return false; 417 } 418 HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type); 419 invoke->SetArgumentAt(argument_index, arg); 420 if (is_wide) { 421 i++; 422 } 423 } 424 425 DCHECK_EQ(argument_index, number_of_arguments); 426 current_block_->AddInstruction(invoke); 427 latest_result_ = invoke; 428 return true; 429} 430 431bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, 432 uint32_t dex_offset, 433 bool is_put) { 434 uint32_t source_or_dest_reg = instruction.VRegA_22c(); 435 uint32_t obj_reg = instruction.VRegB_22c(); 436 uint16_t field_index = instruction.VRegC_22c(); 437 438 ScopedObjectAccess soa(Thread::Current()); 439 StackHandleScope<1> hs(soa.Self()); 440 Handle<mirror::ArtField> resolved_field(hs.NewHandle( 441 compiler_driver_->ComputeInstanceFieldInfo(field_index, dex_compilation_unit_, is_put, soa))); 442 443 if (resolved_field.Get() == nullptr) { 444 return false; 445 } 446 if (resolved_field->IsVolatile()) { 447 return false; 448 } 449 450 Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType(); 451 if (!IsTypeSupported(field_type)) { 452 return false; 453 } 454 455 HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot); 456 current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_offset)); 457 if (is_put) { 458 Temporaries temps(graph_, 1); 459 HInstruction* null_check = current_block_->GetLastInstruction(); 460 // We need one temporary for the null check. 461 temps.Add(null_check); 462 HInstruction* value = LoadLocal(source_or_dest_reg, field_type); 463 current_block_->AddInstruction(new (arena_) HInstanceFieldSet( 464 null_check, 465 value, 466 field_type, 467 resolved_field->GetOffset())); 468 } else { 469 current_block_->AddInstruction(new (arena_) HInstanceFieldGet( 470 current_block_->GetLastInstruction(), 471 field_type, 472 resolved_field->GetOffset())); 473 474 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction()); 475 } 476 return true; 477} 478 479 480 481bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, 482 uint32_t dex_offset, 483 bool is_put) { 484 uint32_t source_or_dest_reg = instruction.VRegA_21c(); 485 uint16_t field_index = instruction.VRegB_21c(); 486 487 uint32_t storage_index; 488 bool is_referrers_class; 489 bool is_initialized; 490 bool is_volatile; 491 MemberOffset field_offset(0u); 492 Primitive::Type field_type; 493 494 bool fast_path = compiler_driver_->ComputeStaticFieldInfo(field_index, 495 dex_compilation_unit_, 496 is_put, 497 &field_offset, 498 &storage_index, 499 &is_referrers_class, 500 &is_volatile, 501 &is_initialized, 502 &field_type); 503 if (!fast_path) { 504 return false; 505 } 506 507 if (is_volatile) { 508 return false; 509 } 510 511 if (!IsTypeSupported(field_type)) { 512 return false; 513 } 514 515 HLoadClass* constant = new (arena_) HLoadClass( 516 storage_index, is_referrers_class, dex_offset); 517 current_block_->AddInstruction(constant); 518 519 HInstruction* cls = constant; 520 if (!is_initialized) { 521 cls = new (arena_) HClinitCheck(constant, dex_offset); 522 current_block_->AddInstruction(cls); 523 } 524 525 if (is_put) { 526 // We need to keep the class alive before loading the value. 527 Temporaries temps(graph_, 1); 528 temps.Add(cls); 529 HInstruction* value = LoadLocal(source_or_dest_reg, field_type); 530 DCHECK_EQ(value->GetType(), field_type); 531 current_block_->AddInstruction( 532 new (arena_) HStaticFieldSet(cls, value, field_type, field_offset)); 533 } else { 534 current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls, field_type, field_offset)); 535 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction()); 536 } 537 return true; 538} 539 540void HGraphBuilder::BuildCheckedDiv(const Instruction& instruction, 541 uint32_t dex_offset, 542 Primitive::Type type, 543 bool second_is_lit) { 544 DCHECK(type == Primitive::kPrimInt); 545 546 HInstruction* first = LoadLocal(instruction.VRegB(), type); 547 HInstruction* second = second_is_lit 548 ? GetIntConstant(instruction.VRegC()) 549 : LoadLocal(instruction.VRegC(), type); 550 if (!second->IsIntConstant() || (second->AsIntConstant()->GetValue() == 0)) { 551 second = new (arena_) HDivZeroCheck(second, dex_offset); 552 Temporaries temps(graph_, 1); 553 current_block_->AddInstruction(second); 554 temps.Add(current_block_->GetLastInstruction()); 555 } 556 557 current_block_->AddInstruction(new (arena_) HDiv(type, first, second)); 558 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 559} 560 561void HGraphBuilder::BuildArrayAccess(const Instruction& instruction, 562 uint32_t dex_offset, 563 bool is_put, 564 Primitive::Type anticipated_type) { 565 uint8_t source_or_dest_reg = instruction.VRegA_23x(); 566 uint8_t array_reg = instruction.VRegB_23x(); 567 uint8_t index_reg = instruction.VRegC_23x(); 568 569 DCHECK(IsTypeSupported(anticipated_type)); 570 571 // We need one temporary for the null check, one for the index, and one for the length. 572 Temporaries temps(graph_, 3); 573 574 HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot); 575 object = new (arena_) HNullCheck(object, dex_offset); 576 current_block_->AddInstruction(object); 577 temps.Add(object); 578 579 HInstruction* length = new (arena_) HArrayLength(object); 580 current_block_->AddInstruction(length); 581 temps.Add(length); 582 HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt); 583 index = new (arena_) HBoundsCheck(index, length, dex_offset); 584 current_block_->AddInstruction(index); 585 temps.Add(index); 586 if (is_put) { 587 HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type); 588 // TODO: Insert a type check node if the type is Object. 589 current_block_->AddInstruction(new (arena_) HArraySet( 590 object, index, value, anticipated_type, dex_offset)); 591 } else { 592 current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type)); 593 UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction()); 594 } 595} 596 597void HGraphBuilder::BuildFilledNewArray(uint32_t dex_offset, 598 uint32_t type_index, 599 uint32_t number_of_vreg_arguments, 600 bool is_range, 601 uint32_t* args, 602 uint32_t register_index) { 603 HInstruction* length = GetIntConstant(number_of_vreg_arguments); 604 HInstruction* object = new (arena_) HNewArray(length, dex_offset, type_index); 605 current_block_->AddInstruction(object); 606 607 const char* descriptor = dex_file_->StringByTypeIdx(type_index); 608 DCHECK_EQ(descriptor[0], '[') << descriptor; 609 char primitive = descriptor[1]; 610 DCHECK(primitive == 'I' 611 || primitive == 'L' 612 || primitive == '[') << descriptor; 613 bool is_reference_array = (primitive == 'L') || (primitive == '['); 614 Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt; 615 616 Temporaries temps(graph_, 1); 617 temps.Add(object); 618 for (size_t i = 0; i < number_of_vreg_arguments; ++i) { 619 HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type); 620 HInstruction* index = GetIntConstant(i); 621 current_block_->AddInstruction( 622 new (arena_) HArraySet(object, index, value, type, dex_offset)); 623 } 624 latest_result_ = object; 625} 626 627template <typename T> 628void HGraphBuilder::BuildFillArrayData(HInstruction* object, 629 const T* data, 630 uint32_t element_count, 631 Primitive::Type anticipated_type, 632 uint32_t dex_offset) { 633 for (uint32_t i = 0; i < element_count; ++i) { 634 HInstruction* index = GetIntConstant(i); 635 HInstruction* value = GetIntConstant(data[i]); 636 current_block_->AddInstruction(new (arena_) HArraySet( 637 object, index, value, anticipated_type, dex_offset)); 638 } 639} 640 641void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_offset) { 642 Temporaries temps(graph_, 1); 643 HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot); 644 HNullCheck* null_check = new (arena_) HNullCheck(array, dex_offset); 645 current_block_->AddInstruction(null_check); 646 temps.Add(null_check); 647 648 HInstruction* length = new (arena_) HArrayLength(null_check); 649 current_block_->AddInstruction(length); 650 651 int32_t payload_offset = instruction.VRegB_31t() + dex_offset; 652 const Instruction::ArrayDataPayload* payload = 653 reinterpret_cast<const Instruction::ArrayDataPayload*>(code_start_ + payload_offset); 654 const uint8_t* data = payload->data; 655 uint32_t element_count = payload->element_count; 656 657 // Implementation of this DEX instruction seems to be that the bounds check is 658 // done before doing any stores. 659 HInstruction* last_index = GetIntConstant(payload->element_count - 1); 660 current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_offset)); 661 662 switch (payload->element_width) { 663 case 1: 664 BuildFillArrayData(null_check, 665 reinterpret_cast<const int8_t*>(data), 666 element_count, 667 Primitive::kPrimByte, 668 dex_offset); 669 break; 670 case 2: 671 BuildFillArrayData(null_check, 672 reinterpret_cast<const int16_t*>(data), 673 element_count, 674 Primitive::kPrimShort, 675 dex_offset); 676 break; 677 case 4: 678 BuildFillArrayData(null_check, 679 reinterpret_cast<const int32_t*>(data), 680 element_count, 681 Primitive::kPrimInt, 682 dex_offset); 683 break; 684 case 8: 685 BuildFillWideArrayData(null_check, 686 reinterpret_cast<const int64_t*>(data), 687 element_count, 688 dex_offset); 689 break; 690 default: 691 LOG(FATAL) << "Unknown element width for " << payload->element_width; 692 } 693} 694 695void HGraphBuilder::BuildFillWideArrayData(HInstruction* object, 696 const int64_t* data, 697 uint32_t element_count, 698 uint32_t dex_offset) { 699 for (uint32_t i = 0; i < element_count; ++i) { 700 HInstruction* index = GetIntConstant(i); 701 HInstruction* value = GetLongConstant(data[i]); 702 current_block_->AddInstruction(new (arena_) HArraySet( 703 object, index, value, Primitive::kPrimLong, dex_offset)); 704 } 705} 706 707void HGraphBuilder::PotentiallyAddSuspendCheck(int32_t target_offset, uint32_t dex_offset) { 708 if (target_offset <= 0) { 709 // Unconditionnally add a suspend check to backward branches. We can remove 710 // them after we recognize loops in the graph. 711 current_block_->AddInstruction(new (arena_) HSuspendCheck(dex_offset)); 712 } 713} 714 715bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32_t dex_offset) { 716 if (current_block_ == nullptr) { 717 return true; // Dead code 718 } 719 720 switch (instruction.Opcode()) { 721 case Instruction::CONST_4: { 722 int32_t register_index = instruction.VRegA(); 723 HIntConstant* constant = GetIntConstant(instruction.VRegB_11n()); 724 UpdateLocal(register_index, constant); 725 break; 726 } 727 728 case Instruction::CONST_16: { 729 int32_t register_index = instruction.VRegA(); 730 HIntConstant* constant = GetIntConstant(instruction.VRegB_21s()); 731 UpdateLocal(register_index, constant); 732 break; 733 } 734 735 case Instruction::CONST: { 736 int32_t register_index = instruction.VRegA(); 737 HIntConstant* constant = GetIntConstant(instruction.VRegB_31i()); 738 UpdateLocal(register_index, constant); 739 break; 740 } 741 742 case Instruction::CONST_HIGH16: { 743 int32_t register_index = instruction.VRegA(); 744 HIntConstant* constant = GetIntConstant(instruction.VRegB_21h() << 16); 745 UpdateLocal(register_index, constant); 746 break; 747 } 748 749 case Instruction::CONST_WIDE_16: { 750 int32_t register_index = instruction.VRegA(); 751 // Get 16 bits of constant value, sign extended to 64 bits. 752 int64_t value = instruction.VRegB_21s(); 753 value <<= 48; 754 value >>= 48; 755 HLongConstant* constant = GetLongConstant(value); 756 UpdateLocal(register_index, constant); 757 break; 758 } 759 760 case Instruction::CONST_WIDE_32: { 761 int32_t register_index = instruction.VRegA(); 762 // Get 32 bits of constant value, sign extended to 64 bits. 763 int64_t value = instruction.VRegB_31i(); 764 value <<= 32; 765 value >>= 32; 766 HLongConstant* constant = GetLongConstant(value); 767 UpdateLocal(register_index, constant); 768 break; 769 } 770 771 case Instruction::CONST_WIDE: { 772 int32_t register_index = instruction.VRegA(); 773 HLongConstant* constant = GetLongConstant(instruction.VRegB_51l()); 774 UpdateLocal(register_index, constant); 775 break; 776 } 777 778 case Instruction::CONST_WIDE_HIGH16: { 779 int32_t register_index = instruction.VRegA(); 780 int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48; 781 HLongConstant* constant = GetLongConstant(value); 782 UpdateLocal(register_index, constant); 783 break; 784 } 785 786 // TODO: these instructions are also used to move floating point values, so what is 787 // the type (int or float)? 788 case Instruction::MOVE: 789 case Instruction::MOVE_FROM16: 790 case Instruction::MOVE_16: { 791 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt); 792 UpdateLocal(instruction.VRegA(), value); 793 break; 794 } 795 796 // TODO: these instructions are also used to move floating point values, so what is 797 // the type (long or double)? 798 case Instruction::MOVE_WIDE: 799 case Instruction::MOVE_WIDE_FROM16: 800 case Instruction::MOVE_WIDE_16: { 801 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong); 802 UpdateLocal(instruction.VRegA(), value); 803 break; 804 } 805 806 case Instruction::MOVE_OBJECT: 807 case Instruction::MOVE_OBJECT_16: 808 case Instruction::MOVE_OBJECT_FROM16: { 809 HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot); 810 UpdateLocal(instruction.VRegA(), value); 811 break; 812 } 813 814 case Instruction::RETURN_VOID: { 815 BuildReturn(instruction, Primitive::kPrimVoid); 816 break; 817 } 818 819#define IF_XX(comparison, cond) \ 820 case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_offset); break; \ 821 case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_offset); break 822 823 IF_XX(HEqual, EQ); 824 IF_XX(HNotEqual, NE); 825 IF_XX(HLessThan, LT); 826 IF_XX(HLessThanOrEqual, LE); 827 IF_XX(HGreaterThan, GT); 828 IF_XX(HGreaterThanOrEqual, GE); 829 830 case Instruction::GOTO: 831 case Instruction::GOTO_16: 832 case Instruction::GOTO_32: { 833 int32_t offset = instruction.GetTargetOffset(); 834 PotentiallyAddSuspendCheck(offset, dex_offset); 835 HBasicBlock* target = FindBlockStartingAt(offset + dex_offset); 836 DCHECK(target != nullptr); 837 current_block_->AddInstruction(new (arena_) HGoto()); 838 current_block_->AddSuccessor(target); 839 current_block_ = nullptr; 840 break; 841 } 842 843 case Instruction::RETURN: { 844 DCHECK_NE(return_type_, Primitive::kPrimNot); 845 DCHECK_NE(return_type_, Primitive::kPrimLong); 846 DCHECK_NE(return_type_, Primitive::kPrimDouble); 847 BuildReturn(instruction, return_type_); 848 break; 849 } 850 851 case Instruction::RETURN_OBJECT: { 852 DCHECK(return_type_ == Primitive::kPrimNot); 853 BuildReturn(instruction, return_type_); 854 break; 855 } 856 857 case Instruction::RETURN_WIDE: { 858 DCHECK(return_type_ == Primitive::kPrimDouble || return_type_ == Primitive::kPrimLong); 859 BuildReturn(instruction, return_type_); 860 break; 861 } 862 863 case Instruction::INVOKE_STATIC: 864 case Instruction::INVOKE_DIRECT: 865 case Instruction::INVOKE_VIRTUAL: { 866 uint32_t method_idx = instruction.VRegB_35c(); 867 uint32_t number_of_vreg_arguments = instruction.VRegA_35c(); 868 uint32_t args[5]; 869 instruction.GetVarArgs(args); 870 if (!BuildInvoke(instruction, dex_offset, method_idx, number_of_vreg_arguments, false, args, -1)) { 871 return false; 872 } 873 break; 874 } 875 876 case Instruction::INVOKE_STATIC_RANGE: 877 case Instruction::INVOKE_DIRECT_RANGE: 878 case Instruction::INVOKE_VIRTUAL_RANGE: { 879 uint32_t method_idx = instruction.VRegB_3rc(); 880 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc(); 881 uint32_t register_index = instruction.VRegC(); 882 if (!BuildInvoke(instruction, dex_offset, method_idx, 883 number_of_vreg_arguments, true, nullptr, register_index)) { 884 return false; 885 } 886 break; 887 } 888 889 case Instruction::NEG_INT: { 890 Unop_12x<HNeg>(instruction, Primitive::kPrimInt); 891 break; 892 } 893 894 case Instruction::NEG_LONG: { 895 Unop_12x<HNeg>(instruction, Primitive::kPrimLong); 896 break; 897 } 898 899 case Instruction::NEG_FLOAT: { 900 Unop_12x<HNeg>(instruction, Primitive::kPrimFloat); 901 break; 902 } 903 904 case Instruction::NEG_DOUBLE: { 905 Unop_12x<HNeg>(instruction, Primitive::kPrimDouble); 906 break; 907 } 908 909 case Instruction::NOT_INT: { 910 Unop_12x<HNot>(instruction, Primitive::kPrimInt); 911 break; 912 } 913 914 case Instruction::NOT_LONG: { 915 Unop_12x<HNot>(instruction, Primitive::kPrimLong); 916 break; 917 } 918 919 case Instruction::INT_TO_LONG: { 920 Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong); 921 break; 922 } 923 924 case Instruction::ADD_INT: { 925 Binop_23x<HAdd>(instruction, Primitive::kPrimInt); 926 break; 927 } 928 929 case Instruction::ADD_LONG: { 930 Binop_23x<HAdd>(instruction, Primitive::kPrimLong); 931 break; 932 } 933 934 case Instruction::ADD_DOUBLE: { 935 Binop_23x<HAdd>(instruction, Primitive::kPrimDouble); 936 break; 937 } 938 939 case Instruction::ADD_FLOAT: { 940 Binop_23x<HAdd>(instruction, Primitive::kPrimFloat); 941 break; 942 } 943 944 case Instruction::SUB_INT: { 945 Binop_23x<HSub>(instruction, Primitive::kPrimInt); 946 break; 947 } 948 949 case Instruction::SUB_LONG: { 950 Binop_23x<HSub>(instruction, Primitive::kPrimLong); 951 break; 952 } 953 954 case Instruction::SUB_FLOAT: { 955 Binop_23x<HSub>(instruction, Primitive::kPrimFloat); 956 break; 957 } 958 959 case Instruction::SUB_DOUBLE: { 960 Binop_23x<HSub>(instruction, Primitive::kPrimDouble); 961 break; 962 } 963 964 case Instruction::ADD_INT_2ADDR: { 965 Binop_12x<HAdd>(instruction, Primitive::kPrimInt); 966 break; 967 } 968 969 case Instruction::MUL_INT: { 970 Binop_23x<HMul>(instruction, Primitive::kPrimInt); 971 break; 972 } 973 974 case Instruction::MUL_LONG: { 975 Binop_23x<HMul>(instruction, Primitive::kPrimLong); 976 break; 977 } 978 979 case Instruction::MUL_FLOAT: { 980 Binop_23x<HMul>(instruction, Primitive::kPrimFloat); 981 break; 982 } 983 984 case Instruction::MUL_DOUBLE: { 985 Binop_23x<HMul>(instruction, Primitive::kPrimDouble); 986 break; 987 } 988 989 case Instruction::DIV_INT: { 990 BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, false); 991 break; 992 } 993 994 case Instruction::DIV_FLOAT: { 995 Binop_23x<HDiv>(instruction, Primitive::kPrimFloat); 996 break; 997 } 998 999 case Instruction::DIV_DOUBLE: { 1000 Binop_23x<HDiv>(instruction, Primitive::kPrimDouble); 1001 break; 1002 } 1003 1004 case Instruction::ADD_LONG_2ADDR: { 1005 Binop_12x<HAdd>(instruction, Primitive::kPrimLong); 1006 break; 1007 } 1008 1009 case Instruction::ADD_DOUBLE_2ADDR: { 1010 Binop_12x<HAdd>(instruction, Primitive::kPrimDouble); 1011 break; 1012 } 1013 1014 case Instruction::ADD_FLOAT_2ADDR: { 1015 Binop_12x<HAdd>(instruction, Primitive::kPrimFloat); 1016 break; 1017 } 1018 1019 case Instruction::SUB_INT_2ADDR: { 1020 Binop_12x<HSub>(instruction, Primitive::kPrimInt); 1021 break; 1022 } 1023 1024 case Instruction::SUB_LONG_2ADDR: { 1025 Binop_12x<HSub>(instruction, Primitive::kPrimLong); 1026 break; 1027 } 1028 1029 case Instruction::SUB_FLOAT_2ADDR: { 1030 Binop_12x<HSub>(instruction, Primitive::kPrimFloat); 1031 break; 1032 } 1033 1034 case Instruction::SUB_DOUBLE_2ADDR: { 1035 Binop_12x<HSub>(instruction, Primitive::kPrimDouble); 1036 break; 1037 } 1038 1039 case Instruction::MUL_INT_2ADDR: { 1040 Binop_12x<HMul>(instruction, Primitive::kPrimInt); 1041 break; 1042 } 1043 1044 case Instruction::MUL_LONG_2ADDR: { 1045 Binop_12x<HMul>(instruction, Primitive::kPrimLong); 1046 break; 1047 } 1048 1049 case Instruction::MUL_FLOAT_2ADDR: { 1050 Binop_12x<HMul>(instruction, Primitive::kPrimFloat); 1051 break; 1052 } 1053 1054 case Instruction::MUL_DOUBLE_2ADDR: { 1055 Binop_12x<HMul>(instruction, Primitive::kPrimDouble); 1056 break; 1057 } 1058 1059 case Instruction::DIV_FLOAT_2ADDR: { 1060 Binop_12x<HDiv>(instruction, Primitive::kPrimFloat); 1061 break; 1062 } 1063 1064 case Instruction::DIV_DOUBLE_2ADDR: { 1065 Binop_12x<HDiv>(instruction, Primitive::kPrimDouble); 1066 break; 1067 } 1068 1069 case Instruction::ADD_INT_LIT16: { 1070 Binop_22s<HAdd>(instruction, false); 1071 break; 1072 } 1073 1074 case Instruction::RSUB_INT: { 1075 Binop_22s<HSub>(instruction, true); 1076 break; 1077 } 1078 1079 case Instruction::MUL_INT_LIT16: { 1080 Binop_22s<HMul>(instruction, false); 1081 break; 1082 } 1083 1084 case Instruction::ADD_INT_LIT8: { 1085 Binop_22b<HAdd>(instruction, false); 1086 break; 1087 } 1088 1089 case Instruction::RSUB_INT_LIT8: { 1090 Binop_22b<HSub>(instruction, true); 1091 break; 1092 } 1093 1094 case Instruction::MUL_INT_LIT8: { 1095 Binop_22b<HMul>(instruction, false); 1096 break; 1097 } 1098 1099 case Instruction::DIV_INT_LIT16: 1100 case Instruction::DIV_INT_LIT8: { 1101 BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, true); 1102 break; 1103 } 1104 1105 case Instruction::NEW_INSTANCE: { 1106 current_block_->AddInstruction( 1107 new (arena_) HNewInstance(dex_offset, instruction.VRegB_21c())); 1108 UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); 1109 break; 1110 } 1111 1112 case Instruction::NEW_ARRAY: { 1113 HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt); 1114 current_block_->AddInstruction( 1115 new (arena_) HNewArray(length, dex_offset, instruction.VRegC_22c())); 1116 UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction()); 1117 break; 1118 } 1119 1120 case Instruction::FILLED_NEW_ARRAY: { 1121 uint32_t number_of_vreg_arguments = instruction.VRegA_35c(); 1122 uint32_t type_index = instruction.VRegB_35c(); 1123 uint32_t args[5]; 1124 instruction.GetVarArgs(args); 1125 BuildFilledNewArray(dex_offset, type_index, number_of_vreg_arguments, false, args, 0); 1126 break; 1127 } 1128 1129 case Instruction::FILLED_NEW_ARRAY_RANGE: { 1130 uint32_t number_of_vreg_arguments = instruction.VRegA_3rc(); 1131 uint32_t type_index = instruction.VRegB_3rc(); 1132 uint32_t register_index = instruction.VRegC_3rc(); 1133 BuildFilledNewArray( 1134 dex_offset, type_index, number_of_vreg_arguments, true, nullptr, register_index); 1135 break; 1136 } 1137 1138 case Instruction::FILL_ARRAY_DATA: { 1139 BuildFillArrayData(instruction, dex_offset); 1140 break; 1141 } 1142 1143 case Instruction::MOVE_RESULT: 1144 case Instruction::MOVE_RESULT_WIDE: 1145 case Instruction::MOVE_RESULT_OBJECT: 1146 UpdateLocal(instruction.VRegA(), latest_result_); 1147 latest_result_ = nullptr; 1148 break; 1149 1150 case Instruction::CMP_LONG: { 1151 Binop_23x<HCompare>(instruction, Primitive::kPrimLong); 1152 break; 1153 } 1154 1155 case Instruction::NOP: 1156 break; 1157 1158 case Instruction::IGET: 1159 case Instruction::IGET_WIDE: 1160 case Instruction::IGET_OBJECT: 1161 case Instruction::IGET_BOOLEAN: 1162 case Instruction::IGET_BYTE: 1163 case Instruction::IGET_CHAR: 1164 case Instruction::IGET_SHORT: { 1165 if (!BuildInstanceFieldAccess(instruction, dex_offset, false)) { 1166 return false; 1167 } 1168 break; 1169 } 1170 1171 case Instruction::IPUT: 1172 case Instruction::IPUT_WIDE: 1173 case Instruction::IPUT_OBJECT: 1174 case Instruction::IPUT_BOOLEAN: 1175 case Instruction::IPUT_BYTE: 1176 case Instruction::IPUT_CHAR: 1177 case Instruction::IPUT_SHORT: { 1178 if (!BuildInstanceFieldAccess(instruction, dex_offset, true)) { 1179 return false; 1180 } 1181 break; 1182 } 1183 1184 case Instruction::SGET: 1185 case Instruction::SGET_WIDE: 1186 case Instruction::SGET_OBJECT: 1187 case Instruction::SGET_BOOLEAN: 1188 case Instruction::SGET_BYTE: 1189 case Instruction::SGET_CHAR: 1190 case Instruction::SGET_SHORT: { 1191 if (!BuildStaticFieldAccess(instruction, dex_offset, false)) { 1192 return false; 1193 } 1194 break; 1195 } 1196 1197 case Instruction::SPUT: 1198 case Instruction::SPUT_WIDE: 1199 case Instruction::SPUT_OBJECT: 1200 case Instruction::SPUT_BOOLEAN: 1201 case Instruction::SPUT_BYTE: 1202 case Instruction::SPUT_CHAR: 1203 case Instruction::SPUT_SHORT: { 1204 if (!BuildStaticFieldAccess(instruction, dex_offset, true)) { 1205 return false; 1206 } 1207 break; 1208 } 1209 1210#define ARRAY_XX(kind, anticipated_type) \ 1211 case Instruction::AGET##kind: { \ 1212 BuildArrayAccess(instruction, dex_offset, false, anticipated_type); \ 1213 break; \ 1214 } \ 1215 case Instruction::APUT##kind: { \ 1216 BuildArrayAccess(instruction, dex_offset, true, anticipated_type); \ 1217 break; \ 1218 } 1219 1220 ARRAY_XX(, Primitive::kPrimInt); 1221 ARRAY_XX(_WIDE, Primitive::kPrimLong); 1222 ARRAY_XX(_OBJECT, Primitive::kPrimNot); 1223 ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean); 1224 ARRAY_XX(_BYTE, Primitive::kPrimByte); 1225 ARRAY_XX(_CHAR, Primitive::kPrimChar); 1226 ARRAY_XX(_SHORT, Primitive::kPrimShort); 1227 1228 case Instruction::ARRAY_LENGTH: { 1229 HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot); 1230 current_block_->AddInstruction(new (arena_) HArrayLength(object)); 1231 UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction()); 1232 break; 1233 } 1234 1235 case Instruction::CONST_STRING: { 1236 current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_21c(), dex_offset)); 1237 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction()); 1238 break; 1239 } 1240 1241 case Instruction::CONST_STRING_JUMBO: { 1242 current_block_->AddInstruction(new (arena_) HLoadString(instruction.VRegB_31c(), dex_offset)); 1243 UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction()); 1244 break; 1245 } 1246 1247 case Instruction::CONST_CLASS: { 1248 uint16_t type_index = instruction.VRegB_21c(); 1249 bool type_known_final; 1250 bool type_known_abstract; 1251 bool is_referrers_class; 1252 bool can_access = compiler_driver_->CanAccessTypeWithoutChecks( 1253 dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index, 1254 &type_known_final, &type_known_abstract, &is_referrers_class); 1255 if (!can_access) { 1256 return false; 1257 } 1258 current_block_->AddInstruction( 1259 new (arena_) HLoadClass(instruction.VRegB_21c(), is_referrers_class, dex_offset)); 1260 UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction()); 1261 break; 1262 } 1263 1264 default: 1265 return false; 1266 } 1267 return true; 1268} 1269 1270HIntConstant* HGraphBuilder::GetIntConstant0() { 1271 if (constant0_ != nullptr) { 1272 return constant0_; 1273 } 1274 constant0_ = new(arena_) HIntConstant(0); 1275 entry_block_->AddInstruction(constant0_); 1276 return constant0_; 1277} 1278 1279HIntConstant* HGraphBuilder::GetIntConstant1() { 1280 if (constant1_ != nullptr) { 1281 return constant1_; 1282 } 1283 constant1_ = new(arena_) HIntConstant(1); 1284 entry_block_->AddInstruction(constant1_); 1285 return constant1_; 1286} 1287 1288HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) { 1289 switch (constant) { 1290 case 0: return GetIntConstant0(); 1291 case 1: return GetIntConstant1(); 1292 default: { 1293 HIntConstant* instruction = new (arena_) HIntConstant(constant); 1294 entry_block_->AddInstruction(instruction); 1295 return instruction; 1296 } 1297 } 1298} 1299 1300HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) { 1301 HLongConstant* instruction = new (arena_) HLongConstant(constant); 1302 entry_block_->AddInstruction(instruction); 1303 return instruction; 1304} 1305 1306HLocal* HGraphBuilder::GetLocalAt(int register_index) const { 1307 return locals_.Get(register_index); 1308} 1309 1310void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const { 1311 HLocal* local = GetLocalAt(register_index); 1312 current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction)); 1313} 1314 1315HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const { 1316 HLocal* local = GetLocalAt(register_index); 1317 current_block_->AddInstruction(new (arena_) HLoadLocal(local, type)); 1318 return current_block_->GetLastInstruction(); 1319} 1320 1321} // namespace art 1322