[LoadIC] Handle simple field loads in the dispatcher

No compiled handlers required! Instead, the type feedback vector
contains a Smi encoding the field index.

Review-Url: https://codereview.chromium.org/2133233002
Cr-Commit-Position: refs/heads/master@{#37803}
This commit is contained in:
jkummerow 2016-07-15 10:41:14 -07:00 committed by Commit bot
parent 7e1d1fc708
commit 9c59539f27
10 changed files with 237 additions and 111 deletions

View File

@ -2143,8 +2143,7 @@ void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map,
Bind(&rebox_double);
{
Comment("rebox_double");
Node* heap_number = AllocateHeapNumber();
StoreHeapNumberValue(heap_number, var_double_value.value());
Node* heap_number = AllocateHeapNumberWithValue(var_double_value.value());
var_value->Bind(heap_number);
Goto(&done);
}
@ -2940,14 +2939,69 @@ void CodeStubAssembler::LoadIC(const LoadICParameters* p) {
&var_handler, &try_polymorphic);
Bind(&if_handler);
{
Comment("LoadIC_if_handler");
Label call_handler(this);
Node* handler = var_handler.value();
GotoUnless(WordIsSmi(handler), &call_handler);
// |handler| is a Smi. It encodes a field index as obtained by
// FieldIndex.GetLoadByFieldOffset().
{
Label inobject_double(this), out_of_object(this),
out_of_object_double(this);
Variable var_double_value(this, MachineRepresentation::kFloat64);
Label rebox_double(this, &var_double_value);
Node* handler_word = SmiToWord32(handler);
// handler == (offset << 1) | is_double.
Node* double_bit = Word32And(handler_word, Int32Constant(1));
Node* offset = Word32Sar(handler_word, Int32Constant(1));
// Negative index -> out of object.
GotoIf(Int32LessThan(offset, Int32Constant(0)), &out_of_object);
Node* offset_ptr = ChangeInt32ToIntPtr(offset);
GotoUnless(Word32Equal(double_bit, Int32Constant(0)), &inobject_double);
Return(LoadObjectField(p->receiver, offset_ptr));
Bind(&inobject_double);
if (FLAG_unbox_double_fields) {
var_double_value.Bind(
LoadObjectField(p->receiver, offset_ptr, MachineType::Float64()));
} else {
Node* mutable_heap_number = LoadObjectField(p->receiver, offset_ptr);
var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
}
Goto(&rebox_double);
Bind(&out_of_object);
// |offset| == -actual_offset
offset_ptr = ChangeInt32ToIntPtr(Int32Sub(Int32Constant(0), offset));
Node* properties = LoadProperties(p->receiver);
Node* value = LoadObjectField(properties, offset_ptr);
GotoUnless(Word32Equal(double_bit, Int32Constant(0)),
&out_of_object_double);
Return(value);
Bind(&out_of_object_double);
var_double_value.Bind(LoadHeapNumberValue(value));
Goto(&rebox_double);
Bind(&rebox_double);
Return(AllocateHeapNumberWithValue(var_double_value.value()));
}
// |handler| is a heap object. Must be code, call it.
Bind(&call_handler);
LoadWithVectorDescriptor descriptor(isolate());
TailCallStub(descriptor, var_handler.value(), p->context, p->receiver,
p->name, p->slot, p->vector);
TailCallStub(descriptor, handler, p->context, p->receiver, p->name, p->slot,
p->vector);
}
Bind(&try_polymorphic);
{
// Check polymorphic case.
Comment("LoadIC_try_polymorphic");
GotoUnless(
WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)),
&try_megamorphic);

View File

