Home | History | Annotate | Download | only in verifier
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
     18 #define ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
     19 
     20 #include "reg_type.h"
     21 
     22 #include "base/casts.h"
     23 #include "base/scoped_arena_allocator.h"
     24 #include "mirror/class.h"
     25 
     26 namespace art {
     27 namespace verifier {
     28 
     29 inline bool RegType::CanAccess(const RegType& other) const {
     30   if (Equals(other)) {
     31     return true;  // Trivial accessibility.
     32   } else {
     33     bool this_unresolved = IsUnresolvedTypes();
     34     bool other_unresolved = other.IsUnresolvedTypes();
     35     if (!this_unresolved && !other_unresolved) {
     36       return GetClass()->CanAccess(other.GetClass());
     37     } else if (!other_unresolved) {
     38       return other.GetClass()->IsPublic();  // Be conservative, only allow if other is public.
     39     } else {
     40       return false;  // More complicated test not possible on unresolved types, be conservative.
     41     }
     42   }
     43 }
     44 
     45 inline bool RegType::CanAccessMember(mirror::Class* klass, uint32_t access_flags) const {
     46   if ((access_flags & kAccPublic) != 0) {
     47     return true;
     48   }
     49   if (!IsUnresolvedTypes()) {
     50     return GetClass()->CanAccessMember(klass, access_flags);
     51   } else {
     52     return false;  // More complicated test not possible on unresolved types, be conservative.
     53   }
     54 }
     55 
     56 inline bool RegType::IsConstantBoolean() const {
     57   if (!IsConstant()) {
     58     return false;
     59   } else {
     60     const ConstantType* const_val = down_cast<const ConstantType*>(this);
     61     return const_val->ConstantValue() >= 0 && const_val->ConstantValue() <= 1;
     62   }
     63 }
     64 
     65 inline bool RegType::AssignableFrom(const RegType& lhs, const RegType& rhs, bool strict) {
     66   if (lhs.Equals(rhs)) {
     67     return true;
     68   } else {
     69     if (lhs.IsBoolean()) {
     70       return rhs.IsBooleanTypes();
     71     } else if (lhs.IsByte()) {
     72       return rhs.IsByteTypes();
     73     } else if (lhs.IsShort()) {
     74       return rhs.IsShortTypes();
     75     } else if (lhs.IsChar()) {
     76       return rhs.IsCharTypes();
     77     } else if (lhs.IsInteger()) {
     78       return rhs.IsIntegralTypes();
     79     } else if (lhs.IsFloat()) {
     80       return rhs.IsFloatTypes();
     81     } else if (lhs.IsLongLo()) {
     82       return rhs.IsLongTypes();
     83     } else if (lhs.IsDoubleLo()) {
     84       return rhs.IsDoubleTypes();
     85     } else if (lhs.IsConflict()) {
     86       LOG(WARNING) << "RegType::AssignableFrom lhs is Conflict!";
     87       return false;
     88     } else {
     89       CHECK(lhs.IsReferenceTypes())
     90           << "Unexpected register type in IsAssignableFrom: '"
     91           << lhs << "' := '" << rhs << "'";
     92       if (rhs.IsZero()) {
     93         return true;  // All reference types can be assigned null.
     94       } else if (!rhs.IsReferenceTypes()) {
     95         return false;  // Expect rhs to be a reference type.
     96       } else if (lhs.IsUninitializedTypes() || rhs.IsUninitializedTypes()) {
     97         // Uninitialized types are only allowed to be assigned to themselves.
     98         // TODO: Once we have a proper "reference" super type, this needs to be extended.
     99         return false;
    100       } else if (lhs.IsJavaLangObject()) {
    101         return true;  // All reference types can be assigned to Object.
    102       } else if (!strict && !lhs.IsUnresolvedTypes() && lhs.GetClass()->IsInterface()) {
    103         // If we're not strict allow assignment to any interface, see comment in ClassJoin.
    104         return true;
    105       } else if (lhs.IsJavaLangObjectArray()) {
    106         return rhs.IsObjectArrayTypes();  // All reference arrays may be assigned to Object[]
    107       } else if (lhs.HasClass() && rhs.HasClass() &&
    108                  lhs.GetClass()->IsAssignableFrom(rhs.GetClass())) {
    109         // We're assignable from the Class point-of-view.
    110         return true;
    111       } else {
    112         // Unresolved types are only assignable for null and equality.
    113         return false;
    114       }
    115     }
    116   }
    117 }
    118 
    119 inline bool RegType::IsAssignableFrom(const RegType& src) const {
    120   return AssignableFrom(*this, src, false);
    121 }
    122 
    123 inline bool RegType::IsStrictlyAssignableFrom(const RegType& src) const {
    124   return AssignableFrom(*this, src, true);
    125 }
    126 
    127 inline const DoubleHiType* DoubleHiType::GetInstance() {
    128   DCHECK(instance_ != nullptr);
    129   return instance_;
    130 }
    131 
    132 inline const DoubleLoType* DoubleLoType::GetInstance() {
    133   DCHECK(instance_ != nullptr);
    134   return instance_;
    135 }
    136 
    137 inline const LongHiType* LongHiType::GetInstance() {
    138   DCHECK(instance_ != nullptr);
    139   return instance_;
    140 }
    141 
    142 inline const LongLoType* LongLoType::GetInstance() {
    143   DCHECK(instance_ != nullptr);
    144   return instance_;
    145 }
    146 
    147 inline const FloatType* FloatType::GetInstance() {
    148   DCHECK(instance_ != nullptr);
    149   return instance_;
    150 }
    151 
    152 inline const CharType* CharType::GetInstance() {
    153   DCHECK(instance_ != nullptr);
    154   return instance_;
    155 }
    156 
    157 inline const ShortType* ShortType::GetInstance() {
    158   DCHECK(instance_ != nullptr);
    159   return instance_;
    160 }
    161 
    162 inline const ByteType* ByteType::GetInstance() {
    163   DCHECK(instance_ != nullptr);
    164   return instance_;
    165 }
    166 
    167 
    168 inline const IntegerType* IntegerType::GetInstance() {
    169   DCHECK(instance_ != nullptr);
    170   return instance_;
    171 }
    172 
    173 inline const BooleanType* BooleanType::GetInstance() {
    174   DCHECK(BooleanType::instance_ != nullptr);
    175   return BooleanType::instance_;
    176 }
    177 
    178 inline const ConflictType* ConflictType::GetInstance() {
    179   DCHECK(instance_ != nullptr);
    180   return instance_;
    181 }
    182 
    183 inline const UndefinedType* UndefinedType::GetInstance() {
    184   DCHECK(instance_ != nullptr);
    185   return instance_;
    186 }
    187 
    188 inline void* RegType::operator new(size_t size, ScopedArenaAllocator* arena) {
    189   return arena->Alloc(size, kArenaAllocMisc);
    190 }
    191 
    192 }  // namespace verifier
    193 }  // namespace art
    194 
    195 #endif  // ART_RUNTIME_VERIFIER_REG_TYPE_INL_H_
    196