Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc
index c51d987..698f2a6 100644
--- a/src/type-feedback-vector.cc
+++ b/src/type-feedback-vector.cc
@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
+#include "src/type-feedback-vector.h"
+#include "src/code-stubs.h"
#include "src/ic/ic.h"
#include "src/ic/ic-state.h"
#include "src/objects.h"
@@ -12,111 +13,149 @@
namespace v8 {
namespace internal {
-// static
-TypeFeedbackVector::VectorICKind TypeFeedbackVector::FromCodeKind(
- Code::Kind kind) {
- switch (kind) {
- case Code::CALL_IC:
- return KindCallIC;
- case Code::LOAD_IC:
- return KindLoadIC;
- case Code::KEYED_LOAD_IC:
- return KindKeyedLoadIC;
- default:
- // Shouldn't get here.
- UNREACHABLE();
- }
- return KindUnused;
+static bool IsPropertyNameFeedback(Object* feedback) {
+ return feedback->IsString() ||
+ (feedback->IsSymbol() && !Symbol::cast(feedback)->is_private());
}
-// static
-Code::Kind TypeFeedbackVector::FromVectorICKind(VectorICKind kind) {
- switch (kind) {
- case KindCallIC:
- return Code::CALL_IC;
- case KindLoadIC:
- return Code::LOAD_IC;
- case KindKeyedLoadIC:
- return Code::KEYED_LOAD_IC;
- case KindUnused:
- break;
- }
- // Sentinel for no information.
- return Code::NUMBER_OF_KINDS;
+std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind) {
+ return os << TypeFeedbackMetadata::Kind2String(kind);
}
-Code::Kind TypeFeedbackVector::GetKind(FeedbackVectorICSlot slot) const {
- if (!FLAG_vector_ics) {
- // We only have CALL_ICs
- return Code::CALL_IC;
- }
-
+FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind(
+ FeedbackVectorSlot slot) const {
int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
int data = Smi::cast(get(index))->value();
- VectorICKind b = VectorICComputer::decode(data, slot.ToInt());
- return FromVectorICKind(b);
+ return VectorICComputer::decode(data, slot.ToInt());
}
-void TypeFeedbackVector::SetKind(FeedbackVectorICSlot slot, Code::Kind kind) {
- if (!FLAG_vector_ics) {
- // Nothing to do if we only have CALL_ICs
- return;
- }
-
- VectorICKind b = FromCodeKind(kind);
+void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
+ FeedbackVectorSlotKind kind) {
int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
int data = Smi::cast(get(index))->value();
- int new_data = VectorICComputer::encode(data, slot.ToInt(), b);
+ int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
set(index, Smi::FromInt(new_data));
}
+template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
+ Isolate* isolate, const StaticFeedbackVectorSpec* spec);
+template Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(
+ Isolate* isolate, const FeedbackVectorSpec* spec);
+
+
// static
-Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(
- Isolate* isolate, const FeedbackVectorSpec& spec) {
- const int slot_count = spec.slots();
- const int ic_slot_count = spec.ic_slots();
- const int index_count =
- FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0;
- const int length =
- slot_count + ic_slot_count + index_count + kReservedIndexCount;
+template <typename Spec>
+Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
+ const Spec* spec) {
+ const int slot_count = spec->slots();
+ const int slot_kinds_length = VectorICComputer::word_count(slot_count);
+ const int length = slot_kinds_length + kReservedIndexCount;
if (length == kReservedIndexCount) {
- return Handle<TypeFeedbackVector>::cast(
+ return Handle<TypeFeedbackMetadata>::cast(
isolate->factory()->empty_fixed_array());
}
+#ifdef DEBUG
+ for (int i = 0; i < slot_count;) {
+ FeedbackVectorSlotKind kind = spec->GetKind(i);
+ int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
+ for (int j = 1; j < entry_size; j++) {
+ FeedbackVectorSlotKind kind = spec->GetKind(i + j);
+ DCHECK_EQ(FeedbackVectorSlotKind::INVALID, kind);
+ }
+ i += entry_size;
+ }
+#endif
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
- if (ic_slot_count > 0) {
- array->set(kFirstICSlotIndex,
- Smi::FromInt(slot_count + index_count + kReservedIndexCount));
- } else {
- array->set(kFirstICSlotIndex, Smi::FromInt(length));
- }
- array->set(kWithTypesIndex, Smi::FromInt(0));
- array->set(kGenericCountIndex, Smi::FromInt(0));
- // Fill the indexes with zeros.
- for (int i = 0; i < index_count; i++) {
+ array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
+ // Fill the bit-vector part with zeros.
+ for (int i = 0; i < slot_kinds_length; i++) {
array->set(kReservedIndexCount + i, Smi::FromInt(0));
}
+ Handle<TypeFeedbackMetadata> metadata =
+ Handle<TypeFeedbackMetadata>::cast(array);
+ for (int i = 0; i < slot_count; i++) {
+ metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i));
+ }
+ return metadata;
+}
+
+
+bool TypeFeedbackMetadata::SpecDiffersFrom(
+ const FeedbackVectorSpec* other_spec) const {
+ if (other_spec->slots() != slot_count()) {
+ return true;
+ }
+
+ int slots = slot_count();
+ for (int i = 0; i < slots; i++) {
+ if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
+ switch (kind) {
+ case FeedbackVectorSlotKind::INVALID:
+ return "INVALID";
+ case FeedbackVectorSlotKind::CALL_IC:
+ return "CALL_IC";
+ case FeedbackVectorSlotKind::LOAD_IC:
+ return "LOAD_IC";
+ case FeedbackVectorSlotKind::KEYED_LOAD_IC:
+ return "KEYED_LOAD_IC";
+ case FeedbackVectorSlotKind::STORE_IC:
+ return "STORE_IC";
+ case FeedbackVectorSlotKind::KEYED_STORE_IC:
+ return "KEYED_STORE_IC";
+ case FeedbackVectorSlotKind::GENERAL:
+ return "STUB";
+ case FeedbackVectorSlotKind::KINDS_NUMBER:
+ break;
+ }
+ UNREACHABLE();
+ return "?";
+}
+
+
+// static
+Handle<TypeFeedbackVector> TypeFeedbackVector::New(
+ Isolate* isolate, Handle<TypeFeedbackMetadata> metadata) {
+ Factory* factory = isolate->factory();
+
+ const int slot_count = metadata->slot_count();
+ const int length = slot_count + kReservedIndexCount;
+ if (length == kReservedIndexCount) {
+ return Handle<TypeFeedbackVector>::cast(factory->empty_fixed_array());
+ }
+
+ Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
+ array->set(kMetadataIndex, *metadata);
+
// Ensure we can skip the write barrier
Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
- DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel);
- for (int i = kReservedIndexCount + index_count; i < length; i++) {
+ DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
+ for (int i = kReservedIndexCount; i < length; i++) {
array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
}
- Handle<TypeFeedbackVector> vector = Handle<TypeFeedbackVector>::cast(array);
- if (FLAG_vector_ics) {
- for (int i = 0; i < ic_slot_count; i++) {
- vector->SetKind(FeedbackVectorICSlot(i), spec.GetKind(i));
- }
- }
- return vector;
+ return Handle<TypeFeedbackVector>::cast(array);
+}
+
+
+// static
+int TypeFeedbackVector::GetIndexFromSpec(const FeedbackVectorSpec* spec,
+ FeedbackVectorSlot slot) {
+ return kReservedIndexCount + slot.ToInt();
}
@@ -132,81 +171,114 @@
// This logic is copied from
// StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
-// TODO(mvstanton): with weak handling of all vector ics, this logic should
-// actually be completely eliminated and we no longer need to clear the
-// vector ICs.
-static bool ClearLogic(Heap* heap, int ic_age, Code::Kind kind,
- InlineCacheState state) {
- if (FLAG_cleanup_code_caches_at_gc &&
- (kind == Code::CALL_IC || heap->flush_monomorphic_ics() ||
- // TODO(mvstanton): is this ic_age granular enough? it comes from
- // the SharedFunctionInfo which may change on a different schedule
- // than ic targets.
- // ic_age != heap->global_ic_age() ||
- // is_invalidated_weak_stub ||
- heap->isolate()->serializer_enabled())) {
- return true;
- }
- return false;
+static bool ClearLogic(Isolate* isolate) {
+ return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled();
}
-void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) {
- int slots = Slots();
+void TypeFeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
+ bool force_clear) {
Isolate* isolate = GetIsolate();
+
+ if (!force_clear && !ClearLogic(isolate)) return;
+
Object* uninitialized_sentinel =
- TypeFeedbackVector::RawUninitializedSentinel(isolate->heap());
+ TypeFeedbackVector::RawUninitializedSentinel(isolate);
- for (int i = 0; i < slots; i++) {
- FeedbackVectorSlot slot(i);
- Object* obj = Get(slot);
- if (obj->IsHeapObject()) {
- InstanceType instance_type =
- HeapObject::cast(obj)->map()->instance_type();
- // AllocationSites are exempt from clearing. They don't store Maps
- // or Code pointers which can cause memory leaks if not cleared
- // regularly.
- if (instance_type != ALLOCATION_SITE_TYPE) {
- Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
- }
- }
- }
+ TypeFeedbackMetadataIterator iter(metadata());
+ while (iter.HasNext()) {
+ FeedbackVectorSlot slot = iter.Next();
+ FeedbackVectorSlotKind kind = iter.kind();
- slots = ICSlots();
- if (slots == 0) return;
-
- // Now clear vector-based ICs.
- // Try and pass the containing code (the "host").
- Heap* heap = isolate->heap();
- Code* host = shared->code();
- // I'm not sure yet if this ic age is the correct one.
- int ic_age = shared->ic_age();
- for (int i = 0; i < slots; i++) {
- FeedbackVectorICSlot slot(i);
Object* obj = Get(slot);
if (obj != uninitialized_sentinel) {
- Code::Kind kind = GetKind(slot);
- if (kind == Code::CALL_IC) {
- CallICNexus nexus(this, slot);
- if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
- nexus.Clear(host);
+ switch (kind) {
+ case FeedbackVectorSlotKind::CALL_IC: {
+ CallICNexus nexus(this, slot);
+ nexus.Clear(shared->code());
+ break;
}
- } else if (kind == Code::LOAD_IC) {
- LoadICNexus nexus(this, slot);
- if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
- nexus.Clear(host);
+ case FeedbackVectorSlotKind::LOAD_IC: {
+ LoadICNexus nexus(this, slot);
+ nexus.Clear(shared->code());
+ break;
}
- } else if (kind == Code::KEYED_LOAD_IC) {
- KeyedLoadICNexus nexus(this, slot);
- if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
- nexus.Clear(host);
+ case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
+ KeyedLoadICNexus nexus(this, slot);
+ nexus.Clear(shared->code());
+ break;
}
+ case FeedbackVectorSlotKind::STORE_IC: {
+ StoreICNexus nexus(this, slot);
+ nexus.Clear(shared->code());
+ break;
+ }
+ case FeedbackVectorSlotKind::KEYED_STORE_IC: {
+ KeyedStoreICNexus nexus(this, slot);
+ nexus.Clear(shared->code());
+ break;
+ }
+ case FeedbackVectorSlotKind::GENERAL: {
+ if (obj->IsHeapObject()) {
+ InstanceType instance_type =
+ HeapObject::cast(obj)->map()->instance_type();
+ // AllocationSites are exempt from clearing. They don't store Maps
+ // or Code pointers which can cause memory leaks if not cleared
+ // regularly.
+ if (instance_type != ALLOCATION_SITE_TYPE) {
+ Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
+ }
+ }
+ break;
+ }
+ case FeedbackVectorSlotKind::INVALID:
+ case FeedbackVectorSlotKind::KINDS_NUMBER:
+ UNREACHABLE();
+ break;
}
}
}
}
+// static
+void TypeFeedbackVector::ClearAllKeyedStoreICs(Isolate* isolate) {
+ SharedFunctionInfo::Iterator iterator(isolate);
+ SharedFunctionInfo* shared;
+ while ((shared = iterator.Next())) {
+ TypeFeedbackVector* vector = shared->feedback_vector();
+ vector->ClearKeyedStoreICs(shared);
+ }
+}
+
+
+void TypeFeedbackVector::ClearKeyedStoreICs(SharedFunctionInfo* shared) {
+ Isolate* isolate = GetIsolate();
+
+ Code* host = shared->code();
+ Object* uninitialized_sentinel =
+ TypeFeedbackVector::RawUninitializedSentinel(isolate);
+
+ TypeFeedbackMetadataIterator iter(metadata());
+ while (iter.HasNext()) {
+ FeedbackVectorSlot slot = iter.Next();
+ FeedbackVectorSlotKind kind = iter.kind();
+ if (kind != FeedbackVectorSlotKind::KEYED_STORE_IC) continue;
+ Object* obj = Get(slot);
+ if (obj != uninitialized_sentinel) {
+ KeyedStoreICNexus nexus(this, slot);
+ nexus.Clear(host);
+ }
+ }
+}
+
+
+// static
+Handle<TypeFeedbackVector> TypeFeedbackVector::DummyVector(Isolate* isolate) {
+ return isolate->factory()->dummy_vector();
+}
+
+
Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
Isolate* isolate = GetIsolate();
Handle<Object> feedback = handle(GetFeedback(), isolate);
@@ -220,37 +292,74 @@
}
-void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types,
- CodeHandleList* handlers) {
+Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
Isolate* isolate = GetIsolate();
- Handle<FixedArray> array = handle(FixedArray::cast(GetFeedback()), isolate);
- int receiver_count = types->length();
- for (int current = 0; current < receiver_count; ++current) {
- Handle<HeapType> type = types->at(current);
- Handle<Map> map = IC::TypeToMap(*type, isolate);
- Handle<WeakCell> cell = Map::WeakCellForMap(map);
- array->set(start_index + (current * 2), *cell);
- array->set(start_index + (current * 2 + 1), *handlers->at(current));
+ Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
+ if (!feedback_extra->IsFixedArray() ||
+ FixedArray::cast(*feedback_extra)->length() != length) {
+ Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
+ SetFeedbackExtra(*array);
+ return array;
}
+ return Handle<FixedArray>::cast(feedback_extra);
+}
+
+
+void FeedbackNexus::InstallHandlers(Handle<FixedArray> array,
+ MapHandleList* maps,
+ CodeHandleList* handlers) {
+ int receiver_count = maps->length();
+ for (int current = 0; current < receiver_count; ++current) {
+ Handle<Map> map = maps->at(current);
+ Handle<WeakCell> cell = Map::WeakCellForMap(map);
+ array->set(current * 2, *cell);
+ array->set(current * 2 + 1, *handlers->at(current));
+ }
+}
+
+
+void FeedbackNexus::ConfigureUninitialized() {
+ SetFeedback(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
+}
+
+
+void FeedbackNexus::ConfigurePremonomorphic() {
+ SetFeedback(*TypeFeedbackVector::PremonomorphicSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
+}
+
+
+void FeedbackNexus::ConfigureMegamorphic() {
+ Isolate* isolate = GetIsolate();
+ SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(isolate),
+ SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+ SKIP_WRITE_BARRIER);
}
InlineCacheState LoadICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
- if (feedback == *vector()->UninitializedSentinel(isolate)) {
+
+ if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
return UNINITIALIZED;
- } else if (feedback == *vector()->MegamorphicSentinel(isolate)) {
+ } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
return MEGAMORPHIC;
- } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) {
+ } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
return PREMONOMORPHIC;
} else if (feedback->IsFixedArray()) {
// Determine state purely by our structure, don't check if the maps are
// cleared.
- FixedArray* array = FixedArray::cast(feedback);
- int length = array->length();
- DCHECK(length >= 2);
- return length == 2 ? MONOMORPHIC : POLYMORPHIC;
+ return POLYMORPHIC;
+ } else if (feedback->IsWeakCell()) {
+ // Don't check if the map is cleared.
+ return MONOMORPHIC;
}
return UNINITIALIZED;
@@ -260,19 +369,74 @@
InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
- if (feedback == *vector()->UninitializedSentinel(isolate)) {
+
+ if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
return UNINITIALIZED;
- } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) {
+ } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
return PREMONOMORPHIC;
- } else if (feedback == *vector()->GenericSentinel(isolate)) {
- return GENERIC;
+ } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
+ return MEGAMORPHIC;
} else if (feedback->IsFixedArray()) {
// Determine state purely by our structure, don't check if the maps are
// cleared.
- FixedArray* array = FixedArray::cast(feedback);
- int length = array->length();
- DCHECK(length >= 3);
- return length == 3 ? MONOMORPHIC : POLYMORPHIC;
+ return POLYMORPHIC;
+ } else if (feedback->IsWeakCell()) {
+ // Don't check if the map is cleared.
+ return MONOMORPHIC;
+ } else if (feedback->IsName()) {
+ Object* extra = GetFeedbackExtra();
+ FixedArray* extra_array = FixedArray::cast(extra);
+ return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
+ }
+
+ return UNINITIALIZED;
+}
+
+
+InlineCacheState StoreICNexus::StateFromFeedback() const {
+ Isolate* isolate = GetIsolate();
+ Object* feedback = GetFeedback();
+
+ if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
+ return UNINITIALIZED;
+ } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
+ return MEGAMORPHIC;
+ } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
+ return PREMONOMORPHIC;
+ } else if (feedback->IsFixedArray()) {
+ // Determine state purely by our structure, don't check if the maps are
+ // cleared.
+ return POLYMORPHIC;
+ } else if (feedback->IsWeakCell()) {
+ // Don't check if the map is cleared.
+ return MONOMORPHIC;
+ }
+
+ return UNINITIALIZED;
+}
+
+
+InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
+ Isolate* isolate = GetIsolate();
+ Object* feedback = GetFeedback();
+
+ if (feedback == *TypeFeedbackVector::UninitializedSentinel(isolate)) {
+ return UNINITIALIZED;
+ } else if (feedback == *TypeFeedbackVector::PremonomorphicSentinel(isolate)) {
+ return PREMONOMORPHIC;
+ } else if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
+ return MEGAMORPHIC;
+ } else if (feedback->IsFixedArray()) {
+ // Determine state purely by our structure, don't check if the maps are
+ // cleared.
+ return POLYMORPHIC;
+ } else if (feedback->IsWeakCell()) {
+ // Don't check if the map is cleared.
+ return MONOMORPHIC;
+ } else if (feedback->IsName()) {
+ Object* extra = GetFeedbackExtra();
+ FixedArray* extra_array = FixedArray::cast(extra);
+ return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
}
return UNINITIALIZED;
@@ -282,26 +446,34 @@
InlineCacheState CallICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
+ DCHECK(GetFeedbackExtra() ==
+ *TypeFeedbackVector::UninitializedSentinel(isolate) ||
+ GetFeedbackExtra()->IsSmi());
- if (feedback == *vector()->MegamorphicSentinel(isolate)) {
+ if (feedback == *TypeFeedbackVector::MegamorphicSentinel(isolate)) {
return GENERIC;
- } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) {
+ } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
return MONOMORPHIC;
}
- CHECK(feedback == *vector()->UninitializedSentinel(isolate));
+ CHECK(feedback == *TypeFeedbackVector::UninitializedSentinel(isolate));
return UNINITIALIZED;
}
-void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
-
-
-void CallICNexus::ConfigureGeneric() {
- SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
+int CallICNexus::ExtractCallCount() {
+ Object* call_count = GetFeedbackExtra();
+ if (call_count->IsSmi()) {
+ int value = Smi::cast(call_count)->value() / 2;
+ return value;
+ }
+ return -1;
}
+void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
+
+
void CallICNexus::ConfigureMonomorphicArray() {
Object* feedback = GetFeedback();
if (!feedback->IsAllocationSite()) {
@@ -309,100 +481,182 @@
GetIsolate()->factory()->NewAllocationSite();
SetFeedback(*new_site);
}
-}
-
-
-void CallICNexus::ConfigureUninitialized() {
- SetFeedback(*vector()->UninitializedSentinel(GetIsolate()),
- SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
}
void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
- SetFeedback(*function);
+ Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
+ SetFeedback(*new_cell);
+ SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
}
-void KeyedLoadICNexus::ConfigureGeneric() {
- SetFeedback(*vector()->GenericSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
+void CallICNexus::ConfigureMegamorphic() {
+ FeedbackNexus::ConfigureMegamorphic();
}
-void LoadICNexus::ConfigureMegamorphic() {
- SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
-}
-
-
-void LoadICNexus::ConfigurePremonomorphic() {
- SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()),
+void CallICNexus::ConfigureMegamorphic(int call_count) {
+ SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement),
+ SKIP_WRITE_BARRIER);
}
-void KeyedLoadICNexus::ConfigurePremonomorphic() {
- SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()),
- SKIP_WRITE_BARRIER);
-}
-
-
-void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type,
+void LoadICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
Handle<Code> handler) {
- Handle<FixedArray> array = EnsureArrayOfSize(2);
- Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
- array->set(0, *cell);
- array->set(1, *handler);
+ SetFeedback(*cell);
+ SetFeedbackExtra(*handler);
}
void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
- Handle<HeapType> type,
+ Handle<Map> receiver_map,
Handle<Code> handler) {
- Handle<FixedArray> array = EnsureArrayOfSize(3);
- Handle<Map> receiver_map = IC::TypeToMap(*type, GetIsolate());
- if (name.is_null()) {
- array->set(0, Smi::FromInt(0));
- } else {
- array->set(0, *name);
- }
Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
- array->set(1, *cell);
- array->set(2, *handler);
+ if (name.is_null()) {
+ SetFeedback(*cell);
+ SetFeedbackExtra(*handler);
+ } else {
+ Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
+ SetFeedback(*name);
+ array->set(0, *cell);
+ array->set(1, *handler);
+ }
}
-void LoadICNexus::ConfigurePolymorphic(TypeHandleList* types,
+void StoreICNexus::ConfigureMonomorphic(Handle<Map> receiver_map,
+ Handle<Code> handler) {
+ Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+ SetFeedback(*cell);
+ SetFeedbackExtra(*handler);
+}
+
+
+void KeyedStoreICNexus::ConfigureMonomorphic(Handle<Name> name,
+ Handle<Map> receiver_map,
+ Handle<Code> handler) {
+ Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
+ if (name.is_null()) {
+ SetFeedback(*cell);
+ SetFeedbackExtra(*handler);
+ } else {
+ Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
+ SetFeedback(*name);
+ array->set(0, *cell);
+ array->set(1, *handler);
+ }
+}
+
+
+void LoadICNexus::ConfigurePolymorphic(MapHandleList* maps,
CodeHandleList* handlers) {
- int receiver_count = types->length();
- EnsureArrayOfSize(receiver_count * 2);
- InstallHandlers(0, types, handlers);
+ Isolate* isolate = GetIsolate();
+ int receiver_count = maps->length();
+ Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
+ InstallHandlers(array, maps, handlers);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+ SKIP_WRITE_BARRIER);
}
void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
- TypeHandleList* types,
+ MapHandleList* maps,
CodeHandleList* handlers) {
- int receiver_count = types->length();
- Handle<FixedArray> array = EnsureArrayOfSize(1 + receiver_count * 2);
+ int receiver_count = maps->length();
+ DCHECK(receiver_count > 1);
+ Handle<FixedArray> array;
if (name.is_null()) {
- array->set(0, Smi::FromInt(0));
+ array = EnsureArrayOfSize(receiver_count * 2);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
} else {
- array->set(0, *name);
+ array = EnsureExtraArrayOfSize(receiver_count * 2);
+ SetFeedback(*name);
}
- InstallHandlers(1, types, handlers);
+
+ InstallHandlers(array, maps, handlers);
}
-int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const {
+void StoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
+ CodeHandleList* handlers) {
+ Isolate* isolate = GetIsolate();
+ int receiver_count = maps->length();
+ Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 2);
+ InstallHandlers(array, maps, handlers);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+ SKIP_WRITE_BARRIER);
+}
+
+
+void KeyedStoreICNexus::ConfigurePolymorphic(Handle<Name> name,
+ MapHandleList* maps,
+ CodeHandleList* handlers) {
+ int receiver_count = maps->length();
+ DCHECK(receiver_count > 1);
+ Handle<FixedArray> array;
+ if (name.is_null()) {
+ array = EnsureArrayOfSize(receiver_count * 2);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
+ } else {
+ array = EnsureExtraArrayOfSize(receiver_count * 2);
+ SetFeedback(*name);
+ }
+
+ InstallHandlers(array, maps, handlers);
+}
+
+
+void KeyedStoreICNexus::ConfigurePolymorphic(MapHandleList* maps,
+ MapHandleList* transitioned_maps,
+ CodeHandleList* handlers) {
+ int receiver_count = maps->length();
+ DCHECK(receiver_count > 1);
+ Handle<FixedArray> array = EnsureArrayOfSize(receiver_count * 3);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(GetIsolate()),
+ SKIP_WRITE_BARRIER);
+
+ Handle<Oddball> undefined_value = GetIsolate()->factory()->undefined_value();
+ for (int i = 0; i < receiver_count; ++i) {
+ Handle<Map> map = maps->at(i);
+ Handle<WeakCell> cell = Map::WeakCellForMap(map);
+ array->set(i * 3, *cell);
+ if (!transitioned_maps->at(i).is_null()) {
+ Handle<Map> transitioned_map = transitioned_maps->at(i);
+ cell = Map::WeakCellForMap(transitioned_map);
+ array->set((i * 3) + 1, *cell);
+ } else {
+ array->set((i * 3) + 1, *undefined_value);
+ }
+ array->set((i * 3) + 2, *handlers->at(i));
+ }
+}
+
+
+int FeedbackNexus::ExtractMaps(MapHandleList* maps) const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
- if (feedback->IsFixedArray()) {
+ bool is_named_feedback = IsPropertyNameFeedback(feedback);
+ if (feedback->IsFixedArray() || is_named_feedback) {
int found = 0;
+ if (is_named_feedback) {
+ feedback = GetFeedbackExtra();
+ }
FixedArray* array = FixedArray::cast(feedback);
- // The array should be of the form [<optional name>], then
- // [map, handler, map, handler, ... ]
- DCHECK(array->length() >= (2 + start_index));
- for (int i = start_index; i < array->length(); i += 2) {
+ // 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;
+ 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* map = Map::cast(cell->value());
@@ -411,63 +665,96 @@
}
}
return found;
+ } else if (feedback->IsWeakCell()) {
+ WeakCell* cell = WeakCell::cast(feedback);
+ if (!cell->cleared()) {
+ Map* map = Map::cast(cell->value());
+ maps->Add(handle(map, isolate));
+ return 1;
+ }
}
return 0;
}
-MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(int start_index,
- Handle<Map> map) const {
+MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
Object* feedback = GetFeedback();
- if (feedback->IsFixedArray()) {
+ bool is_named_feedback = IsPropertyNameFeedback(feedback);
+ if (feedback->IsFixedArray() || is_named_feedback) {
+ if (is_named_feedback) {
+ feedback = GetFeedbackExtra();
+ }
FixedArray* array = FixedArray::cast(feedback);
- for (int i = start_index; i < array->length(); i += 2) {
+ DCHECK(array->length() >= 2);
+ int increment = array->get(1)->IsCode() ? 2 : 3;
+ 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 + 1));
+ Code* code = Code::cast(array->get(i + increment - 1));
DCHECK(code->kind() == Code::HANDLER);
return handle(code);
}
}
}
+ } else if (feedback->IsWeakCell()) {
+ WeakCell* cell = WeakCell::cast(feedback);
+ 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);
+ }
+ }
}
return MaybeHandle<Code>();
}
-bool FeedbackNexus::FindHandlers(int start_index, CodeHandleList* code_list,
- int length) const {
+bool FeedbackNexus::FindHandlers(CodeHandleList* code_list, int length) const {
Object* feedback = GetFeedback();
int count = 0;
- if (feedback->IsFixedArray()) {
+ bool is_named_feedback = IsPropertyNameFeedback(feedback);
+ if (feedback->IsFixedArray() || is_named_feedback) {
+ if (is_named_feedback) {
+ feedback = GetFeedbackExtra();
+ }
FixedArray* array = FixedArray::cast(feedback);
- // The array should be of the form [<optional name>], then
- // [map, handler, map, handler, ... ]. Be sure to skip handlers whose maps
- // have been cleared.
- DCHECK(array->length() >= (2 + start_index));
- for (int i = start_index; i < array->length(); i += 2) {
+ // 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;
+ for (int i = 0; i < array->length(); i += increment) {
+ DCHECK(array->get(i)->IsWeakCell());
WeakCell* cell = WeakCell::cast(array->get(i));
if (!cell->cleared()) {
- Code* code = Code::cast(array->get(i + 1));
+ Code* code = Code::cast(array->get(i + increment - 1));
DCHECK(code->kind() == Code::HANDLER);
code_list->Add(handle(code));
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));
+ count++;
+ }
}
return count == length;
}
-int LoadICNexus::ExtractMaps(MapHandleList* maps) const {
- return FeedbackNexus::ExtractMaps(0, maps);
-}
-
-
void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
@@ -476,41 +763,66 @@
}
-int KeyedLoadICNexus::ExtractMaps(MapHandleList* maps) const {
- return FeedbackNexus::ExtractMaps(1, maps);
-}
-
-
-MaybeHandle<Code> LoadICNexus::FindHandlerForMap(Handle<Map> map) const {
- return FeedbackNexus::FindHandlerForMap(0, map);
-}
-
-
-MaybeHandle<Code> KeyedLoadICNexus::FindHandlerForMap(Handle<Map> map) const {
- return FeedbackNexus::FindHandlerForMap(1, map);
-}
-
-
-bool LoadICNexus::FindHandlers(CodeHandleList* code_list, int length) const {
- return FeedbackNexus::FindHandlers(0, code_list, length);
-}
-
-
-bool KeyedLoadICNexus::FindHandlers(CodeHandleList* code_list,
- int length) const {
- return FeedbackNexus::FindHandlers(1, code_list, length);
-}
-
-
Name* KeyedLoadICNexus::FindFirstName() const {
Object* feedback = GetFeedback();
- if (feedback->IsFixedArray()) {
- FixedArray* array = FixedArray::cast(feedback);
- DCHECK(array->length() >= 3);
- Object* name = array->get(0);
- if (name->IsName()) return Name::cast(name);
+ if (IsPropertyNameFeedback(feedback)) {
+ return Name::cast(feedback);
}
return NULL;
}
+
+
+Name* KeyedStoreICNexus::FindFirstName() const {
+ Object* feedback = GetFeedback();
+ if (IsPropertyNameFeedback(feedback)) {
+ return Name::cast(feedback);
+ }
+ return NULL;
}
-} // namespace v8::internal
+
+
+void StoreICNexus::Clear(Code* host) {
+ StoreIC::Clear(GetIsolate(), host, this);
+}
+
+
+void KeyedStoreICNexus::Clear(Code* host) {
+ KeyedStoreIC::Clear(GetIsolate(), host, this);
+}
+
+
+KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
+ KeyedAccessStoreMode mode = STANDARD_STORE;
+ MapHandleList maps;
+ CodeHandleList handlers;
+
+ if (GetKeyType() == PROPERTY) return mode;
+
+ ExtractMaps(&maps);
+ 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);
+ CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
+ uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
+ CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
+ major_key == CodeStub::StoreFastElement ||
+ major_key == CodeStub::StoreElement ||
+ major_key == CodeStub::ElementsTransitionAndStore ||
+ major_key == CodeStub::NoCache);
+ if (major_key != CodeStub::NoCache) {
+ mode = CommonStoreModeBits::decode(minor_key);
+ break;
+ }
+ }
+
+ return mode;
+}
+
+
+IcCheckType KeyedStoreICNexus::GetKeyType() const {
+ // The structure of the vector slots tells us the type.
+ return GetFeedback()->IsName() ? PROPERTY : ELEMENT;
+}
+} // namespace internal
+} // namespace v8