From 808a3f23bc4d6340a1f5d081f9a3eda91d20ee9d Mon Sep 17 00:00:00 2001 From: Igor Sheludko Date: Wed, 29 Jan 2020 18:05:52 +0100 Subject: [PATCH] [ptr-compr] Introduce TaggedIndex class ... a Smi-looking type containing properly sign-extended int31 integer. The idea is to use this kind of tagged integers for the cases where the value is guaranteed to fit into int31. For example, feedback vector slots is one of the candidates for using TaggedIndex representation. Bug: v8:10047 Change-Id: Ifaa2978a5d42467578ff243dc44d327536efbe93 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1960292 Reviewed-by: Tobias Tebbi Reviewed-by: Toon Verwaest Commit-Queue: Igor Sheludko Cr-Commit-Position: refs/heads/master@{#66170} --- BUILD.gn | 1 + src/compiler/code-assembler.cc | 1 + src/compiler/code-assembler.h | 1 + src/diagnostics/objects-debug.cc | 4 ++ src/objects/objects-inl.h | 5 ++ src/objects/objects.h | 3 ++ src/objects/tagged-index.h | 90 ++++++++++++++++++++++++++++++++ 7 files changed, 105 insertions(+) create mode 100644 src/objects/tagged-index.h diff --git a/BUILD.gn b/BUILD.gn index 1d94063a21..69c8e03b45 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2689,6 +2689,7 @@ v8_source_set("v8_base_without_compiler") { "src/objects/tagged-impl-inl.h", "src/objects/tagged-impl.cc", "src/objects/tagged-impl.h", + "src/objects/tagged-index.h", "src/objects/tagged-value-inl.h", "src/objects/tagged-value.h", "src/objects/template-objects-inl.h", diff --git a/src/compiler/code-assembler.cc b/src/compiler/code-assembler.cc index 2eee2aed15..cf2ecabda5 100644 --- a/src/compiler/code-assembler.cc +++ b/src/compiler/code-assembler.cc @@ -1625,6 +1625,7 @@ Address CheckObjectType(Address raw_value, Address raw_type, TYPE_CASE(Object) TYPE_CASE(Smi) + TYPE_CASE(TaggedIndex) TYPE_CASE(HeapObject) OBJECT_TYPE_LIST(TYPE_CASE) HEAP_OBJECT_TYPE_LIST(TYPE_CASE) diff --git a/src/compiler/code-assembler.h b/src/compiler/code-assembler.h index af49852015..6c85cf72d4 100644 --- a/src/compiler/code-assembler.h +++ b/src/compiler/code-assembler.h @@ -86,6 +86,7 @@ class Signature; enum class ObjectType { ENUM_ELEMENT(Object) // ENUM_ELEMENT(Smi) // + ENUM_ELEMENT(TaggedIndex) // ENUM_ELEMENT(HeapObject) // OBJECT_TYPE_LIST(ENUM_ELEMENT) // HEAP_OBJECT_TYPE_LIST(ENUM_ELEMENT) // diff --git a/src/diagnostics/objects-debug.cc b/src/diagnostics/objects-debug.cc index d087a6d21d..4def6098b6 100644 --- a/src/diagnostics/objects-debug.cc +++ b/src/diagnostics/objects-debug.cc @@ -138,6 +138,10 @@ void Smi::SmiVerify(Isolate* isolate) { CHECK(!IsConstructor()); } +void TaggedIndex::TaggedIndexVerify(Isolate* isolate) { + CHECK(IsTaggedIndex()); +} + void HeapObject::HeapObjectVerify(Isolate* isolate) { TorqueGeneratedClassVerifiers::HeapObjectVerify(*this, isolate); diff --git a/src/objects/objects-inl.h b/src/objects/objects-inl.h index 2cf349364f..9877b67c19 100644 --- a/src/objects/objects-inl.h +++ b/src/objects/objects-inl.h @@ -40,6 +40,7 @@ #include "src/objects/smi-inl.h" #include "src/objects/tagged-field-inl.h" #include "src/objects/tagged-impl-inl.h" +#include "src/objects/tagged-index.h" #include "src/objects/templates.h" #include "src/sanitizer/tsan.h" #include "torque-generated/class-definitions-tq-inl.h" @@ -74,6 +75,10 @@ DEF_GETTER(HeapObject, IsClassBoilerplate, bool) { return IsFixedArrayExact(isolate); } +bool Object::IsTaggedIndex() const { + return IsSmi() && TaggedIndex::IsValid(TaggedIndex(ptr()).value()); +} + #define IS_TYPE_FUNCTION_DEF(type_) \ bool Object::Is##type_() const { \ return IsHeapObject() && HeapObject::cast(*this).Is##type_(); \ diff --git a/src/objects/objects.h b/src/objects/objects.h index 5ac6907e6d..9153bf96a3 100644 --- a/src/objects/objects.h +++ b/src/objects/objects.h @@ -38,6 +38,7 @@ // Inheritance hierarchy: // - Object // - Smi (immediate small integer) +// - TaggedIndex (properly sign-extended immediate small integer) // - HeapObject (superclass for everything allocated in the heap) // - JSReceiver (suitable for property access) // - JSObject @@ -275,6 +276,8 @@ class Object : public TaggedImpl { constexpr Object() : TaggedImpl(kNullAddress) {} explicit constexpr Object(Address ptr) : TaggedImpl(ptr) {} + V8_INLINE bool IsTaggedIndex() const; + #define IS_TYPE_FUNCTION_DECL(Type) \ V8_INLINE bool Is##Type() const; \ V8_INLINE bool Is##Type(const Isolate* isolate) const; diff --git a/src/objects/tagged-index.h b/src/objects/tagged-index.h new file mode 100644 index 0000000000..a3c80ff9c6 --- /dev/null +++ b/src/objects/tagged-index.h @@ -0,0 +1,90 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_OBJECTS_TAGGED_INDEX_H_ +#define V8_OBJECTS_TAGGED_INDEX_H_ + +#include "src/common/globals.h" +#include "src/objects/heap-object.h" + +// Has to be the last include (doesn't have include guards): +#include "src/objects/object-macros.h" + +namespace v8 { +namespace internal { + +// TaggedIndex represents integer values that can be stored in 31 bits. +// The on 32-bit architectures ptr_ value has the following format: +// [31 bit signed int] 0 +// The on 64-bit architectures ptr_ value has the following format: +// [32 bits of sign-extended lower part][31 bit signed int] 0 +// Thus, on 32-bit architectures TaggedIndex is exactly the same as Smi but +// on 64-bit architectures TaggedIndex differs from Smi in the following +// aspects: +// 1) TaggedIndex payload is always 31 bit independent of the Smi payload size +// 2) TaggedIndex is always properly sign-extended independent of whether +// pointer compression is enabled or not. In the former case, upper 32 bits +// of a Smi value may contain 0 or sign or isolate root value. +// +// Given the above constraints TaggedIndex has the following properties: +// 1) it still looks like a Smi from GC point of view and therefore it's safe +// to pass TaggedIndex values to runtime functions or builtins on the stack +// 2) since the TaggedIndex values are already properly sign-extended it's +// safe to use them as indices in offset-computation functions. +class TaggedIndex : public Object { + public: + // This replaces the OBJECT_CONSTRUCTORS macro, because TaggedIndex are + // special in that we want them to be constexprs. + constexpr TaggedIndex() : Object() {} + explicit constexpr TaggedIndex(Address ptr) : Object(ptr) { +#if V8_HAS_CXX14_CONSTEXPR + DCHECK(HAS_SMI_TAG(ptr)); +#endif + } + + // Returns the integer value. + inline intptr_t value() const { + // Truncate and shift down (requires >> to be sign extending). + return static_cast(ptr()) >> kSmiTagSize; + } + + // Convert a value to a TaggedIndex object. + static inline TaggedIndex FromIntptr(intptr_t value) { +#if V8_HAS_CXX14_CONSTEXPR + DCHECK(TaggedIndex::IsValid(value)); +#endif + return TaggedIndex((static_cast
(value) << kSmiTagSize) | kSmiTag); + } + + // Returns whether value can be represented in a TaggedIndex. + static inline bool constexpr IsValid(intptr_t value) { + // Is value in range [kMinValue, kMaxValue]. + // Use unsigned operations in order to avoid undefined behaviour in case of + // signed integer overflow. + return (static_cast(value) - + static_cast(kMinValue)) <= + (static_cast(kMaxValue) - + static_cast(kMinValue)); + } + + DECL_CAST(TaggedIndex) + + // Dispatched behavior. + DECL_VERIFIER(TaggedIndex) + + STATIC_ASSERT(kSmiTagSize == 1); + static constexpr int kTaggedValueSize = 31; + static constexpr intptr_t kMinValue = + static_cast(kUintptrAllBitsSet << (kTaggedValueSize - 1)); + static constexpr intptr_t kMaxValue = -(kMinValue + 1); +}; + +CAST_ACCESSOR(TaggedIndex) + +} // namespace internal +} // namespace v8 + +#include "src/objects/object-macros-undef.h" + +#endif // V8_OBJECTS_TAGGED_INDEX_H_