diff options
Diffstat (limited to 'compiler/optimizing/builder.cc')
| -rw-r--r-- | compiler/optimizing/builder.cc | 184 | 
1 files changed, 120 insertions, 64 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 3257de1858..d7754e8ea9 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -876,12 +876,96 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,                        clinit_check);  } +bool HGraphBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc) { +  bool finalizable; +  bool can_throw = NeedsAccessCheck(type_index, &finalizable); + +  // Only the non-resolved entrypoint handles the finalizable class case. If we +  // need access checks, then we haven't resolved the method and the class may +  // again be finalizable. +  QuickEntrypointEnum entrypoint = (finalizable || can_throw) +      ? kQuickAllocObject +      : kQuickAllocObjectInitialized; + +  ScopedObjectAccess soa(Thread::Current()); +  StackHandleScope<3> hs(soa.Self()); +  Handle<mirror::DexCache> dex_cache(hs.NewHandle( +      dex_compilation_unit_->GetClassLinker()->FindDexCache( +          soa.Self(), *dex_compilation_unit_->GetDexFile()))); +  Handle<mirror::Class> resolved_class(hs.NewHandle(dex_cache->GetResolvedType(type_index))); +  const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile(); +  Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle( +      outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file))); + +  if (outer_dex_cache.Get() != dex_cache.Get()) { +    // We currently do not support inlining allocations across dex files. +    return false; +  } + +  HLoadClass* load_class = new (arena_) HLoadClass( +      graph_->GetCurrentMethod(), +      type_index, +      outer_dex_file, +      IsOutermostCompilingClass(type_index), +      dex_pc, +      /*needs_access_check*/ can_throw, +      compiler_driver_->CanAssumeTypeIsPresentInDexCache(outer_dex_file, type_index)); + +  current_block_->AddInstruction(load_class); +  HInstruction* cls = load_class; +  if (!IsInitialized(resolved_class)) { +    cls = new (arena_) HClinitCheck(load_class, dex_pc); +    current_block_->AddInstruction(cls); +  } + +  current_block_->AddInstruction(new (arena_) HNewInstance( +      cls, +      graph_->GetCurrentMethod(), +      dex_pc, +      type_index, +      *dex_compilation_unit_->GetDexFile(), +      can_throw, +      finalizable, +      entrypoint)); +  return true; +} + +static bool IsSubClass(mirror::Class* to_test, mirror::Class* super_class) +    SHARED_REQUIRES(Locks::mutator_lock_) { +  return to_test != nullptr && !to_test->IsInterface() && to_test->IsSubClass(super_class); +} + +bool HGraphBuilder::IsInitialized(Handle<mirror::Class> cls) const { +  if (cls.Get() == nullptr) { +    return false; +  } + +  // `CanAssumeClassIsLoaded` will return true if we're JITting, or will +  // check whether the class is in an image for the AOT compilation. +  if (cls->IsInitialized() && +      compiler_driver_->CanAssumeClassIsLoaded(cls.Get())) { +    return true; +  } + +  if (IsSubClass(GetOutermostCompilingClass(), cls.Get())) { +    return true; +  } + +  // TODO: We should walk over the inlined methods, but we don't pass +  //       that information to the builder. +  if (IsSubClass(GetCompilingClass(), cls.Get())) { +    return true; +  } + +  return false; +} +  HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(        uint32_t dex_pc,        uint32_t method_idx,        HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {    ScopedObjectAccess soa(Thread::Current()); -  StackHandleScope<4> hs(soa.Self()); +  StackHandleScope<5> hs(soa.Self());    Handle<mirror::DexCache> dex_cache(hs.NewHandle(        dex_compilation_unit_->GetClassLinker()->FindDexCache(            soa.Self(), *dex_compilation_unit_->GetDexFile()))); @@ -896,6 +980,7 @@ HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(    Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(        outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));    Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass())); +  Handle<mirror::Class> resolved_method_class(hs.NewHandle(resolved_method->GetDeclaringClass()));    // The index at which the method's class is stored in the DexCache's type array.    uint32_t storage_index = DexFile::kDexNoIndex; @@ -913,41 +998,21 @@ HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(    HClinitCheck* clinit_check = nullptr; -  if (!outer_class->IsInterface() -      && outer_class->IsSubClass(resolved_method->GetDeclaringClass())) { -    // If the outer class is the declaring class or a subclass -    // of the declaring class, no class initialization is needed -    // before the static method call. -    // Note that in case of inlining, we do not need to add clinit checks -    // to calls that satisfy this subclass check with any inlined methods. This -    // will be detected by the optimization passes. +  if (IsInitialized(resolved_method_class)) {      *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;    } else if (storage_index != DexFile::kDexNoIndex) { -    // If the method's class type index is available, check -    // whether we should add an explicit class initialization -    // check for its declaring class before the static method call. - -    // TODO: find out why this check is needed. -    bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache( -        *outer_compilation_unit_->GetDexFile(), storage_index); -    bool is_initialized = -        resolved_method->GetDeclaringClass()->IsInitialized() && is_in_dex_cache; - -    if (is_initialized) { -      *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone; -    } else { -      *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit; -      HLoadClass* load_class = new (arena_) HLoadClass( -          graph_->GetCurrentMethod(), -          storage_index, -          *dex_compilation_unit_->GetDexFile(), -          is_outer_class, -          dex_pc, -          /*needs_access_check*/ false); -      current_block_->AddInstruction(load_class); -      clinit_check = new (arena_) HClinitCheck(load_class, dex_pc); -      current_block_->AddInstruction(clinit_check); -    } +    *clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit; +    HLoadClass* load_class = new (arena_) HLoadClass( +        graph_->GetCurrentMethod(), +        storage_index, +        outer_dex_file, +        is_outer_class, +        dex_pc, +        /*needs_access_check*/ false, +        compiler_driver_->CanAssumeTypeIsPresentInDexCache(outer_dex_file, storage_index)); +    current_block_->AddInstruction(load_class); +    clinit_check = new (arena_) HClinitCheck(load_class, dex_pc); +    current_block_->AddInstruction(clinit_check);    }    return clinit_check;  } @@ -1272,7 +1337,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,    uint16_t field_index = instruction.VRegB_21c();    ScopedObjectAccess soa(Thread::Current()); -  StackHandleScope<4> hs(soa.Self()); +  StackHandleScope<5> hs(soa.Self());    Handle<mirror::DexCache> dex_cache(hs.NewHandle(        dex_compilation_unit_->GetClassLinker()->FindDexCache(            soa.Self(), *dex_compilation_unit_->GetDexFile()))); @@ -1318,26 +1383,26 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,      }    } -  // TODO: find out why this check is needed. -  bool is_in_dex_cache = compiler_driver_->CanAssumeTypeIsPresentInDexCache( -      *outer_compilation_unit_->GetDexFile(), storage_index); -  bool is_initialized = resolved_field->GetDeclaringClass()->IsInitialized() && is_in_dex_cache; - +  bool is_in_cache = +      compiler_driver_->CanAssumeTypeIsPresentInDexCache(outer_dex_file, storage_index);    HLoadClass* constant = new (arena_) HLoadClass(graph_->GetCurrentMethod(),                                                   storage_index, -                                                 *dex_compilation_unit_->GetDexFile(), +                                                 outer_dex_file,                                                   is_outer_class,                                                   dex_pc, -                                                 /*needs_access_check*/ false); +                                                 /*needs_access_check*/ false, +                                                 is_in_cache);    current_block_->AddInstruction(constant);    HInstruction* cls = constant; -  if (!is_initialized && !is_outer_class) { + +  Handle<mirror::Class> klass(hs.NewHandle(resolved_field->GetDeclaringClass())); +  if (!IsInitialized(klass)) {      cls = new (arena_) HClinitCheck(constant, dex_pc);      current_block_->AddInstruction(cls);    } -  uint16_t class_def_index = resolved_field->GetDeclaringClass()->GetDexClassDefIndex(); +  uint16_t class_def_index = klass->GetDexClassDefIndex();    if (is_put) {      // We need to keep the class alive before loading the value.      Temporaries temps(graph_); @@ -1601,19 +1666,20 @@ void HGraphBuilder::BuildTypeCheck(const Instruction& instruction,    ScopedObjectAccess soa(Thread::Current());    StackHandleScope<2> hs(soa.Self()); +  const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();    Handle<mirror::DexCache> dex_cache(hs.NewHandle( -      dex_compilation_unit_->GetClassLinker()->FindDexCache( -          soa.Self(), *dex_compilation_unit_->GetDexFile()))); +      dex_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), dex_file)));    Handle<mirror::Class> resolved_class(hs.NewHandle(dex_cache->GetResolvedType(type_index)));    HInstruction* object = LoadLocal(reference, Primitive::kPrimNot, dex_pc);    HLoadClass* cls = new (arena_) HLoadClass(        graph_->GetCurrentMethod(),        type_index, -      *dex_compilation_unit_->GetDexFile(), +      dex_file,        IsOutermostCompilingClass(type_index),        dex_pc, -      !can_access); +      !can_access, +      compiler_driver_->CanAssumeTypeIsPresentInDexCache(dex_file, type_index));    current_block_->AddInstruction(cls);    // The class needs a temporary before being used by the type check. @@ -2509,20 +2575,9 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32          current_block_->AddInstruction(fake_string);          UpdateLocal(register_index, fake_string, dex_pc);        } else { -        bool finalizable; -        bool can_throw = NeedsAccessCheck(type_index, &finalizable); -        QuickEntrypointEnum entrypoint = can_throw -            ? kQuickAllocObjectWithAccessCheck -            : kQuickAllocObject; - -        current_block_->AddInstruction(new (arena_) HNewInstance( -            graph_->GetCurrentMethod(), -            dex_pc, -            type_index, -            *dex_compilation_unit_->GetDexFile(), -            can_throw, -            finalizable, -            entrypoint)); +        if (!BuildNewInstance(type_index, dex_pc)) { +          return false; +        }          UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);        }        break; @@ -2750,10 +2805,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32        current_block_->AddInstruction(new (arena_) HLoadClass(            graph_->GetCurrentMethod(),            type_index, -          *dex_compilation_unit_->GetDexFile(), +          *dex_file_,            IsOutermostCompilingClass(type_index),            dex_pc, -          !can_access)); +          !can_access, +          compiler_driver_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_index)));        UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc);        break;      }  |