Commit 4655c9d3 authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

[heap] Move all Maps into RO_SPACE

Allocates almost all maps found in the start up snapshot into RO_SPACE.
There are 2 JSObject maps that are excluded as they contain a mutable cell.

Also updates VerifyReadOnlyPointers to check that RO_SPACE objects' maps are
also in RO_SPACE. Previously the invariant did not hold for Strings which still
had their maps in MAP_SPACE.

Also moves invalid_prototype_validity_cell to RO_SPACE.

    RO_SPACE  NEW_SPACE  OLD_SPACE  CODE_SPACE  MAP_SPACE  LO_SPACE
old    22024          0     229184       32928       8184         0
new    31488          0     229184       32928        176         0

Bug: v8:7464
Change-Id: I870d22cc5234ba60b3ef8a2ada590ee6ae426c9f
Reviewed-on: https://chromium-review.googlesource.com/1013494Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52848}
parent e4df1398
......@@ -1685,7 +1685,7 @@ Handle<Map> Factory::NewMap(InstanceType type, int instance_size,
ElementsKind elements_kind,
int inobject_properties) {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
DCHECK_IMPLIES(type >= FIRST_JS_OBJECT_TYPE &&
DCHECK_IMPLIES(Map::IsJSObject(type) &&
!Map::CanHaveFastTransitionableElementsKind(type),
IsDictionaryElementsKind(elements_kind) ||
IsTerminalElementsKind(elements_kind));
......@@ -1705,6 +1705,7 @@ Map* Factory::InitializeMap(Map* map, InstanceType type, int instance_size,
map->set_constructor_or_backpointer(*null_value(), SKIP_WRITE_BARRIER);
map->set_instance_size(instance_size);
if (map->IsJSObjectMap()) {
DCHECK(!isolate()->heap()->InReadOnlySpace(map));
map->SetInObjectPropertiesStartInWords(instance_size / kPointerSize -
inobject_properties);
DCHECK_EQ(map->GetInObjectProperties(), inobject_properties);
......
......@@ -366,6 +366,10 @@ bool Heap::InToSpace(HeapObject* heap_object) {
bool Heap::InOldSpace(Object* object) { return old_space_->Contains(object); }
bool Heap::InReadOnlySpace(Object* object) {
return read_only_space_->Contains(object);
}
bool Heap::InNewSpaceSlow(Address address) {
return new_space_->ContainsSlow(address);
}
......
......@@ -3669,13 +3669,16 @@ class VerifyReadOnlyPointersVisitor : public VerifyPointersVisitor {
protected:
void VerifyPointers(HeapObject* host, MaybeObject** start,
MaybeObject** end) override {
Heap* heap = host->GetIsolate()->heap();
if (host != nullptr) {
CHECK(heap->InReadOnlySpace(host->map()));
}
VerifyPointersVisitor::VerifyPointers(host, start, end);
for (MaybeObject** current = start; current < end; current++) {
HeapObject* object;
if ((*current)->ToStrongOrWeakHeapObject(&object)) {
CHECK(
object->GetIsolate()->heap()->read_only_space()->Contains(object));
CHECK(heap->InReadOnlySpace(object));
}
}
}
......
......@@ -1365,6 +1365,9 @@ class Heap {
// Returns whether the object resides in old space.
inline bool InOldSpace(Object* object);
// Returns whether the object resides in read-only space.
inline bool InReadOnlySpace(Object* object);
// Checks whether an address/object in the heap (including auxiliary
// area and unused area).
bool Contains(HeapObject* value);
......
......@@ -83,18 +83,33 @@ AllocationResult Heap::AllocateMap(InstanceType instance_type,
ElementsKind elements_kind,
int inobject_properties) {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
DCHECK_IMPLIES(instance_type >= FIRST_JS_OBJECT_TYPE &&
bool is_js_object = Map::IsJSObject(instance_type);
DCHECK_IMPLIES(is_js_object &&
!Map::CanHaveFastTransitionableElementsKind(instance_type),
IsDictionaryElementsKind(elements_kind) ||
IsTerminalElementsKind(elements_kind));
HeapObject* result = nullptr;
AllocationResult allocation = AllocateRaw(Map::kSize, MAP_SPACE);
// JSObjects have maps with a mutable prototype_validity_cell, so they cannot
// go in RO_SPACE.
AllocationResult allocation =
AllocateRaw(Map::kSize, is_js_object ? MAP_SPACE : RO_SPACE);
if (!allocation.To(&result)) return allocation;
result->set_map_after_allocation(meta_map(), SKIP_WRITE_BARRIER);
return isolate()->factory()->InitializeMap(Map::cast(result), instance_type,
instance_size, elements_kind,
inobject_properties);
Map* map = isolate()->factory()->InitializeMap(
Map::cast(result), instance_type, instance_size, elements_kind,
inobject_properties);
if (!is_js_object) {
// Eagerly initialize the WeakCell cache for the map as it will not be
// writable in RO_SPACE.
HandleScope handle_scope(isolate());
Handle<WeakCell> weak_cell =
isolate()->factory()->NewWeakCell(Handle<Map>(map), TENURED_READ_ONLY);
map->set_weak_cell_cache(*weak_cell);
}
return map;
}
AllocationResult Heap::AllocatePartialMap(InstanceType instance_type,
......
......@@ -487,25 +487,25 @@ void Map::NotifyLeafMapLayoutChange() {
}
}
bool Map::IsJSObject(InstanceType type) {
STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE);
return type >= FIRST_JS_OBJECT_TYPE;
}
bool Map::CanTransition() const {
// Only JSObject and subtypes have map transitions and back pointers.
STATIC_ASSERT(LAST_TYPE == LAST_JS_OBJECT_TYPE);
return instance_type() >= FIRST_JS_OBJECT_TYPE;
return IsJSObject(instance_type());
}
bool Map::IsBooleanMap() const { return this == GetHeap()->boolean_map(); }
bool Map::IsPrimitiveMap() const {
STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
return instance_type() <= LAST_PRIMITIVE_TYPE;
}
bool Map::IsJSReceiverMap() const {
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
return instance_type() >= FIRST_JS_RECEIVER_TYPE;
}
bool Map::IsJSObjectMap() const {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
return instance_type() >= FIRST_JS_OBJECT_TYPE;
}
bool Map::IsJSObjectMap() const { return IsJSObject(instance_type()); }
bool Map::IsJSPromiseMap() const { return instance_type() == JS_PROMISE_TYPE; }
bool Map::IsJSArrayMap() const { return instance_type() == JS_ARRAY_TYPE; }
bool Map::IsJSFunctionMap() const {
......
......@@ -736,6 +736,8 @@ class Map : public HeapObject {
// found at all.
Map* FindElementsKindTransitionedMap(MapHandles const& candidates);
inline static bool IsJSObject(InstanceType type);
inline bool CanTransition() const;
inline bool IsBooleanMap() const;
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment