v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
property-details.h
Go to the documentation of this file.
1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_OBJECTS_PROPERTY_DETAILS_H_
6#define V8_OBJECTS_PROPERTY_DETAILS_H_
7
8#include "include/v8-object.h"
10#include "src/common/globals.h"
11#include "src/flags/flags.h"
13
14namespace v8 {
15namespace internal {
16
17// ES6 6.1.7.1
23
25
28
29 ABSENT = 64, // Used in runtime to indicate a property is absent.
30 // ABSENT can never be stored in or returned from a descriptor's attributes
31 // bitfield. It is only used as a return value meaning the attributes of
32 // a non-existent property.
33};
34
39
40// Number of distinct bits in PropertyAttributes.
41static const int kPropertyAttributesBitsCount = 3;
42
45
56// Enable fast comparisons of PropertyAttributes against PropertyFilters.
57static_assert(ALL_PROPERTIES == static_cast<PropertyFilter>(NONE));
58static_assert(ONLY_WRITABLE == static_cast<PropertyFilter>(READ_ONLY));
59static_assert(ONLY_ENUMERABLE == static_cast<PropertyFilter>(DONT_ENUM));
60static_assert(ONLY_CONFIGURABLE == static_cast<PropertyFilter>(DONT_DELETE));
61static_assert(((SKIP_STRINGS | SKIP_SYMBOLS) & ALL_ATTRIBUTES_MASK) == 0);
62static_assert(ALL_PROPERTIES ==
64static_assert(ONLY_WRITABLE ==
66static_assert(ONLY_ENUMERABLE ==
68static_assert(ONLY_CONFIGURABLE == static_cast<PropertyFilter>(
70static_assert(SKIP_STRINGS ==
72static_assert(SKIP_SYMBOLS ==
74
75// Assert that kPropertyAttributesBitsCount value matches the definition of
76// ALL_ATTRIBUTES_MASK.
77static_assert((ALL_ATTRIBUTES_MASK == (READ_ONLY | DONT_ENUM | DONT_DELETE)) ==
79
80class Smi;
81class TypeInfo;
82
83// Order of kinds is significant.
84// Must fit in the BitField PropertyDetails::KindField.
85enum class PropertyKind { kData = 0, kAccessor = 1 };
86
87// Order of modes is significant.
88// Must fit in the BitField PropertyDetails::LocationField.
89enum class PropertyLocation { kField = 0, kDescriptor = 1 };
90
91// Order of modes is significant.
92// Must fit in the BitField PropertyDetails::ConstnessField.
93enum class PropertyConstness { kMutable = 0, kConst = 1 };
94
96 public:
97 enum Kind {
103 // This representation is used for WasmObject fields and basically means
104 // that the actual field type information must be taken from the Wasm RTT
105 // associated with the map.
108 };
109
110 constexpr Representation() : kind_(kNone) {}
111
112 static constexpr Representation None() { return Representation(kNone); }
113 static constexpr Representation Tagged() { return Representation(kTagged); }
114 static constexpr Representation Smi() { return Representation(kSmi); }
115 static constexpr Representation Double() { return Representation(kDouble); }
116 static constexpr Representation HeapObject() {
118 }
119 static constexpr Representation WasmValue() {
121 }
122
123 static constexpr Representation FromKind(Kind kind) {
124 return Representation(kind);
125 }
126
127 bool Equals(const Representation& other) const {
128 return kind_ == other.kind_;
129 }
130
131 bool IsCompatibleForLoad(const Representation& other) const {
132 return IsDouble() == other.IsDouble();
133 }
134
135 bool IsCompatibleForStore(const Representation& other) const {
136 return Equals(other);
137 }
138
139 // Returns true if a change from this representation to a more general one
140 // might cause a map deprecation.
142 // HeapObject to tagged representation change can be done in-place.
143 // Boxed double to tagged transition is always done in-place.
144 // Note that WasmValue is not supposed to be changed at all (the only
145 // representation it fits into is WasmValue), so for the sake of predicate
146 // correctness we treat it as in-place "changeable".
147 if (IsTagged() || IsHeapObject() || IsDouble() || IsWasmValue()) {
148 return false;
149 }
150 // None to double and smi to double representation changes require
151 // deprecation, because doubles might require box allocation, see
152 // CanBeInPlaceChangedTo().
153 DCHECK(IsNone() || IsSmi());
154 return true;
155 }
156
157 bool CanBeInPlaceChangedTo(const Representation& other) const {
158 if (Equals(other)) return true;
159 if (IsWasmValue() || other.IsWasmValue()) return false;
160 // If it's just a representation generalization case (i.e. property kind and
161 // attributes stays unchanged) it's fine to transition from None to anything
162 // but double without any modification to the object, because the default
163 // uninitialized value for representation None can be overwritten by both
164 // smi and tagged values. Doubles, however, would require a box allocation.
165 if (IsNone()) return !other.IsDouble();
166 if (!other.IsTagged()) return false;
167 DCHECK(IsSmi() || IsDouble() || IsHeapObject());
168 return true;
169 }
170
171 // Return the most generic representation that this representation can be
172 // changed to in-place. If an in-place representation change is not allowed,
173 // then this will return the current representation.
178
179 bool is_more_general_than(const Representation& other) const {
180 if (IsWasmValue()) return false;
181 if (IsHeapObject()) return other.IsNone();
182 return kind_ > other.kind_;
183 }
184
185 bool fits_into(const Representation& other) const {
186 return other.is_more_general_than(*this) || other.Equals(*this);
187 }
188
190 if (other.fits_into(*this)) return *this;
191 if (other.is_more_general_than(*this)) return other;
192 return Representation::Tagged();
193 }
194
195 int size() const {
196 DCHECK(!IsNone());
197 if (IsDouble()) return kDoubleSize;
198 DCHECK(IsTagged() || IsSmi() || IsHeapObject());
199 return kTaggedSize;
200 }
201
202 constexpr Kind kind() const { return static_cast<Kind>(kind_); }
203 constexpr bool IsNone() const { return kind_ == kNone; }
204 constexpr bool IsWasmValue() const { return kind_ == kWasmValue; }
205 constexpr bool IsTagged() const { return kind_ == kTagged; }
206 constexpr bool IsSmi() const { return kind_ == kSmi; }
207 constexpr bool IsSmiOrTagged() const { return IsSmi() || IsTagged(); }
208 constexpr bool IsDouble() const { return kind_ == kDouble; }
209 constexpr bool IsHeapObject() const { return kind_ == kHeapObject; }
210
211 const char* Mnemonic() const {
212 switch (kind_) {
213 case kNone:
214 return "v";
215 case kTagged:
216 return "t";
217 case kSmi:
218 return "s";
219 case kDouble:
220 return "d";
221 case kHeapObject:
222 return "h";
223 case kWasmValue:
224 return "w";
225 }
226 UNREACHABLE();
227 }
228
229 bool operator==(const Representation& other) const {
230 return kind_ == other.kind_;
231 }
232
233 private:
234 explicit constexpr Representation(Kind k) : kind_(k) {}
235
236 // Make sure kind fits in int8.
237 static_assert(kNumRepresentations <= (1 << kBitsPerByte));
238
239 int8_t kind_;
240};
241
242static const int kDescriptorIndexBitCount = 10;
244// The maximum number of descriptors we want in a descriptor array. It should
245// fit in a page and also the following should hold:
246// kMaxNumberOfDescriptors + kFieldsAdded <= PropertyArray::kMaxLength.
249 (1 << kDescriptorIndexBitCount) - 1;
250
251// A PropertyCell's property details contains a cell type that is meaningful if
252// the cell is still valid (does not hold the hole).
254 kMutable, // Cell will no longer be tracked as constant.
255 kUndefined, // The PREMONOMORPHIC of property cells.
256 kConstant, // Cell has been assigned only once.
257 kConstantType, // Cell has been assigned only one type.
258 // Temporary value indicating an ongoing property cell state transition. Only
259 // observable by a background thread.
261 // Value for dictionaries not holding cells, must be 0:
263};
264
265// PropertyDetails captures type and attributes for a property.
266// They are used both in property dictionaries and instance descriptors.
268 public:
269 // Property details for global dictionary properties.
272 int dictionary_index = 0)
273 : value_(KindField::encode(kind) |
275 AttributesField::encode(attributes) |
276 // We track PropertyCell constness via PropertyCellTypeField,
277 // so we set ConstnessField to kMutable to simplify DCHECKs
278 // related to non-global property constness tracking.
282
283 // Property details for dictionary mode properties/elements.
293
294 // Property details for fast mode properties.
305
310
311 bool operator==(PropertyDetails const& other) const {
312 return value_ == other.value_;
313 }
314
315 bool operator!=(PropertyDetails const& other) const {
316 return value_ != other.value_;
317 }
318
319 int pointer() const { return DescriptorPointer::decode(value_); }
320
322 return PropertyDetails(value_, i);
323 }
324
326 PropertyDetails details = *this;
327 details.value_ = PropertyCellTypeField::update(details.value_, type);
328 return details;
329 }
330
331 PropertyDetails set_index(int index) const {
332 PropertyDetails details = *this;
333 details.value_ = DictionaryStorageField::update(details.value_, index);
334 return details;
335 }
336
344 new_attributes =
345 static_cast<PropertyAttributes>(attributes() | new_attributes);
346 return PropertyDetails(value_, new_attributes);
347 }
348
349 // Conversion for storing details as Object.
350 explicit inline PropertyDetails(Tagged<Smi> smi);
351 inline Tagged<Smi> AsSmi() const;
352
354 return representation.kind();
355 }
356
357 static Representation DecodeRepresentation(uint32_t bits) {
358 return Representation::FromKind(static_cast<Representation::Kind>(bits));
359 }
360
364
368
373
377
381
383
384 inline int field_width_in_words() const;
385
386 static bool IsValidIndex(int index) {
388 }
389
390 bool IsReadOnly() const { return (attributes() & READ_ONLY) != 0; }
391 bool IsConfigurable() const { return (attributes() & DONT_DELETE) == 0; }
392 bool IsDontEnum() const { return (attributes() & DONT_ENUM) != 0; }
393 bool IsEnumerable() const { return !IsDontEnum(); }
397
398 // Bit fields in value_ (type, shift, size). Must be public so the
399 // constants can be embedded in generated code.
403 static const int kAttributesReadOnlyMask =
405 static const int kAttributesDontDeleteMask =
407 static const int kAttributesDontEnumMask =
409
410 // Bit fields for normalized/dictionary mode objects.
413
414 // Bit fields for fast objects.
421
422 // All bits for both fast and slow objects must fit in a smi.
423 static_assert(DictionaryStorageField::kLastUsedBit < 31);
424 static_assert(FieldIndexField::kLastUsedBit < 31);
425
426 // DictionaryStorageField must be the last field, so that overflowing it
427 // doesn't overwrite other fields.
428 static_assert(DictionaryStorageField::kLastUsedBit == 30);
429
430 // All bits for non-global dictionary mode objects except enumeration index
431 // must fit in a byte.
432 static_assert(KindField::kLastUsedBit < 8);
433 static_assert(ConstnessField::kLastUsedBit < 8);
434 static_assert(AttributesField::kLastUsedBit < 8);
435
436 static const int kInitialIndex = 1;
437
441
442#ifdef OBJECT_PRINT
443 // For our gdb macros, we should perhaps change these in the future.
444 void Print(bool dictionary_mode);
445#endif
446
457 void PrintAsSlowTo(std::ostream& out, bool print_dict_index);
458 void PrintAsFastTo(std::ostream& out, PrintMode mode = kPrintFull);
459
460 // Encodes those property details for non-global dictionary properties
461 // with an enumeration index of 0 as a single byte.
462 uint8_t ToByte() {
463 // We only care about the value of KindField, ConstnessField, and
464 // AttributesField. We've statically asserted earlier that these fields fit
465 // into a byte together.
466
468 static_assert(static_cast<int>(PropertyLocation::kField) == 0);
469
471 static_assert(static_cast<int>(PropertyCellType::kNoCell) == 0);
472
473 // Only to be used when the enum index isn't actually maintained
474 // by the PropertyDetails:
476
477 return value_;
478 }
479
480 // Only to be used for bytes obtained by ToByte. In particular, only used for
481 // non-global dictionary properties.
482 static PropertyDetails FromByte(uint8_t encoded_details) {
483 // The 0-extension to 32bit sets PropertyLocation to kField,
484 // PropertyCellType to kNoCell, and enumeration index to 0, as intended.
485 // Everything else is obtained from |encoded_details|.
486 PropertyDetails details(encoded_details);
489 DCHECK_EQ(0, details.dictionary_index());
490 return details;
491 }
492
493 private:
494 PropertyDetails(int value, int pointer) {
495 value_ = DescriptorPointer::update(value, pointer);
496 }
507
508 explicit PropertyDetails(uint32_t value) : value_{value} {}
509
510 uint32_t value_;
511};
512
513// kField location is more general than kDescriptor, kDescriptor generalizes
514// only to itself.
518
519// PropertyConstness::kMutable constness is more general than
520// VariableMode::kConst, VariableMode::kConst generalizes only to itself.
524
529
530V8_EXPORT_PRIVATE std::ostream& operator<<(
531 std::ostream& os, const Representation& representation);
532V8_EXPORT_PRIVATE std::ostream& operator<<(
533 std::ostream& os, const PropertyAttributes& attributes);
534V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
535 PropertyConstness constness);
536V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
537 PropertyCellType type);
538} // namespace internal
539} // namespace v8
540
541#endif // V8_OBJECTS_PROPERTY_DETAILS_H_
static constexpr int kLastUsedBit
Definition bit-field.h:42
static constexpr T decode(U value)
Definition bit-field.h:66
static constexpr bool is_valid(T value)
Definition bit-field.h:50
static constexpr U encode(T value)
Definition bit-field.h:55
static V8_NODISCARD constexpr U update(U previous, T value)
Definition bit-field.h:61
static constexpr U kMask
Definition bit-field.h:41
static constexpr int kShift
Definition bit-field.h:39
constexpr PropertyDetails(PropertyKind kind, PropertyAttributes attributes, PropertyLocation location, PropertyConstness constness, Representation representation, int field_index=0)
constexpr PropertyDetails(PropertyKind kind, PropertyAttributes attributes, PropertyConstness constness, int dictionary_index=0)
constexpr PropertyDetails(PropertyKind kind, PropertyAttributes attributes, PropertyCellType cell_type, int dictionary_index=0)
PropertyAttributes attributes() const
PropertyDetails CopyWithConstness(PropertyConstness constness) const
PropertyLocation location() const
bool operator==(PropertyDetails const &other) const
Representation representation() const
PropertyCellType cell_type() const
PropertyDetails(int value, int pointer)
static constexpr PropertyConstness kConstIfDictConstnessTracking
PropertyDetails(int value, PropertyConstness constness)
static const int kAttributesDontEnumMask
static const int kAttributesReadOnlyMask
void PrintAsFastTo(std::ostream &out, PrintMode mode=kPrintFull)
Definition property.cc:139
PropertyDetails set_index(int index) const
bool HasKindAndAttributes(PropertyKind kind, PropertyAttributes attributes)
static bool IsValidIndex(int index)
static constexpr PropertyDetails Empty(PropertyCellType cell_type=PropertyCellType::kNoCell)
PropertyConstness constness() const
static PropertyDetails FromByte(uint8_t encoded_details)
PropertyDetails CopyAddAttributes(PropertyAttributes new_attributes) const
static Representation DecodeRepresentation(uint32_t bits)
PropertyDetails set_cell_type(PropertyCellType type) const
static const int kAttributesDontDeleteMask
PropertyDetails(int value, PropertyAttributes attributes)
static constexpr uint8_t EncodeRepresentation(Representation representation)
PropertyDetails(int value, Representation representation)
Tagged< Smi > AsSmi() const
Definition objects-inl.h:79
void PrintAsSlowTo(std::ostream &out, bool print_dict_index)
Definition property.cc:128
PropertyDetails set_pointer(int i) const
bool operator!=(PropertyDetails const &other) const
PropertyDetails CopyWithRepresentation(Representation representation) const
constexpr bool IsHeapObject() const
bool is_more_general_than(const Representation &other) const
const char * Mnemonic() const
bool fits_into(const Representation &other) const
constexpr bool IsNone() const
bool IsCompatibleForStore(const Representation &other) const
constexpr bool IsSmiOrTagged() const
Representation MostGenericInPlaceChange() const
constexpr bool IsWasmValue() const
constexpr Kind kind() const
static constexpr Representation Double()
bool IsCompatibleForLoad(const Representation &other) const
Representation generalize(Representation other)
constexpr bool IsTagged() const
bool operator==(const Representation &other) const
bool Equals(const Representation &other) const
constexpr bool IsSmi() const
static constexpr Representation WasmValue()
static constexpr Representation FromKind(Kind kind)
static constexpr Representation HeapObject()
static constexpr Representation None()
static constexpr Representation Smi()
static constexpr Representation Tagged()
constexpr bool IsDouble() const
bool CanBeInPlaceChangedTo(const Representation &other) const
#define V8_DICT_PROPERTY_CONST_TRACKING_BOOL
Definition globals.h:249
constexpr int kTaggedSize
Definition globals.h:542
constexpr int kBitsPerByte
Definition globals.h:682
static const int kFirstInobjectPropertyOffsetBitCount
static const int kPropertyAttributesCombinationsCount
PropertyConstness GeneralizeConstness(PropertyConstness a, PropertyConstness b)
std::ostream & operator<<(std::ostream &os, AtomicMemoryOrder order)
void Print(Tagged< Object > obj)
Definition objects.h:774
static const int kInvalidEnumCacheSentinel
static const int kMaxNumberOfDescriptors
V8_INLINE PropertyAttributes PropertyAttributesFromInt(int value)
static const int kDescriptorIndexBitCount
bool IsGeneralizableTo(PropertyLocation a, PropertyLocation b)
return value
Definition map-inl.h:893
constexpr int kDoubleSize
Definition globals.h:407
static const int kPropertyAttributesBitsCount
@ DontEnum
Definition v8-object.h:145
@ None
Definition v8-object.h:141
@ DontDelete
Definition v8-object.h:147
@ ReadOnly
Definition v8-object.h:143
PropertyFilter
Definition v8-object.h:179
@ ONLY_CONFIGURABLE
Definition v8-object.h:183
@ SKIP_SYMBOLS
Definition v8-object.h:185
@ ONLY_WRITABLE
Definition v8-object.h:181
@ ALL_PROPERTIES
Definition v8-object.h:180
@ SKIP_STRINGS
Definition v8-object.h:184
@ ONLY_ENUMERABLE
Definition v8-object.h:182
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_INLINE
Definition v8config.h:500