From 42f2e1fcc0cc5af5c31f649111f18e9e12eccd7f Mon Sep 17 00:00:00 2001 From: Clemens Backes Date: Mon, 9 Mar 2020 12:04:51 +0100 Subject: [PATCH] [API] Use proper C++ methods to implement type checks The {TYPE_CHECK} macro used an ancient pattern to check for assignability, by assigning to a static_casted nullptrs of the respective types. C++11 introduced standard library helpers to express this more naturally. The most direct translation would have been to use {std::is_assignable} or {std::is_convertible} on the pointer types, but in most cases we can be even more strict and force one type to be a proper subtype of the other. The only exception is {ReturnValue}, which allows to assign anything if it's void. R=ulan@chromium.org Bug: v8:10155 Change-Id: I41c1103e0206514c8700c47a0bf107ad704cfc47 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2093497 Reviewed-by: Ulan Degenbaev Commit-Queue: Clemens Backes Cr-Commit-Position: refs/heads/master@{#66695} --- include/v8.h | 80 ++++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/include/v8.h b/include/v8.h index 35e497919e..809e575219 100644 --- a/include/v8.h +++ b/include/v8.h @@ -151,11 +151,6 @@ class ConsoleCallArguments; // --- Handles --- -#define TYPE_CHECK(T, S) \ - while (false) { \ - *(static_cast(0)) = static_cast(0); \ - } - /** * An object reference managed by the v8 garbage collector. * @@ -199,7 +194,7 @@ class Local { * handles. For example, converting from a Local to a * Local. */ - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -365,7 +360,7 @@ class MaybeLocal { template V8_INLINE MaybeLocal(Local that) : val_(reinterpret_cast(*that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } V8_INLINE bool IsEmpty() const { return val_ == nullptr; } @@ -625,11 +620,8 @@ class NonCopyablePersistentTraits { template V8_INLINE static void Copy(const Persistent& source, NonCopyablePersistent* dest) { - Uncompilable(); - } - // TODO(dcarney): come up with a good compile error here. - template V8_INLINE static void Uncompilable() { - TYPE_CHECK(O, Primitive); + static_assert(sizeof(S) < 0, + "NonCopyablePersistentTraits::Copy is not instantiable"); } }; @@ -672,7 +664,7 @@ template class Persistent : public PersistentBase { template V8_INLINE Persistent(Isolate* isolate, Local that) : PersistentBase(PersistentBase::New(isolate, *that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** * Construct a Persistent from a Persistent. @@ -682,7 +674,7 @@ template class Persistent : public PersistentBase { template V8_INLINE Persistent(Isolate* isolate, const Persistent& that) : PersistentBase(PersistentBase::New(isolate, *that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** * The copy constructors and assignment operator create a Persistent @@ -767,7 +759,7 @@ class Global : public PersistentBase { template V8_INLINE Global(Isolate* isolate, Local that) : PersistentBase(PersistentBase::New(isolate, *that)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -778,7 +770,7 @@ class Global : public PersistentBase { template V8_INLINE Global(Isolate* isolate, const PersistentBase& that) : PersistentBase(PersistentBase::New(isolate, that.val_)) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -958,7 +950,7 @@ class TracedGlobal : public TracedReferenceBase { TracedGlobal(Isolate* isolate, Local that) : TracedReferenceBase() { this->val_ = this->New(isolate, that.val_, &this->val_, TracedReferenceBase::kWithDestructor); - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -1081,7 +1073,7 @@ class TracedReference : public TracedReferenceBase { TracedReference(Isolate* isolate, Local that) : TracedReferenceBase() { this->val_ = this->New(isolate, that.val_, &this->val_, TracedReferenceBase::kWithoutDestructor); - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } /** @@ -4215,7 +4207,7 @@ class ReturnValue { public: template V8_INLINE ReturnValue(const ReturnValue& that) : value_(that.value_) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); } // Local setters template @@ -10700,7 +10692,7 @@ Local Local::New(Isolate* isolate, T* that) { template template void Eternal::Set(Isolate* isolate, Local handle) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); val_ = reinterpret_cast( V8::Eternalize(isolate, reinterpret_cast(*handle))); } @@ -10744,7 +10736,7 @@ T* PersistentBase::New(Isolate* isolate, T* that) { template template void Persistent::Copy(const Persistent& that) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); this->Reset(); if (that.IsEmpty()) return; internal::Address* p = reinterpret_cast(that.val_); @@ -10772,7 +10764,7 @@ void PersistentBase::Reset() { template template void PersistentBase::Reset(Isolate* isolate, const Local& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = New(isolate, other.val_); @@ -10783,7 +10775,7 @@ template template void PersistentBase::Reset(Isolate* isolate, const PersistentBase& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = New(isolate, other.val_); @@ -10849,7 +10841,7 @@ Global::Global(Global&& other) : PersistentBase(other.val_) { template template Global& Global::operator=(Global&& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); if (this != &rhs) { this->Reset(); if (rhs.val_ != nullptr) { @@ -10884,7 +10876,7 @@ void TracedReferenceBase::Reset() { template template void TracedGlobal::Reset(Isolate* isolate, const Local& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = this->New(isolate, other.val_, &this->val_, @@ -10894,7 +10886,7 @@ void TracedGlobal::Reset(Isolate* isolate, const Local& other) { template template TracedGlobal& TracedGlobal::operator=(TracedGlobal&& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = std::move(rhs.template As()); return *this; } @@ -10902,7 +10894,7 @@ TracedGlobal& TracedGlobal::operator=(TracedGlobal&& rhs) { template template TracedGlobal& TracedGlobal::operator=(const TracedGlobal& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = rhs.template As(); return *this; } @@ -10933,7 +10925,7 @@ TracedGlobal& TracedGlobal::operator=(const TracedGlobal& rhs) { template template void TracedReference::Reset(Isolate* isolate, const Local& other) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); Reset(); if (other.IsEmpty()) return; this->val_ = this->New(isolate, other.val_, &this->val_, @@ -10943,7 +10935,7 @@ void TracedReference::Reset(Isolate* isolate, const Local& other) { template template TracedReference& TracedReference::operator=(TracedReference&& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = std::move(rhs.template As()); return *this; } @@ -10952,7 +10944,7 @@ template template TracedReference& TracedReference::operator=( const TracedReference& rhs) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); *this = rhs.template As(); return *this; } @@ -11011,7 +11003,7 @@ ReturnValue::ReturnValue(internal::Address* slot) : value_(slot) {} template template void ReturnValue::Set(const Global& handle) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); if (V8_UNLIKELY(handle.IsEmpty())) { *value_ = GetDefaultValue(); } else { @@ -11022,7 +11014,7 @@ void ReturnValue::Set(const Global& handle) { template template void ReturnValue::Set(const TracedReferenceBase& handle) { - TYPE_CHECK(T, S); + static_assert(std::is_base_of::value, "type check"); if (V8_UNLIKELY(handle.IsEmpty())) { *value_ = GetDefaultValue(); } else { @@ -11033,7 +11025,8 @@ void ReturnValue::Set(const TracedReferenceBase& handle) { template template void ReturnValue::Set(const Local handle) { - TYPE_CHECK(T, S); + static_assert(std::is_void::value || std::is_base_of::value, + "type check"); if (V8_UNLIKELY(handle.IsEmpty())) { *value_ = GetDefaultValue(); } else { @@ -11043,13 +11036,13 @@ void ReturnValue::Set(const Local handle) { template void ReturnValue::Set(double i) { - TYPE_CHECK(T, Number); + static_assert(std::is_base_of::value, "type check"); Set(Number::New(GetIsolate(), i)); } template void ReturnValue::Set(int32_t i) { - TYPE_CHECK(T, Integer); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; if (V8_LIKELY(I::IsValidSmi(i))) { *value_ = I::IntToSmi(i); @@ -11060,7 +11053,7 @@ void ReturnValue::Set(int32_t i) { template void ReturnValue::Set(uint32_t i) { - TYPE_CHECK(T, Integer); + static_assert(std::is_base_of::value, "type check"); // Can't simply use INT32_MAX here for whatever reason. bool fits_into_int32_t = (i & (1U << 31)) == 0; if (V8_LIKELY(fits_into_int32_t)) { @@ -11072,7 +11065,7 @@ void ReturnValue::Set(uint32_t i) { template void ReturnValue::Set(bool value) { - TYPE_CHECK(T, Boolean); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; int root_index; if (value) { @@ -11085,21 +11078,21 @@ void ReturnValue::Set(bool value) { template void ReturnValue::SetNull() { - TYPE_CHECK(T, Primitive); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; *value_ = *I::GetRoot(GetIsolate(), I::kNullValueRootIndex); } template void ReturnValue::SetUndefined() { - TYPE_CHECK(T, Primitive); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; *value_ = *I::GetRoot(GetIsolate(), I::kUndefinedValueRootIndex); } template void ReturnValue::SetEmptyString() { - TYPE_CHECK(T, String); + static_assert(std::is_base_of::value, "type check"); typedef internal::Internals I; *value_ = *I::GetRoot(GetIsolate(), I::kEmptyStringRootIndex); } @@ -11121,8 +11114,7 @@ Local ReturnValue::Get() const { template template void ReturnValue::Set(S* whatever) { - // Uncompilable to prevent inadvertent misuse. - TYPE_CHECK(S*, Primitive); + static_assert(sizeof(S) < 0, "incompilable to prevent inadvertent misuse"); } template @@ -12033,8 +12025,4 @@ size_t SnapshotCreator::AddData(Local object) { } // namespace v8 - -#undef TYPE_CHECK - - #endif // INCLUDE_V8_H_