--- /dev/null 2017-08-13 17:24:39.427578209 -0400 +++ new/src/share/vm/metaprogramming/integerTypes.hpp 2017-08-16 01:19:16.966657882 -0400 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP +#define SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP + +#include "memory/allocation.hpp" +#include "metaprogramming/enableIf.hpp" +#include "metaprogramming/integralConstant.hpp" +#include "metaprogramming/isFloatingPoint.hpp" +#include "metaprogramming/isIntegral.hpp" +#include "metaprogramming/isRegisteredEnum.hpp" +#include "utilities/debug.hpp" + +class IntegerTypes : public AllStatic { +public: + // Return a value of type T with the same representation as x. + // + // T and U must be of the same size. + // + // At least one of T or U must be an integral type. The other must + // be an integral, floating point, or pointer type. + template static T cast(U x); + + // Support thin wrappers over primitive types. + // If derived from TrueType, provides representational conversion + // from T to some other type. When true, must provide + // - Value: typedef for T. + // - Decayed: typedef for decayed type. + // - static Decayed decay(T x): return value of type Decayed with + // the same representation as x. + // - static T recover(Decayed x): return a value of type T with the + // same representation as x. + template struct Translate : public FalseType {}; + +private: + + template + struct Cast; + + template static T cast_using_union(U x); +}; + +// Return an object of type T with the same value representation as x. +// +// T and U must be of the same size. It is expected that one of T and +// U is an integral type, and the other is an integral type, a +// (registered) enum type, or a floating point type +// +// This implementation uses the "union trick", which seems to be the +// best of a bad set of options. Though technically undefined +// behavior, it is widely and well supported, producing good code. In +// some cases, such as gcc, that support is explicitly documented. +// +// Using memcpy is the correct method, but some compilers produce +// wretched code for that method, even at maximal optimization levels. +// +// Using static_cast is only possible for integral and enum types, not +// for floating point types. And for integral and enum conversions, +// static_cast has unspecified or implementation-defined behavior for +// some cases. C++11 can be used to avoid most or all +// of those unspecified or implementation-defined issues, though that +// may require multi-step conversions. +// +// Using reinterpret_cast of references has undefined behavior for +// many cases, and there is much less empirical basis for its use, as +// compared to the union trick. +template +inline T IntegerTypes::cast_using_union(U x) { + STATIC_ASSERT(sizeof(T) == sizeof(U)); + union { T t; U u; }; + u = x; + return t; +} + +////////////////////////////////////////////////////////////////////////////// +// cast(x) +// +// Cast + +// Give an informative error if the sizes differ. +template +struct IntegerTypes::Cast VALUE_OBJ_CLASS_SPEC { + STATIC_ASSERT(sizeof(T) == sizeof(U)); +}; + +// Conversion between integral types. +template +struct IntegerTypes::Cast< + T, U, true, + typename EnableIf::value && IsIntegral::value>::type> + VALUE_OBJ_CLASS_SPEC +{ + T operator()(U x) const { return cast_using_union(x); } +}; + +// Convert an enum or floating point value to an integer value. +template +struct IntegerTypes::Cast< + T, U, true, + typename EnableIf::value && + (IsRegisteredEnum::value || + IsFloatingPoint::value)>::type> + VALUE_OBJ_CLASS_SPEC +{ + T operator()(U x) const { return cast_using_union(x); } +}; + +// Convert an integer to an enum or floating point value. +template +struct IntegerTypes::Cast< + T, U, true, + typename EnableIf::value && + (IsRegisteredEnum::value || + IsFloatingPoint::value)>::type> + VALUE_OBJ_CLASS_SPEC +{ + T operator()(U x) const { return cast_using_union(x); } +}; + +// Convert a pointer to an integral value. +template +struct IntegerTypes::Cast< + T, U*, true, + typename EnableIf::value>::type> + VALUE_OBJ_CLASS_SPEC +{ + T operator()(U* x) const { return reinterpret_cast(x); } +}; + +// Convert an integral value to a pointer. +template +struct IntegerTypes::Cast< + T*, U, true, + typename EnableIf::value>::type> + VALUE_OBJ_CLASS_SPEC +{ + T* operator()(U x) const { return reinterpret_cast(x); } +}; + +template +inline T IntegerTypes::cast(U x) { + return Cast()(x); +} + +#endif // SHARE_VM_METAPROGRAMMING_INTEGERTYPES_HPP