/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dex_file_annotations.h"

#include <stdlib.h>

#include "android-base/macros.h"
#include "android-base/stringprintf.h"
#include "art_field-inl.h"
#include "art_method-alloc-inl.h"
#include "base/sdk_version.h"
#include "class_linker-inl.h"
#include "class_root-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_instruction-inl.h"
#include "jni/jni_internal.h"
#include "jvalue-inl.h"
#include "mirror/array-alloc-inl.h"
#include "mirror/class-alloc-inl.h"
#include "mirror/field.h"
#include "mirror/method.h"
#include "mirror/object_array-alloc-inl.h"
#include "mirror/object_array-inl.h"
#include "oat_file.h"
#include "obj_ptr-inl.h"
#include "reflection.h"
#include "thread.h"
#include "well_known_classes.h"

namespace art {

using android::base::StringPrintf;

using dex::AnnotationItem;
using dex::AnnotationSetItem;
using dex::AnnotationSetRefItem;
using dex::AnnotationSetRefList;
using dex::AnnotationsDirectoryItem;
using dex::FieldAnnotationsItem;
using dex::MethodAnnotationsItem;
using dex::ParameterAnnotationsItem;

struct DexFile::AnnotationValue {
  JValue value_;
  uint8_t type_;
};

namespace {

// A helper class that contains all the data needed to do annotation lookup.
class ClassData {
 public:
  explicit ClassData(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
    : ClassData(ScopedNullHandle<mirror::Class>(),  // klass
                method,
                *method->GetDexFile(),
                &method->GetClassDef()) {}

  // Requires Scope to be able to create at least 1 handles.
  template <typename Scope>
  ClassData(Scope& hs, ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_)
    : ClassData(hs.NewHandle(field->GetDeclaringClass())) { }

  explicit ClassData(Handle<mirror::Class> klass) REQUIRES_SHARED(art::Locks::mutator_lock_)
    : ClassData(klass,  // klass
                nullptr,  // method
                klass->GetDexFile(),
                klass->GetClassDef()) {}

  const DexFile& GetDexFile() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return dex_file_;
  }

  const dex::ClassDef* GetClassDef() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return class_def_;
  }

  ObjPtr<mirror::DexCache> GetDexCache() const REQUIRES_SHARED(Locks::mutator_lock_) {
    if (method_ != nullptr) {
      return method_->GetDexCache();
    } else {
      return real_klass_->GetDexCache();
    }
  }

  ObjPtr<mirror::ClassLoader> GetClassLoader() const REQUIRES_SHARED(Locks::mutator_lock_) {
    if (method_ != nullptr) {
      return method_->GetDeclaringClass()->GetClassLoader();
    } else {
      return real_klass_->GetClassLoader();
    }
  }

  ObjPtr<mirror::Class> GetRealClass() const REQUIRES_SHARED(Locks::mutator_lock_) {
    if (method_ != nullptr) {
      return method_->GetDeclaringClass();
    } else {
      return real_klass_.Get();
    }
  }

 private:
  ClassData(Handle<mirror::Class> klass,
            ArtMethod* method,
            const DexFile& dex_file,
            const dex::ClassDef* class_def) REQUIRES_SHARED(Locks::mutator_lock_)
      : real_klass_(klass),
        method_(method),
        dex_file_(dex_file),
        class_def_(class_def) {
    DCHECK((method_ == nullptr) || real_klass_.IsNull());
  }

  Handle<mirror::Class> real_klass_;
  ArtMethod* method_;
  const DexFile& dex_file_;
  const dex::ClassDef* class_def_;

  DISALLOW_COPY_AND_ASSIGN(ClassData);
};

ObjPtr<mirror::Object> CreateAnnotationMember(const ClassData& klass,
                                              Handle<mirror::Class> annotation_class,
                                              const uint8_t** annotation)
    REQUIRES_SHARED(Locks::mutator_lock_);

bool IsVisibilityCompatible(uint32_t actual, uint32_t expected) {
  if (expected == DexFile::kDexVisibilityRuntime) {
    if (IsSdkVersionSetAndAtMost(Runtime::Current()->GetTargetSdkVersion(), SdkVersion::kM)) {
      return actual == DexFile::kDexVisibilityRuntime || actual == DexFile::kDexVisibilityBuild;
    }
  }
  return actual == expected;
}

static const AnnotationSetItem* FindAnnotationSetForField(const DexFile& dex_file,
                                                          const dex::ClassDef& class_def,
                                                          uint32_t field_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationsDirectoryItem* annotations_dir = dex_file.GetAnnotationsDirectory(class_def);
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const FieldAnnotationsItem* field_annotations = dex_file.GetFieldAnnotations(annotations_dir);
  if (field_annotations == nullptr) {
    return nullptr;
  }
  uint32_t field_count = annotations_dir->fields_size_;
  for (uint32_t i = 0; i < field_count; ++i) {
    if (field_annotations[i].field_idx_ == field_index) {
      return dex_file.GetFieldAnnotationSetItem(field_annotations[i]);
    }
  }
  return nullptr;
}

static const AnnotationSetItem* FindAnnotationSetForField(ArtField* field)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
  const dex::ClassDef* class_def = klass->GetClassDef();
  if (class_def == nullptr) {
    DCHECK(klass->IsProxyClass());
    return nullptr;
  }
  return FindAnnotationSetForField(*field->GetDexFile(), *class_def, field->GetDexFieldIndex());
}

const AnnotationItem* SearchAnnotationSet(const DexFile& dex_file,
                                          const AnnotationSetItem* annotation_set,
                                          const char* descriptor,
                                          uint32_t visibility)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationItem* result = nullptr;
  for (uint32_t i = 0; i < annotation_set->size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);

    if (strcmp(descriptor, dex_file.StringByTypeIdx(dex::TypeIndex(type_index))) == 0) {
      result = annotation_item;
      break;
    }
  }
  return result;
}

inline static void SkipEncodedValueHeaderByte(const uint8_t** annotation_ptr) {
  (*annotation_ptr)++;
}

bool SkipAnnotationValue(const DexFile& dex_file, const uint8_t** annotation_ptr)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const uint8_t* annotation = *annotation_ptr;
  uint8_t header_byte = *(annotation++);
  uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
  uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
  int32_t width = value_arg + 1;

  switch (value_type) {
    case DexFile::kDexAnnotationByte:
    case DexFile::kDexAnnotationShort:
    case DexFile::kDexAnnotationChar:
    case DexFile::kDexAnnotationInt:
    case DexFile::kDexAnnotationLong:
    case DexFile::kDexAnnotationFloat:
    case DexFile::kDexAnnotationDouble:
    case DexFile::kDexAnnotationString:
    case DexFile::kDexAnnotationType:
    case DexFile::kDexAnnotationMethod:
    case DexFile::kDexAnnotationField:
    case DexFile::kDexAnnotationEnum:
      break;
    case DexFile::kDexAnnotationArray:
    {
      uint32_t size = DecodeUnsignedLeb128(&annotation);
      for (; size != 0u; --size) {
        if (!SkipAnnotationValue(dex_file, &annotation)) {
          return false;
        }
      }
      width = 0;
      break;
    }
    case DexFile::kDexAnnotationAnnotation:
    {
      DecodeUnsignedLeb128(&annotation);  // unused type_index
      uint32_t size = DecodeUnsignedLeb128(&annotation);
      for (; size != 0u; --size) {
        DecodeUnsignedLeb128(&annotation);  // unused element_name_index
        if (!SkipAnnotationValue(dex_file, &annotation)) {
          return false;
        }
      }
      width = 0;
      break;
    }
    case DexFile::kDexAnnotationBoolean:
    case DexFile::kDexAnnotationNull:
      width = 0;
      break;
    default:
      LOG(FATAL) << StringPrintf("Bad annotation element value byte 0x%02x", value_type);
      UNREACHABLE();
  }

  annotation += width;
  *annotation_ptr = annotation;
  return true;
}

