Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  dex_cache-inl.h

  Sprache: C
 

/*
 * Copyright (C) 2013 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.
 */


#ifndef ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_
#define ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_

#include "dex_cache.h"

#include <atomic>

#include "android-base/logging.h"
#include "art_field.h"
#include "art_method.h"
#include "base/atomic_pair.h"
#include "base/casts.h"
#include "base/globals.h"
#include "base/pointer_size.h"
#include "class_linker.h"
#include "dex/dex_file.h"
#include "gc_root-inl.h"
#include "linear_alloc-inl.h"
#include "mirror/call_site.h"
#include "mirror/class.h"
#include "mirror/method_type.h"
#include "obj_ptr.h"
#include "object-inl.h"
#include "runtime.h"
#include "write_barrier-inl.h"

namespace art HIDDEN {
namespace mirror {

template<typename DexCachePair>
static void InitializeArray(std::atomic<DexCachePair>* array) {
  DexCachePair::Initialize(array);
}

template<typename T>
static void InitializeArray(T*) {
  // Nothing to do.
}

template<typename T>
T* DexCache::AllocArray(MemberOffset obj_offset, size_t num, LinearAllocKind kind, bool startup) {
  Thread* self = Thread::Current();
  mirror::DexCache* dex_cache = this;
  if (gUseReadBarrier && self->GetIsGcMarking()) {
    // Several code paths use DexCache without read-barrier for performance.
    // We have to check the "to-space" object here to avoid allocating twice.
    dex_cache = reinterpret_cast<DexCache*>(ReadBarrier::Mark(this));
  }
  // DON'T USE 'this' from now on.
  Runtime* runtime = Runtime::Current();
  // Note: in the 1002-notify-startup test, the startup linear alloc can become null
  // concurrently, even if the runtime is marked at startup. Therefore we should only
  // fetch it once here.
  LinearAlloc* startup_linear_alloc = runtime->GetStartupLinearAlloc();
  LinearAlloc* alloc = (startup && startup_linear_alloc != nullptr)
      ? startup_linear_alloc
      : runtime->GetClassLinker()->GetOrCreateAllocatorForClassLoader(GetClassLoader());
  MutexLock mu(self, *Locks::dex_cache_lock_);  // Avoid allocation by multiple threads.
  T* array = dex_cache->GetFieldPtr64<T*>(obj_offset);
  if (array != nullptr) {
    DCHECK(alloc->Contains(array));
    return array;  // Other thread just allocated the array.
  }
  array = reinterpret_cast<T*>(alloc->AllocAlign16(self, RoundUp(num * sizeof(T), 16), kind));
  InitializeArray(array);  // Ensure other threads see the array initialized.
  dex_cache->SetField64Volatile<falsefalse>(obj_offset, reinterpret_cast64<uint64_t>(array));
  return array;
}

template <typename T>
inline DexCachePair<T>::DexCachePair(ObjPtr<T> object, uint32_t index)
    : object(object), index(index) {}

template <typename T>
inline T* DexCachePair<T>::GetObjectForIndex(uint32_t idx) {
  if (idx != index) {
    return nullptr;
  }
  DCHECK(!object.IsNull());
  return object.Read();
}

template <typename T>
inline void DexCachePair<T>::Initialize(std::atomic<DexCachePair<T>>* dex_cache) {
  DexCachePair<T> first_elem;
  first_elem.object = GcRoot<T>(nullptr);
  first_elem.index = InvalidIndexForSlot(0);
  dex_cache[0].store(first_elem, std::memory_order_relaxed);
}

template <typename T>
inline void NativeDexCachePair<T>::Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache) {
  NativeDexCachePair<T> first_elem;
  first_elem.object = nullptr;
  first_elem.index = InvalidIndexForSlot(0);

  auto* array = reinterpret_cast<AtomicPair<uintptr_t>*>(dex_cache);
  AtomicPair<uintptr_t> v(first_elem.index, reinterpret_cast<size_t>(first_elem.object));
  AtomicPairStoreRelease(&array[0], v);
}

template <typename T>
inline void GcRootArray<T>::Set(uint32_t index, T* value) {
  GcRoot<T> root(value);
  entries_[index].store(root, std::memory_order_relaxed);
}

template <typename T>
inline T* GcRootArray<T>::Get(uint32_t index) {
  return entries_[index].load(std::memory_order_relaxed).Read();
}

inline uint32_t DexCache::ClassSize(PointerSize pointer_size) {
  const uint32_t vtable_entries = Object::kVTableLength;
  return Class::ComputeClassSize(true, vtable_entries, 000000, pointer_size);
}

inline String* DexCache::GetResolvedString(dex::StringIndex string_idx) {
  return GetStringsEntry(string_idx.index_);
}

inline void DexCache::SetResolvedString(dex::StringIndex string_idx, ObjPtr<String> resolved) {
  DCHECK(resolved != nullptr);
  SetStringsEntry(string_idx.index_, resolved.Ptr());
  Runtime* const runtime = Runtime::Current();
  if (UNLIKELY(runtime->IsActiveTransaction())) {
    DCHECK(runtime->IsAotCompiler());
    runtime->GetClassLinker()->RecordResolveString(this, string_idx);
  }
  // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
  WriteBarrier::ForEveryFieldWrite(this);
}

inline void DexCache::ClearString(dex::StringIndex string_idx) {
  DCHECK(Runtime::Current()->IsAotCompiler());
  auto* array = GetStringsArray();
  if (array != nullptr) {
    array->Set(string_idx.index_, nullptr);
  }
  auto* strings = GetStrings();
  if (UNLIKELY(strings == nullptr)) {
    return;
  }
  strings->Clear(string_idx.index_);
}

inline Class* DexCache::GetResolvedType(dex::TypeIndex type_idx) {
  return GetResolvedTypesEntry(type_idx.index_);
}

inline void DexCache::ClearResolvedType(dex::TypeIndex type_idx) {
  DCHECK(Runtime::Current()->IsAotCompiler());
  auto* array = GetResolvedTypesArray();
  if (array != nullptr) {
    array->Set(type_idx.index_, nullptr);
  }
  auto* resolved_types = GetResolvedTypes();
  if (UNLIKELY(resolved_types == nullptr)) {
    return;
  }
  resolved_types->Clear(type_idx.index_);
}

inline MethodType* DexCache::GetResolvedMethodType(dex::ProtoIndex proto_idx) {
  return GetResolvedMethodTypesEntry(proto_idx.index_);
}

inline void DexCache::SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved) {
  DCHECK(resolved != nullptr);
  SetResolvedMethodTypesEntry(proto_idx.index_, resolved);

  Runtime* const runtime = Runtime::Current();
  if (UNLIKELY(runtime->IsActiveTransaction())) {
    DCHECK(runtime->IsAotCompiler());
    runtime->GetClassLinker()->RecordResolveMethodType(this, proto_idx);
  }
  // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
  WriteBarrier::ForEveryFieldWrite(this);
}

