Commit 99bf9068 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[in-place weak refs] Replace the WeakCell(transition_map) in DataHandlers.

BUG=v8:7308

Change-Id: Ia74e5696133ec183ff550da011452b0c12a06e40
Reviewed-on: https://chromium-review.googlesource.com/1068883
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53350}
parent e5630ea9
......@@ -18,6 +18,7 @@ namespace internal {
class BigInt;
class BytecodeArray;
class DataHandler;
class JSArrayBuffer;
class JSRegExp;
class JSWeakCollection;
......@@ -31,6 +32,7 @@ class JSWeakCollection;
V(Code) \
V(CodeDataContainer) \
V(ConsString) \
V(DataHandler) \
V(FeedbackCell) \
V(FeedbackVector) \
V(FixedArray) \
......
......@@ -26,7 +26,7 @@ using SloppyTNode = compiler::SloppyTNode<T>;
//////////////////// Private helpers.
// Loads dataX field from the DataHandler object.
TNode<Object> AccessorAssembler::LoadHandlerDataField(
TNode<MaybeObject> AccessorAssembler::LoadHandlerDataField(
SloppyTNode<DataHandler> handler, int data_index) {
#ifdef DEBUG
TNode<Map> handler_map = LoadMap(handler);
......@@ -58,7 +58,7 @@ TNode<Object> AccessorAssembler::LoadHandlerDataField(
CSA_ASSERT(this, UintPtrGreaterThanOrEqual(
LoadMapInstanceSizeInWords(handler_map),
IntPtrConstant(minimum_size / kPointerSize)));
return LoadObjectField(handler, offset);
return LoadMaybeWeakObjectField(handler, offset);
}
TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
......@@ -476,8 +476,8 @@ void AccessorAssembler::HandleLoadICSmiHandlerCase(
// the access check is enabled for this handler or not.
TNode<Object> context_cell = Select<Object>(
IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
[=] { return LoadHandlerDataField(handler, 3); },
[=] { return LoadHandlerDataField(handler, 2); });
[=] { return CAST(LoadHandlerDataField(handler, 3)); },
[=] { return CAST(LoadHandlerDataField(handler, 2)); });
Node* context = LoadWeakCellValueUnchecked(CAST(context_cell));
Node* foreign =
......@@ -661,7 +661,7 @@ Node* AccessorAssembler::HandleProtoHandler(
BIND(&if_do_access_check);
{
Node* data2 = LoadHandlerDataField(handler, 2);
TNode<WeakCell> data2 = CAST(LoadHandlerDataField(handler, 2));
Node* expected_native_context = LoadWeakCellValue(data2, miss);
EmitAccessCheck(expected_native_context, p->context, p->receiver, &done,
miss);
......@@ -722,7 +722,7 @@ void AccessorAssembler::HandleLoadICProtoHandler(
},
miss, ic_mode);
Node* maybe_holder_cell = LoadHandlerDataField(handler, 1);
TNode<Object> maybe_holder_cell = CAST(LoadHandlerDataField(handler, 1));
Label load_from_cached_holder(this), done(this);
......@@ -733,7 +733,7 @@ void AccessorAssembler::HandleLoadICProtoHandler(
// For regular holders, having passed the receiver map check and the
// validity cell check implies that |holder| is alive. However, for
// global object receivers, the |maybe_holder_cell| may be cleared.
Node* holder = LoadWeakCellValue(maybe_holder_cell, miss);
Node* holder = LoadWeakCellValue(CAST(maybe_holder_cell), miss);
var_holder->Bind(holder);
Goto(&done);
......@@ -1220,9 +1220,10 @@ void AccessorAssembler::HandleStoreICProtoHandler(
BIND(&if_transitioning_element_store);
{
Node* transition_map_cell = LoadHandlerDataField(handler, 1);
Node* transition_map = LoadWeakCellValue(transition_map_cell, miss);
CSA_ASSERT(this, IsMap(transition_map));
TNode<MaybeObject> maybe_transition_map =
LoadHandlerDataField(handler, 1);
TNode<Map> transition_map =
CAST(ToWeakHeapObject(maybe_transition_map, miss));
GotoIf(IsDeprecatedMap(transition_map), miss);
......@@ -1262,7 +1263,7 @@ void AccessorAssembler::HandleStoreICProtoHandler(
GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kNormal)),
&if_add_normal);
Node* holder_cell = LoadHandlerDataField(handler, 1);
TNode<WeakCell> holder_cell = CAST(LoadHandlerDataField(handler, 1));
Node* holder = LoadWeakCellValue(holder_cell, miss);
GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kGlobalProxy)),
......@@ -1321,8 +1322,8 @@ void AccessorAssembler::HandleStoreICProtoHandler(
// the access check is enabled for this handler or not.
TNode<Object> context_cell = Select<Object>(
IsSetWord<LoadHandler::DoAccessCheckOnReceiverBits>(handler_word),
[=] { return LoadHandlerDataField(handler, 3); },
[=] { return LoadHandlerDataField(handler, 2); });
[=] { return CAST(LoadHandlerDataField(handler, 3)); },
[=] { return CAST(LoadHandlerDataField(handler, 2)); });
Node* context = LoadWeakCellValueUnchecked(CAST(context_cell));
......@@ -3078,9 +3079,10 @@ void AccessorAssembler::StoreInArrayLiteralIC(const StoreICParameters* p) {
BIND(&if_transitioning_element_store);
{
Node* transition_map_cell = LoadHandlerDataField(CAST(handler), 1);
Node* transition_map = LoadWeakCellValue(transition_map_cell, &miss);
CSA_ASSERT(this, IsMap(transition_map));
TNode<MaybeObject> maybe_transition_map =
LoadHandlerDataField(CAST(handler), 1);
TNode<Map> transition_map =
CAST(ToWeakHeapObject(maybe_transition_map, &miss));
GotoIf(IsDeprecatedMap(transition_map), &miss);
Node* code = LoadObjectField(handler, StoreHandler::kSmiHandlerOffset);
CSA_ASSERT(this, IsCode(code));
......
......@@ -88,8 +88,8 @@ class AccessorAssembler : public CodeStubAssembler {
void LoadIC_BytecodeHandler(const LoadICParameters* p, ExitPoint* exit_point);
// Loads dataX field from the DataHandler object.
TNode<Object> LoadHandlerDataField(SloppyTNode<DataHandler> handler,
int data_index);
TNode<MaybeObject> LoadHandlerDataField(SloppyTNode<DataHandler> handler,
int data_index);
protected:
struct StoreICParameters : public LoadICParameters {
......
......@@ -59,7 +59,7 @@ int InitPrototypeChecksImpl(Isolate* isolate, Handle<ICHandler> handler,
}
}
if (fill_handler) {
handler->set_data1(*data1);
handler->set_data1(MaybeObject::FromObject(*data1));
}
Handle<Object> data2;
if (maybe_data2.ToHandle(&data2)) {
......@@ -187,11 +187,10 @@ Handle<Object> StoreHandler::StoreElementTransition(
.GetCode();
Handle<Object> validity_cell =
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate);
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
Handle<StoreHandler> handler = isolate->factory()->NewStoreHandler(1);
handler->set_smi_handler(*stub);
handler->set_validity_cell(*validity_cell);
handler->set_data1(*cell);
handler->set_data1(HeapObjectReference::Weak(*transition));
return handler;
}
......
......@@ -529,6 +529,31 @@ class Map::BodyDescriptor final : public BodyDescriptorBase {
static inline int SizeOf(Map* map, HeapObject* obj) { return Map::kSize; }
};
class DataHandler::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map* map, HeapObject* obj, int offset) {
return offset >= HeapObject::kHeaderSize;
}
template <typename ObjectVisitor>
static inline void IterateBody(Map* map, HeapObject* obj, int object_size,
ObjectVisitor* v) {
static_assert(kSmiHandlerOffset < kData1Offset,
"Field order must be in sync with this iteration code");
static_assert(kData1Offset < kSizeWithData1,
"Field order must be in sync with this iteration code");
IteratePointers(obj, kSmiHandlerOffset, kData1Offset, v);
if (object_size >= kSizeWithData1) {
IterateMaybeWeakPointer(obj, kData1Offset, v);
IteratePointers(obj, kData1Offset + kPointerSize, object_size, v);
}
}
static inline int SizeOf(Map* map, HeapObject* object) {
return object->SizeFromMap(map);
}
};
template <typename Op, typename ReturnType, typename T1, typename T2,
typename T3, typename T4>
ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
......@@ -701,9 +726,10 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
}
case CALL_HANDLER_INFO_TYPE:
return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
case LOAD_HANDLER_TYPE:
case STORE_HANDLER_TYPE:
return Op::template apply<StructBodyDescriptor>(p1, p2, p3, p4);
return Op::template apply<DataHandler::BodyDescriptor>(p1, p2, p3, p4);
default:
PrintF("Unknown type: %d\n", type);
UNREACHABLE();
......
......@@ -1629,7 +1629,7 @@ void DataHandler::DataHandlerVerify() {
CHECK(validity_cell()->IsSmi() || validity_cell()->IsCell());
int data_count = data_field_count();
if (data_count >= 1) {
VerifyObjectField(kData1Offset);
VerifyMaybeObjectField(kData1Offset);
}
if (data_count >= 2) {
VerifyObjectField(kData2Offset);
......
......@@ -969,6 +969,10 @@ void HeapObject::VerifyObjectField(int offset) {
VerifyPointer(READ_FIELD(this, offset));
}
void HeapObject::VerifyMaybeObjectField(int offset) {
MaybeObject::VerifyMaybeObjectPointer(READ_WEAK_FIELD(this, offset));
}
void HeapObject::VerifySmiField(int offset) {
CHECK(READ_FIELD(this, offset)->IsSmi());
}
......
......@@ -1729,7 +1729,7 @@ void LoadHandler::LoadHandlerPrint(std::ostream& os) { // NOLINT
os << "\n - validity_cell: " << Brief(validity_cell());
int data_count = data_field_count();
if (data_count >= 1) {
os << "\n - data1: " << Brief(data1());
os << "\n - data1: " << MaybeObjectBrief(data1());
}
if (data_count >= 2) {
os << "\n - data2: " << Brief(data2());
......@@ -1747,7 +1747,7 @@ void StoreHandler::StoreHandlerPrint(std::ostream& os) { // NOLINT
os << "\n - validity_cell: " << Brief(validity_cell());
int data_count = data_field_count();
if (data_count >= 1) {
os << "\n - data1: " << Brief(data1());
os << "\n - data1: " << MaybeObjectBrief(data1());
}
if (data_count >= 2) {
os << "\n - data2: " << Brief(data2());
......
......@@ -3140,7 +3140,7 @@ VisitorId Map::GetVisitorId(Map* map) {
case LOAD_HANDLER_TYPE:
case STORE_HANDLER_TYPE:
return kVisitStruct;
return kVisitDataHandler;
default:
UNREACHABLE();
......
......@@ -1869,6 +1869,7 @@ class HeapObject: public Object {
#ifdef VERIFY_HEAP
inline void VerifyObjectField(int offset);
inline void VerifySmiField(int offset);
inline void VerifyMaybeObjectField(int offset);
// Verify a pointer is a valid HeapObject pointer that points to object
// areas in the heap.
......
......@@ -26,8 +26,8 @@ int DataHandler::data_field_count() const {
return (map()->instance_size() - kSizeWithData0) / kPointerSize;
}
ACCESSORS_CHECKED(DataHandler, data1, Object, kData1Offset,
map()->instance_size() >= kSizeWithData1)
WEAK_ACCESSORS_CHECKED(DataHandler, data1, kData1Offset,
map()->instance_size() >= kSizeWithData1)
ACCESSORS_CHECKED(DataHandler, data2, Object, kData2Offset,
map()->instance_size() >= kSizeWithData2)
ACCESSORS_CHECKED(DataHandler, data3, Object, kData3Offset,
......
......@@ -31,7 +31,7 @@ class DataHandler : public Struct {
// [data1-3]: These are optional general-purpose fields whose content and
// presence depends on the handler kind.
DECL_ACCESSORS(data1, Object)
DECL_ACCESSORS(data1, MaybeObject)
DECL_ACCESSORS(data2, Object)
DECL_ACCESSORS(data3, Object)
......@@ -53,6 +53,8 @@ class DataHandler : public Struct {
DECL_CAST(DataHandler)
DECL_VERIFIER(DataHandler)
class BodyDescriptor;
};
} // namespace internal
......
......@@ -25,6 +25,7 @@ namespace internal {
V(Code) \
V(CodeDataContainer) \
V(ConsString) \
V(DataHandler) \
V(DataObject) \
V(FeedbackCell) \
V(FeedbackVector) \
......
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