const uint8_t* SearchEncodedAnnotation(const DexFile& dex_file,
                                       const uint8_t* annotation,
                                       const char* name)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DecodeUnsignedLeb128(&annotation);  // unused type_index
  uint32_t size = DecodeUnsignedLeb128(&annotation);

  while (size != 0) {
    uint32_t element_name_index = DecodeUnsignedLeb128(&annotation);
    const char* element_name =
        dex_file.GetStringData(dex_file.GetStringId(dex::StringIndex(element_name_index)));
    if (strcmp(name, element_name) == 0) {
      return annotation;
    }
    SkipAnnotationValue(dex_file, &annotation);
    size--;
  }
  return nullptr;
}

static const AnnotationSetItem* FindAnnotationSetForMethod(const DexFile& dex_file,
                                                           const dex::ClassDef& class_def,
                                                           uint32_t method_index) {
  const AnnotationsDirectoryItem* annotations_dir = dex_file.GetAnnotationsDirectory(class_def);
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const MethodAnnotationsItem* method_annotations = dex_file.GetMethodAnnotations(annotations_dir);
  if (method_annotations == nullptr) {
    return nullptr;
  }
  uint32_t method_count = annotations_dir->methods_size_;
  for (uint32_t i = 0; i < method_count; ++i) {
    if (method_annotations[i].method_idx_ == method_index) {
      return dex_file.GetMethodAnnotationSetItem(method_annotations[i]);
    }
  }
  return nullptr;
}

inline const AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (method->IsProxyMethod()) {
    return nullptr;
  }
  return FindAnnotationSetForMethod(*method->GetDexFile(),
                                    method->GetClassDef(),
                                    method->GetDexMethodIndex());
}

const ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile* dex_file = method->GetDexFile();
  const AnnotationsDirectoryItem* annotations_dir =
      dex_file->GetAnnotationsDirectory(method->GetClassDef());
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const ParameterAnnotationsItem* parameter_annotations =
      dex_file->GetParameterAnnotations(annotations_dir);
  if (parameter_annotations == nullptr) {
    return nullptr;
  }
  uint32_t method_index = method->GetDexMethodIndex();
  uint32_t parameter_count = annotations_dir->parameters_size_;
  for (uint32_t i = 0; i < parameter_count; ++i) {
    if (parameter_annotations[i].method_idx_ == method_index) {
      return &parameter_annotations[i];
    }
  }
  return nullptr;
}

static const AnnotationSetItem* FindAnnotationSetForClass(const ClassData& klass)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  const dex::ClassDef* class_def = klass.GetClassDef();
  if (class_def == nullptr) {
    DCHECK(klass.GetRealClass()->IsProxyClass());
    return nullptr;
  }
  const AnnotationsDirectoryItem* annotations_dir = dex_file.GetAnnotationsDirectory(*class_def);
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  return dex_file.GetClassAnnotationSet(annotations_dir);
}

ObjPtr<mirror::Object> ProcessEncodedAnnotation(const ClassData& klass, const uint8_t** annotation)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  uint32_t type_index = DecodeUnsignedLeb128(annotation);
  uint32_t size = DecodeUnsignedLeb128(annotation);

  Thread* self = Thread::Current();
  StackHandleScope<4> hs(self);
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  Handle<mirror::Class> annotation_class(hs.NewHandle(
      class_linker->ResolveType(dex::TypeIndex(type_index),
                                hs.NewHandle(klass.GetDexCache()),
                                hs.NewHandle(klass.GetClassLoader()))));
  if (annotation_class == nullptr) {
    LOG(INFO) << "Unable to resolve " << klass.GetRealClass()->PrettyClass()
              << " annotation class " << type_index;
    DCHECK(Thread::Current()->IsExceptionPending());
    Thread::Current()->ClearException();
    return nullptr;
  }

  ObjPtr<mirror::Class> annotation_member_array_class =
      WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember__array);
  if (annotation_member_array_class == nullptr) {
    return nullptr;
  }
  ObjPtr<mirror::ObjectArray<mirror::Object>> element_array = nullptr;
  if (size > 0) {
    element_array =
        mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_member_array_class, size);
    if (element_array == nullptr) {
      LOG(ERROR) << "Failed to allocate annotation member array (" << size << " elements)";
      return nullptr;
    }
  }

  Handle<mirror::ObjectArray<mirror::Object>> h_element_array(hs.NewHandle(element_array));
  for (uint32_t i = 0; i < size; ++i) {
    ObjPtr<mirror::Object> new_member = CreateAnnotationMember(klass, annotation_class, annotation);
    if (new_member == nullptr) {
      return nullptr;
    }
    h_element_array->SetWithoutChecks<false>(i, new_member);
  }

  ArtMethod* create_annotation_method =
      WellKnownClasses::libcore_reflect_AnnotationFactory_createAnnotation;
  ObjPtr<mirror::Object> result = create_annotation_method->InvokeStatic<'L', 'L', 'L'>(
      self, annotation_class.Get(), h_element_array.Get());
  if (self->IsExceptionPending()) {
    LOG(INFO) << "Exception in AnnotationFactory.createAnnotation";
    return nullptr;
  }

  return result;
}

