Commit 1684cd8b authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[in-place weak refs] Add MaybeObjectHandle.

This gets rid of the weakness hacks which were needed for remembering that maps
as handlers are weak, and other handles are strong.

BUG=v8:7308

Change-Id: I7fd3252ba67350803e2207dc12bbdf6abbae7e23
Reviewed-on: https://chromium-review.googlesource.com/1055449Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53151}
parent 8ec92f51
......@@ -668,15 +668,11 @@ bool FeedbackNexus::ConfigureLexicalVarMode(int script_context_index,
return true;
}
void FeedbackNexus::ConfigureHandlerMode(Handle<Object> handler) {
void FeedbackNexus::ConfigureHandlerMode(const MaybeObjectHandle& handler) {
DCHECK(IsGlobalICKind(kind()));
DCHECK(IC::IsHandler(*handler));
SetFeedback(GetIsolate()->heap()->empty_weak_cell());
if (handler->IsMap()) {
SetFeedbackExtra(HeapObjectReference::Weak(HeapObject::cast(*handler)));
} else {
SetFeedbackExtra(*handler);
}
SetFeedbackExtra(*handler);
}
int FeedbackNexus::GetCallCount() {
......@@ -722,7 +718,7 @@ float FeedbackNexus::ComputeCallFrequency() {
void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name,
Handle<Map> receiver_map,
Handle<Object> handler) {
const MaybeObjectHandle& handler) {
DCHECK(handler.is_null() || IC::IsHandler(*handler));
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
if (kind() == FeedbackSlotKind::kStoreDataPropertyInLiteral) {
......@@ -731,27 +727,19 @@ void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name,
} else {
if (name.is_null()) {
SetFeedback(*cell);
if (handler->IsMap()) {
SetFeedbackExtra(HeapObjectReference::Weak(*handler));
} else {
SetFeedbackExtra(*handler);
}
SetFeedbackExtra(*handler);
} else {
Handle<WeakFixedArray> array = EnsureExtraArrayOfSize(2);
SetFeedback(*name);
array->Set(0, HeapObjectReference::Strong(*cell));
if (handler->IsMap()) {
array->Set(1, HeapObjectReference::Weak(*handler));
} else {
array->Set(1, MaybeObject::FromObject(*handler));
}
array->Set(1, *handler);
}
}
}
void FeedbackNexus::ConfigurePolymorphic(Handle<Name> name,
MapHandles const& maps,
ObjectHandles* handlers) {
MaybeObjectHandles* handlers) {
DCHECK_EQ(handlers->size(), maps.size());
int receiver_count = static_cast<int>(maps.size());
DCHECK_GT(receiver_count, 1);
......@@ -770,13 +758,7 @@ void FeedbackNexus::ConfigurePolymorphic(Handle<Name> name,
Handle<WeakCell> cell = Map::WeakCellForMap(map);
array->Set(current * 2, HeapObjectReference::Strong(*cell));
DCHECK(IC::IsHandler(*handlers->at(current)));
if (handlers->at(current)->IsMap()) {
array->Set(current * 2 + 1,
HeapObjectReference::Weak(*handlers->at(current)));
} else {
array->Set(current * 2 + 1,
MaybeObject::FromObject(*handlers->at(current)));
}
array->Set(current * 2 + 1, *handlers->at(current));
}
}
......@@ -819,7 +801,7 @@ int FeedbackNexus::ExtractMaps(MapHandles* maps) const {
return 0;
}
MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
MaybeObjectHandle FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
DCHECK(IsLoadICKind(kind()) || IsStoreICKind(kind()) ||
IsKeyedLoadICKind(kind()) || IsKeyedStoreICKind(kind()) ||
IsStoreOwnICKind(kind()) || IsStoreDataPropertyInLiteralKind(kind()));
......@@ -841,8 +823,7 @@ MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
Map* array_map = Map::cast(cell->value());
if (array_map == *map &&
!array->Get(i + increment - 1)->IsClearedWeakHeapObject()) {
// This converts a weak reference to a strong reference.
Object* handler = array->Get(i + increment - 1)->GetHeapObjectOrSmi();
MaybeObject* handler = array->Get(i + increment - 1);
DCHECK(IC::IsHandler(handler));
return handle(handler, isolate);
}
......@@ -853,18 +834,18 @@ MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
if (!cell->cleared()) {
Map* cell_map = Map::cast(cell->value());
if (cell_map == *map && !GetFeedbackExtra()->IsClearedWeakHeapObject()) {
// This converts a weak reference to a strong reference.
Object* handler = GetFeedbackExtra()->GetHeapObjectOrSmi();
MaybeObject* handler = GetFeedbackExtra();
DCHECK(IC::IsHandler(handler));
return handle(handler, isolate);
}
}
}
return MaybeHandle<Code>();
return MaybeObjectHandle();
}
bool FeedbackNexus::FindHandlers(ObjectHandles* code_list, int length) const {
bool FeedbackNexus::FindHandlers(MaybeObjectHandles* code_list,
int length) const {
DCHECK(IsLoadICKind(kind()) || IsStoreICKind(kind()) ||
IsKeyedLoadICKind(kind()) || IsKeyedStoreICKind(kind()) ||
IsStoreOwnICKind(kind()) || IsStoreDataPropertyInLiteralKind(kind()) ||
......@@ -887,8 +868,7 @@ bool FeedbackNexus::FindHandlers(ObjectHandles* code_list, int length) const {
// Be sure to skip handlers whose maps have been cleared.
if (!cell->cleared() &&
!array->Get(i + increment - 1)->IsClearedWeakHeapObject()) {
// This converts a weak reference to a strong reference.
Object* handler = array->Get(i + increment - 1)->GetHeapObjectOrSmi();
MaybeObject* handler = array->Get(i + increment - 1);
DCHECK(IC::IsHandler(handler));
code_list->push_back(handle(handler, isolate));
count++;
......@@ -898,10 +878,8 @@ bool FeedbackNexus::FindHandlers(ObjectHandles* code_list, int length) const {
WeakCell* cell = WeakCell::cast(feedback);
MaybeObject* extra = GetFeedbackExtra();
if (!cell->cleared() && !extra->IsClearedWeakHeapObject()) {
// This converts a weak reference to a strong reference.
Object* handler = extra->GetHeapObjectOrSmi();
DCHECK(IC::IsHandler(handler));
code_list->push_back(handle(handler, isolate));
DCHECK(IC::IsHandler(extra));
code_list->push_back(handle(extra, isolate));
count++;
}
}
......@@ -921,13 +899,13 @@ Name* FeedbackNexus::FindFirstName() const {
KeyedAccessLoadMode FeedbackNexus::GetKeyedAccessLoadMode() const {
DCHECK(IsKeyedLoadICKind(kind()));
MapHandles maps;
ObjectHandles handlers;
MaybeObjectHandles handlers;
if (GetKeyType() == PROPERTY) return STANDARD_LOAD;
ExtractMaps(&maps);
FindHandlers(&handlers, static_cast<int>(maps.size()));
for (Handle<Object> const& handler : handlers) {
for (MaybeObjectHandle const& handler : handlers) {
KeyedAccessLoadMode mode = LoadHandler::GetKeyedAccessLoadMode(*handler);
if (mode != STANDARD_LOAD) return mode;
}
......@@ -939,26 +917,27 @@ KeyedAccessStoreMode FeedbackNexus::GetKeyedAccessStoreMode() const {
DCHECK(IsKeyedStoreICKind(kind()) || IsStoreInArrayLiteralICKind(kind()));
KeyedAccessStoreMode mode = STANDARD_STORE;
MapHandles maps;
ObjectHandles handlers;
MaybeObjectHandles handlers;
if (GetKeyType() == PROPERTY) return mode;
ExtractMaps(&maps);
FindHandlers(&handlers, static_cast<int>(maps.size()));
for (const Handle<Object>& maybe_code_handler : handlers) {
for (const MaybeObjectHandle& maybe_code_handler : handlers) {
// The first handler that isn't the slow handler will have the bits we need.
Handle<Code> handler;
if (maybe_code_handler->IsStoreHandler()) {
if (maybe_code_handler.object()->IsStoreHandler()) {
Handle<StoreHandler> data_handler =
Handle<StoreHandler>::cast(maybe_code_handler);
Handle<StoreHandler>::cast(maybe_code_handler.object());
handler = handle(Code::cast(data_handler->smi_handler()));
} else if (maybe_code_handler->IsSmi()) {
} else if (maybe_code_handler.object()->IsSmi()) {
// Skip proxy handlers.
DCHECK_EQ(*maybe_code_handler, *StoreHandler::StoreProxy(GetIsolate()));
DCHECK_EQ(*(maybe_code_handler.object()),
*StoreHandler::StoreProxy(GetIsolate()));
continue;
} else {
// Element store without prototype chain check.
handler = Handle<Code>::cast(maybe_code_handler);
handler = Handle<Code>::cast(maybe_code_handler.object());
if (handler->is_builtin()) continue;
}
CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
......
......@@ -129,7 +129,7 @@ inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind);
typedef std::vector<Handle<Object>> ObjectHandles;
typedef std::vector<MaybeObjectHandle> MaybeObjectHandles;
class FeedbackMetadata;
......@@ -595,8 +595,8 @@ class FeedbackNexus final {
InlineCacheState StateFromFeedback() const;
int ExtractMaps(MapHandles* maps) const;
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
bool FindHandlers(ObjectHandles* code_list, int length = -1) const;
MaybeObjectHandle FindHandlerForMap(Handle<Map> map) const;
bool FindHandlers(MaybeObjectHandles* code_list, int length = -1) const;
bool IsCleared() const {
InlineCacheState state = StateFromFeedback();
......@@ -615,10 +615,10 @@ class FeedbackNexus final {
inline Isolate* GetIsolate() const;
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
Handle<Object> handler);
const MaybeObjectHandle& handler);
void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps,
ObjectHandles* handlers);
MaybeObjectHandles* handlers);
BinaryOperationHint GetBinaryOperationFeedback() const;
CompareOperationHint GetCompareOperationFeedback() const;
......@@ -657,7 +657,7 @@ class FeedbackNexus final {
// Returns false if given combination of indices is not allowed.
bool ConfigureLexicalVarMode(int script_context_index,
int context_slot_index);
void ConfigureHandlerMode(Handle<Object> handler);
void ConfigureHandlerMode(const MaybeObjectHandle& handler);
// Bit positions in a smi that encodes lexical environment variable access.
#define LEXICAL_MODE_BIT_FIELDS(V, _) \
......
......@@ -9,6 +9,7 @@
#include "src/isolate.h"
#include "src/msan.h"
#include "src/objects-inl.h"
#include "src/objects/maybe-object-inl.h"
namespace v8 {
namespace internal {
......@@ -44,6 +45,65 @@ inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) {
return os << Brief(*handle);
}
MaybeObjectHandle::MaybeObjectHandle()
: reference_type_(HeapObjectReferenceType::STRONG),
handle_(Handle<Object>::null()) {}
MaybeObjectHandle::MaybeObjectHandle(MaybeObject* object, Isolate* isolate) {
HeapObject* heap_object;
DCHECK(!object->IsClearedWeakHeapObject());
if (object->ToWeakHeapObject(&heap_object)) {
handle_ = handle(heap_object, isolate);
reference_type_ = HeapObjectReferenceType::WEAK;
} else {
handle_ = handle(object->ToObject(), isolate);
reference_type_ = HeapObjectReferenceType::STRONG;
}
}
MaybeObjectHandle::MaybeObjectHandle(Handle<Object> object)
: reference_type_(HeapObjectReferenceType::STRONG), handle_(object) {}
MaybeObjectHandle::MaybeObjectHandle(Object* object, Isolate* isolate)
: reference_type_(HeapObjectReferenceType::STRONG),
handle_(object, isolate) {}
MaybeObjectHandle::MaybeObjectHandle(Object* object,
HeapObjectReferenceType reference_type,
Isolate* isolate)
: reference_type_(reference_type), handle_(handle(object, isolate)) {}
MaybeObjectHandle::MaybeObjectHandle(Handle<Object> object,
HeapObjectReferenceType reference_type)
: reference_type_(reference_type), handle_(object) {}
MaybeObjectHandle MaybeObjectHandle::Weak(Handle<Object> object) {
return MaybeObjectHandle(object, HeapObjectReferenceType::WEAK);
}
MaybeObject* MaybeObjectHandle::operator*() const {
if (reference_type_ == HeapObjectReferenceType::WEAK) {
return HeapObjectReference::Weak(*handle_.ToHandleChecked());
} else {
return MaybeObject::FromObject(*handle_.ToHandleChecked());
}
}
MaybeObject* MaybeObjectHandle::operator->() const {
if (reference_type_ == HeapObjectReferenceType::WEAK) {
return HeapObjectReference::Weak(*handle_.ToHandleChecked());
} else {
return MaybeObject::FromObject(*handle_.ToHandleChecked());
}
}
Handle<Object> MaybeObjectHandle::object() const {
return handle_.ToHandleChecked();
}
inline MaybeObjectHandle handle(MaybeObject* object, Isolate* isolate) {
return MaybeObjectHandle(object, isolate);
}
HandleScope::~HandleScope() {
#ifdef DEBUG
......
......@@ -235,6 +235,43 @@ class MaybeHandle final {
friend class MaybeHandle;
};
// A handle which contains a potentially weak pointer. Keeps it alive (strongly)
// while the MaybeObjectHandle is alive.
class MaybeObjectHandle {
public:
inline MaybeObjectHandle();
inline MaybeObjectHandle(MaybeObject* object, Isolate* isolate);
inline MaybeObjectHandle(Object* object, Isolate* isolate);
inline explicit MaybeObjectHandle(Handle<Object> object);
static inline MaybeObjectHandle Weak(Object* object, Isolate* isolate);
static inline MaybeObjectHandle Weak(Handle<Object> object);
inline MaybeObject* operator*() const;
inline MaybeObject* operator->() const;
inline Handle<Object> object() const;
bool is_identical_to(const MaybeObjectHandle& other) const {
Handle<Object> this_handle;
Handle<Object> other_handle;
return reference_type_ == other.reference_type_ &&
handle_.ToHandle(&this_handle) ==
other.handle_.ToHandle(&other_handle) &&
this_handle.is_identical_to(other_handle);
}
bool is_null() const { return handle_.is_null(); }
private:
inline MaybeObjectHandle(Object* object,
HeapObjectReferenceType reference_type,
Isolate* isolate);
inline MaybeObjectHandle(Handle<Object> object,
HeapObjectReferenceType reference_type);
HeapObjectReferenceType reference_type_;
MaybeHandle<Object> handle_;
};
// ----------------------------------------------------------------------------
// A stack-allocated class that governs a number of local handles.
......
......@@ -162,10 +162,10 @@ Handle<Object> LoadHandler::LoadFullChain(Isolate* isolate,
}
// static
KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(Object* handler) {
KeyedAccessLoadMode LoadHandler::GetKeyedAccessLoadMode(MaybeObject* handler) {
DisallowHeapAllocation no_gc;
if (handler->IsSmi()) {
int const raw_handler = Smi::cast(handler)->value();
int const raw_handler = Smi::cast(handler->ToSmi())->value();
Kind const kind = KindBits::decode(raw_handler);
if ((kind == kElement || kind == kIndexedString) &&
AllowOutOfBoundsBits::decode(raw_handler)) {
......@@ -195,8 +195,8 @@ Handle<Object> StoreHandler::StoreElementTransition(
return handler;
}
Handle<Object> StoreHandler::StoreTransition(Isolate* isolate,
Handle<Map> transition_map) {
MaybeObjectHandle StoreHandler::StoreTransition(Isolate* isolate,
Handle<Map> transition_map) {
bool is_dictionary_map = transition_map->is_dictionary_map();
#ifdef DEBUG
if (!is_dictionary_map) {
......@@ -229,14 +229,14 @@ Handle<Object> StoreHandler::StoreTransition(Isolate* isolate,
int config = KindBits::encode(kNormal) | LookupOnReceiverBits::encode(true);
handler->set_smi_handler(Smi::FromInt(config));
handler->set_validity_cell(*validity_cell);
return handler;
return MaybeObjectHandle(handler);
} else {
// Ensure the transition map contains a valid prototype validity cell.
if (!validity_cell.is_null()) {
transition_map->set_prototype_validity_cell(*validity_cell);
}
return transition_map;
return MaybeObjectHandle::Weak(transition_map);
}
}
......
......@@ -175,7 +175,7 @@ class LoadHandler final : public DataHandler {
KeyedAccessLoadMode load_mode);
// Decodes the KeyedAccessLoadMode from a {handler}.
static KeyedAccessLoadMode GetKeyedAccessLoadMode(Object* handler);
static KeyedAccessLoadMode GetKeyedAccessLoadMode(MaybeObject* handler);
};
// A set of bit fields representing Smi handlers for stores and a HeapObject
......@@ -249,8 +249,8 @@ class StoreHandler final : public DataHandler {
PropertyConstness constness,
Representation representation);
static Handle<Object> StoreTransition(Isolate* isolate,
Handle<Map> transition_map);
static MaybeObjectHandle StoreTransition(Isolate* isolate,
Handle<Map> transition_map);
// Creates a Smi-handler for storing a native data property on a fast object.
static inline Handle<Smi> StoreNativeDataProperty(Isolate* isolate,
......
......@@ -39,15 +39,17 @@ Address IC::raw_constant_pool() const {
}
}
bool IC::IsHandler(Object* object) {
return (object->IsSmi() && (object != nullptr)) || object->IsDataHandler() ||
object->IsMap() ||
(object->IsWeakCell() &&
(WeakCell::cast(object)->cleared() ||
WeakCell::cast(object)->value()->IsMap() ||
WeakCell::cast(object)->value()->IsPropertyCell())) ||
object->IsCode();
bool IC::IsHandler(MaybeObject* object) {
HeapObject* heap_object;
return (object->IsSmi() && (object != nullptr)) ||
(object->ToWeakHeapObject(&heap_object) && heap_object->IsMap()) ||
(object->ToStrongHeapObject(&heap_object) &&
(heap_object->IsDataHandler() ||
(heap_object->IsWeakCell() &&
(WeakCell::cast(heap_object)->cleared() ||
WeakCell::cast(heap_object)->value()->IsMap() ||
WeakCell::cast(heap_object)->value()->IsPropertyCell())) ||
heap_object->IsCode()));
}
bool IC::AddressIsDeoptimizedCode() const {
......
This diff is collapsed.
......@@ -64,7 +64,7 @@ class IC {
IsKeyedStoreIC() || IsStoreInArrayLiteralICKind(kind());
}
static inline bool IsHandler(Object* object);
static inline bool IsHandler(MaybeObject* object);
// Nofity the IC system that a feedback has changed.
static void OnFeedbackChanged(Isolate* isolate, FeedbackVector* vector,
......@@ -101,9 +101,11 @@ class IC {
// Configure the vector for MONOMORPHIC.
void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Object> handler);
void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
const MaybeObjectHandle& handler);
// Configure the vector for POLYMORPHIC.
void ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
ObjectHandles* handlers);
MaybeObjectHandles* handlers);
char TransitionMarkFromState(IC::State state);
void TraceIC(const char* type, Handle<Object> name);
......@@ -116,16 +118,17 @@ class IC {
void TraceHandlerCacheHitStats(LookupIterator* lookup);
void UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name);
bool UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code);
void UpdateMonomorphicIC(const MaybeObjectHandle& handler, Handle<Name> name);
bool UpdatePolymorphicIC(Handle<Name> name, const MaybeObjectHandle& handler);
void UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
Handle<Object> code);
const MaybeObjectHandle& handler);
StubCache* stub_cache();
void CopyICToMegamorphicCache(Handle<Name> name);
bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
void PatchCache(Handle<Name> name, Handle<Object> code);
void PatchCache(Handle<Name> name, Handle<Object> handler);
void PatchCache(Handle<Name> name, const MaybeObjectHandle& handler);
FeedbackSlotKind kind() const { return kind_; }
bool IsGlobalIC() const { return IsLoadGlobalIC() || IsStoreGlobalIC(); }
bool IsLoadIC() const { return IsLoadICKind(kind_); }
......@@ -199,7 +202,7 @@ class IC {
State state_;
FeedbackSlotKind kind_;
Handle<Map> receiver_map_;
MaybeHandle<Object> maybe_handler_;
MaybeObjectHandle maybe_handler_;
MapHandles target_maps_;
bool target_maps_set_;
......@@ -288,7 +291,7 @@ class KeyedLoadIC : public LoadIC {
KeyedAccessLoadMode load_mode);
void LoadElementPolymorphicHandlers(MapHandles* receiver_maps,
ObjectHandles* handlers,
MaybeObjectHandles* handlers,
KeyedAccessLoadMode load_mode);
// Returns true if the receiver_map has a kElement or kIndexedString
......@@ -328,7 +331,7 @@ class StoreIC : public IC {
JSReceiver::StoreFromKeyed store_mode);
private:
Handle<Object> ComputeHandler(LookupIterator* lookup);
MaybeObjectHandle ComputeHandler(LookupIterator* lookup);
friend class IC;
};
......@@ -385,7 +388,7 @@ class KeyedStoreIC : public StoreIC {
KeyedAccessStoreMode store_mode);
void StoreElementPolymorphicHandlers(MapHandles* receiver_maps,
ObjectHandles* handlers,
MaybeObjectHandles* handlers,
KeyedAccessStoreMode store_mode);
friend class IC;
......
......@@ -65,7 +65,7 @@ bool CommonStubCacheChecks(StubCache* stub_cache, Name* name, Map* map,
DCHECK(!name->GetHeap()->InNewSpace(handler));
DCHECK(name->IsUniqueName());
DCHECK(name->HasHashCode());
if (handler) DCHECK(IC::IsHandler(handler));
if (handler) DCHECK(IC::IsHandler(MaybeObject::FromObject(handler)));
return true;
}
......
......@@ -5,6 +5,8 @@
#ifndef V8_OBJECTS_MAYBE_OBJECT_INL_H_
#define V8_OBJECTS_MAYBE_OBJECT_INL_H_
#include "src/objects/maybe-object.h"
#include "include/v8.h"
#include "src/globals.h"
......
......@@ -803,7 +803,7 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
if (nexus.ic_state() == UNINITIALIZED) {
if (name->IsUniqueName()) {
nexus.ConfigureMonomorphic(name, handle(object->map()),
Handle<Code>::null());
MaybeObjectHandle());
} else {
nexus.ConfigureMegamorphic(PROPERTY);
}
......
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