[runtime] Cleanup Map class definition.

.. by using macros for defining field offsets.

Bug: v8:5799
Change-Id: Id76e81bedb8f348b2efaa1d553bebac0ff90b474
Reviewed-on: https://chromium-review.googlesource.com/768382
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49351}
This commit is contained in:
Igor Sheludko 2017-11-14 12:01:17 +01:00 committed by Commit Bot
parent e634740bf9
commit 68f1dcf9e7
10 changed files with 63 additions and 105 deletions

View File

@ -131,7 +131,8 @@ inline constexpr unsigned CountTrailingZeros64(uint64_t value) {
// Returns true iff |value| is a power of 2.
template <typename T,
typename = typename std::enable_if<std::is_integral<T>::value>::type>
typename = typename std::enable_if<std::is_integral<T>::value ||
std::is_enum<T>::value>::type>
constexpr inline bool IsPowerOfTwo(T value) {
return value > 0 && (value & (value - 1)) == 0;
}

View File

@ -1372,7 +1372,6 @@ TNode<IntPtrT> CodeStubAssembler::LoadMapInobjectProperties(
SloppyTNode<Map> map) {
CSA_SLOW_ASSERT(this, IsMap(map));
// See Map::GetInObjectProperties() for details.
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
CSA_ASSERT(this, IsJSObjectMap(map));
return ChangeInt32ToIntPtr(LoadObjectField(
map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
@ -1383,9 +1382,7 @@ TNode<IntPtrT> CodeStubAssembler::LoadMapConstructorFunctionIndex(
SloppyTNode<Map> map) {
CSA_SLOW_ASSERT(this, IsMap(map));
// See Map::GetConstructorFunctionIndex() for details.
STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
CSA_ASSERT(this, Int32LessThanOrEqual(LoadMapInstanceType(map),
Int32Constant(LAST_PRIMITIVE_TYPE)));
CSA_ASSERT(this, IsPrimitiveInstanceType(LoadMapInstanceType(map)));
return ChangeInt32ToIntPtr(LoadObjectField(
map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
MachineType::Uint8()));

View File

@ -148,6 +148,7 @@ const int kMinUInt16 = 0;
const uint32_t kMaxUInt32 = 0xFFFFFFFFu;
const int kMinUInt32 = 0;
const int kUInt8Size = sizeof(uint8_t);
const int kCharSize = sizeof(char);
const int kShortSize = sizeof(short); // NOLINT
const int kIntSize = sizeof(int);

View File

@ -31,7 +31,7 @@ template <typename ResultType, typename ConcreteVisitor>
ResultType HeapVisitor<ResultType, ConcreteVisitor>::Visit(Map* map,
HeapObject* object) {
ConcreteVisitor* visitor = static_cast<ConcreteVisitor*>(this);
switch (static_cast<VisitorId>(map->visitor_id())) {
switch (map->visitor_id()) {
#define CASE(type) \
case kVisit##type: \
return visitor->Visit##type(map, \

View File

@ -116,7 +116,7 @@ bool Scavenger::PromoteObject(Map* map, HeapObject** slot, HeapObject* object,
}
*slot = target;
if (!ContainsOnlyData(static_cast<VisitorId>(map->visitor_id()))) {
if (!ContainsOnlyData(map->visitor_id())) {
promotion_list_.Push(ObjectAndSize(target, object_size));
}
promoted_size_ += object_size;
@ -206,7 +206,7 @@ void Scavenger::EvacuateObject(HeapObject** slot, Map* map,
int size = source->SizeFromMap(map);
// Cannot use ::cast() below because that would add checks in debug mode
// that require re-reading the map.
switch (static_cast<VisitorId>(map->visitor_id())) {
switch (map->visitor_id()) {
case kVisitThinString:
EvacuateThinString(map, slot, reinterpret_cast<ThinString*>(source),
size);

View File

@ -2968,9 +2968,11 @@ Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
return isolate->factory()->NewNumber(scalar);
}
int Map::visitor_id() const { return READ_BYTE_FIELD(this, kVisitorIdOffset); }
VisitorId Map::visitor_id() const {
return static_cast<VisitorId>(READ_BYTE_FIELD(this, kVisitorIdOffset));
}
void Map::set_visitor_id(int id) {
void Map::set_visitor_id(VisitorId id) {
DCHECK_LE(0, id);
DCHECK_LT(id, 256);
WRITE_BYTE_FIELD(this, kVisitorIdOffset, static_cast<byte>(id));
@ -3573,12 +3575,14 @@ void Map::set_prototype(Object* value, WriteBarrierMode mode) {
}
LayoutDescriptor* Map::layout_descriptor_gc_safe() const {
DCHECK(FLAG_unbox_double_fields);
Object* layout_desc = RELAXED_READ_FIELD(this, kLayoutDescriptorOffset);
return LayoutDescriptor::cast_gc_safe(layout_desc);
}
bool Map::HasFastPointerLayout() const {
DCHECK(FLAG_unbox_double_fields);
Object* layout_desc = RELAXED_READ_FIELD(this, kLayoutDescriptorOffset);
return LayoutDescriptor::IsFastPointerLayout(layout_desc);
}
@ -3595,7 +3599,7 @@ void Map::UpdateDescriptors(DescriptorArray* descriptors,
// TODO(ishell): remove these checks from VERIFY_HEAP mode.
if (FLAG_verify_heap) {
CHECK(layout_descriptor()->IsConsistentWithMap(this));
CHECK(visitor_id() == Map::GetVisitorId(this));
CHECK_EQ(Map::GetVisitorId(this), visitor_id());
}
#else
SLOW_DCHECK(layout_descriptor()->IsConsistentWithMap(this));
@ -3627,7 +3631,8 @@ void Map::InitializeDescriptors(DescriptorArray* descriptors,
ACCESSORS(Map, instance_descriptors, DescriptorArray, kDescriptorsOffset)
ACCESSORS(Map, layout_descriptor, LayoutDescriptor, kLayoutDescriptorOffset)
ACCESSORS_CHECKED(Map, layout_descriptor, LayoutDescriptor,
kLayoutDescriptorOffset, FLAG_unbox_double_fields)
void Map::set_bit_field3(uint32_t bits) {
if (kInt32Size != kPointerSize) {

View File

@ -151,7 +151,9 @@ typedef std::vector<Handle<Map>> MapHandles;
// | TaggedPointer | [instance_descriptors] |
// +*************************************************************+
// ! TaggedPointer ! [layout_descriptors] !
// ! ! Field is only present on 64 bit arch !
// ! ! Field is only present if compile-time flag !
// ! ! FLAG_unbox_double_fields is enabled !
// ! ! (basically on 64 bit architectures) !
// +*************************************************************+
// | TaggedPointer | [dependent_code] |
// +---------------+---------------------------------------------+
@ -163,14 +165,13 @@ class Map : public HeapObject {
// Instance size.
// Size in bytes or kVariableSizeSentinel if instances do not have
// a fixed size.
inline int instance_size() const;
inline void set_instance_size(int value);
DECL_INT_ACCESSORS(instance_size)
// [inobject_properties_or_constructor_function_index]: Provides access
// to the inobject properties in case of JSObject maps, or the constructor
// function index in case of primitive maps.
inline int inobject_properties_or_constructor_function_index() const;
inline void set_inobject_properties_or_constructor_function_index(int value);
DECL_INT_ACCESSORS(inobject_properties_or_constructor_function_index)
// Count of properties allocated in the object (JSObject only).
inline int GetInObjectProperties() const;
inline void SetInObjectProperties(int value);
@ -206,8 +207,7 @@ class Map : public HeapObject {
// - there is no slack in the object.
// - the property array has value slack slots.
// Note that this encoding requires that H = JSObject::kFieldsAdded.
inline int used_instance_size_in_words() const;
inline void set_used_instance_size_in_words(int value);
DECL_INT_ACCESSORS(used_instance_size_in_words)
inline int UsedInstanceSize() const;
inline int UnusedPropertyFields() const;
@ -320,21 +320,18 @@ class Map : public HeapObject {
// Tells whether the instance has a [[Construct]] internal method.
// This property is implemented according to ES6, section 7.2.4.
inline void set_is_constructor(bool value);
inline bool is_constructor() const;
DECL_BOOLEAN_ACCESSORS(is_constructor)
// Tells whether the instance with this map may have properties for
// interesting symbols on it.
// An "interesting symbol" is one for which Name::IsInterestingSymbol()
// returns true, i.e. a well-known symbol like @@toStringTag.
inline void set_may_have_interesting_symbols(bool value);
inline bool may_have_interesting_symbols() const;
DECL_BOOLEAN_ACCESSORS(may_have_interesting_symbols)
DECL_BOOLEAN_ACCESSORS(has_prototype_slot)
// Tells whether the instance with this map has a hidden prototype.
inline void set_has_hidden_prototype(bool value);
inline bool has_hidden_prototype() const;
DECL_BOOLEAN_ACCESSORS(has_hidden_prototype)
// Records and queries whether the instance has a named interceptor.
inline void set_has_named_interceptor();
@ -358,12 +355,9 @@ class Map : public HeapObject {
inline void set_is_callable();
inline bool is_callable() const;
inline void set_new_target_is_base(bool value);
inline bool new_target_is_base() const;
inline void set_is_extensible(bool value);
inline bool is_extensible() const;
inline void set_is_prototype_map(bool value);
inline bool is_prototype_map() const;
DECL_BOOLEAN_ACCESSORS(new_target_is_base)
DECL_BOOLEAN_ACCESSORS(is_extensible)
DECL_BOOLEAN_ACCESSORS(is_prototype_map)
inline bool is_abandoned_prototype_map() const;
inline void set_elements_kind(ElementsKind elements_kind);
@ -571,16 +565,14 @@ class Map : public HeapObject {
inline int EnumLength() const;
inline void SetEnumLength(int length);
inline bool owns_descriptors() const;
inline void set_owns_descriptors(bool owns_descriptors);
DECL_BOOLEAN_ACCESSORS(owns_descriptors)
inline void mark_unstable();
inline bool is_stable() const;
inline void set_migration_target(bool value);
inline bool is_migration_target() const;
inline void set_immutable_proto(bool value);
inline bool is_immutable_proto() const;
inline void set_construction_counter(int value);
inline int construction_counter() const;
DECL_INT_ACCESSORS(construction_counter)
inline void deprecate();
inline bool is_deprecated() const;
inline bool CanBeDeprecated() const;
@ -725,8 +717,7 @@ class Map : public HeapObject {
void DictionaryMapVerify();
#endif
inline int visitor_id() const;
inline void set_visitor_id(int visitor_id);
DECL_PRIMITIVE_ACCESSORS(visitor_id, VisitorId)
static Handle<Map> TransitionToPrototype(Handle<Map> map,
Handle<Object> prototype);
@ -736,46 +727,29 @@ class Map : public HeapObject {
static const int kMaxPreAllocatedPropertyFields = 255;
// Layout description.
static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
static const int kBitField3Offset = kInstanceAttributesOffset + kIntSize;
static const int kPrototypeOffset = kBitField3Offset + kPointerSize;
static const int kConstructorOrBackPointerOffset =
kPrototypeOffset + kPointerSize;
// When there is only one transition, it is stored directly in this field;
// otherwise a transition array is used.
// For prototype maps, this slot is used to store this map's PrototypeInfo
// struct.
static const int kTransitionsOrPrototypeInfoOffset =
kConstructorOrBackPointerOffset + kPointerSize;
static const int kDescriptorsOffset =
kTransitionsOrPrototypeInfoOffset + kPointerSize;
#if V8_DOUBLE_FIELDS_UNBOXING
static const int kLayoutDescriptorOffset = kDescriptorsOffset + kPointerSize;
static const int kDependentCodeOffset =
kLayoutDescriptorOffset + kPointerSize;
#else
static const int kLayoutDescriptorOffset = 1; // Must not be ever accessed.
static const int kDependentCodeOffset = kDescriptorsOffset + kPointerSize;
#endif
static const int kWeakCellCacheOffset = kDependentCodeOffset + kPointerSize;
static const int kSize = kWeakCellCacheOffset + kPointerSize;
#define MAP_FIELDS(V) \
/* Raw data fields. */ \
V(kInstanceSizeOffset, kUInt8Size) \
V(kInObjectPropertiesOrConstructorFunctionIndexOffset, kUInt8Size) \
V(kUsedInstanceSizeInWordsOffset, kUInt8Size) \
V(kVisitorIdOffset, kUInt8Size) \
V(kInstanceAttributesOffset, kInt32Size) \
V(kBitField3Offset, kPointerSize) \
/* Pointer fields. */ \
V(kPointerFieldsBeginOffset, 0) \
V(kPrototypeOffset, kPointerSize) \
V(kConstructorOrBackPointerOffset, kPointerSize) \
V(kTransitionsOrPrototypeInfoOffset, kPointerSize) \
V(kDescriptorsOffset, kPointerSize) \
V(kLayoutDescriptorOffset, (FLAG_unbox_double_fields ? kPointerSize : 0)) \
V(kDependentCodeOffset, kPointerSize) \
V(kWeakCellCacheOffset, kPointerSize) \
V(kPointerFieldsEndOffset, 0) \
/* Total size. */ \
V(kSize, 0)
// Layout of pointer fields. Heap iteration code relies on them
// being continuously allocated.
static const int kPointerFieldsBeginOffset = Map::kPrototypeOffset;
static const int kPointerFieldsEndOffset = kSize;
// Byte offsets within kInstanceSizesOffset.
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
static const int kInObjectPropertiesOrConstructorFunctionIndexByte = 1;
static const int kInObjectPropertiesOrConstructorFunctionIndexOffset =
kInstanceSizesOffset + kInObjectPropertiesOrConstructorFunctionIndexByte;
static const int kUsedInstanceSizeInWordsByte = 2;
static const int kUsedInstanceSizeInWordsOffset =
kInstanceSizesOffset + kUsedInstanceSizeInWordsByte;
static const int kVisitorIdByte = 3;
static const int kVisitorIdOffset = kInstanceSizesOffset + kVisitorIdByte;
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, MAP_FIELDS)
#undef MAP_FIELDS
// Byte offsets within kInstanceAttributesOffset attributes.
#if V8_TARGET_LITTLE_ENDIAN
@ -814,24 +788,6 @@ class Map : public HeapObject {
class IsPrototypeMapBits : public BitField<bool, 2, 1> {};
class ElementsKindBits : public BitField<ElementsKind, 3, 5> {};
// Derived values from bit field 2
static const int8_t kMaximumBitField2FastElementValue =
static_cast<int8_t>((PACKED_ELEMENTS + 1)
<< Map::ElementsKindBits::kShift) -
1;
static const int8_t kMaximumBitField2FastSmiElementValue =
static_cast<int8_t>((PACKED_SMI_ELEMENTS + 1)
<< Map::ElementsKindBits::kShift) -
1;
static const int8_t kMaximumBitField2FastHoleyElementValue =
static_cast<int8_t>((HOLEY_ELEMENTS + 1)
<< Map::ElementsKindBits::kShift) -
1;
static const int8_t kMaximumBitField2FastHoleySmiElementValue =
static_cast<int8_t>((HOLEY_SMI_ELEMENTS + 1)
<< Map::ElementsKindBits::kShift) -
1;
typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
kPointerFieldsEndOffset, kSize>
BodyDescriptor;

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#undef DECL_PRIMITIVE_ACCESSORS
#undef DECL_BOOLEAN_ACCESSORS
#undef DECL_INT_ACCESSORS
#undef DECL_ACCESSORS
@ -17,6 +18,7 @@
#undef RELAXED_SMI_ACCESSORS
#undef BOOL_GETTER
#undef BOOL_ACCESSORS
#undef BIT_FIELD_ACCESSORS
#undef TYPE_CHECKER
#undef FIELD_ADDR
#undef FIELD_ADDR_CONST

View File

@ -12,17 +12,15 @@
// for fields that can be written to and read from multiple threads at the same
// time. See comments in src/base/atomicops.h for the memory ordering sematics.
#define DECL_BOOLEAN_ACCESSORS(name) \
inline bool name() const; \
inline void set_##name(bool value);
#define DECL_PRIMITIVE_ACCESSORS(name, type) \
inline type name() const; \
inline void set_##name(type value);
#define DECL_INT_ACCESSORS(name) \
inline int name() const; \
inline void set_##name(int value);
#define DECL_BOOLEAN_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, bool)
#define DECL_INT32_ACCESSORS(name) \
inline int32_t name() const; \
inline void set_##name(int32_t value);
#define DECL_INT_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, int)
#define DECL_INT32_ACCESSORS(name) DECL_PRIMITIVE_ACCESSORS(name, int32_t)
#define DECL_ACCESSORS(name, type) \
inline type* name() const; \

View File

@ -1097,13 +1097,11 @@ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
Map::kDescriptorsOffset);
SetInternalReference(map, entry, "prototype", map->prototype(),
Map::kPrototypeOffset);
#if V8_DOUBLE_FIELDS_UNBOXING
if (FLAG_unbox_double_fields) {
SetInternalReference(map, entry, "layout_descriptor",
map->layout_descriptor(),
Map::kLayoutDescriptorOffset);
}
#endif
Object* constructor_or_backpointer = map->constructor_or_backpointer();
if (constructor_or_backpointer->IsMap()) {
TagObject(constructor_or_backpointer, "(back pointer)");