template <bool kTransactionActive>
bool ProcessAnnotationValue(const ClassData& klass,
                            const uint8_t** annotation_ptr,
                            DexFile::AnnotationValue* annotation_value,
                            Handle<mirror::Class> array_class,
                            DexFile::AnnotationResultStyle result_style)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  Thread* self = Thread::Current();
  ObjPtr<mirror::Object> element_object = nullptr;
  bool set_object = false;
  Primitive::Type primitive_type = Primitive::kPrimVoid;
  const uint8_t* annotation = *annotation_ptr;
  uint8_t header_byte = *(annotation++);
  uint8_t value_type = header_byte & DexFile::kDexAnnotationValueTypeMask;
  uint8_t value_arg = header_byte >> DexFile::kDexAnnotationValueArgShift;
  int32_t width = value_arg + 1;
  annotation_value->type_ = value_type;

  switch (value_type) {
    case DexFile::kDexAnnotationByte:
      annotation_value->value_.SetB(
          static_cast<int8_t>(DexFile::ReadSignedInt(annotation, value_arg)));
      primitive_type = Primitive::kPrimByte;
      break;
    case DexFile::kDexAnnotationShort:
      annotation_value->value_.SetS(
          static_cast<int16_t>(DexFile::ReadSignedInt(annotation, value_arg)));
      primitive_type = Primitive::kPrimShort;
      break;
    case DexFile::kDexAnnotationChar:
      annotation_value->value_.SetC(
          static_cast<uint16_t>(DexFile::ReadUnsignedInt(annotation, value_arg, false)));
      primitive_type = Primitive::kPrimChar;
      break;
    case DexFile::kDexAnnotationInt:
      annotation_value->value_.SetI(DexFile::ReadSignedInt(annotation, value_arg));
      primitive_type = Primitive::kPrimInt;
      break;
    case DexFile::kDexAnnotationLong:
      annotation_value->value_.SetJ(DexFile::ReadSignedLong(annotation, value_arg));
      primitive_type = Primitive::kPrimLong;
      break;
    case DexFile::kDexAnnotationFloat:
      annotation_value->value_.SetI(DexFile::ReadUnsignedInt(annotation, value_arg, true));
      primitive_type = Primitive::kPrimFloat;
      break;
    case DexFile::kDexAnnotationDouble:
      annotation_value->value_.SetJ(DexFile::ReadUnsignedLong(annotation, value_arg, true));
      primitive_type = Primitive::kPrimDouble;
      break;
    case DexFile::kDexAnnotationBoolean:
      annotation_value->value_.SetZ(value_arg != 0);
      primitive_type = Primitive::kPrimBoolean;
      width = 0;
      break;
    case DexFile::kDexAnnotationString: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<1> hs(self);
        element_object = Runtime::Current()->GetClassLinker()->ResolveString(
            dex::StringIndex(index), hs.NewHandle(klass.GetDexCache()));
        set_object = true;
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationType: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        dex::TypeIndex type_index(index);
        StackHandleScope<2> hs(self);
        element_object = Runtime::Current()->GetClassLinker()->ResolveType(
            type_index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()));
        set_object = true;
        if (element_object == nullptr) {
          CHECK(self->IsExceptionPending());
          if (result_style == DexFile::kAllObjects) {
            const char* msg = dex_file.StringByTypeIdx(type_index);
            self->ThrowNewWrappedException("Ljava/lang/TypeNotPresentException;", msg);
            element_object = self->GetException();
            self->ClearException();
          } else {
            return false;
          }
        }
      }
      break;
    }
    case DexFile::kDexAnnotationMethod: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
        StackHandleScope<2> hs(self);
        ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType(
            index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()));
        if (method == nullptr) {
          return false;
        }
        PointerSize pointer_size = class_linker->GetImagePointerSize();
        set_object = true;
        if (method->IsConstructor()) {
          element_object = (pointer_size == PointerSize::k64)
              ? mirror::Constructor::CreateFromArtMethod<PointerSize::k64>(self, method)
              : mirror::Constructor::CreateFromArtMethod<PointerSize::k32>(self, method);
        } else {
          element_object = (pointer_size == PointerSize::k64)
              ? mirror::Method::CreateFromArtMethod<PointerSize::k64>(self, method)
              : mirror::Method::CreateFromArtMethod<PointerSize::k32>(self, method);
        }
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationField: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<2> hs(self);
        ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(
            index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()));
        if (field == nullptr) {
          return false;
        }
        set_object = true;
        element_object = mirror::Field::CreateFromArtField(self, field, true);
        if (element_object == nullptr) {
          return false;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationEnum: {
      uint32_t index = DexFile::ReadUnsignedInt(annotation, value_arg, false);
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(index);
      } else {
        StackHandleScope<3> hs(self);
        ArtField* enum_field = Runtime::Current()->GetClassLinker()->ResolveField(
            index,
            hs.NewHandle(klass.GetDexCache()),
            hs.NewHandle(klass.GetClassLoader()),
            true);
        if (enum_field == nullptr) {
          return false;
        } else {
          Handle<mirror::Class> field_class(hs.NewHandle(enum_field->GetDeclaringClass()));
          Runtime::Current()->GetClassLinker()->EnsureInitialized(self, field_class, true, true);
          element_object = enum_field->GetObject(field_class.Get());
          set_object = true;
        }
      }
      break;
    }
    case DexFile::kDexAnnotationArray:
      if (result_style == DexFile::kAllRaw || array_class == nullptr) {
        return false;
      } else {
        ScopedObjectAccessUnchecked soa(self);
        StackHandleScope<2> hs(self);
        uint32_t size = DecodeUnsignedLeb128(&annotation);
        Handle<mirror::Class> component_type(hs.NewHandle(array_class->GetComponentType()));
        Handle<mirror::Array> new_array(hs.NewHandle(mirror::Array::Alloc(
            self, array_class.Get(), size, array_class->GetComponentSizeShift(),
            Runtime::Current()->GetHeap()->GetCurrentAllocator())));
        if (new_array == nullptr) {
          LOG(ERROR) << "Annotation element array allocation failed with size " << size;
          return false;
        }
        DexFile::AnnotationValue new_annotation_value;
        for (uint32_t i = 0; i < size; ++i) {
          if (!ProcessAnnotationValue<kTransactionActive>(klass,
                                                          &annotation,
                                                          &new_annotation_value,
                                                          component_type,
                                                          DexFile::kPrimitivesOrObjects)) {
            return false;
          }
          if (!component_type->IsPrimitive()) {
            ObjPtr<mirror::Object> obj = new_annotation_value.value_.GetL();
            new_array->AsObjectArray<mirror::Object>()->
                SetWithoutChecks<kTransactionActive>(i, obj);
          } else {
            switch (new_annotation_value.type_) {
              case DexFile::kDexAnnotationByte:
                new_array->AsByteArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetB());
                break;
              case DexFile::kDexAnnotationShort:
                new_array->AsShortArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetS());
                break;
              case DexFile::kDexAnnotationChar:
                new_array->AsCharArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetC());
                break;
              case DexFile::kDexAnnotationInt:
                new_array->AsIntArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetI());
                break;
              case DexFile::kDexAnnotationLong:
                new_array->AsLongArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetJ());
                break;
              case DexFile::kDexAnnotationFloat:
                new_array->AsFloatArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetF());
                break;
              case DexFile::kDexAnnotationDouble:
                new_array->AsDoubleArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetD());
                break;
              case DexFile::kDexAnnotationBoolean:
                new_array->AsBooleanArray()->SetWithoutChecks<kTransactionActive>(
                    i, new_annotation_value.value_.GetZ());
                break;
              default:
                LOG(FATAL) << "Found invalid annotation value type while building annotation array";
                return false;
            }
          }
        }
        element_object = new_array.Get();
        set_object = true;
        width = 0;
      }
      break;
    case DexFile::kDexAnnotationAnnotation:
      if (result_style == DexFile::kAllRaw) {
        return false;
      }
      element_object = ProcessEncodedAnnotation(klass, &annotation);
      if (element_object == nullptr) {
        return false;
      }
      set_object = true;
      width = 0;
      break;
    case DexFile::kDexAnnotationNull:
      if (result_style == DexFile::kAllRaw) {
        annotation_value->value_.SetI(0);
      } else {
        CHECK(element_object == nullptr);
        set_object = true;
      }
      width = 0;
      break;
    default:
      LOG(ERROR) << StringPrintf("Bad annotation element value type 0x%02x", value_type);
      return false;
  }

  annotation += width;
  *annotation_ptr = annotation;

  if (result_style == DexFile::kAllObjects && primitive_type != Primitive::kPrimVoid) {
    element_object = BoxPrimitive(primitive_type, annotation_value->value_);
    set_object = true;
  }

  if (set_object) {
    annotation_value->value_.SetL(element_object);
  }

  return true;
}

ObjPtr<mirror::Object> CreateAnnotationMember(const ClassData& klass,
                                              Handle<mirror::Class> annotation_class,
                                              const uint8_t** annotation) {
  const DexFile& dex_file = klass.GetDexFile();
  Thread* self = Thread::Current();
  ScopedObjectAccessUnchecked soa(self);
  StackHandleScope<5> hs(self);
  uint32_t element_name_index = DecodeUnsignedLeb128(annotation);
  const char* name = dex_file.StringDataByIdx(dex::StringIndex(element_name_index));

  PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
  ArtMethod* annotation_method =
      annotation_class->FindDeclaredVirtualMethodByName(name, pointer_size);
  if (annotation_method == nullptr) {
    return nullptr;
  }

  Handle<mirror::String> string_name =
      hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, name));
  if (UNLIKELY(string_name == nullptr)) {
    LOG(ERROR) << "Failed to allocate name for annotation member";
    return nullptr;
  }

  Handle<mirror::Class> method_return = hs.NewHandle(annotation_method->ResolveReturnType());
  if (UNLIKELY(method_return == nullptr)) {
    LOG(ERROR) << "Failed to resolve method return type for annotation member";
    return nullptr;
  }

  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(klass,
                                     annotation,
                                     &annotation_value,
                                     method_return,
                                     DexFile::kAllObjects)) {
    // TODO: Logging the error breaks run-test 005-annotations.
    // LOG(ERROR) << "Failed to process annotation value for annotation member";
    return nullptr;
  }
  Handle<mirror::Object> value_object = hs.NewHandle(annotation_value.value_.GetL());

  Handle<mirror::Method> method_object = hs.NewHandle((pointer_size == PointerSize::k64)
      ? mirror::Method::CreateFromArtMethod<PointerSize::k64>(self, annotation_method)
      : mirror::Method::CreateFromArtMethod<PointerSize::k32>(self, annotation_method));
  if (UNLIKELY(method_object == nullptr)) {
    LOG(ERROR) << "Failed to create method object for annotation member";
    return nullptr;
  }

  Handle<mirror::Object> new_member =
      WellKnownClasses::libcore_reflect_AnnotationMember_init->NewObject<'L', 'L', 'L', 'L'>(
          hs, self, string_name, value_object, method_return, method_object);
  if (new_member == nullptr) {
    DCHECK(self->IsExceptionPending());
    LOG(ERROR) << "Failed to create annotation member";
    return nullptr;
  }

  return new_member.Get();
}

