template <> struct ShortyTraits<'V'> { using Type = void; static Type Get([[maybe_unused]] const JValue& value) {} // `kVRegCount` and `Set()` are not defined.
};
template <> struct ShortyTraits<'Z'> { // Despite using `uint8_t` for `boolean` in `JValue`, we shall use `bool` here. using Type = bool; static Type Get(const JValue& value) { return value.GetZ() != 0u; } static constexpr size_t kVRegCount = 1u; staticvoid Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value ? 1u : 0u); }
};
template <> struct ShortyTraits<'B'> { using Type = int8_t; static Type Get(const JValue& value) { return value.GetB(); } static constexpr size_t kVRegCount = 1u; staticvoid Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
};
template <> struct ShortyTraits<'C'> { using Type = uint16_t; static Type Get(const JValue& value) { return value.GetC(); } static constexpr size_t kVRegCount = 1u; staticvoid Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
};
template <> struct ShortyTraits<'S'> { using Type = int16_t; static Type Get(const JValue& value) { return value.GetS(); } static constexpr size_t kVRegCount = 1u; staticvoid Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
};
template <> struct ShortyTraits<'I'> { using Type = int32_t; static Type Get(const JValue& value) { return value.GetI(); } static constexpr size_t kVRegCount = 1u; staticvoid Set(uint32_t* args, Type value) { args[0] = static_cast<uint32_t>(value); }
};
inlinebool ArtMethod::IsStringConstructor() {
uint32_t access_flags = GetAccessFlags();
DCHECK(!IsClassInitializer(access_flags)); return IsConstructor(access_flags) && // No read barrier needed for reading a constant reference only to read // a constant string class flag. See `ReadBarrierOption`.
GetDeclaringClass<kWithoutReadBarrier>()->IsStringClass();
}
inlinebool ArtMethod::IsOverridableByDefaultMethod() { // It is safe to avoid the read barrier here since the constant interface flag // in the `Class` object is stored before creating the `ArtMethod` and storing // the declaring class reference. See `ReadBarrierOption`. return GetDeclaringClass<kWithoutReadBarrier>()->IsInterface();
}
inlinebool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { switch (type) { case kStatic: return !IsStatic(); case kDirect: return !IsDirect() || IsStatic(); case kVirtual: { // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface // method.
ObjPtr<mirror::Class> methods_class = GetDeclaringClass(); return IsDirect() || (methods_class->IsInterface() && !IsCopied());
} case kSuper: // Constructors and static methods are called with invoke-direct. return IsConstructor() || IsStatic(); case kInterface: {
ObjPtr<mirror::Class> methods_class = GetDeclaringClass(); return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
} case kPolymorphic: return !IsSignaturePolymorphic(); default:
LOG(FATAL) << "Unreachable - invocation type: " << type;
UNREACHABLE();
}
}
inlinebool ArtMethod::IsCalleeSaveMethod() { if (!IsRuntimeMethod()) { returnfalse;
}
Runtime* runtime = Runtime::Current(); bool result = false; for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); i++) { if (this == runtime->GetCalleeSaveMethod(CalleeSaveType(i))) {
result = true; break;
}
} return result;
}
inlinebool ArtMethod::IsResolutionMethod() { bool result = this == Runtime::Current()->GetResolutionMethod(); // Check that if we do think it is phony it looks like the resolution method.
DCHECK_IMPLIES(result, IsRuntimeMethod()); return result;
}
inlinebool ArtMethod::IsImtUnimplementedMethod() { bool result = this == Runtime::Current()->GetImtUnimplementedMethod(); // Check that if we do think it is phony it looks like the imt unimplemented method.
DCHECK_IMPLIES(result, IsRuntimeMethod()); return result;
}
inlineconst DexFile* ArtMethod::GetDexFile() { // It is safe to avoid the read barrier here since the dex file is constant, so if we read the // from-space dex file pointer it will be equal to the to-space copy. return GetDexCache<kWithoutReadBarrier>()->GetDexFile();
}
inlinebool ArtMethod::IsProxyMethod() {
DCHECK(!IsRuntimeMethod()) << "ArtMethod::IsProxyMethod called on a runtime method"; // No read barrier needed, we're reading the constant declaring class only to read // the constant proxy flag. See ReadBarrierOption. return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass();
}
inline ArtMethod* ArtMethod::GetInterfaceMethodForProxyUnchecked(PointerSize pointer_size) {
DCHECK(IsProxyMethod()); // Do not check IsAssignableFrom() here as it relies on raw reference comparison // which may give false negatives while visiting references for a non-CC moving GC. returnreinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size));
}
inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) { if (LIKELY(!IsProxyMethod())) { returnthis;
}
ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size); // We can check that the proxy class implements the interface only if the proxy class // is resolved, otherwise the interface table is not yet initialized.
DCHECK_IMPLIES(GetDeclaringClass()->IsResolved(),
interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass())); return interface_method;
}
inlinebool ArtMethod::HasSingleImplementation() { // No read barrier needed for reading a constant reference only to read // a constant final class flag. See `ReadBarrierOption`. if (IsFinal() || GetDeclaringClass<kWithoutReadBarrier>()->IsFinal()) { // We don't set kAccSingleImplementation for these cases since intrinsic // can use the flag also. returntrue;
} return (GetAccessFlags() & kAccSingleImplementation) != 0;
}
template<ReadBarrierOption kReadBarrierOption, bool kVisitProxyMethod, typename RootVisitorType> void ArtMethod::VisitRoots(RootVisitorType& visitor, PointerSize pointer_size) { if (LIKELY(!declaring_class_.IsNull())) {
visitor.VisitRoot(declaring_class_.AddressWithoutBarrier()); if (kVisitProxyMethod) {
ObjPtr<mirror::Class> klass = declaring_class_.Read<kReadBarrierOption>(); if (UNLIKELY(klass->IsProxyClass())) { // For normal methods, dex cache shortcuts will be visited through the declaring class. // However, for proxies we need to keep the interface method alive, so we visit its roots.
ArtMethod* interface_method = GetInterfaceMethodForProxyUnchecked(pointer_size);
DCHECK(interface_method != nullptr);
interface_method->VisitRoots<kReadBarrierOption, kVisitProxyMethod>(visitor, pointer_size);
}
}
}
// JIT-ted code can hold references to heap objects like MethodType-s. Visiting them here to // treat them as strongly reachable.
Runtime* runtime = Runtime::Current(); if (runtime->GetJit() != nullptr) {
runtime->GetJit()->GetCodeCache()->VisitRootTables(this, visitor);
}
}
template <ReadBarrierOption kReadBarrierOption> inlinebool ArtMethod::StillNeedsClinitCheck() { if (!NeedsClinitCheckBeforeCall()) { returnfalse;
}
ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>(); return !klass->IsVisiblyInitialized();
}
inlinebool ArtMethod::StillNeedsClinitCheckMayBeDead() { if (!NeedsClinitCheckBeforeCall()) { returnfalse;
}
ObjPtr<mirror::Class> klass = GetDeclaringClassMayBeDead(); return !klass->IsVisiblyInitialized();
}
inlinebool ArtMethod::IsDeclaringClassVerifiedMayBeDead() {
ObjPtr<mirror::Class> klass = GetDeclaringClassMayBeDead(); return klass->IsVerified();
}
inline ObjPtr<mirror::Class> ArtMethod::GetDeclaringClassMayBeDead() { // Helper method for checking the status of the declaring class which may be dead. // // To avoid resurrecting an unreachable object, or crashing the GC in some GC phases, // we must not use a full read barrier. Therefore we read the declaring class without // a read barrier and check if it's already marked. If yes, we check the status of the // to-space class object as intended. Otherwise, there is no to-space object and the // from-space class object contains the most recent value of the status field; even if // this races with another thread doing a read barrier and updating the status, that's // no different from a race with a thread that just updates the status.
ObjPtr<mirror::Class> klass = GetDeclaringClass<kWithoutReadBarrier>();
ObjPtr<mirror::Class> marked = ReadBarrier::IsMarked(klass.Ptr()); return (marked != nullptr) ? marked : klass;
}
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.