@ -39,8 +39,7 @@ inline FieldIndex FieldIndex::ForPropertyIndex(Map* map,
is_double, inobject_properties, first_inobject_offset);
}
// Takes an index as computed by GetLoadFieldByIndex and reconstructs a
// Takes an index as computed by GetLoadByFieldIndex and reconstructs a
// FieldIndex object from it.
inline FieldIndex FieldIndex::ForLoadByFieldIndex(Map* map, int orig_index) {
int field_index = orig_index;
@ -85,6 +84,42 @@ inline int FieldIndex::GetLoadByFieldIndex() const {
return is_double() ? (result | 1) : result;
}
// Takes an offset as computed by GetLoadByFieldOffset and reconstructs a
// FieldIndex object from it.
inline FieldIndex FieldIndex::ForLoadByFieldOffset(Map* map, int offset) {
bool is_double = offset & 1;
int field_index = (offset >> 1) / kPointerSize;
int is_inobject = true;
int first_inobject_offset = 0;
if (field_index < 0) {
field_index = -field_index;
is_inobject = false;
first_inobject_offset = FixedArray::kHeaderSize;
} else {
first_inobject_offset =
map->IsJSObjectMap() ? map->GetInObjectPropertyOffset(0) : 0;
}
int inobject_properties =
map->IsJSObjectMap() ? map->GetInObjectProperties() : 0;
FieldIndex result(is_inobject, field_index, is_double, inobject_properties,
first_inobject_offset);
DCHECK(result.GetLoadByFieldOffset() == offset);
return result;
}
// Returns the offset format consumed by TurboFan stubs:
// In-object: zero-based from object start,
// out-of-object: zero-based from FixedArray start.
inline int FieldIndex::GetLoadByFieldOffset() const {
// For efficiency, stubs consume an offset that is optimized for quick
// access. If the property is in-object, the offset is positive.
// If it's out-of-object, the encoded offset is -raw_offset.
// In either case, the offset itself is shifted up by one bit, the lower-most
// bit signifying if the field is a mutable double box (1) or not (0).
int result = index() << kPointerSizeLog2;
if (!is_inobject()) result = -result;
return (result << 1) | (is_double() ? 1 : 0);
}
inline FieldIndex FieldIndex::ForDescriptor(Map* map, int descriptor_index) {
PropertyDetails details =

View File

@ -27,10 +27,12 @@ class FieldIndex final {
static FieldIndex ForInObjectOffset(int offset, Map* map = NULL);
static FieldIndex ForDescriptor(Map* map, int descriptor_index);
static FieldIndex ForLoadByFieldIndex(Map* map, int index);
static FieldIndex ForLoadByFieldOffset(Map* map, int index);
static FieldIndex ForKeyedLookupCacheIndex(Map* map, int index);
static FieldIndex FromFieldAccessStubKey(int key);
int GetLoadByFieldIndex() const;
int GetLoadByFieldOffset() const;
bool is_inobject() const {
return IsInObjectBits::decode(bit_field_);

View File

@ -173,6 +173,7 @@ void FullCodeGenerator::PrepareForBailout(Expression* node,
void FullCodeGenerator::CallLoadIC(TypeFeedbackId id) {
Handle<Code> ic = CodeFactory::LoadIC(isolate()).code();
CallIC(ic, id);
if (FLAG_tf_load_ic_stub) RestoreContext();
}
void FullCodeGenerator::CallLoadGlobalIC(TypeofMode typeof_mode,

View File

@ -577,7 +577,7 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
#undef __
void ElementHandlerCompiler::CompileElementHandlers(
MapHandleList* receiver_maps, CodeHandleList* handlers) {
MapHandleList* receiver_maps, List<Handle<Object>>* handlers) {
for (int i = 0; i < receiver_maps->length(); ++i) {
Handle<Map> receiver_map = receiver_maps->at(i);
Handle<Code> cached_stub;

View File

@ -280,7 +280,7 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler {
virtual ~ElementHandlerCompiler() {}
void CompileElementHandlers(MapHandleList* receiver_maps,
CodeHandleList* handlers);
List<Handle<Object>>* handlers);
static void GenerateStoreSlow(MacroAssembler* masm);
};

View File

@ -541,35 +541,33 @@ void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
OnTypeFeedbackChanged(isolate(), get_host());
}
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Code> handler) {
Handle<Object> handler) {
DCHECK(UseVector());
if (kind() == Code::LOAD_IC) {
LoadICNexus* nexus = casted_nexus<LoadICNexus>();
nexus->ConfigureMonomorphic(map, handler);
} else if (kind() == Code::LOAD_GLOBAL_IC) {
LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
nexus->ConfigureHandlerMode(handler);
nexus->ConfigureHandlerMode(Handle<Code>::cast(handler));
} else if (kind() == Code::KEYED_LOAD_IC) {
KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>();
nexus->ConfigureMonomorphic(name, map, handler);
nexus->ConfigureMonomorphic(name, map, Handle<Code>::cast(handler));
} else if (kind() == Code::STORE_IC) {
StoreICNexus* nexus = casted_nexus<StoreICNexus>();
nexus->ConfigureMonomorphic(map, handler);
nexus->ConfigureMonomorphic(map, Handle<Code>::cast(handler));
} else {
DCHECK(kind() == Code::KEYED_STORE_IC);
KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>();
nexus->ConfigureMonomorphic(name, map, handler);
nexus->ConfigureMonomorphic(name, map, Handle<Code>::cast(handler));
}
vector_set_ = true;
OnTypeFeedbackChanged(isolate(), get_host());
}
void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
CodeHandleList* handlers) {
List<Handle<Object>>* handlers) {
DCHECK(UseVector());
if (kind() == Code::LOAD_IC) {
LoadICNexus* nexus = casted_nexus<LoadICNexus>();
@ -686,13 +684,15 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
return true;
}
bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
if (!code->is_handler()) return false;
bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) {
DCHECK(code->IsSmi() || code->IsCode());
if (!code->IsSmi() && !Code::cast(*code)->is_handler()) {
return false;
}
if (is_keyed() && state() != RECOMPUTE_HANDLER) return false;
Handle<Map> map = receiver_map();
MapHandleList maps;
CodeHandleList handlers;
List<Handle<Object>> handlers;
TargetMaps(&maps);
int number_of_maps = maps.length();
@ -747,16 +747,16 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
return true;
}
void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) {
DCHECK(handler->is_handler());
void IC::UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name) {
DCHECK(handler->IsSmi() ||
(handler->IsCode() && Handle<Code>::cast(handler)->is_handler()));
ConfigureVectorState(name, receiver_map(), handler);
}
void IC::CopyICToMegamorphicCache(Handle<Name> name) {
MapHandleList maps;
CodeHandleList handlers;
List<Handle<Object>> handlers;
TargetMaps(&maps);
if (!nexus()->FindHandlers(&handlers, maps.length())) return;
for (int i = 0; i < maps.length(); i++) {
@ -780,8 +780,8 @@ bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
return transitioned_map == target_map;
}
void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
void IC::PatchCache(Handle<Name> name, Handle<Object> code) {
DCHECK(code->IsCode() || (kind() == Code::LOAD_IC && code->IsSmi()));
switch (state()) {
case UNINITIALIZED:
case PREMONOMORPHIC:
@ -849,8 +849,11 @@ Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate,
: isolate->builtins()->KeyedStoreIC_Megamorphic();
}
Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
Handle<Object> LoadIC::SimpleFieldLoad(FieldIndex index) {
if (kind() == Code::LOAD_IC && FLAG_tf_load_ic_stub) {
return handle(Smi::FromInt(index.GetLoadByFieldOffset()), isolate());
}
DCHECK(kind() == Code::KEYED_LOAD_IC || !FLAG_tf_load_ic_stub);
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
LoadFieldStub stub(isolate(), index);
return stub.GetCode();
@ -905,7 +908,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup) {
return;
}
Handle<Code> code;
Handle<Object> code;
if (lookup->state() == LookupIterator::JSPROXY ||
lookup->state() == LookupIterator::ACCESS_CHECK) {
code = slow_stub();
@ -980,15 +983,31 @@ StubCache* IC::stub_cache() {
return nullptr;
}
void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
stub_cache()->Set(name, map, code);
void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* code) {
if (code->IsSmi()) {
// TODO(jkummerow): Support Smis in the code cache.
Handle<Map> map_handle(map, isolate());
Handle<Name> name_handle(name, isolate());
FieldIndex index =
FieldIndex::ForLoadByFieldOffset(map, Smi::cast(code)->value());
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadFieldStub);
LoadFieldStub stub(isolate(), index);
Code* handler = *stub.GetCode();
stub_cache()->Set(*name_handle, *map_handle, handler);
return;
}
DCHECK(code->IsCode());
stub_cache()->Set(name, map, Code::cast(code));
}
Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
Handle<Object> IC::ComputeHandler(LookupIterator* lookup,
Handle<Object> value) {
// Try to find a globally shared handler stub.
Handle<Code> code = GetMapIndependentHandler(lookup);
if (!code.is_null()) return code;
Handle<Object> handler_or_index = GetMapIndependentHandler(lookup);
if (!handler_or_index.is_null()) {
DCHECK(handler_or_index->IsCode() || handler_or_index->IsSmi());
return handler_or_index;
}
// Otherwise check the map's handler cache for a map-specific handler, and
// compile one if the cache comes up empty.
@ -1007,12 +1026,12 @@ Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
stub_holder_map = receiver_map();
}
code = PropertyHandlerCompiler::Find(lookup->name(), stub_holder_map, kind(),
flag);
Handle<Code> code = PropertyHandlerCompiler::Find(
lookup->name(), stub_holder_map, kind(), flag);
// Use the cached value if it exists, and if it is different from the
// handler that just missed.
if (!code.is_null()) {
Handle<Code> handler;
Handle<Object> handler;
if (maybe_handler_.ToHandle(&handler)) {
if (!handler.is_identical_to(code)) {
TRACE_HANDLER_STATS(isolate(), IC_HandlerCacheHit);
@ -1045,7 +1064,7 @@ Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
return code;
}
Handle<Code> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
Handle<Object> receiver = lookup->GetReceiver();
if (receiver->IsString() &&
Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
@ -1389,7 +1408,7 @@ void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver) {
return;
}
CodeHandleList handlers(target_receiver_maps.length());
List<Handle<Object>> handlers(target_receiver_maps.length());
TRACE_HANDLER_STATS(isolate(), KeyedLoadIC_PolymorphicElement);
ElementHandlerCompiler compiler(isolate());
compiler.CompileElementHandlers(&target_receiver_maps, &handlers);
@ -1606,7 +1625,8 @@ void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
if (!use_ic) {
TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'");
}
Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub();
Handle<Code> code =
use_ic ? Handle<Code>::cast(ComputeHandler(lookup, value)) : slow_stub();
PatchCache(lookup->name(), code);
TRACE_IC("StoreIC", lookup->name());
@ -1628,7 +1648,7 @@ static Handle<Code> PropertyCellStoreHandler(
return code;
}
Handle<Code> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
// This is currently guaranteed by checks in StoreIC::Store.

View File

@ -107,10 +107,10 @@ class IC {
void ConfigureVectorState(IC::State new_state, Handle<Object> key);
// Configure the vector for MONOMORPHIC.
void ConfigureVectorState(Handle<Name> name, Handle<Map> map,
Handle<Code> handler);
Handle<Object> handler);
// Configure the vector for POLYMORPHIC.
void ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
CodeHandleList* handlers);
List<Handle<Object>>* handlers);
// Configure the vector for POLYMORPHIC with transitions (only for element
// keyed stores).
void ConfigureVectorState(MapHandleList* maps,
@ -136,9 +136,9 @@ class IC {
static void PostPatching(Address address, Code* target, Code* old_target);
// Compute the handler either by compiling or by retrieving a cached version.
Handle<Code> ComputeHandler(LookupIterator* lookup,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> GetMapIndependentHandler(LookupIterator* lookup) {
Handle<Object> ComputeHandler(LookupIterator* lookup,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) {
UNREACHABLE();
return Handle<Code>::null();
}
@ -149,15 +149,15 @@ class IC {
return Handle<Code>::null();
}
void UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name);
bool UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code);
void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
void UpdateMonomorphicIC(Handle<Object> handler, Handle<Name> name);
bool UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code);
void UpdateMegamorphicCache(Map* map, Name* name, Object* code);
StubCache* stub_cache();
void CopyICToMegamorphicCache(Handle<Name> name);
bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
void PatchCache(Handle<Name> name, Handle<Code> code);
void PatchCache(Handle<Name> name, Handle<Object> code);
Code::Kind kind() const { return kind_; }
bool is_keyed() const {
return kind_ == Code::KEYED_LOAD_IC || kind_ == Code::KEYED_STORE_IC;
@ -239,7 +239,7 @@ class IC {
State state_;
Code::Kind kind_;
Handle<Map> receiver_map_;
MaybeHandle<Code> maybe_handler_;
MaybeHandle<Object> maybe_handler_;
ExtraICState extra_ic_state_;
MapHandleList target_maps_;
@ -305,13 +305,13 @@ class LoadIC : public IC {
// lookup result.
void UpdateCaches(LookupIterator* lookup);
Handle<Code> GetMapIndependentHandler(LookupIterator* lookup) override;
Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) override;
Handle<Code> CompileHandler(LookupIterator* lookup, Handle<Object> unused,
CacheHolderFlag cache_holder) override;
private:
Handle<Code> SimpleFieldLoad(FieldIndex index);
Handle<Object> SimpleFieldLoad(FieldIndex index);
friend class IC;
};
@ -418,7 +418,7 @@ class StoreIC : public IC {
// lookup result.
void UpdateCaches(LookupIterator* lookup, Handle<Object> value,
JSReceiver::StoreFromKeyed store_mode);
Handle<Code> GetMapIndependentHandler(LookupIterator* lookup) override;
Handle<Object> GetMapIndependentHandler(LookupIterator* lookup) override;
Handle<Code> CompileHandler(LookupIterator* lookup, Handle<Object> value,
CacheHolderFlag cache_holder) override;

View File

@ -427,10 +427,9 @@ Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
return Handle<FixedArray>::cast(feedback_extra);
}
void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
MapHandleList* maps,
CodeHandleList* handlers) {
List<Handle<Object>>* handlers) {
int receiver_count = maps->length();
for (int current = 0; current < receiver_count; ++current) {
Handle<Map> map = maps->at(current);
@ -656,9 +655,8 @@ void CallICNexus::ConfigureMegamorphic(int call_count) {
SetFeedbackExtra(Smi::FromInt(call_count), SKIP_WRITE_BARRIER);
}
void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
Handle<Code> handler) {
Handle<Object> handler) {
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
SetFeedback(*cell);
SetFeedbackExtra(*handler);
@ -722,9 +720,8 @@ void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
}
}
void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
CodeHandleList* handlers) {
List<Handle<Object>>* handlers) {
Isolate* isolate = GetIsolate();
int receiver_count = maps->length();
Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
@ -735,7 +732,7 @@ void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
MapHandleList* maps,
CodeHandleList* handlers) {
List<Handle<Object>>* handlers) {
int receiver_count = maps->length();
DCHECK(receiver_count > 1);
Handle<FixedArray> array;
@ -751,9 +748,8 @@ void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
InstallHandlers(array, maps, handlers);
}
void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
CodeHandleList* handlers) {
List<Handle<Object>>* handlers) {
Isolate* isolate = GetIsolate();
int receiver_count = maps->length();
Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
@ -762,10 +758,9 @@ void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
SKIP_WRITE_BARRIER);
}
void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
MapHandleList* maps,
CodeHandleList* handlers) {
List<Handle<Object>>* handlers) {
int receiver_count = maps->length();
DCHECK(receiver_count > 1);
Handle<FixedArray> array;
@ -807,6 +802,30 @@ void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
}
}
namespace {
int GetStepSize(FixedArray* array, Isolate* isolate) {
// The array should be of the form
// [map, handler, map, handler, ...]
// or
// [map, map, handler, map, map, handler, ...]
// where "map" is either a WeakCell or |undefined|,
// and "handler" is either a Code object or a Smi.
DCHECK(array->length() >= 2);
Object* second = array->get(1);
if (second->IsWeakCell() || second->IsUndefined(isolate)) return 3;
DCHECK(second->IsCode() || second->IsSmi());
return 2;
}
#ifdef DEBUG // Only used by DCHECKs below.
bool IsHandler(Object* object) {
return object->IsSmi() ||
(object->IsCode() && Code::cast(object)->is_handler());
}
#endif
} // namespace
int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
Isolate* isolate = GetIsolate();
@ -818,12 +837,7 @@ int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
feedback = GetFeedbackExtra();
}
FixedArray* array = FixedArray::cast(feedback);
// The array should be of the form
// [map, handler, map, handler, ...]
// or
// [map, map, handler, map, map, handler, ...]
DCHECK(array->length() >= 2);
int increment = array->get(1)->IsCode() ? 2 : 3;
int increment = GetStepSize(array, isolate);
for (int i = 0; i < array->length(); i += increment) {
DCHECK(array->get(i)->IsWeakCell());
WeakCell* cell = WeakCell::cast(array->get(i));
@ -846,26 +860,25 @@ int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
return 0;
}
MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
Object* feedback = GetFeedback();
Isolate* isolate = GetIsolate();
bool is_named_feedback = IsPropertyNameFeedback(feedback);
if (feedback->IsFixedArray() || is_named_feedback) {
if (is_named_feedback) {
feedback = GetFeedbackExtra();
}
FixedArray* array = FixedArray::cast(feedback);
DCHECK(array->length() >= 2);
int increment = array->get(1)->IsCode() ? 2 : 3;
int increment = GetStepSize(array, isolate);
for (int i = 0; i < array->length(); i += increment) {
DCHECK(array->get(i)->IsWeakCell());
WeakCell* cell = WeakCell::cast(array->get(i));
if (!cell->cleared()) {
Map* array_map = Map::cast(cell->value());
if (array_map == *map) {
Code* code = Code::cast(array->get(i + increment - 1));
DCHECK(code->kind() == Code::HANDLER);
return handle(code);
Object* code = array->get(i + increment - 1);
DCHECK(IsHandler(code));
return handle(code, isolate);
}
}
}
@ -874,9 +887,9 @@ MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
if (!cell->cleared()) {
Map* cell_map = Map::cast(cell->value());
if (cell_map == *map) {
Code* code = Code::cast(GetFeedbackExtra());
DCHECK(code->kind() == Code::HANDLER);
return handle(code);
Object* code = GetFeedbackExtra();
DCHECK(IsHandler(code));
return handle(code, isolate);
}
}
}
@ -884,9 +897,10 @@ MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
return MaybeHandle<Code>();
}
bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
bool FeedbackNexus::FindHandlers(List<Handle<Object>>* code_list,
int length) const {
Object* feedback = GetFeedback();
Isolate* isolate = GetIsolate();
int count = 0;
bool is_named_feedback = IsPropertyNameFeedback(feedback);
if (feedback->IsFixedArray() || is_named_feedback) {
@ -894,29 +908,24 @@ bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
feedback = GetFeedbackExtra();
}
FixedArray* array = FixedArray::cast(feedback);
// The array should be of the form
// [map, handler, map, handler, ...]
// or
// [map, map, handler, map, map, handler, ...]
// Be sure to skip handlers whose maps have been cleared.
DCHECK(array->length() >= 2);
int increment = array->get(1)->IsCode() ? 2 : 3;
int increment = GetStepSize(array, isolate);
for (int i = 0; i < array->length(); i += increment) {
DCHECK(array->get(i)->IsWeakCell());
WeakCell* cell = WeakCell::cast(array->get(i));
// Be sure to skip handlers whose maps have been cleared.
if (!cell->cleared()) {
Code* code = Code::cast(array->get(i + increment - 1));
DCHECK(code->kind() == Code::HANDLER);
code_list->Add(handle(code));
Object* code = array->get(i + increment - 1);
DCHECK(IsHandler(code));
code_list->Add(handle(code, isolate));
count++;
}
}
} else if (feedback->IsWeakCell()) {
WeakCell* cell = WeakCell::cast(feedback);
if (!cell->cleared()) {
Code* code = Code::cast(GetFeedbackExtra());
DCHECK(code->kind() == Code::HANDLER);
code_list->Add(handle(code));
Object* code = GetFeedbackExtra();
DCHECK(IsHandler(code));
code_list->Add(handle(code, isolate));
count++;
}
}
@ -966,7 +975,7 @@ void KeyedStoreICNexus::Clear(Code* host) {
KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
KeyedAccessStoreMode mode = STANDARD_STORE;
MapHandleList maps;
CodeHandleList handlers;
List<Handle<Object>> handlers;
if (GetKeyType() == PROPERTY) return mode;
@ -974,7 +983,7 @@ KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
FindHandlers(&handlers, maps.length());
for (int i = 0; i < handlers.length(); i++) {
// The first handler that isn't the slow handler will have the bits we need.
Handle<Code> handler = handlers.at(i);
Handle<Code> handler = Handle<Code>::cast(handlers.at(i));
CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||

View File

@ -412,8 +412,9 @@ class FeedbackNexus {
virtual InlineCacheState StateFromFeedback() const = 0;
virtual int ExtractMaps(MapHandleList* maps) const;
virtual MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const;
virtual bool FindHandlers(CodeHandleList* code_list, int length = -1) const;
virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
virtual bool FindHandlers(List<Handle<Object>>* code_list,
int length = -1) const;
virtual Name* FindFirstName() const { return NULL; }
virtual void ConfigureUninitialized();
@ -434,7 +435,7 @@ class FeedbackNexus {
Handle<FixedArray> EnsureArrayOfSize(int length);
Handle<FixedArray> EnsureExtraArrayOfSize(int length);
void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps,
CodeHandleList* handlers);
List<Handle<Object>>* handlers);
private:
// The reason for having a vector handle and a raw pointer is that we can and
@ -471,10 +472,11 @@ class CallICNexus final : public FeedbackNexus {
// CallICs don't record map feedback.
return 0;
}
MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const final {
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
return MaybeHandle<Code>();
}
bool FindHandlers(CodeHandleList* code_list, int length = -1) const final {
bool FindHandlers(List<Handle<Object>>* code_list,
int length = -1) const final {
return length == 0;
}
@ -499,9 +501,10 @@ class LoadICNexus : public FeedbackNexus {
void Clear(Code* host);
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers);
void ConfigurePolymorphic(MapHandleList* maps,
List<Handle<Object>>* handlers);
InlineCacheState StateFromFeedback() const override;
};
@ -521,10 +524,11 @@ class LoadGlobalICNexus : public FeedbackNexus {
// LoadGlobalICs don't record map feedback.
return 0;
}
MaybeHandle<Code> FindHandlerForMap(Handle<Map> map) const final {
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
return MaybeHandle<Code>();
}
bool FindHandlers(CodeHandleList* code_list, int length = -1) const final {
bool FindHandlers(List<Handle<Object>>* code_list,
int length = -1) const final {
return length == 0;
}
@ -556,7 +560,7 @@ class KeyedLoadICNexus : public FeedbackNexus {
Handle<Code> handler);
// name can be null.
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
CodeHandleList* handlers);
List<Handle<Object>>* handlers);
void ConfigureMegamorphicKeyed(IcCheckType property_type);
@ -585,7 +589,8 @@ class StoreICNexus : public FeedbackNexus {
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);
void ConfigurePolymorphic(MapHandleList* maps, CodeHandleList* handlers);
void ConfigurePolymorphic(MapHandleList* maps,
List<Handle<Object>>* handlers);
InlineCacheState StateFromFeedback() const override;
};
@ -613,7 +618,7 @@ class KeyedStoreICNexus : public FeedbackNexus {
Handle<Code> handler);
// name can be null.
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
CodeHandleList* handlers);
List<Handle<Object>>* handlers);
void ConfigurePolymorphic(MapHandleList* maps,
MapHandleList* transitioned_maps,
CodeHandleList* handlers);