const AnnotationItem* GetAnnotationItemFromAnnotationSet(const ClassData& klass,
                                                         const AnnotationSetItem* annotation_set,
                                                         uint32_t visibility,
                                                         Handle<mirror::Class> annotation_class)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  for (uint32_t i = 0; i < annotation_set->size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    if (!IsVisibilityCompatible(annotation_item->visibility_, visibility)) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    Thread* self = Thread::Current();
    StackHandleScope<2> hs(self);
    ObjPtr<mirror::Class> resolved_class = class_linker->ResolveType(
        dex::TypeIndex(type_index),
        hs.NewHandle(klass.GetDexCache()),
        hs.NewHandle(klass.GetClassLoader()));
    if (resolved_class == nullptr) {
      std::string temp;
      LOG(WARNING) << StringPrintf("Unable to resolve %s annotation class %d",
                                   klass.GetRealClass()->GetDescriptor(&temp), type_index);
      CHECK(self->IsExceptionPending());
      self->ClearException();
      continue;
    }
    if (resolved_class == annotation_class.Get()) {
      return annotation_item;
    }
  }

  return nullptr;
}

ObjPtr<mirror::Object> GetAnnotationObjectFromAnnotationSet(const ClassData& klass,
                                                            const AnnotationSetItem* annotation_set,
                                                            uint32_t visibility,
                                                            Handle<mirror::Class> annotation_class)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      klass, annotation_set, visibility, annotation_class);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation = annotation_item->annotation_;
  return ProcessEncodedAnnotation(klass, &annotation);
}

ObjPtr<mirror::Object> GetAnnotationValue(const ClassData& klass,
                                          const AnnotationItem* annotation_item,
                                          const char* annotation_name,
                                          Handle<mirror::Class> array_class,
                                          uint32_t expected_type)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  const uint8_t* annotation =
      SearchEncodedAnnotation(dex_file, annotation_item->annotation_, annotation_name);
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  bool result = Runtime::Current()->IsActiveTransaction()
      ? ProcessAnnotationValue<true>(klass,
                                     &annotation,
                                     &annotation_value,
                                     array_class,
                                     DexFile::kAllObjects)
      : ProcessAnnotationValue<false>(klass,
                                      &annotation,
                                      &annotation_value,
                                      array_class,
                                      DexFile::kAllObjects);
  if (!result) {
    return nullptr;
  }
  if (annotation_value.type_ != expected_type) {
    return nullptr;
  }
  return annotation_value.value_.GetL();
}

template<typename T>
static inline ObjPtr<mirror::ObjectArray<T>> GetAnnotationArrayValue(
                                     Handle<mirror::Class> klass,
                                     const char* annotation_name,
                                     const char* value_name)
            REQUIRES_SHARED(Locks::mutator_lock_) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(data.GetDexFile(), annotation_set, annotation_name,
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  Handle<mirror::Class> class_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<T>>());
  DCHECK(class_array_class != nullptr);
  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
                                                  annotation_item,
                                                  value_name,
                                                  class_array_class,
                                                  DexFile::kDexAnnotationArray);
  if (obj == nullptr) {
    return nullptr;
  }
  return obj->AsObjectArray<T>();
}

static ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureValue(
    const ClassData& klass,
    const AnnotationSetItem* annotation_set)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  StackHandleScope<1> hs(Thread::Current());
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Signature;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  Handle<mirror::Class> string_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>());
  DCHECK(string_array_class != nullptr);
  ObjPtr<mirror::Object> obj =
      GetAnnotationValue(klass, annotation_item, "value", string_array_class,
                         DexFile::kDexAnnotationArray);
  if (obj == nullptr) {
    return nullptr;
  }
  return obj->AsObjectArray<mirror::String>();
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetThrowsValue(const ClassData& klass,
                                                          const AnnotationSetItem* annotation_set)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(dex_file, annotation_set, "Ldalvik/annotation/Throws;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  Handle<mirror::Class> class_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
  DCHECK(class_array_class != nullptr);
  ObjPtr<mirror::Object> obj =
      GetAnnotationValue(klass, annotation_item, "value", class_array_class,
                         DexFile::kDexAnnotationArray);
  if (obj == nullptr) {
    return nullptr;
  }
  return obj->AsObjectArray<mirror::Class>();
}

ObjPtr<mirror::ObjectArray<mirror::Object>> ProcessAnnotationSet(
    const ClassData& klass,
    const AnnotationSetItem* annotation_set,
    uint32_t visibility)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  Thread* self = Thread::Current();
  StackHandleScope<2> hs(self);
  Handle<mirror::Class> annotation_array_class(hs.NewHandle(
      WellKnownClasses::ToClass(WellKnownClasses::java_lang_annotation_Annotation__array)));
  if (annotation_set == nullptr) {
    return mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), 0);
  }

  uint32_t size = annotation_set->size_;
  Handle<mirror::ObjectArray<mirror::Object>> result(hs.NewHandle(
      mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), size)));
  if (result == nullptr) {
    return nullptr;
  }

  uint32_t dest_index = 0;
  for (uint32_t i = 0; i < size; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    // Note that we do not use IsVisibilityCompatible here because older code
    // was correct for this case.
    if (annotation_item->visibility_ != visibility) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    ObjPtr<mirror::Object> annotation_obj = ProcessEncodedAnnotation(klass, &annotation);
    if (annotation_obj != nullptr) {
      result->SetWithoutChecks<false>(dest_index, annotation_obj);
      ++dest_index;
    } else if (self->IsExceptionPending()) {
      return nullptr;
    }
  }

  if (dest_index == size) {
    return result.Get();
  }

  ObjPtr<mirror::ObjectArray<mirror::Object>> trimmed_result =
      mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_class.Get(), dest_index);
  if (trimmed_result == nullptr) {
    return nullptr;
  }

  for (uint32_t i = 0; i < dest_index; ++i) {
    ObjPtr<mirror::Object> obj = result->GetWithoutChecks(i);
    trimmed_result->SetWithoutChecks<false>(i, obj);
  }

  return trimmed_result;
}

ObjPtr<mirror::ObjectArray<mirror::Object>> ProcessAnnotationSetRefList(
    const ClassData& klass,
    const AnnotationSetRefList* set_ref_list,
    uint32_t size)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const DexFile& dex_file = klass.GetDexFile();
  Thread* self = Thread::Current();
  StackHandleScope<1> hs(self);
  ObjPtr<mirror::Class> annotation_array_class =
      WellKnownClasses::ToClass(WellKnownClasses::java_lang_annotation_Annotation__array);
  ObjPtr<mirror::Class> annotation_array_array_class =
      Runtime::Current()->GetClassLinker()->FindArrayClass(self, annotation_array_class);
  if (annotation_array_array_class == nullptr) {
    return nullptr;
  }
  Handle<mirror::ObjectArray<mirror::Object>> annotation_array_array(hs.NewHandle(
      mirror::ObjectArray<mirror::Object>::Alloc(self, annotation_array_array_class, size)));
  if (annotation_array_array == nullptr) {
    LOG(ERROR) << "Annotation set ref array allocation failed";
    return nullptr;
  }
  for (uint32_t index = 0; index < size; ++index) {
    const AnnotationSetRefItem* set_ref_item = &set_ref_list->list_[index];
    const AnnotationSetItem* set_item = dex_file.GetSetRefItemItem(set_ref_item);
    ObjPtr<mirror::Object> annotation_set = ProcessAnnotationSet(klass,
                                                                 set_item,
                                                                 DexFile::kDexVisibilityRuntime);
    if (annotation_set == nullptr) {
      return nullptr;
    }
    annotation_array_array->SetWithoutChecks<false>(index, annotation_set);
  }
  return annotation_array_array.Get();
}
}  // namespace

