1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Slightly adapted for inclusion in V8. 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved. 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_BASE_SAFE_MATH_H_ 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_BASE_SAFE_MATH_H_ 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/safe_math_impl.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CheckedNumeric implements all the logic and operators for detecting integer 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// boundary conditions such as overflow, underflow, and invalid conversions. 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The CheckedNumeric type implicitly converts from floating point and integer 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// data types, and contains overloads for basic arithmetic operations (i.e.: +, 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -, *, /, %). 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The following methods convert from CheckedNumeric to standard numeric values: 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// IsValid() - Returns true if the underlying numeric value is valid (i.e. has 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// has not wrapped and is not the result of an invalid conversion). 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ValueOrDie() - Returns the underlying value. If the state is not valid this 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// call will crash on a CHECK. 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ValueOrDefault() - Returns the current value, or the supplied default if the 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// state is not valid. 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ValueFloating() - Returns the underlying floating point value (valid only 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// only for floating point CheckedNumeric types). 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Bitwise operations are explicitly not supported, because correct 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// operations are explicitly not supported because they could result in a crash 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on a CHECK condition. You should use patterns like the following for these 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// operations: 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Bitwise operation: 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CheckedNumeric<int> checked_int = untrusted_input_value; 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// int x = checked_int.ValueOrDefault(0) | kFlagValues; 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Comparison: 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CheckedNumeric<size_t> checked_size; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CheckedNumeric<int> checked_size = untrusted_input_value; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// checked_size = checked_size + HEADER LENGTH; 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Do stuff... 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T> 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CheckedNumeric { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef T type; 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric() {} 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy constructor. 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric(const CheckedNumeric<Src>& rhs) 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : state_(rhs.ValueUnsafe(), rhs.validity()) {} 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric(Src value, RangeConstraint validity) 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : state_(value, validity) {} 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is not an explicit constructor because we implicitly upgrade regular 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // numerics to CheckedNumerics to make them easier to use. 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric(Src value) // NOLINT 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : state_(value) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument must be numeric. 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(std::numeric_limits<Src>::is_specialized); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // IsValid() is the public API to test if a CheckedNumeric is currently valid. 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValid() const { return validity() == RANGE_VALID; } 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ValueOrDie() The primary accessor for the underlying value. If the current 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // state is not valid it will CHECK and crash. 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T ValueOrDie() const { 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(IsValid()); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return state_.value(); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ValueOrDefault(T default_value) A convenience method that returns the 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // current value if the state is valid, and the supplied default_value for 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // any other state. 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T ValueOrDefault(T default_value) const { 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return IsValid() ? state_.value() : default_value; 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ValueFloating() - Since floating point values include their validity state, 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we provide an easy method for extracting them directly, without a risk of 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // crashing on a CHECK. 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T ValueFloating() const { 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Argument must be a floating-point value. 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(std::numeric_limits<T>::is_iec559); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<T>::cast(*this).ValueUnsafe(); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tests and to avoid a big matrix of friend operator overloads. But the 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values it returns are likely to change in the future. 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns: current validity state (i.e. valid, overflow, underflow, nan). 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // saturation/wrapping so we can expose this state consistently and implement 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // saturated arithmetic. 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RangeConstraint validity() const { return state_.validity(); } 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for tests and to avoid a big matrix of friend operator overloads. But the 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values it returns are likely to change in the future. 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns: the raw numeric value, regardless of the current state. 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // saturation/wrapping so we can expose this state consistently and implement 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // saturated arithmetic. 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T ValueUnsafe() const { return state_.value(); } 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prototypes for the supported arithmetic operator overloads. 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> CheckedNumeric& operator+=(Src rhs); 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> CheckedNumeric& operator-=(Src rhs); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> CheckedNumeric& operator*=(Src rhs); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> CheckedNumeric& operator/=(Src rhs); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> CheckedNumeric& operator%=(Src rhs); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric operator-() const { 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RangeConstraint validity; 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T value = CheckedNeg(state_.value(), &validity); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Negation is always valid for floating point. 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (std::numeric_limits<T>::is_iec559) 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<T>(value); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch validity = GetRangeConstraint(state_.validity() | validity); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<T>(value, validity); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric Abs() const { 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RangeConstraint validity; 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T value = CheckedAbs(state_.value(), &validity); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Absolute value is always valid for floating point. 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (std::numeric_limits<T>::is_iec559) 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<T>(value); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch validity = GetRangeConstraint(state_.validity() | validity); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<T>(value, validity); 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric& operator++() { 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *this += 1; 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return *this; 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric operator++(int) { 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric value = *this; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *this += 1; 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return value; 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric& operator--() { 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *this -= 1; 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return *this; 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric operator--(int) { 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric value = *this; 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *this -= 1; 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return value; 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // These static methods behave like a convenience cast operator targeting 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the desired CheckedNumeric type. As an optimization, a reference is 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // returned when Src is the same type as T. 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CheckedNumeric<T> cast( 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Src u, 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typename enable_if<std::numeric_limits<Src>::is_specialized, int>::type = 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0) { 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return u; 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CheckedNumeric<T> cast( 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CheckedNumeric<Src>& u, 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typename enable_if<!is_same<Src, T>::value, int>::type = 0) { 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return u; 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const CheckedNumeric<T>& cast(const CheckedNumeric<T>& u) { return u; } 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumericState<T> state_; 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This is the boilerplate for the standard arithmetic operator overloads. A 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// macro isn't the prettiest solution, but it beats rewriting these five times. 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Some details worth noting are: 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * We apply the standard arithmetic promotions. 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * We skip range checks for floating points. 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * We skip range checks for destination integers with sufficient range. 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(jschuh): extract these out into templates. 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename T> \ 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \ 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef typename ArithmeticPromotion<T>::type Promotion; \ 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch /* Floating point always takes the fast path */ \ 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (std::numeric_limits<T>::is_iec559) \ 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>( \ 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetRangeConstraint(rhs.validity() | lhs.validity())); \ 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RangeConstraint validity = RANGE_VALID; \ 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch T result = Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \ 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<Promotion>(rhs.ValueUnsafe()), \ 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &validity); \ 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>( \ 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result, \ 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \ 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } \ 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename T> \ 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename Src> \ 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *this = CheckedNumeric<T>::cast(*this) OP CheckedNumeric<Src>::cast(rhs); \ 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return *this; \ 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } \ 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch /* Binary arithmetic operator for CheckedNumeric of different type. */ \ 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename T, typename Src> \ 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \ 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>( \ 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetRangeConstraint(rhs.validity() | lhs.validity())); \ 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>::cast(lhs) \ 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OP CheckedNumeric<Promotion>::cast(rhs); \ 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } \ 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename T, typename Src> \ 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CheckedNumeric<T>& lhs, Src rhs) { \ 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, \ 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lhs.validity()); \ 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>::cast(lhs) \ 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OP CheckedNumeric<Promotion>::cast(rhs); \ 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } \ 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch /* Binary arithmetic operator for right numeric and left CheckedNumeric. */ \ 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template <typename T, typename Src> \ 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Src lhs, const CheckedNumeric<T>& rhs) { \ 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), \ 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rhs.validity()); \ 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CheckedNumeric<Promotion>::cast(lhs) \ 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OP CheckedNumeric<Promotion>::cast(rhs); \ 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, += ) 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -= ) 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *= ) 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /= ) 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %= ) 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef BASE_NUMERIC_ARITHMETIC_OPERATORS 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace internal 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochusing internal::CheckedNumeric; 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace base 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_BASE_SAFE_MATH_H_ 277