inline void DexCache::ClearMethodType(dex::ProtoIndex proto_idx) {
  DCHECK(Runtime::Current()->IsAotCompiler());
  auto* array = GetResolvedMethodTypesArray();
  if (array != nullptr) {
    array->Set(proto_idx.index_, nullptr);
  }
  auto* methods = GetResolvedMethodTypes();
  if (methods == nullptr) {
    return;
  }
  methods->Clear(proto_idx.index_);
}

inline CallSite* DexCache::GetResolvedCallSite(uint32_t call_site_idx) {
  DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
  DCHECK_LT(call_site_idx, GetDexFile()->NumCallSiteIds());
  GcRootArray<CallSite>* call_sites = GetResolvedCallSites();
  if (UNLIKELY(call_sites == nullptr)) {
    return nullptr;
  }
  Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);
  return target->load(std::memory_order_seq_cst).Read();
}

inline ObjPtr<CallSite> DexCache::SetResolvedCallSite(uint32_t call_site_idx,
                                                      ObjPtr<CallSite> call_site) {
  DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
  DCHECK_LT(call_site_idx, GetDexFile()->NumCallSiteIds());

  GcRoot<mirror::CallSite> null_call_site(nullptr);
  GcRoot<mirror::CallSite> candidate(call_site);
  GcRootArray<CallSite>* call_sites = GetResolvedCallSites();
  if (UNLIKELY(call_sites == nullptr)) {
    call_sites = AllocateResolvedCallSites();
  }
  Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);

  // The first assignment for a given call site wins.
  if (target->CompareAndSetStrongSequentiallyConsistent(null_call_site, candidate)) {
    // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
    WriteBarrier::ForEveryFieldWrite(this);
    return call_site;
  } else {
    return target->load(std::memory_order_relaxed).Read();
  }
}

inline ArtField* DexCache::GetResolvedField(uint32_t field_idx) {
  return GetResolvedFieldsEntry(field_idx);
}

inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field) {
  SetResolvedFieldsEntry(field_idx, field);
}

inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) {
  return GetResolvedMethodsEntry(method_idx);
}

inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method) {
  SetResolvedMethodsEntry(method_idx, method);
}

template <ReadBarrierOption kReadBarrierOption,
          typename Visitor,
          typename T>
inline void VisitDexCachePairs(T* array,
                               size_t num_pairs,
                               const Visitor& visitor)
    REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
  DCHECK_NE(array, nullptr);
  for (size_t i = 0; i < num_pairs; ++i) {
    auto source = array->GetPair(i);
    // NOTE: We need the "template" keyword here to avoid a compilation
    // failure. GcRoot<T> is a template argument-dependent type and we need to
    // tell the compiler to treat "Read" as a template rather than a field or
    // function. Otherwise, on encountering the "<" token, the compiler would
    // treat "Read" as a field.
    auto const before = source.object.template Read<kReadBarrierOption>();
    visitor.VisitRootIfNonNull(source.object.AddressWithoutBarrier());
    if (source.object.template Read<kReadBarrierOption>() != before) {
      array->SetPair(i, source);
    }
  }
}

