| /* |
| * Copyright (C) 2011 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_RUNTIME_PRIMITIVE_H_ |
| #define ART_RUNTIME_PRIMITIVE_H_ |
| |
| #include <sys/types.h> |
| |
| #include "base/logging.h" |
| #include "base/macros.h" |
| |
| namespace art { |
| |
| static constexpr size_t kObjectReferenceSize = 4; |
| |
| constexpr size_t ComponentSizeShiftWidth(size_t component_size) { |
| return component_size == 1u ? 0u : |
| component_size == 2u ? 1u : |
| component_size == 4u ? 2u : |
| component_size == 8u ? 3u : 0u; |
| } |
| |
| class Primitive { |
| public: |
| enum Type { |
| kPrimNot = 0, |
| kPrimBoolean, |
| kPrimByte, |
| kPrimChar, |
| kPrimShort, |
| kPrimInt, |
| kPrimLong, |
| kPrimFloat, |
| kPrimDouble, |
| kPrimVoid, |
| kPrimLast = kPrimVoid |
| }; |
| |
| static Type GetType(char type) { |
| switch (type) { |
| case 'B': |
| return kPrimByte; |
| case 'C': |
| return kPrimChar; |
| case 'D': |
| return kPrimDouble; |
| case 'F': |
| return kPrimFloat; |
| case 'I': |
| return kPrimInt; |
| case 'J': |
| return kPrimLong; |
| case 'S': |
| return kPrimShort; |
| case 'Z': |
| return kPrimBoolean; |
| case 'V': |
| return kPrimVoid; |
| default: |
| return kPrimNot; |
| } |
| } |
| |
| static size_t ComponentSizeShift(Type type) { |
| switch (type) { |
| case kPrimVoid: |
| case kPrimBoolean: |
| case kPrimByte: return 0; |
| case kPrimChar: |
| case kPrimShort: return 1; |
| case kPrimInt: |
| case kPrimFloat: return 2; |
| case kPrimLong: |
| case kPrimDouble: return 3; |
| case kPrimNot: return ComponentSizeShiftWidth(kObjectReferenceSize); |
| default: |
| LOG(FATAL) << "Invalid type " << static_cast<int>(type); |
| return 0; |
| } |
| } |
| |
| static size_t ComponentSize(Type type) { |
| switch (type) { |
| case kPrimVoid: return 0; |
| case kPrimBoolean: |
| case kPrimByte: return 1; |
| case kPrimChar: |
| case kPrimShort: return 2; |
| case kPrimInt: |
| case kPrimFloat: return 4; |
| case kPrimLong: |
| case kPrimDouble: return 8; |
| case kPrimNot: return kObjectReferenceSize; |
| default: |
| LOG(FATAL) << "Invalid type " << static_cast<int>(type); |
| return 0; |
| } |
| } |
| |
| static const char* Descriptor(Type type) { |
| switch (type) { |
| case kPrimBoolean: |
| return "Z"; |
| case kPrimByte: |
| return "B"; |
| case kPrimChar: |
| return "C"; |
| case kPrimShort: |
| return "S"; |
| case kPrimInt: |
| return "I"; |
| case kPrimFloat: |
| return "F"; |
| case kPrimLong: |
| return "J"; |
| case kPrimDouble: |
| return "D"; |
| case kPrimVoid: |
| return "V"; |
| default: |
| LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type); |
| return nullptr; |
| } |
| } |
| |
| static const char* PrettyDescriptor(Type type); |
| |
| // Returns the descriptor corresponding to the boxed type of |type|. |
| static const char* BoxedDescriptor(Type type); |
| |
| static bool IsFloatingPointType(Type type) { |
| return type == kPrimFloat || type == kPrimDouble; |
| } |
| |
| static bool IsIntegralType(Type type) { |
| // The Java language does not allow treating boolean as an integral type but |
| // our bit representation makes it safe. |
| switch (type) { |
| case kPrimBoolean: |
| case kPrimByte: |
| case kPrimChar: |
| case kPrimShort: |
| case kPrimInt: |
| case kPrimLong: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| // Return true if |type| is an numeric type. |
| static constexpr bool IsNumericType(Type type) { |
| switch (type) { |
| case Primitive::Type::kPrimNot: return false; |
| case Primitive::Type::kPrimBoolean: return false; |
| case Primitive::Type::kPrimByte: return true; |
| case Primitive::Type::kPrimChar: return false; |
| case Primitive::Type::kPrimShort: return true; |
| case Primitive::Type::kPrimInt: return true; |
| case Primitive::Type::kPrimLong: return true; |
| case Primitive::Type::kPrimFloat: return true; |
| case Primitive::Type::kPrimDouble: return true; |
| case Primitive::Type::kPrimVoid: return false; |
| } |
| } |
| |
| // Returns true if it is possible to widen type |from| to type |to|. Both |from| and |
| // |to| should be numeric primitive types. |
| static bool IsWidenable(Type from, Type to) { |
| static_assert(Primitive::Type::kPrimByte < Primitive::Type::kPrimShort, "Bad ordering"); |
| static_assert(Primitive::Type::kPrimShort < Primitive::Type::kPrimInt, "Bad ordering"); |
| static_assert(Primitive::Type::kPrimInt < Primitive::Type::kPrimLong, "Bad ordering"); |
| static_assert(Primitive::Type::kPrimLong < Primitive::Type::kPrimFloat, "Bad ordering"); |
| static_assert(Primitive::Type::kPrimFloat < Primitive::Type::kPrimDouble, "Bad ordering"); |
| // Widening is only applicable between numeric types, like byte |
| // and int. Non-numeric types, such as boolean, cannot be widened. |
| return IsNumericType(from) && IsNumericType(to) && from <= to; |
| } |
| |
| static bool IsIntOrLongType(Type type) { |
| return type == kPrimInt || type == kPrimLong; |
| } |
| |
| static bool Is64BitType(Type type) { |
| return type == kPrimLong || type == kPrimDouble; |
| } |
| |
| // Return the general kind of `type`, fusing integer-like types as kPrimInt. |
| static Type PrimitiveKind(Type type) { |
| switch (type) { |
| case kPrimBoolean: |
| case kPrimByte: |
| case kPrimShort: |
| case kPrimChar: |
| case kPrimInt: |
| return kPrimInt; |
| default: |
| return type; |
| } |
| } |
| |
| static int64_t MinValueOfIntegralType(Type type) { |
| switch (type) { |
| case kPrimBoolean: |
| return std::numeric_limits<bool>::min(); |
| case kPrimByte: |
| return std::numeric_limits<int8_t>::min(); |
| case kPrimChar: |
| return std::numeric_limits<uint16_t>::min(); |
| case kPrimShort: |
| return std::numeric_limits<int16_t>::min(); |
| case kPrimInt: |
| return std::numeric_limits<int32_t>::min(); |
| case kPrimLong: |
| return std::numeric_limits<int64_t>::min(); |
| default: |
| LOG(FATAL) << "non integral type"; |
| } |
| return 0; |
| } |
| |
| static int64_t MaxValueOfIntegralType(Type type) { |
| switch (type) { |
| case kPrimBoolean: |
| return std::numeric_limits<bool>::max(); |
| case kPrimByte: |
| return std::numeric_limits<int8_t>::max(); |
| case kPrimChar: |
| return std::numeric_limits<uint16_t>::max(); |
| case kPrimShort: |
| return std::numeric_limits<int16_t>::max(); |
| case kPrimInt: |
| return std::numeric_limits<int32_t>::max(); |
| case kPrimLong: |
| return std::numeric_limits<int64_t>::max(); |
| default: |
| LOG(FATAL) << "non integral type"; |
| } |
| return 0; |
| } |
| |
| private: |
| DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive); |
| }; |
| |
| std::ostream& operator<<(std::ostream& os, const Primitive::Type& state); |
| |
| } // namespace art |
| |
| #endif // ART_RUNTIME_PRIMITIVE_H_ |