blob: 7c4253604cdebd66efd9eab5b8deeb02b80d8471 [file] [log] [blame]
/*
* Copyright (C) 2012 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_SRC_VERIFIER_REG_TYPE_H_
#define ART_SRC_VERIFIER_REG_TYPE_H_
#include "base/macros.h"
#include "primitive.h"
#include "jni.h"
#include <limits>
#include <stdint.h>
#include <set>
#include <string>
namespace art {
namespace mirror {
class Class;
} // namespace mirror
namespace verifier {
class RegTypeCache;
/*
* RegType holds information about the "type" of data held in a register.
*/
class RegType {
public:
// The high half that corresponds to this low half
const RegType& HighHalf(RegTypeCache* cache) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
inline virtual bool IsUndefined() const {
return false;
}
inline virtual bool IsConflict() const {
return false;
}
inline virtual bool IsBoolean() const {
return false;
}
inline virtual bool IsByte() const {
return false;
}
inline virtual bool IsChar() const {
return false;
}
inline virtual bool IsShort() const {
return false;
}
inline virtual bool IsInteger() const {
return false;
}
inline virtual bool IsLongLo() const {
return false;
}
inline virtual bool IsLongHi() const {
return false;
}
inline virtual bool IsFloat() const {
return false;
}
inline virtual bool IsDouble() const {
return false;
}
inline virtual bool IsDoubleLo() const {
return false;
}
inline virtual bool IsDoubleHi() const {
return false;
}
inline virtual bool IsUnresolvedReference() const {
return false;
}
inline virtual bool IsUninitializedReference() const {
return false;
}
inline virtual bool IsUninitializedThisReference() const {
return false;
}
inline virtual bool IsUnresolvedAndUninitializedReference() const {
return false;
}
inline virtual bool IsUnresolvedAndUninitializedThisReference() const {
return false;
}
inline virtual bool IsUnresolvedMergedReference() const {
return false;
}
inline virtual bool IsUnresolvedSuperClass() const {
return false;
}
inline virtual bool IsReference() const {
return false;
}
inline virtual bool IsPreciseReference() const {
return false;
}
inline virtual bool IsPreciseConstant() const {
return false;
}
inline virtual bool IsPreciseConstantLo() const {
return false;
}
inline virtual bool IsPreciseConstantHi() const {
return false;
}
inline virtual bool IsImpreciseConstantLo() const {
return false;
}
inline virtual bool IsImpreciseConstantHi() const {
return false;
}
virtual bool IsImpreciseConstant() const {
return false;
}
inline virtual bool IsConstantTypes() const {
return false;
}
bool IsConstant() const {
return (IsPreciseConstant() || IsImpreciseConstant());
}
bool IsConstantLo() const {
return (IsPreciseConstantLo() || IsImpreciseConstantLo());
}
bool IsPrecise() const {
return (IsPreciseConstantLo() || IsPreciseConstant() ||
IsPreciseConstantHi());
}
bool IsLongConstant() const {
return IsConstantLo();
}
bool IsConstantHi() const {
return (IsPreciseConstantHi() || IsImpreciseConstantHi());
}
bool IsLongConstantHigh() const {
return IsConstantHi();
}
bool IsUninitializedTypes() const {
return IsUninitializedReference() || IsUninitializedThisReference() ||
IsUnresolvedAndUninitializedReference() ||
IsUnresolvedAndUninitializedThisReference();
}
bool IsUnresolvedTypes() const {
return IsUnresolvedReference() || IsUnresolvedAndUninitializedReference() ||
IsUnresolvedAndUninitializedThisReference() ||
IsUnresolvedMergedReference() || IsUnresolvedSuperClass();
}
bool IsLowHalf() const {
return (IsLongLo() || IsDoubleLo() || IsPreciseConstantLo() ||
IsImpreciseConstantLo());
}
bool IsHighHalf() const {
return (IsLongHi() || IsDoubleHi() || IsPreciseConstantHi() ||
IsImpreciseConstantHi());
}
bool IsLongOrDoubleTypes() const {
return IsLowHalf();
}
// Check this is the low half, and that type_h is its matching high-half
inline bool CheckWidePair(const RegType& type_h) const {
if (IsLowHalf()) {
return ((IsPreciseConstantLo() && type_h.IsPreciseConstantHi()) ||
(IsPreciseConstantLo() && type_h.IsImpreciseConstantHi()) ||
(IsImpreciseConstantLo() && type_h.IsPreciseConstantHi()) ||
(IsImpreciseConstantLo() && type_h.IsImpreciseConstantHi()) ||
(IsDoubleLo() && type_h.IsDoubleHi()) ||
(IsLongLo() && type_h.IsLongHi()));
}
return false;
}
bool IsConstantBoolean() const {
return IsConstant() && (ConstantValue() >= 0) && (ConstantValue() <= 1);
}
inline virtual bool IsConstantChar() const {
return false;
}
inline virtual bool IsConstantByte() const {
return false;
}
inline virtual bool IsConstantShort() const {
return false;
}
inline virtual bool IsOne() const {
return false;
}
inline virtual bool IsZero() const {
return false;
}
bool IsReferenceTypes() const {
return IsNonZeroReferenceTypes() || IsZero();
}
bool IsNonZeroReferenceTypes() const {
return IsReference() || IsPreciseReference() ||
IsUninitializedReference() || IsUninitializedThisReference() ||
IsUnresolvedReference() || IsUnresolvedAndUninitializedReference() ||
IsUnresolvedAndUninitializedThisReference() ||
IsUnresolvedMergedReference() || IsUnresolvedSuperClass();
}
bool IsCategory1Types() const {
return (IsChar() || IsInteger() || IsFloat() || IsConstant() || IsByte() ||
IsShort() || IsBoolean() );
}
bool IsCategory2Types() const {
return IsLowHalf(); // Don't expect explicit testing of high halves
}
bool IsBooleanTypes() const {
return IsBoolean() || IsConstantBoolean();
}
bool IsByteTypes() const {
return IsConstantByte() || IsByte() || IsBoolean();
}
bool IsShortTypes() const {
return IsShort() || IsByte() || IsBoolean() || IsConstantShort();
}
bool IsCharTypes() const {
return IsChar() || IsBooleanTypes() || IsConstantChar();
}
bool IsIntegralTypes() const {
return (IsInteger() || IsConstant() || IsByte() || IsShort() || IsChar() || IsBoolean() );
}
inline virtual int32_t ConstantValue() const {
DCHECK(IsConstant());
return -1;
}
inline virtual int32_t ConstantValueLo() const {
DCHECK(IsConstantLo());
return -1;
}
inline virtual int32_t ConstantValueHi() const {
DCHECK(IsConstantHi());
return -1;
}
bool IsArrayIndexTypes() const {
return IsIntegralTypes();
}
// Float type may be derived from any constant type
bool IsFloatTypes() const {
return IsFloat() || IsConstant();
}
bool IsLongTypes() const {
return IsLongLo() || IsLongConstant();
}
bool IsLongHighTypes() const {
return (IsLongHi() ||
IsPreciseConstantHi() ||
IsImpreciseConstantHi());
}
bool IsDoubleTypes() const {
return IsDoubleLo() || IsLongConstant();
}
bool IsDoubleHighTypes() const {
return (IsDoubleHi() || IsPreciseConstantHi() || IsImpreciseConstantHi());
}
inline virtual bool IsLong() const {
return false;
}
bool HasClass() const {
return IsReference() || IsPreciseReference() || IsUninitializedReference() ||
IsUninitializedThisReference();
}
bool IsJavaLangObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Primitive::Type GetPrimitiveType() const ;
bool IsJavaLangObjectArray() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsInstantiableTypes() const;
const std::string& GetDescriptor() const {
DCHECK(IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass());
return descriptor_;
}
uint16_t GetId() const {
return cache_id_;
}
const RegType& GetSuperClass(RegTypeCache* cache) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
virtual std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) = 0;
// Can this type access other?
bool CanAccess(const RegType& other) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Can this type access a member with the given properties?
bool CanAccessMember(mirror::Class* klass, uint32_t access_flags) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Can this type be assigned by src?
bool IsAssignableFrom(const RegType& src) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool Equals(const RegType& other) const {
return GetId() == other.GetId();
}
// Compute the merge of this register from one edge (path) with incoming_type from another.
virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Class* GetClass() const {
DCHECK(!IsUnresolvedReference());
DCHECK(klass_ != NULL);
DCHECK(HasClass());
return klass_;
}
/*
* A basic Join operation on classes. For a pair of types S and T the Join, written S v T = J, is
* S <: J, T <: J and for-all U such that S <: U, T <: U then J <: U. That is J is the parent of
* S and T such that there isn't a parent of both S and T that isn't also the parent of J (ie J
* is the deepest (lowest upper bound) parent of S and T).
*
* This operation applies for regular classes and arrays, however, for interface types there needn't
* be a partial ordering on the types. We could solve the problem of a lack of a partial order by
* introducing sets of types, however, the only operation permissible on an interface is
* invoke-interface. In the tradition of Java verifiers [1] we defer the verification of interface
* types until an invoke-interface call on the interface typed reference at runtime and allow
* the perversion of Object being assignable to an interface type (note, however, that we don't
* allow assignment of Object or Interface to any concrete class and are therefore type safe).
*
* [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
*/
static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
RegType(mirror::Class* klass, std::string descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: descriptor_(descriptor), klass_(klass), cache_id_(cache_id) {
}
inline virtual ~RegType() {
}
virtual void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
friend class RegTypeCache;
protected:
const std::string descriptor_;
mirror::Class* klass_;
const uint16_t cache_id_;
DISALLOW_COPY_AND_ASSIGN(RegType);
};
class ConflictType : public RegType {
public:
bool IsConflict() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ConflictType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ConflictType* GetInstance();
static void Destroy();
private:
ConflictType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ConflictType* instance_;
};
class UndefinedType : public RegType {
public:
bool IsUndefined() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static UndefinedType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static UndefinedType* GetInstance();
static void Destroy();
private:
UndefinedType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: RegType(klass, descriptor, cache_id) {
}
virtual const RegType& Merge(const RegType& incoming_type, RegTypeCache* reg_types) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static UndefinedType* instance_;
};
class IntegerType : public RegType {
public:
bool IsInteger() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static IntegerType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static IntegerType* GetInstance();
static void Destroy();
private:
IntegerType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static IntegerType* instance_;
};
class BooleanType : public RegType {
public:
bool IsBoolean() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static BooleanType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static BooleanType* GetInstance();
static void Destroy();
private:
BooleanType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static BooleanType* instance;
};
class ByteType : public RegType {
public:
bool IsByte() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ByteType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ByteType* GetInstance();
static void Destroy();
private:
ByteType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ByteType* instance_;
};
class ShortType : public RegType {
public:
bool IsShort() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ShortType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ShortType* GetInstance();
static void Destroy();
private:
ShortType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static ShortType* instance_;
};
class CharType : public RegType {
public:
bool IsChar() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static CharType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static CharType* GetInstance();
static void Destroy();
private:
CharType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static CharType* instance_;
};
class FloatType : public RegType {
public:
bool IsFloat() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static FloatType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static FloatType* GetInstance();
static void Destroy();
private:
FloatType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static FloatType* instance_;
};
class LongLoType : public RegType {
public:
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsLongLo() const {
return true;
}
bool IsLong() const {
return true;
}
static LongLoType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static LongLoType* GetInstance();
static void Destroy();
private:
LongLoType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static LongLoType* instance_;
};
class LongHiType : public RegType {
public:
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsLongHi() const {
return true;
}
static LongHiType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static LongHiType* GetInstance();
static void Destroy();
private:
LongHiType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static LongHiType* instance_;
};
class DoubleLoType : public RegType {
public:
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsDoubleLo() const {
return true;
}
bool IsDouble() const {
return true;
}
static DoubleLoType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static DoubleLoType* GetInstance();
static void Destroy();
private:
DoubleLoType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static DoubleLoType* instance_;
};
class DoubleHiType : public RegType {
public:
std::string Dump() const;
virtual bool IsDoubleHi() const {
return true;
}
static DoubleHiType* CreateInstance(mirror::Class* klass, std::string& descriptor,
uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static DoubleHiType* GetInstance();
static void Destroy();
private:
DoubleHiType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static DoubleHiType* instance_;
};
class ConstantType : public RegType {
public:
ConstantType(uint32_t constat, uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
inline virtual ~ConstantType() {
}
const uint32_t constant_;
// If this is a 32-bit constant, what is the value? This value may be imprecise in which case
// the value represents part of the integer range of values that may be held in the register.
virtual int32_t ConstantValue() const;
virtual int32_t ConstantValueLo() const;
virtual int32_t ConstantValueHi() const;
bool IsZero() const {
return IsPreciseConstant() && ConstantValue() == 0;
}
bool IsOne() const {
return IsPreciseConstant() && ConstantValue() == 1;
}
bool IsConstantChar() const {
return IsConstant() && ConstantValue() >= 0 &&
ConstantValue() <= std::numeric_limits<jchar>::max();
}
bool IsConstantByte() const {
return IsConstant() &&
ConstantValue() >= std::numeric_limits<jbyte>::min() &&
ConstantValue() <= std::numeric_limits<jbyte>::max();
}
bool IsConstantShort() const {
return IsConstant() &&
ConstantValue() >= std::numeric_limits<jshort>::min() &&
ConstantValue() <= std::numeric_limits<jshort>::max();
}
inline virtual bool IsConstantTypes() const { return true; }
};
class PreciseConstType : public ConstantType {
public:
PreciseConstType(uint32_t constat, uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: ConstantType(constat, cache_id) {
}
bool IsPreciseConstant() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class PreciseConstLoType : public ConstantType {
public:
PreciseConstLoType(uint32_t constat, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: ConstantType(constat, cache_id) {
}
bool IsPreciseConstantLo() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class PreciseConstHiType : public ConstantType {
public:
PreciseConstHiType(uint32_t constat, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: ConstantType(constat, cache_id) {
}
bool IsPreciseConstantHi() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class ImpreciseConstType : public ConstantType {
public:
ImpreciseConstType(uint32_t constat, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsImpreciseConstant() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class ImpreciseConstLoType : public ConstantType {
public:
ImpreciseConstLoType(uint32_t constat, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : ConstantType(constat, cache_id) {
}
bool IsImpreciseConstantLo() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class ImpreciseConstHiType : public ConstantType {
public:
ImpreciseConstHiType(uint32_t constat, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : ConstantType(constat, cache_id) {
}
bool IsImpreciseConstantHi() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class UninitializedType : public RegType {
public:
UninitializedType(mirror::Class* klass, std::string& descriptor, uint32_t allocation_pc,
uint16_t cache_id);
inline virtual ~UninitializedType() {
}
uint32_t GetAllocationPc() const {
DCHECK(IsUninitializedTypes());
return allocation_pc_;
}
virtual void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
const uint32_t allocation_pc_;
};
class UninitialisedReferenceType : public UninitializedType {
public:
UninitialisedReferenceType(mirror::Class* klass, std::string& descriptor, uint32_t allocation_pc,
uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsUninitializedReference() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class UnresolvedUninitializedRefType : public UninitializedType {
public:
UnresolvedUninitializedRefType(std::string& descriptor, uint32_t allocation_pc,
uint16_t cache_id) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsUnresolvedAndUninitializedReference() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class UninitialisedThisReferenceType : public UninitializedType {
public:
UninitialisedThisReferenceType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
inline virtual bool IsUninitializedThisReference() const {
return true;
}
};
class UnresolvedUninitialisedThisRefType : public UninitializedType {
public:
UnresolvedUninitialisedThisRefType(std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsUnresolvedAndUninitializedThisReference() const {
return true;
}
};
class ReferenceType : public RegType {
public:
ReferenceType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsReference() const {
return true;
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
};
class PreciseReferenceType : public RegType {
public:
PreciseReferenceType(mirror::Class* klass, std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsPreciseReference() const {
return true;
}
};
class UnresolvedReferenceType : public RegType {
public:
UnresolvedReferenceType(std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : RegType(NULL, descriptor, cache_id) {
}
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsUnresolvedReference() const {
return true;
}
};
class UnresolvedSuperClass : public RegType {
public:
UnresolvedSuperClass(uint16_t child_id, RegTypeCache* reg_type_cache, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: RegType(NULL, "", cache_id), unresolved_child_id_(child_id),
reg_type_cache_(reg_type_cache) {
}
bool IsUnresolvedSuperClass() const {
return true;
}
uint16_t GetUnresolvedSuperClassChildId() const {
DCHECK(IsUnresolvedSuperClass());
return static_cast<uint16_t>(unresolved_child_id_ & 0xFFFF);
}
void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
const uint16_t unresolved_child_id_;
const RegTypeCache* const reg_type_cache_;
};
class UnresolvedMergedType : public RegType {
public:
UnresolvedMergedType(uint16_t left_id, uint16_t right_id, const RegTypeCache* reg_type_cache, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: RegType(NULL, "", cache_id), reg_type_cache_(reg_type_cache) ,merged_types_(left_id, right_id) {
}
// The top of a tree of merged types.
std::pair<uint16_t, uint16_t> GetTopMergedTypes() const {
DCHECK(IsUnresolvedMergedReference());
return merged_types_;
}
// The complete set of merged types.
std::set<uint16_t> GetMergedTypes() const;
bool IsUnresolvedMergedReference() const {
return true;
}
void CheckInvariants() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
const RegTypeCache* const reg_type_cache_;
const std::pair<uint16_t, uint16_t> merged_types_;
};
std::ostream& operator<<(std::ostream& os, const RegType& rhs)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
} // namespace verifier
} // namespace art
#endif // ART_SRC_VERIFIER_REG_TYPE_H_