[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 <tebbi@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66170}
This commit is contained in:
Igor Sheludko 2020-01-29 18:05:52 +01:00 committed by Commit Bot
parent 2877a2ad12
commit 808a3f23bc
7 changed files with 105 additions and 0 deletions

View File

@ -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",

View File

@ -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)

View File

@ -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) //

View File

@ -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);

View File

@ -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_(); \

View File

@ -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<HeapObjectReferenceType::STRONG, Address> {
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;

View File

@ -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<intptr_t>(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<Address>(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<uintptr_t>(value) -
static_cast<uintptr_t>(kMinValue)) <=
(static_cast<uintptr_t>(kMaxValue) -
static_cast<uintptr_t>(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<intptr_t>(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_