namespace annotations {

ObjPtr<mirror::Object> GetAnnotationForField(ArtField* field,
                                             Handle<mirror::Class> annotation_class) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  return GetAnnotationObjectFromAnnotationSet(field_class,
                                              annotation_set,
                                              DexFile::kDexVisibilityRuntime,
                                              annotation_class);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForField(ArtField* field) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  return ProcessAnnotationSet(field_class, annotation_set, DexFile::kDexVisibilityRuntime);
}

ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForField(ArtField* field) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  return GetSignatureValue(field_class, annotation_set);
}

bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForField(field);
  if (annotation_set == nullptr) {
    return false;
  }
  StackHandleScope<1> hs(Thread::Current());
  const ClassData field_class(hs, field);
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      field_class, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class);
  return annotation_item != nullptr;
}

ObjPtr<mirror::Object> GetAnnotationDefaultValue(ArtMethod* method) {
  const ClassData klass(method);
  const DexFile* dex_file = &klass.GetDexFile();
  const AnnotationsDirectoryItem* annotations_dir =
      dex_file->GetAnnotationsDirectory(*klass.GetClassDef());
  if (annotations_dir == nullptr) {
    return nullptr;
  }
  const AnnotationSetItem* annotation_set =
      dex_file->GetClassAnnotationSet(annotations_dir);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(*dex_file, annotation_set,
      "Ldalvik/annotation/AnnotationDefault;", DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(*dex_file, annotation_item->annotation_, "value");
  if (annotation == nullptr) {
    return nullptr;
  }
  uint8_t header_byte = *(annotation++);
  if ((header_byte & DexFile::kDexAnnotationValueTypeMask) != DexFile::kDexAnnotationAnnotation) {
    return nullptr;
  }
  annotation = SearchEncodedAnnotation(*dex_file, annotation, method->GetName());
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  StackHandleScope<1> hs(Thread::Current());
  Handle<mirror::Class> return_type(hs.NewHandle(method->ResolveReturnType()));
  if (!ProcessAnnotationValue<false>(klass,
                                     &annotation,
                                     &annotation_value,
                                     return_type,
                                     DexFile::kAllObjects)) {
    return nullptr;
  }
  return annotation_value.value_.GetL();
}

ObjPtr<mirror::Object> GetAnnotationForMethod(ArtMethod* method,
                                              Handle<mirror::Class> annotation_class) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetAnnotationObjectFromAnnotationSet(ClassData(method), annotation_set,
                                              DexFile::kDexVisibilityRuntime, annotation_class);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForMethod(ArtMethod* method) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  return ProcessAnnotationSet(ClassData(method),
                              annotation_set,
                              DexFile::kDexVisibilityRuntime);
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetExceptionTypesForMethod(ArtMethod* method) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetThrowsValue(ClassData(method), annotation_set);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetParameterAnnotations(ArtMethod* method) {
  const DexFile* dex_file = method->GetDexFile();
  const ParameterAnnotationsItem* parameter_annotations =
      FindAnnotationsItemForMethod(method);
  if (parameter_annotations == nullptr) {
    return nullptr;
  }
  const AnnotationSetRefList* set_ref_list =
      dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
  if (set_ref_list == nullptr) {
    return nullptr;
  }
  uint32_t size = set_ref_list->size_;
  return ProcessAnnotationSetRefList(ClassData(method), set_ref_list, size);
}

uint32_t GetNumberOfAnnotatedMethodParameters(ArtMethod* method) {
  const DexFile* dex_file = method->GetDexFile();
  const ParameterAnnotationsItem* parameter_annotations =
      FindAnnotationsItemForMethod(method);
  if (parameter_annotations == nullptr) {
    return 0u;
  }
  const AnnotationSetRefList* set_ref_list =
      dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
  if (set_ref_list == nullptr) {
    return 0u;
  }
  return set_ref_list->size_;
}

ObjPtr<mirror::Object> GetAnnotationForMethodParameter(ArtMethod* method,
                                                       uint32_t parameter_idx,
                                                       Handle<mirror::Class> annotation_class) {
  const DexFile* dex_file = method->GetDexFile();
  const ParameterAnnotationsItem* parameter_annotations = FindAnnotationsItemForMethod(method);
  if (parameter_annotations == nullptr) {
    return nullptr;
  }
  const AnnotationSetRefList* set_ref_list =
      dex_file->GetParameterAnnotationSetRefList(parameter_annotations);
  if (set_ref_list == nullptr) {
    return nullptr;
  }
  if (parameter_idx >= set_ref_list->size_) {
    return nullptr;
  }
  const AnnotationSetRefItem* annotation_set_ref = &set_ref_list->list_[parameter_idx];
  const AnnotationSetItem* annotation_set =
     dex_file->GetSetRefItemItem(annotation_set_ref);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetAnnotationObjectFromAnnotationSet(ClassData(method),
                                              annotation_set,
                                              DexFile::kDexVisibilityRuntime,
                                              annotation_class);
}

bool GetParametersMetadataForMethod(
    ArtMethod* method,
    /*out*/ MutableHandle<mirror::ObjectArray<mirror::String>>* names,
    /*out*/ MutableHandle<mirror::IntArray>* access_flags) {
  const AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return false;
  }

  const DexFile* dex_file = method->GetDexFile();
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(*dex_file,
                          annotation_set,
                          "Ldalvik/annotation/MethodParameters;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return false;
  }

  StackHandleScope<4> hs(Thread::Current());

  // Extract the parameters' names String[].
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  Handle<mirror::Class> string_array_class =
      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::String>>(class_linker));
  DCHECK(string_array_class != nullptr);

  ClassData data(method);
  Handle<mirror::Object> names_obj =
      hs.NewHandle(GetAnnotationValue(data,
                                      annotation_item,
                                      "names",
                                      string_array_class,
                                      DexFile::kDexAnnotationArray));
  if (names_obj == nullptr) {
    return false;
  }

  // Extract the parameters' access flags int[].
  Handle<mirror::Class> int_array_class(hs.NewHandle(GetClassRoot<mirror::IntArray>(class_linker)));
  DCHECK(int_array_class != nullptr);
  Handle<mirror::Object> access_flags_obj =
      hs.NewHandle(GetAnnotationValue(data,
                                      annotation_item,
                                      "accessFlags",
                                      int_array_class,
                                      DexFile::kDexAnnotationArray));
  if (access_flags_obj == nullptr) {
    return false;
  }

  names->Assign(names_obj->AsObjectArray<mirror::String>());
  access_flags->Assign(access_flags_obj->AsIntArray());
  return true;
}

ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForMethod(ArtMethod* method) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetSignatureValue(ClassData(method), annotation_set);
}

bool IsMethodAnnotationPresent(ArtMethod* method,
                               Handle<mirror::Class> annotation_class,
                               uint32_t visibility /* = DexFile::kDexVisibilityRuntime */) {
  const AnnotationSetItem* annotation_set = FindAnnotationSetForMethod(method);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      ClassData(method), annotation_set, visibility, annotation_class);
  return annotation_item != nullptr;
}

static void DCheckNativeAnnotation(const char* descriptor, jclass cls) {
  if (kIsDebugBuild) {
    ScopedObjectAccess soa(Thread::Current());
    ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls);
    ClassLinker* linker = Runtime::Current()->GetClassLinker();
    // WellKnownClasses may not be initialized yet, so `klass` may be null.
    if (klass != nullptr) {
      // Lookup using the boot class path loader should yield the annotation class.
      CHECK_EQ(klass, linker->LookupClass(soa.Self(), descriptor, /* class_loader= */ nullptr));
    }
  }
}

