diff options
Diffstat (limited to 'compiler/optimizing/builder.cc')
| -rw-r--r-- | compiler/optimizing/builder.cc | 89 | 
1 files changed, 62 insertions, 27 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 8418ab0a7e..76a2be927e 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -374,13 +374,12 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,    const size_t number_of_arguments = strlen(descriptor) - (is_instance_call ? 0 : 1);    HInvoke* invoke = nullptr; -  if (invoke_type == kVirtual || invoke_type == kInterface) { +  if (invoke_type == kVirtual || invoke_type == kInterface || invoke_type == kSuper) {      MethodReference target_method(dex_file_, method_idx);      uintptr_t direct_code;      uintptr_t direct_method;      int table_index;      InvokeType optimized_invoke_type = invoke_type; -    // TODO: Add devirtualization support.      compiler_driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_offset, true, true,                                          &optimized_invoke_type, &target_method, &table_index,                                          &direct_code, &direct_method); @@ -388,15 +387,21 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,        return false;      } -    if (invoke_type == kVirtual) { +    if (optimized_invoke_type == kVirtual) {        invoke = new (arena_) HInvokeVirtual(            arena_, number_of_arguments, return_type, dex_offset, table_index); -    } else { -      DCHECK_EQ(invoke_type, kInterface); +    } else if (optimized_invoke_type == kInterface) {        invoke = new (arena_) HInvokeInterface(            arena_, number_of_arguments, return_type, dex_offset, method_idx, table_index); +    } else if (optimized_invoke_type == kDirect) { +      // For this compiler, sharpening only works if we compile PIC. +      DCHECK(compiler_driver_->GetCompilerOptions().GetCompilePic()); +      // Treat invoke-direct like static calls for now. +      invoke = new (arena_) HInvokeStatic( +          arena_, number_of_arguments, return_type, dex_offset, target_method.dex_method_index);      }    } else { +    DCHECK(invoke_type == kDirect || invoke_type == kStatic);      // Treat invoke-direct like static calls for now.      invoke = new (arena_) HInvokeStatic(          arena_, number_of_arguments, return_type, dex_offset, method_idx); @@ -704,6 +709,38 @@ void HGraphBuilder::BuildFillWideArrayData(HInstruction* object,    }  } +bool HGraphBuilder::BuildTypeCheck(const Instruction& instruction, +                                   uint8_t destination, +                                   uint8_t reference, +                                   uint16_t type_index, +                                   uint32_t dex_offset) { +  bool type_known_final; +  bool type_known_abstract; +  bool is_referrers_class; +  bool can_access = compiler_driver_->CanAccessTypeWithoutChecks( +      dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index, +      &type_known_final, &type_known_abstract, &is_referrers_class); +  if (!can_access) { +    return false; +  } +  HInstruction* object = LoadLocal(reference, Primitive::kPrimNot); +  HLoadClass* cls = new (arena_) HLoadClass(type_index, is_referrers_class, dex_offset); +  current_block_->AddInstruction(cls); +  // The class needs a temporary before being used by the type check. +  Temporaries temps(graph_, 1); +  temps.Add(cls); +  if (instruction.Opcode() == Instruction::INSTANCE_OF) { +    current_block_->AddInstruction( +        new (arena_) HInstanceOf(object, cls, type_known_final, dex_offset)); +    UpdateLocal(destination, current_block_->GetLastInstruction()); +  } else { +    DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST); +    current_block_->AddInstruction( +        new (arena_) HCheckCast(object, cls, type_known_final, dex_offset)); +  } +  return true; +} +  void HGraphBuilder::PotentiallyAddSuspendCheck(int32_t target_offset, uint32_t dex_offset) {    if (target_offset <= 0) {      // Unconditionnally add a suspend check to backward branches. We can remove @@ -858,10 +895,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32        break;      } -    case Instruction::INVOKE_STATIC:      case Instruction::INVOKE_DIRECT: -    case Instruction::INVOKE_VIRTUAL: -    case Instruction::INVOKE_INTERFACE: { +    case Instruction::INVOKE_INTERFACE: +    case Instruction::INVOKE_STATIC: +    case Instruction::INVOKE_SUPER: +    case Instruction::INVOKE_VIRTUAL: {        uint32_t method_idx = instruction.VRegB_35c();        uint32_t number_of_vreg_arguments = instruction.VRegA_35c();        uint32_t args[5]; @@ -873,10 +911,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32        break;      } -    case Instruction::INVOKE_STATIC_RANGE:      case Instruction::INVOKE_DIRECT_RANGE: -    case Instruction::INVOKE_VIRTUAL_RANGE: -    case Instruction::INVOKE_INTERFACE_RANGE: { +    case Instruction::INVOKE_INTERFACE_RANGE: +    case Instruction::INVOKE_STATIC_RANGE: +    case Instruction::INVOKE_SUPER_RANGE: +    case Instruction::INVOKE_VIRTUAL_RANGE: {        uint32_t method_idx = instruction.VRegB_3rc();        uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();        uint32_t register_index = instruction.VRegC(); @@ -1292,25 +1331,21 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32      }      case Instruction::INSTANCE_OF: { +      uint8_t destination = instruction.VRegA_22c(); +      uint8_t reference = instruction.VRegB_22c();        uint16_t type_index = instruction.VRegC_22c(); -      bool type_known_final; -      bool type_known_abstract; -      bool is_referrers_class; -      bool can_access = compiler_driver_->CanAccessTypeWithoutChecks( -          dex_compilation_unit_->GetDexMethodIndex(), *dex_file_, type_index, -          &type_known_final, &type_known_abstract, &is_referrers_class); -      if (!can_access) { +      if (!BuildTypeCheck(instruction, destination, reference, type_index, dex_offset)) { +        return false; +      } +      break; +    } + +    case Instruction::CHECK_CAST: { +      uint8_t reference = instruction.VRegA_21c(); +      uint16_t type_index = instruction.VRegB_21c(); +      if (!BuildTypeCheck(instruction, -1, reference, type_index, dex_offset)) {          return false;        } -      HInstruction* object = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimNot); -      HLoadClass* cls = new (arena_) HLoadClass(type_index, is_referrers_class, dex_offset); -      current_block_->AddInstruction(cls); -      // The class needs a temporary before being used by the type check. -      Temporaries temps(graph_, 1); -      temps.Add(cls); -      current_block_->AddInstruction( -          new (arena_) HTypeCheck(object, cls, type_known_final, dex_offset)); -      UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());        break;      }  |