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