// Check whether a method from the `dex_file` with the given `annotation_set`
// is annotated with `annotation_descriptor` with build visibility.
static bool IsMethodBuildAnnotationPresent(const DexFile& dex_file,
                                           const AnnotationSetItem& annotation_set,
                                           const char* annotation_descriptor,
                                           jclass annotation_class) {
  for (uint32_t i = 0; i < annotation_set.size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(&annotation_set, i);
    if (!IsVisibilityCompatible(annotation_item->visibility_, DexFile::kDexVisibilityBuild)) {
      continue;
    }
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);
    const char* descriptor = dex_file.StringByTypeIdx(dex::TypeIndex(type_index));
    if (strcmp(descriptor, annotation_descriptor) == 0) {
      DCheckNativeAnnotation(descriptor, annotation_class);
      return true;
    }
  }
  return false;
}

uint32_t GetNativeMethodAnnotationAccessFlags(const DexFile& dex_file,
                                              const dex::ClassDef& class_def,
                                              uint32_t method_index) {
  const dex::AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return 0u;
  }
  uint32_t access_flags = 0u;
  if (IsMethodBuildAnnotationPresent(
          dex_file,
          *annotation_set,
          "Ldalvik/annotation/optimization/FastNative;",
          WellKnownClasses::dalvik_annotation_optimization_FastNative)) {
    access_flags |= kAccFastNative;
  }
  if (IsMethodBuildAnnotationPresent(
          dex_file,
          *annotation_set,
          "Ldalvik/annotation/optimization/CriticalNative;",
          WellKnownClasses::dalvik_annotation_optimization_CriticalNative)) {
    access_flags |= kAccCriticalNative;
  }
  CHECK_NE(access_flags, kAccFastNative | kAccCriticalNative);
  return access_flags;
}

bool MethodIsNeverCompile(const DexFile& dex_file,
                          const dex::ClassDef& class_def,
                          uint32_t method_index) {
  const dex::AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return false;
  }
  return IsMethodBuildAnnotationPresent(
      dex_file,
      *annotation_set,
      "Ldalvik/annotation/optimization/NeverCompile;",
      WellKnownClasses::dalvik_annotation_optimization_NeverCompile);
}

bool MethodIsNeverInline(const DexFile& dex_file,
                         const dex::ClassDef& class_def,
                         uint32_t method_index) {
  const dex::AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return false;
  }
  return IsMethodBuildAnnotationPresent(
      dex_file,
      *annotation_set,
      "Ldalvik/annotation/optimization/NeverInline;",
      WellKnownClasses::dalvik_annotation_optimization_NeverInline);
}

bool FieldIsReachabilitySensitive(const DexFile& dex_file,
                                  const dex::ClassDef& class_def,
                                  uint32_t field_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationSetItem* annotation_set =
      FindAnnotationSetForField(dex_file, class_def, field_index);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(dex_file, annotation_set,
      "Ldalvik/annotation/optimization/ReachabilitySensitive;", DexFile::kDexVisibilityRuntime);
  // TODO: We're missing the equivalent of DCheckNativeAnnotation (not a DCHECK). Does it matter?
  return annotation_item != nullptr;
}

bool MethodIsReachabilitySensitive(const DexFile& dex_file,
                                   const dex::ClassDef& class_def,
                                   uint32_t method_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationSetItem* annotation_set =
      FindAnnotationSetForMethod(dex_file, class_def, method_index);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(dex_file, annotation_set,
      "Ldalvik/annotation/optimization/ReachabilitySensitive;", DexFile::kDexVisibilityRuntime);
  return annotation_item != nullptr;
}

static bool MethodIsReachabilitySensitive(const DexFile& dex_file,
                                               uint32_t method_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DCHECK(method_index < dex_file.NumMethodIds());
  const dex::MethodId& method_id = dex_file.GetMethodId(method_index);
  dex::TypeIndex class_index = method_id.class_idx_;
  const dex::ClassDef * class_def = dex_file.FindClassDef(class_index);
  return class_def != nullptr
         && MethodIsReachabilitySensitive(dex_file, *class_def, method_index);
}

bool MethodContainsRSensitiveAccess(const DexFile& dex_file,
                                    const dex::ClassDef& class_def,
                                    uint32_t method_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  // TODO: This is too slow to run very regularly. Currently this is only invoked in the
  // presence of @DeadReferenceSafe, which will be rare. In the long run, we need to quickly
  // check once whether a class has any @ReachabilitySensitive annotations. If not, we can
  // immediately return false here for any method in that class.
  uint32_t code_item_offset = dex_file.FindCodeItemOffset(class_def, method_index);
  const dex::CodeItem* code_item = dex_file.GetCodeItem(code_item_offset);
  CodeItemInstructionAccessor accessor(dex_file, code_item);
  if (!accessor.HasCodeItem()) {
    return false;
  }
  for (DexInstructionIterator iter = accessor.begin(); iter != accessor.end(); ++iter) {
    switch (iter->Opcode()) {
      case Instruction::IGET:
      case Instruction::IGET_WIDE:
      case Instruction::IGET_OBJECT:
      case Instruction::IGET_BOOLEAN:
      case Instruction::IGET_BYTE:
      case Instruction::IGET_CHAR:
      case Instruction::IGET_SHORT:
      case Instruction::IPUT:
      case Instruction::IPUT_WIDE:
      case Instruction::IPUT_OBJECT:
      case Instruction::IPUT_BOOLEAN:
      case Instruction::IPUT_BYTE:
      case Instruction::IPUT_CHAR:
      case Instruction::IPUT_SHORT:
        {
          uint32_t field_index = iter->VRegC_22c();
          DCHECK(field_index < dex_file.NumFieldIds());
          // We only guarantee to pay attention to the annotation if it's in the same class,
          // or a containing class, but it's OK to do so in other cases.
          const dex::FieldId& field_id = dex_file.GetFieldId(field_index);
          dex::TypeIndex class_index = field_id.class_idx_;
          const dex::ClassDef * field_class_def = dex_file.FindClassDef(class_index);
          // We do not handle the case in which the field is declared in a superclass, and
          // don't claim to do so. The annotated field should normally be private.
          if (field_class_def != nullptr
              && FieldIsReachabilitySensitive(dex_file, *field_class_def, field_index)) {
            return true;
          }
        }
        break;
      case Instruction::INVOKE_SUPER:
        // Cannot call method in same class. TODO: Try an explicit superclass lookup for
        // better "best effort"?
        break;
      case Instruction::INVOKE_INTERFACE:
        // We handle an interface call just like a virtual call. We will find annotations
        // on interface methods/fields visible to us, but not of the annotation is in a
        // super-interface. Again, we could just ignore it.
      case Instruction::INVOKE_VIRTUAL:
      case Instruction::INVOKE_DIRECT:
        {
          uint32_t called_method_index = iter->VRegB_35c();
          if (MethodIsReachabilitySensitive(dex_file, called_method_index)) {
            return true;
          }
        }
        break;
      case Instruction::INVOKE_INTERFACE_RANGE:
      case Instruction::INVOKE_VIRTUAL_RANGE:
      case Instruction::INVOKE_DIRECT_RANGE:
        {
          uint32_t called_method_index = iter->VRegB_3rc();
          if (MethodIsReachabilitySensitive(dex_file, called_method_index)) {
            return true;
          }
        }
        break;
        // We explicitly do not handle indirect ReachabilitySensitive accesses through VarHandles,
        // etc. Thus we ignore INVOKE_CUSTOM / INVOKE_CUSTOM_RANGE / INVOKE_POLYMORPHIC /
        // INVOKE_POLYMORPHIC_RANGE.
      default:
        // There is no way to add an annotation to array elements, and so far we've encountered no
        // need for that, so we ignore AGET and APUT.
        // It's impractical or impossible to garbage collect a class while one of its methods is
        // on the call stack. We allow ReachabilitySensitive annotations on static methods and
        // fields, but they can be safely ignored.
        break;
    }
  }
  return false;
}

