diff options
Diffstat (limited to 'compiler/optimizing/graph_checker.cc')
| -rw-r--r-- | compiler/optimizing/graph_checker.cc | 92 | 
1 files changed, 76 insertions, 16 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index c88baa8610f..fbcbe3608e6 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -25,6 +25,11 @@  #include "base/bit_vector-inl.h"  #include "base/scoped_arena_allocator.h"  #include "base/scoped_arena_containers.h" +#include "handle.h" +#include "mirror/class.h" +#include "obj_ptr-inl.h" +#include "scoped_thread_state_change-inl.h" +#include "subtype_check.h"  namespace art { @@ -548,30 +553,85 @@ void GraphChecker::VisitReturnVoid(HReturnVoid* ret) {    }  } -void GraphChecker::VisitCheckCast(HCheckCast* check) { -  VisitInstruction(check); -  HInstruction* input = check->InputAt(1); -  if (!input->IsLoadClass()) { -    AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.", +void GraphChecker::CheckTypeCheckBitstringInput(HTypeCheckInstruction* check, +                                                size_t input_pos, +                                                bool check_value, +                                                uint32_t expected_value, +                                                const char* name) { +  if (!check->InputAt(input_pos)->IsIntConstant()) { +    AddError(StringPrintf("%s:%d (bitstring) expects a HIntConstant input %zu (%s), not %s:%d.",                            check->DebugName(),                            check->GetId(), -                          input->DebugName(), -                          input->GetId())); +                          input_pos, +                          name, +                          check->InputAt(2)->DebugName(), +                          check->InputAt(2)->GetId())); +  } else if (check_value) { +    uint32_t actual_value = +        static_cast<uint32_t>(check->InputAt(input_pos)->AsIntConstant()->GetValue()); +    if (actual_value != expected_value) { +      AddError(StringPrintf("%s:%d (bitstring) has %s 0x%x, not 0x%x as expected.", +                            check->DebugName(), +                            check->GetId(), +                            name, +                            actual_value, +                            expected_value)); +    }    }  } -void GraphChecker::VisitInstanceOf(HInstanceOf* instruction) { -  VisitInstruction(instruction); -  HInstruction* input = instruction->InputAt(1); -  if (!input->IsLoadClass()) { -    AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.", -                          instruction->DebugName(), -                          instruction->GetId(), -                          input->DebugName(), -                          input->GetId())); +void GraphChecker::HandleTypeCheckInstruction(HTypeCheckInstruction* check) { +  VisitInstruction(check); +  HInstruction* input = check->InputAt(1); +  if (check->GetTypeCheckKind() == TypeCheckKind::kBitstringCheck) { +    if (!input->IsNullConstant()) { +      AddError(StringPrintf("%s:%d (bitstring) expects a HNullConstant as second input, not %s:%d.", +                            check->DebugName(), +                            check->GetId(), +                            input->DebugName(), +                            input->GetId())); +    } +    bool check_values = false; +    BitString::StorageType expected_path_to_root = 0u; +    BitString::StorageType expected_mask = 0u; +    { +      ScopedObjectAccess soa(Thread::Current()); +      ObjPtr<mirror::Class> klass = check->GetClass().Get(); +      MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_); +      SubtypeCheckInfo::State state = SubtypeCheck<ObjPtr<mirror::Class>>::GetState(klass); +      if (state == SubtypeCheckInfo::kAssigned) { +        expected_path_to_root = +            SubtypeCheck<ObjPtr<mirror::Class>>::GetEncodedPathToRootForTarget(klass); +        expected_mask = SubtypeCheck<ObjPtr<mirror::Class>>::GetEncodedPathToRootMask(klass); +        check_values = true; +      } else { +        AddError(StringPrintf("%s:%d (bitstring) references a class with unassigned bitstring.", +                              check->DebugName(), +                              check->GetId())); +      } +    } +    CheckTypeCheckBitstringInput( +        check, /* input_pos */ 2, check_values, expected_path_to_root, "path_to_root"); +    CheckTypeCheckBitstringInput(check, /* input_pos */ 3, check_values, expected_mask, "mask"); +  } else { +    if (!input->IsLoadClass()) { +      AddError(StringPrintf("%s:%d (classic) expects a HLoadClass as second input, not %s:%d.", +                            check->DebugName(), +                            check->GetId(), +                            input->DebugName(), +                            input->GetId())); +    }    }  } +void GraphChecker::VisitCheckCast(HCheckCast* check) { +  HandleTypeCheckInstruction(check); +} + +void GraphChecker::VisitInstanceOf(HInstanceOf* instruction) { +  HandleTypeCheckInstruction(instruction); +} +  void GraphChecker::HandleLoop(HBasicBlock* loop_header) {    int id = loop_header->GetBlockId();    HLoopInformation* loop_information = loop_header->GetLoopInformation();  | 
