Path: blob/master/src/hotspot/share/metaprogramming/primitiveConversions.hpp
40930 views
/*1* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_METAPROGRAMMING_PRIMITIVECONVERSIONS_HPP25#define SHARE_METAPROGRAMMING_PRIMITIVECONVERSIONS_HPP2627#include "memory/allStatic.hpp"28#include "metaprogramming/enableIf.hpp"29#include "utilities/globalDefinitions.hpp"30#include <type_traits>3132class PrimitiveConversions : public AllStatic {3334// True if types are the same size and either is integral.35template<typename To, typename From>36static constexpr bool check_cast() {37return (sizeof(To) == sizeof(From)) &&38(std::is_integral<To>::value || std::is_integral<From>::value);39}4041public:42// template<typename To, typename From> To cast(From x)43//44// Return a value of type To with the same value representation as x.45//46// To and From must be of the same size.47//48// At least one of To or From must be an integral type. The other must49// be an integral, enum, floating point, or pointer type.5051// integer -> integer52// Use static_cast for conversion. See C++14 4.7 Integral53// conversions. If To is signed and From unsigned, the result is54// implementation-defined. All supported platforms provide two's55// complement behavior, and that behavior is required by C++20.56// Using an lvalue to reference cast (see C++03 3.10/15) involves a57// reinterpret_cast, which prevents constexpr support.58template<typename To, typename From,59ENABLE_IF(sizeof(To) == sizeof(From)),60ENABLE_IF(std::is_integral<To>::value),61ENABLE_IF(std::is_integral<From>::value)>62static constexpr To cast(From x) {63return static_cast<To>(x);64}6566// integer -> enum, enum -> integer67// Use the enum's underlying type for integer -> integer cast.68template<typename To, typename From,69ENABLE_IF(check_cast<To, From>()),70ENABLE_IF(std::is_enum<To>::value)>71static constexpr To cast(From x) {72return static_cast<To>(cast<std::underlying_type_t<To>>(x));73}7475template<typename To, typename From,76ENABLE_IF(check_cast<To, From>()),77ENABLE_IF(std::is_enum<From>::value)>78static constexpr To cast(From x) {79return cast<To>(static_cast<std::underlying_type_t<From>>(x));80}8182// integer -> pointer, pointer -> integer83// Use reinterpret_cast, so no constexpr support.84template<typename To, typename From,85ENABLE_IF(check_cast<To, From>()),86ENABLE_IF(std::is_pointer<To>::value || std::is_pointer<From>::value)>87static To cast(From x) {88return reinterpret_cast<To>(x);89}9091// integer -> floating point, floating point -> integer92// Use the union trick. The union trick is technically UB, but is93// widely and well supported, producing good code. In some cases,94// such as gcc, that support is explicitly documented. Using memcpy95// is the correct method, but some compilers produce wretched code96// for that method, even at maximal optimization levels. Neither97// the union trick nor memcpy provides constexpr support.98template<typename To, typename From,99ENABLE_IF(check_cast<To, From>()),100ENABLE_IF(std::is_floating_point<To>::value ||101std::is_floating_point<From>::value)>102static To cast(From x) {103union { From from; To to; } converter = { x };104return converter.to;105}106107// Support thin wrappers over primitive types.108// If derived from std::true_type, provides representational conversion109// from T to some other type. When true, must provide110// - Value: typedef for T.111// - Decayed: typedef for decayed type.112// - static Decayed decay(T x): return value of type Decayed with113// the same value representation as x.114// - static T recover(Decayed x): return a value of type T with the115// same value representation as x.116template<typename T> struct Translate : public std::false_type {};117};118119// jfloat and jdouble translation to integral types120121template<>122struct PrimitiveConversions::Translate<jdouble> : public std::true_type {123typedef double Value;124typedef int64_t Decayed;125126static Decayed decay(Value x) { return PrimitiveConversions::cast<Decayed>(x); }127static Value recover(Decayed x) { return PrimitiveConversions::cast<Value>(x); }128};129130template<>131struct PrimitiveConversions::Translate<jfloat> : public std::true_type {132typedef float Value;133typedef int32_t Decayed;134135static Decayed decay(Value x) { return PrimitiveConversions::cast<Decayed>(x); }136static Value recover(Decayed x) { return PrimitiveConversions::cast<Value>(x); }137};138139#endif // SHARE_METAPROGRAMMING_PRIMITIVECONVERSIONS_HPP140141142