bool HasDeadReferenceSafeAnnotation(const DexFile& dex_file,
                                    const dex::ClassDef& class_def)
  // TODO: This should check outer classes as well.
  // It's conservatively correct not to do so.
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const AnnotationsDirectoryItem* annotations_dir =
      dex_file.GetAnnotationsDirectory(class_def);
  if (annotations_dir == nullptr) {
    return false;
  }
  const AnnotationSetItem* annotation_set = dex_file.GetClassAnnotationSet(annotations_dir);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(dex_file, annotation_set,
      "Ldalvik/annotation/optimization/DeadReferenceSafe;", DexFile::kDexVisibilityRuntime);
  return annotation_item != nullptr;
}

ObjPtr<mirror::Object> GetAnnotationForClass(Handle<mirror::Class> klass,
                                             Handle<mirror::Class> annotation_class) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetAnnotationObjectFromAnnotationSet(data,
                                              annotation_set,
                                              DexFile::kDexVisibilityRuntime,
                                              annotation_class);
}

ObjPtr<mirror::ObjectArray<mirror::Object>> GetAnnotationsForClass(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  return ProcessAnnotationSet(data, annotation_set, DexFile::kDexVisibilityRuntime);
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetDeclaredClasses(Handle<mirror::Class> klass) {
  return GetAnnotationArrayValue<mirror::Class>(klass,
                                                "Ldalvik/annotation/MemberClasses;",
                                                "value");
}

ObjPtr<mirror::Class> GetDeclaringClass(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/EnclosingClass;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
                                                  annotation_item,
                                                  "value",
                                                  ScopedNullHandle<mirror::Class>(),
                                                  DexFile::kDexAnnotationType);
  if (obj == nullptr) {
    return nullptr;
  }
  if (!obj->IsClass()) {
    // TypeNotPresentException, throw the NoClassDefFoundError.
    Thread::Current()->SetException(obj->AsThrowable()->GetCause());
    return nullptr;
  }
  return obj->AsClass();
}

ObjPtr<mirror::Class> GetEnclosingClass(Handle<mirror::Class> klass) {
  ObjPtr<mirror::Class> declaring_class = GetDeclaringClass(klass);
  if (declaring_class != nullptr || Thread::Current()->IsExceptionPending()) {
    return declaring_class;
  }
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(data.GetDexFile(),
                          annotation_set,
                          "Ldalvik/annotation/EnclosingMethod;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value");
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllRaw)) {
    return nullptr;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationMethod) {
    return nullptr;
  }
  StackHandleScope<2> hs(Thread::Current());
  ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType(
      annotation_value.value_.GetI(),
      hs.NewHandle(data.GetDexCache()),
      hs.NewHandle(data.GetClassLoader()));
  if (method == nullptr) {
    return nullptr;
  }
  return method->GetDeclaringClass();
}

ObjPtr<mirror::Object> GetEnclosingMethod(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(data.GetDexFile(),
                          annotation_set,
                          "Ldalvik/annotation/EnclosingMethod;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  return GetAnnotationValue(data, annotation_item, "value", ScopedNullHandle<mirror::Class>(),
      DexFile::kDexAnnotationMethod);
}

bool GetInnerClass(Handle<mirror::Class> klass, /*out*/ ObjPtr<mirror::String>* name) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(
      data.GetDexFile(),
      annotation_set,
      "Ldalvik/annotation/InnerClass;",
      DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return false;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "name");
  if (annotation == nullptr) {
    return false;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllObjects)) {
    return false;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationNull &&
      annotation_value.type_ != DexFile::kDexAnnotationString) {
    return false;
  }
  *name = down_cast<mirror::String*>(annotation_value.value_.GetL());
  return true;
}

bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/InnerClass;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return false;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "accessFlags");
  if (annotation == nullptr) {
    return false;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllRaw)) {
    return false;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationInt) {
    return false;
  }
  *flags = annotation_value.value_.GetI();
  return true;
}

ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureAnnotationForClass(
    Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  return GetSignatureValue(data, annotation_set);
}

const char* GetSourceDebugExtension(Handle<mirror::Class> klass) {
  // Before instantiating ClassData, check that klass has a DexCache
  // assigned.  The ClassData constructor indirectly dereferences it
  // when calling klass->GetDexFile().
  if (klass->GetDexCache() == nullptr) {
    DCHECK(klass->IsPrimitive() || klass->IsArrayClass());
    return nullptr;
  }

  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }

  const AnnotationItem* annotation_item = SearchAnnotationSet(
      data.GetDexFile(),
      annotation_set,
      "Ldalvik/annotation/SourceDebugExtension;",
      DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }

  const uint8_t* annotation =
      SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value");
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  if (!ProcessAnnotationValue<false>(data,
                                     &annotation,
                                     &annotation_value,
                                     ScopedNullHandle<mirror::Class>(),
                                     DexFile::kAllRaw)) {
    return nullptr;
  }
  if (annotation_value.type_ != DexFile::kDexAnnotationString) {
    return nullptr;
  }
  dex::StringIndex index(static_cast<uint32_t>(annotation_value.value_.GetI()));
  return data.GetDexFile().StringDataByIdx(index);
}

ObjPtr<mirror::Class> GetNestHost(Handle<mirror::Class> klass) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item =
      SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/NestHost;",
                          DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
                                                  annotation_item,
                                                  "host",
                                                  ScopedNullHandle<mirror::Class>(),
                                                  DexFile::kDexAnnotationType);
  if (obj == nullptr) {
    return nullptr;
  }
  if (!obj->IsClass()) {
    // TypeNotPresentException, throw the NoClassDefFoundError.
    Thread::Current()->SetException(obj->AsThrowable()->GetCause());
    return nullptr;
  }
  return obj->AsClass();
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetNestMembers(Handle<mirror::Class> klass) {
  return GetAnnotationArrayValue<mirror::Class>(klass,
                                                "Ldalvik/annotation/NestMembers;",
                                                "classes");
}

ObjPtr<mirror::ObjectArray<mirror::Class>> GetPermittedSubclasses(Handle<mirror::Class> klass) {
  return GetAnnotationArrayValue<mirror::Class>(klass,
                                                "Ldalvik/annotation/PermittedSubclasses;",
                                                "value");
}

ObjPtr<mirror::Object> getRecordAnnotationElement(Handle<mirror::Class> klass,
                                                  Handle<mirror::Class> array_class,
                                                  const char* element_name) {
  ClassData data(klass);
  const DexFile& dex_file = klass->GetDexFile();
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return nullptr;
  }
  const AnnotationItem* annotation_item = SearchAnnotationSet(
      dex_file, annotation_set, "Ldalvik/annotation/Record;", DexFile::kDexVisibilitySystem);
  if (annotation_item == nullptr) {
    return nullptr;
  }
  const uint8_t* annotation =
      SearchEncodedAnnotation(dex_file, annotation_item->annotation_, element_name);
  if (annotation == nullptr) {
    return nullptr;
  }
  DexFile::AnnotationValue annotation_value;
  bool result = Runtime::Current()->IsActiveTransaction()
      ? ProcessAnnotationValue<true>(data,
                                     &annotation,
                                     &annotation_value,
                                     array_class,
                                     DexFile::kPrimitivesOrObjects)
      : ProcessAnnotationValue<false>(data,
                                      &annotation,
                                      &annotation_value,
                                      array_class,
                                      DexFile::kPrimitivesOrObjects);
  if (!result) {
    return nullptr;
  }
  return annotation_value.value_.GetL();
}

bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return false;
  }
  const AnnotationItem* annotation_item = GetAnnotationItemFromAnnotationSet(
      data, annotation_set, DexFile::kDexVisibilityRuntime, annotation_class);
  return annotation_item != nullptr;
}

