[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/1055449
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53151}
This commit is contained in:
Marja Hölttä 2018-05-14 13:38:37 +02:00 committed by Commit Bot
parent 8ec92f5118
commit 1684cd8bd5
12 changed files with 238 additions and 134 deletions

View File

@ -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());

View File

@ -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, _) \

View File

@ -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

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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 {

View File

@ -401,6 +401,11 @@ bool IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Object> handler) {
ConfigureVectorState(name, map, MaybeObjectHandle(handler));
}
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
const MaybeObjectHandle& handler) {
if (IsGlobalIC()) {
nexus()->ConfigureHandlerMode(handler);
} else {
@ -415,7 +420,7 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
}
void IC::ConfigureVectorState(Handle<Name> name, MapHandles const& maps,
ObjectHandles* handlers) {
MaybeObjectHandles* handlers) {
DCHECK(!IsGlobalIC());
// Non-keyed ICs don't track the name explicitly.
if (!is_keyed()) name = Handle<Name>::null();
@ -535,14 +540,15 @@ static bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
return true;
}
bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) {
bool IC::UpdatePolymorphicIC(Handle<Name> name,
const MaybeObjectHandle& handler) {
DCHECK(IsHandler(*handler));
if (is_keyed() && state() != RECOMPUTE_HANDLER) {
if (nexus()->FindFirstName() != *name) return false;
}
Handle<Map> map = receiver_map();
MapHandles maps;
ObjectHandles handlers;
MaybeObjectHandles handlers;
TargetMaps(&maps);
int number_of_maps = static_cast<int>(maps.size());
@ -604,7 +610,8 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> handler) {
return true;
}
void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) {
void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler,
Handle<Name> name) {
DCHECK(IsHandler(*handler));
ConfigureVectorState(name, receiver_map(), handler);
}
@ -612,7 +619,7 @@ void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) {
void IC::CopyICToMegamorphicCache(Handle<Name> name) {
MapHandles maps;
ObjectHandles handlers;
MaybeObjectHandles handlers;
TargetMaps(&maps);
if (!nexus()->FindHandlers(&handlers, static_cast<int>(maps.size()))) return;
for (int i = 0; i < static_cast<int>(maps.size()); i++) {
@ -638,6 +645,10 @@ bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
}
void IC::PatchCache(Handle<Name> name, Handle<Object> handler) {
PatchCache(name, MaybeObjectHandle(handler));
}
void IC::PatchCache(Handle<Name> name, const MaybeObjectHandle& handler) {
DCHECK(IsHandler(*handler));
// Currently only load and store ICs support non-code handlers.
DCHECK(IsAnyLoad() || IsAnyStore());
@ -721,13 +732,17 @@ StubCache* IC::stub_cache() {
}
void IC::UpdateMegamorphicCache(Handle<Map> map, Handle<Name> name,
Handle<Object> handler) {
if (handler->IsMap()) {
const MaybeObjectHandle& handler) {
HeapObject* heap_object;
if (handler->ToWeakHeapObject(&heap_object) && heap_object->IsMap()) {
// TODO(marja): remove this conversion once megamorphic stub cache supports
// weak handlers.
handler = Map::WeakCellForMap(Handle<Map>::cast(handler));
Handle<Object> weak_cell =
Map::WeakCellForMap(handle(Map::cast(heap_object)));
stub_cache()->Set(*name, *map, *weak_cell);
} else {
stub_cache()->Set(*name, *map, handler->ToObject());
}
stub_cache()->Set(*name, *map, *handler);
}
void IC::TraceHandlerCacheHitStats(LookupIterator* lookup) {
@ -997,9 +1012,9 @@ static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
}
bool KeyedLoadIC::CanChangeToAllowOutOfBounds(Handle<Map> receiver_map) {
Handle<Object> handler;
return nexus()->FindHandlerForMap(receiver_map).ToHandle(&handler) &&
LoadHandler::GetKeyedAccessLoadMode(*handler) == STANDARD_LOAD;
const MaybeObjectHandle& handler = nexus()->FindHandlerForMap(receiver_map);
if (handler.is_null()) return false;
return LoadHandler::GetKeyedAccessLoadMode(*handler) == STANDARD_LOAD;
}
void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver,
@ -1066,7 +1081,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver,
return;
}
ObjectHandles handlers;
MaybeObjectHandles handlers;
handlers.reserve(target_receiver_maps.size());
LoadElementPolymorphicHandlers(&target_receiver_maps, &handlers, load_mode);
DCHECK_LE(1, target_receiver_maps.size());
@ -1124,7 +1139,7 @@ Handle<Object> KeyedLoadIC::LoadElementHandler(Handle<Map> receiver_map,
}
void KeyedLoadIC::LoadElementPolymorphicHandlers(
MapHandles* receiver_maps, ObjectHandles* handlers,
MapHandles* receiver_maps, MaybeObjectHandles* handlers,
KeyedAccessLoadMode load_mode) {
// Filter out deprecated maps to ensure their instances get migrated.
receiver_maps->erase(
@ -1143,7 +1158,8 @@ void KeyedLoadIC::LoadElementPolymorphicHandlers(
receiver_map->NotifyLeafMapLayoutChange();
}
}
handlers->push_back(LoadElementHandler(receiver_map, load_mode));
handlers->push_back(
MaybeObjectHandle(LoadElementHandler(receiver_map, load_mode)));
}
}
@ -1447,7 +1463,7 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
return;
}
Handle<Object> handler;
MaybeObjectHandle handler;
if (LookupForWrite(lookup, value, store_mode)) {
if (IsStoreGlobalIC()) {
if (lookup->state() == LookupIterator::DATA &&
@ -1462,14 +1478,15 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
handler = ComputeHandler(lookup);
} else {
set_slow_stub_reason("LookupForWrite said 'false'");
handler = slow_stub();
// TODO(marja): change slow_stub to return MaybeObjectHandle.
handler = MaybeObjectHandle(slow_stub());
}
PatchCache(lookup->name(), handler);
TraceIC("StoreIC", lookup->name());
}
Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {
switch (lookup->state()) {
case LookupIterator::TRANSITION: {
Handle<JSObject> store_target = lookup->GetStoreTarget<JSObject>();
@ -1483,8 +1500,8 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
DCHECK_EQ(*lookup->GetReceiver(), *holder);
DCHECK_EQ(*store_target, *holder);
#endif
return StoreHandler::StoreGlobal(isolate(),
lookup->transition_cell());
return MaybeObjectHandle(
StoreHandler::StoreGlobal(isolate(), lookup->transition_cell()));
}
Handle<Smi> smi_handler = StoreHandler::StoreGlobalProxy(isolate());
@ -1492,7 +1509,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
isolate()->factory()->NewWeakCell(lookup->transition_cell());
Handle<Object> handler = StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), store_target, smi_handler, cell);
return handler;
return MaybeObjectHandle(handler);
}
// Dictionary-to-fast transitions are not expected and not supported.
DCHECK_IMPLIES(!lookup->transition_map()->is_dictionary_map(),
@ -1510,7 +1527,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined(isolate()));
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreInterceptorStub);
StoreInterceptorStub stub(isolate());
return stub.GetCode();
return MaybeObjectHandle(stub.GetCode());
}
case LookupIterator::ACCESSOR: {
@ -1522,7 +1539,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
if (!holder->HasFastProperties()) {
set_slow_stub_reason("accessor on slow map");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
Handle<Object> accessors = lookup->GetAccessors();
if (accessors->IsAccessorInfo()) {
@ -1530,29 +1547,31 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
if (v8::ToCData<Address>(info->setter()) == kNullAddress) {
set_slow_stub_reason("setter == kNullAddress");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
if (AccessorInfo::cast(*accessors)->is_special_data_property() &&
!lookup->HolderIsReceiverOrHiddenPrototype()) {
set_slow_stub_reason("special data property in prototype chain");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
if (!AccessorInfo::IsCompatibleReceiverMap(isolate(), info,
receiver_map())) {
set_slow_stub_reason("incompatible receiver type");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
Handle<Smi> smi_handler = StoreHandler::StoreNativeDataProperty(
isolate(), lookup->GetAccessorIndex());
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNativeDataPropertyDH);
if (receiver.is_identical_to(holder)) return smi_handler;
if (receiver.is_identical_to(holder)) {
return MaybeObjectHandle(smi_handler);
}
TRACE_HANDLER_STATS(isolate(),
StoreIC_StoreNativeDataPropertyOnPrototypeDH);
return StoreHandler::StoreThroughPrototype(isolate(), receiver_map(),
holder, smi_handler);
return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), holder, smi_handler));
} else if (accessors->IsAccessorPair()) {
Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
@ -1560,14 +1579,14 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
if (!setter->IsJSFunction() && !setter->IsFunctionTemplateInfo()) {
set_slow_stub_reason("setter not a function");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
if (setter->IsFunctionTemplateInfo() &&
FunctionTemplateInfo::cast(*setter)->BreakAtEntry()) {
// Do not install an IC if the api function has a breakpoint.
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
CallOptimization call_optimization(setter);
@ -1588,31 +1607,33 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
Handle<WeakCell> data_cell = isolate()->factory()->NewWeakCell(
call_optimization.api_call_info());
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreApiSetterOnPrototypeDH);
return StoreHandler::StoreThroughPrototype(
return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), holder, smi_handler, data_cell,
context_cell);
context_cell));
}
set_slow_stub_reason("incompatible receiver");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
} else if (setter->IsFunctionTemplateInfo()) {
set_slow_stub_reason("setter non-simple template");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
Handle<Smi> smi_handler =
StoreHandler::StoreAccessor(isolate(), lookup->GetAccessorIndex());
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorDH);
if (receiver.is_identical_to(holder)) return smi_handler;
if (receiver.is_identical_to(holder)) {
return MaybeObjectHandle(smi_handler);
}
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreAccessorOnPrototypeDH);
return StoreHandler::StoreThroughPrototype(isolate(), receiver_map(),
holder, smi_handler);
return MaybeObjectHandle(StoreHandler::StoreThroughPrototype(
isolate(), receiver_map(), holder, smi_handler));
}
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
case LookupIterator::DATA: {
@ -1626,12 +1647,12 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
if (lookup->is_dictionary_holder()) {
if (holder->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH);
return StoreHandler::StoreGlobal(isolate(),
lookup->GetPropertyCell());
return MaybeObjectHandle(
StoreHandler::StoreGlobal(isolate(), lookup->GetPropertyCell()));
}
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
DCHECK(holder.is_identical_to(receiver));
return StoreHandler::StoreNormal(isolate());
return MaybeObjectHandle(StoreHandler::StoreNormal(isolate()));
}
// -------------- Fields --------------
@ -1645,22 +1666,22 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
// we must store the value unconditionally even to kConst fields.
constness = kMutable;
}
return StoreHandler::StoreField(isolate(), descriptor, index, constness,
lookup->representation());
return MaybeObjectHandle(StoreHandler::StoreField(
isolate(), descriptor, index, constness, lookup->representation()));
}
// -------------- Constant properties --------------
DCHECK_EQ(kDescriptor, lookup->property_details().location());
set_slow_stub_reason("constant property");
TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub);
return slow_stub();
return MaybeObjectHandle(slow_stub());
}
case LookupIterator::JSPROXY: {
Handle<JSReceiver> receiver =
Handle<JSReceiver>::cast(lookup->GetReceiver());
Handle<JSProxy> holder = lookup->GetHolder<JSProxy>();
return StoreHandler::StoreProxy(isolate(), receiver_map(), holder,
receiver);
return MaybeObjectHandle(StoreHandler::StoreProxy(
isolate(), receiver_map(), holder, receiver));
}
case LookupIterator::INTEGER_INDEXED_EXOTIC:
@ -1668,7 +1689,7 @@ Handle<Object> StoreIC::ComputeHandler(LookupIterator* lookup) {
case LookupIterator::NOT_FOUND:
UNREACHABLE();
}
return Handle<Code>::null();
return MaybeObjectHandle();
}
void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
@ -1786,7 +1807,7 @@ void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
}
}
ObjectHandles handlers;
MaybeObjectHandles handlers;
handlers.reserve(target_receiver_maps.size());
StoreElementPolymorphicHandlers(&target_receiver_maps, &handlers, store_mode);
if (target_receiver_maps.size() == 0) {
@ -1878,7 +1899,7 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
}
void KeyedStoreIC::StoreElementPolymorphicHandlers(
MapHandles* receiver_maps, ObjectHandles* handlers,
MapHandles* receiver_maps, MaybeObjectHandles* handlers,
KeyedAccessStoreMode store_mode) {
DCHECK(store_mode == STANDARD_STORE ||
store_mode == STORE_AND_GROW_NO_TRANSITION_HANDLE_COW ||
@ -1930,7 +1951,7 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
}
}
DCHECK(!handler.is_null());
handlers->push_back(handler);
handlers->push_back(MaybeObjectHandle(handler));
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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"

View File

@ -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);
}