Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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_PRIMITIVE_H_
     18 #define ART_RUNTIME_PRIMITIVE_H_
     19 
     20 #include <sys/types.h>
     21 
     22 #include "base/logging.h"
     23 #include "base/macros.h"
     24 
     25 namespace art {
     26 
     27 static constexpr size_t kObjectReferenceSize = 4;
     28 
     29 constexpr size_t ComponentSizeShiftWidth(size_t component_size) {
     30   return component_size == 1u ? 0u :
     31       component_size == 2u ? 1u :
     32           component_size == 4u ? 2u :
     33               component_size == 8u ? 3u : 0u;
     34 }
     35 
     36 class Primitive {
     37  public:
     38   enum Type {
     39     kPrimNot = 0,
     40     kPrimBoolean,
     41     kPrimByte,
     42     kPrimChar,
     43     kPrimShort,
     44     kPrimInt,
     45     kPrimLong,
     46     kPrimFloat,
     47     kPrimDouble,
     48     kPrimVoid,
     49     kPrimLast = kPrimVoid
     50   };
     51 
     52   static Type GetType(char type) {
     53     switch (type) {
     54       case 'B':
     55         return kPrimByte;
     56       case 'C':
     57         return kPrimChar;
     58       case 'D':
     59         return kPrimDouble;
     60       case 'F':
     61         return kPrimFloat;
     62       case 'I':
     63         return kPrimInt;
     64       case 'J':
     65         return kPrimLong;
     66       case 'S':
     67         return kPrimShort;
     68       case 'Z':
     69         return kPrimBoolean;
     70       case 'V':
     71         return kPrimVoid;
     72       default:
     73         return kPrimNot;
     74     }
     75   }
     76 
     77   static size_t ComponentSizeShift(Type type) {
     78     switch (type) {
     79       case kPrimVoid:
     80       case kPrimBoolean:
     81       case kPrimByte:    return 0;
     82       case kPrimChar:
     83       case kPrimShort:   return 1;
     84       case kPrimInt:
     85       case kPrimFloat:   return 2;
     86       case kPrimLong:
     87       case kPrimDouble:  return 3;
     88       case kPrimNot:     return ComponentSizeShiftWidth(kObjectReferenceSize);
     89       default:
     90         LOG(FATAL) << "Invalid type " << static_cast<int>(type);
     91         return 0;
     92     }
     93   }
     94 
     95   static size_t ComponentSize(Type type) {
     96     switch (type) {
     97       case kPrimVoid:    return 0;
     98       case kPrimBoolean:
     99       case kPrimByte:    return 1;
    100       case kPrimChar:
    101       case kPrimShort:   return 2;
    102       case kPrimInt:
    103       case kPrimFloat:   return 4;
    104       case kPrimLong:
    105       case kPrimDouble:  return 8;
    106       case kPrimNot:     return kObjectReferenceSize;
    107       default:
    108         LOG(FATAL) << "Invalid type " << static_cast<int>(type);
    109         return 0;
    110     }
    111   }
    112 
    113   static const char* Descriptor(Type type) {
    114     switch (type) {
    115       case kPrimBoolean:
    116         return "Z";
    117       case kPrimByte:
    118         return "B";
    119       case kPrimChar:
    120         return "C";
    121       case kPrimShort:
    122         return "S";
    123       case kPrimInt:
    124         return "I";
    125       case kPrimFloat:
    126         return "F";
    127       case kPrimLong:
    128         return "J";
    129       case kPrimDouble:
    130         return "D";
    131       case kPrimVoid:
    132         return "V";
    133       default:
    134         LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
    135         return nullptr;
    136     }
    137   }
    138 
    139   static const char* PrettyDescriptor(Type type);
    140 
    141   // Returns the descriptor corresponding to the boxed type of |type|.
    142   static const char* BoxedDescriptor(Type type);
    143 
    144   static bool IsFloatingPointType(Type type) {
    145     return type == kPrimFloat || type == kPrimDouble;
    146   }
    147 
    148   static bool IsIntegralType(Type type) {
    149     // The Java language does not allow treating boolean as an integral type but
    150     // our bit representation makes it safe.
    151     switch (type) {
    152       case kPrimBoolean:
    153       case kPrimByte:
    154       case kPrimChar:
    155       case kPrimShort:
    156       case kPrimInt:
    157       case kPrimLong:
    158         return true;
    159       default:
    160         return false;
    161     }
    162   }
    163 
    164   // Return true if |type| is an numeric type.
    165   static constexpr bool IsNumericType(Type type) {
    166     switch (type) {
    167       case Primitive::Type::kPrimNot: return false;
    168       case Primitive::Type::kPrimBoolean: return false;
    169       case Primitive::Type::kPrimByte: return true;
    170       case Primitive::Type::kPrimChar: return false;
    171       case Primitive::Type::kPrimShort: return true;
    172       case Primitive::Type::kPrimInt: return true;
    173       case Primitive::Type::kPrimLong: return true;
    174       case Primitive::Type::kPrimFloat: return true;
    175       case Primitive::Type::kPrimDouble: return true;
    176       case Primitive::Type::kPrimVoid: return false;
    177     }
    178   }
    179 
    180   // Returns true if it is possible to widen type |from| to type |to|. Both |from| and
    181   // |to| should be numeric primitive types.
    182   static bool IsWidenable(Type from, Type to) {
    183     static_assert(Primitive::Type::kPrimByte < Primitive::Type::kPrimShort, "Bad ordering");
    184     static_assert(Primitive::Type::kPrimShort < Primitive::Type::kPrimInt, "Bad ordering");
    185     static_assert(Primitive::Type::kPrimInt < Primitive::Type::kPrimLong, "Bad ordering");
    186     static_assert(Primitive::Type::kPrimLong < Primitive::Type::kPrimFloat, "Bad ordering");
    187     static_assert(Primitive::Type::kPrimFloat < Primitive::Type::kPrimDouble, "Bad ordering");
    188     // Widening is only applicable between numeric types, like byte
    189     // and int. Non-numeric types, such as boolean, cannot be widened.
    190     return IsNumericType(from) && IsNumericType(to) && from <= to;
    191   }
    192 
    193   static bool IsIntOrLongType(Type type) {
    194     return type == kPrimInt || type == kPrimLong;
    195   }
    196 
    197   static bool Is64BitType(Type type) {
    198     return type == kPrimLong || type == kPrimDouble;
    199   }
    200 
    201   // Return the general kind of `type`, fusing integer-like types as kPrimInt.
    202   static Type PrimitiveKind(Type type) {
    203     switch (type) {
    204       case kPrimBoolean:
    205       case kPrimByte:
    206       case kPrimShort:
    207       case kPrimChar:
    208       case kPrimInt:
    209         return kPrimInt;
    210       default:
    211         return type;
    212     }
    213   }
    214 
    215   static int64_t MinValueOfIntegralType(Type type) {
    216     switch (type) {
    217       case kPrimBoolean:
    218         return std::numeric_limits<bool>::min();
    219       case kPrimByte:
    220         return std::numeric_limits<int8_t>::min();
    221       case kPrimChar:
    222         return std::numeric_limits<uint16_t>::min();
    223       case kPrimShort:
    224         return std::numeric_limits<int16_t>::min();
    225       case kPrimInt:
    226         return std::numeric_limits<int32_t>::min();
    227       case kPrimLong:
    228         return std::numeric_limits<int64_t>::min();
    229       default:
    230         LOG(FATAL) << "non integral type";
    231     }
    232     return 0;
    233   }
    234 
    235   static int64_t MaxValueOfIntegralType(Type type) {
    236     switch (type) {
    237       case kPrimBoolean:
    238         return std::numeric_limits<bool>::max();
    239       case kPrimByte:
    240         return std::numeric_limits<int8_t>::max();
    241       case kPrimChar:
    242         return std::numeric_limits<uint16_t>::max();
    243       case kPrimShort:
    244         return std::numeric_limits<int16_t>::max();
    245       case kPrimInt:
    246         return std::numeric_limits<int32_t>::max();
    247       case kPrimLong:
    248         return std::numeric_limits<int64_t>::max();
    249       default:
    250         LOG(FATAL) << "non integral type";
    251     }
    252     return 0;
    253   }
    254 
    255  private:
    256   DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
    257 };
    258 
    259 std::ostream& operator<<(std::ostream& os, const Primitive::Type& state);
    260 
    261 }  // namespace art
    262 
    263 #endif  // ART_RUNTIME_PRIMITIVE_H_
    264