int32_t GetLineNumFromPC(const DexFile* dex_file, ArtMethod* method, uint32_t rel_pc) {
  // For native method, lineno should be -2 to indicate it is native. Note that
  // "line number == -2" is how libcore tells from StackTraceElement.
  if (!method->HasCodeItem()) {
    return -2;
  }

  CodeItemDebugInfoAccessor accessor(method->DexInstructionDebugInfo());
  DCHECK(accessor.HasCodeItem()) << method->PrettyMethod() << " " << dex_file->GetLocation();

  // A method with no line number info should return -1
  uint32_t line_num = -1;
  accessor.GetLineNumForPc(rel_pc, &line_num);
  return line_num;
}

template<bool kTransactionActive>
void RuntimeEncodedStaticFieldValueIterator::ReadValueToField(ArtField* field) const {
  DCHECK(dex_cache_ != nullptr);
  switch (type_) {
    case kBoolean: field->SetBoolean<kTransactionActive>(field->GetDeclaringClass(), jval_.z);
        break;
    case kByte:    field->SetByte<kTransactionActive>(field->GetDeclaringClass(), jval_.b); break;
    case kShort:   field->SetShort<kTransactionActive>(field->GetDeclaringClass(), jval_.s); break;
    case kChar:    field->SetChar<kTransactionActive>(field->GetDeclaringClass(), jval_.c); break;
    case kInt:     field->SetInt<kTransactionActive>(field->GetDeclaringClass(), jval_.i); break;
    case kLong:    field->SetLong<kTransactionActive>(field->GetDeclaringClass(), jval_.j); break;
    case kFloat:   field->SetFloat<kTransactionActive>(field->GetDeclaringClass(), jval_.f); break;
    case kDouble:  field->SetDouble<kTransactionActive>(field->GetDeclaringClass(), jval_.d); break;
    case kNull:    field->SetObject<kTransactionActive>(field->GetDeclaringClass(), nullptr); break;
    case kString: {
      ObjPtr<mirror::String> resolved = linker_->ResolveString(dex::StringIndex(jval_.i),
                                                               dex_cache_);
      field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
      break;
    }
    case kType: {
      ObjPtr<mirror::Class> resolved = linker_->ResolveType(dex::TypeIndex(jval_.i),
                                                            dex_cache_,
                                                            class_loader_);
      field->SetObject<kTransactionActive>(field->GetDeclaringClass(), resolved);
      break;
    }
    default: UNIMPLEMENTED(FATAL) << ": type " << type_;
  }
}
template
void RuntimeEncodedStaticFieldValueIterator::ReadValueToField<true>(ArtField* field) const;
template
void RuntimeEncodedStaticFieldValueIterator::ReadValueToField<false>(ArtField* field) const;

inline static VisitorStatus VisitElement(AnnotationVisitor* visitor,
                                         const char* element_name,
                                         uint8_t depth,
                                         uint32_t element_index,
                                         const DexFile::AnnotationValue& annotation_value)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  if (depth == 0) {
    return visitor->VisitAnnotationElement(
        element_name, annotation_value.type_, annotation_value.value_);
  } else {
    return visitor->VisitArrayElement(
        depth - 1, element_index, annotation_value.type_, annotation_value.value_);
  }
}

static VisitorStatus VisitEncodedValue(const ClassData& klass,
                                       const DexFile& dex_file,
                                       const uint8_t** annotation_ptr,
                                       AnnotationVisitor* visitor,
                                       const char* element_name,
                                       uint8_t depth,
                                       uint32_t element_index)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  DexFile::AnnotationValue annotation_value;
  // kTransactionActive is safe because the result_style is kAllRaw.
  bool is_consumed = ProcessAnnotationValue<false>(klass,
                                                   annotation_ptr,
                                                   &annotation_value,
                                                   ScopedNullHandle<mirror::Class>(),
                                                   DexFile::kAllRaw);

  VisitorStatus status =
      VisitElement(visitor, element_name, depth, element_index, annotation_value);
  switch (annotation_value.type_) {
    case DexFile::kDexAnnotationArray: {
      DCHECK(!is_consumed) << " unexpected consumption of array-typed element '" << element_name
                           << "' annotating the class " << klass.GetRealClass()->PrettyClass();
      SkipEncodedValueHeaderByte(annotation_ptr);
      uint32_t array_size = DecodeUnsignedLeb128(annotation_ptr);
      uint8_t next_depth = depth + 1;
      VisitorStatus element_status = (status == VisitorStatus::kVisitInner) ?
                                         VisitorStatus::kVisitNext :
                                         VisitorStatus::kVisitBreak;
      uint32_t i = 0;
      for (; i < array_size && element_status != VisitorStatus::kVisitBreak; ++i) {
        element_status = VisitEncodedValue(
            klass, dex_file, annotation_ptr, visitor, element_name, next_depth, i);
      }
      for (; i < array_size; ++i) {
        SkipAnnotationValue(dex_file, annotation_ptr);
      }
      break;
    }
    case DexFile::kDexAnnotationAnnotation: {
      DCHECK(!is_consumed) << " unexpected consumption of annotation-typed element '"
                           << element_name << "' annotating the class "
                           << klass.GetRealClass()->PrettyClass();
      SkipEncodedValueHeaderByte(annotation_ptr);
      DecodeUnsignedLeb128(annotation_ptr);  // unused type_index
      uint32_t size = DecodeUnsignedLeb128(annotation_ptr);
      for (; size != 0u; --size) {
        DecodeUnsignedLeb128(annotation_ptr);  // unused element_name_index
        SkipAnnotationValue(dex_file, annotation_ptr);
      }
      break;
    }
    default: {
      // kDexAnnotationArray and kDexAnnotationAnnotation are the only 2 known value_types causing
      // ProcessAnnotationValue return false. For other value_types, we shouldn't need to iterate
      // over annotation_ptr and skip the value here.
      DCHECK(is_consumed) << StringPrintf(
          "consumed annotation element type 0x%02x of %s for the class %s",
          annotation_value.type_,
          element_name,
          klass.GetRealClass()->PrettyClass().c_str());
      if (UNLIKELY(!is_consumed)) {
        SkipAnnotationValue(dex_file, annotation_ptr);
      }
      break;
    }
  }

  return status;
}

void VisitClassAnnotations(Handle<mirror::Class> klass, AnnotationVisitor* visitor) {
  ClassData data(klass);
  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
  if (annotation_set == nullptr) {
    return;
  }

  const DexFile& dex_file = data.GetDexFile();
  for (uint32_t i = 0; i < annotation_set->size_; ++i) {
    const AnnotationItem* annotation_item = dex_file.GetAnnotationItem(annotation_set, i);
    uint8_t visibility = annotation_item->visibility_;
    const uint8_t* annotation = annotation_item->annotation_;
    uint32_t type_index = DecodeUnsignedLeb128(&annotation);
    const char* annotation_descriptor = dex_file.StringByTypeIdx(dex::TypeIndex(type_index));
    VisitorStatus status = visitor->VisitAnnotation(annotation_descriptor, visibility);
    switch (status) {
      case VisitorStatus::kVisitBreak:
        return;
      case VisitorStatus::kVisitNext:
        continue;
      case VisitorStatus::kVisitInner:
        // Visit the annotation elements
        break;
    }

    uint32_t size = DecodeUnsignedLeb128(&annotation);
    while (size != 0) {
      uint32_t element_name_index = DecodeUnsignedLeb128(&annotation);
      const char* element_name =
          dex_file.GetStringData(dex_file.GetStringId(dex::StringIndex(element_name_index)));

      status = VisitEncodedValue(
          data, dex_file, &annotation, visitor, element_name, /*depth=*/0, /*ignored*/ 0);
      if (status == VisitorStatus::kVisitBreak) {
        break;
      }
      size--;
    }
  }
}

}  // namespace annotations

}  // namespace art