template <typename Visitor>
void DexCache::VisitDexCachePairRoots(Visitor& visitor,
                                      DexCachePair<Object>* pairs_begin,
                                      DexCachePair<Object>* pairs_end) {
  for (; pairs_begin < pairs_end; pairs_begin++) {
    visitor.VisitRootIfNonNull(pairs_begin->object.AddressWithoutBarrier());
  }
}

template <bool kVisitNativeRoots,
          VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor>
inline void DexCache::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
  // Visit instance fields first.
  VisitInstanceFieldsReferences<kVerifyFlags>(klass, visitor);
  // Visit arrays after.
  if (kVisitNativeRoots) {
    auto should_visit = [](void* ptr) { return ptr != nullptr; };
    VisitNativeRoots<kVerifyFlags, kReadBarrierOption>(visitor, should_visit);
  }
}

template <VerifyObjectFlags kVerifyFlags,
          ReadBarrierOption kReadBarrierOption,
          typename Visitor,
          typename ShouldVisitVisitor>
inline void DexCache::VisitNativeRoots(const Visitor& visitor,
                                       const ShouldVisitVisitor& should_visit) {
  auto* strings = GetStrings<kVerifyFlags>();
  if (should_visit(strings)) {
    VisitDexCachePairs<kReadBarrierOption, Visitor>(strings, NumStrings<kVerifyFlags>(), visitor);
  }

  auto* resolved_types = GetResolvedTypes<kVerifyFlags>();
  if (should_visit(resolved_types)) {
    VisitDexCachePairs<kReadBarrierOption, Visitor>(
        resolved_types, NumResolvedTypes<kVerifyFlags>(), visitor);
  }

  auto* resolved_method_types = GetResolvedMethodTypes<kVerifyFlags>();
  if (should_visit(resolved_method_types)) {
    VisitDexCachePairs<kReadBarrierOption, Visitor>(
        resolved_method_types, NumResolvedMethodTypes<kVerifyFlags>(), visitor);
  }

  GcRootArray<mirror::CallSite>* resolved_call_sites = GetResolvedCallSites<kVerifyFlags>();
  if (should_visit(resolved_call_sites)) {
    size_t num_call_sites = NumResolvedCallSites<kVerifyFlags>();
    for (size_t i = 0; i != num_call_sites; ++i) {
      visitor.VisitRootIfNonNull(resolved_call_sites->GetGcRootAddress(i)->AddressWithoutBarrier());
    }
  }

  // Dex cache arrays can be reset and cleared during app startup. Assert we do not get
  // suspended to ensure the arrays are not deallocated.
  ScopedAssertNoThreadSuspension soants("dex caches");
  GcRootArray<mirror::Class>* resolved_types_arr = GetResolvedTypesArray<kVerifyFlags>();
  if (should_visit(resolved_types_arr)) {
    size_t num_resolved_types = NumResolvedTypesArray<kVerifyFlags>();
    for (size_t i = 0; i != num_resolved_types; ++i) {
      visitor.VisitRootIfNonNull(resolved_types_arr->GetGcRootAddress(i)->AddressWithoutBarrier());
    }
  }

  GcRootArray<mirror::String>* resolved_strings = GetStringsArray<kVerifyFlags>();
  if (should_visit(resolved_strings)) {
    size_t num_resolved_strings = NumStringsArray<kVerifyFlags>();
    for (size_t i = 0; i != num_resolved_strings; ++i) {
      visitor.VisitRootIfNonNull(resolved_strings->GetGcRootAddress(i)->AddressWithoutBarrier());
    }
  }

  GcRootArray<mirror::MethodType>* resolved_method_types_arr =
      GetResolvedMethodTypesArray<kVerifyFlags>();
  if (should_visit(resolved_method_types_arr)) {
    size_t num_resolved_method_types = NumResolvedMethodTypesArray<kVerifyFlags>();
    for (size_t i = 0; i != num_resolved_method_types; ++i) {
      visitor.VisitRootIfNonNull(
          resolved_method_types_arr->GetGcRootAddress(i)->AddressWithoutBarrier());
    }
  }
}

template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
inline ObjPtr<String> DexCache::GetLocation(bool allow_location_mismatch) {
  ObjPtr<String> location = GetFieldObject<String, kVerifyFlags, kReadBarrierOption>(
      OFFSET_OF_OBJECT_MEMBER(DexCache, location_));
  // At runtime, if the DexCache is from an app image or dynamically created, then its location must
  // match the DexFile location.
  // TODO(jiakaiz): Remove the AOT compiler and boot classpath checks?
  if (kIsDebugBuild && !allow_location_mismatch && !Runtime::Current()->IsAotCompiler() &&
      GetDexFile() != nullptr && !ClassLinker::IsBootClassLoader(GetClassLoader())) {
    DCHECK_EQ(location->ToModifiedUtf8(), GetDexFile()->GetLocation());
  }
  return location;
}

}  // namespace mirror
}  // namespace art

#endif  // ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_

Messung V0.5 in Prozent
C=88 H=95 G=91

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik