Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc
index 4519bd6..bc2f1c2 100644
--- a/src/type-feedback-vector.cc
+++ b/src/type-feedback-vector.cc
@@ -37,6 +37,23 @@
return VectorICComputer::decode(data, slot.ToInt());
}
+String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const {
+ DCHECK(SlotRequiresName(GetKind(slot)));
+ FixedArray* names = FixedArray::cast(get(kNamesTableIndex));
+ // TODO(ishell): consider using binary search here or even Dictionary when we
+ // have more ICs with names.
+ Smi* key = Smi::FromInt(slot.ToInt());
+ for (int entry = 0; entry < names->length(); entry += kNameTableEntrySize) {
+ Object* current_key = names->get(entry + kNameTableSlotIndex);
+ if (current_key == key) {
+ Object* name = names->get(entry + kNameTableNameIndex);
+ DCHECK(name->IsString());
+ return String::cast(name);
+ }
+ }
+ UNREACHABLE();
+ return nullptr;
+}
void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
FeedbackVectorSlotKind kind) {
@@ -57,12 +74,13 @@
template <typename Spec>
Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
const Spec* spec) {
+ Factory* factory = isolate->factory();
+
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<TypeFeedbackMetadata>::cast(
- isolate->factory()->empty_fixed_array());
+ return Handle<TypeFeedbackMetadata>::cast(factory->empty_fixed_array());
}
#ifdef DEBUG
for (int i = 0; i < slot_count;) {
@@ -76,7 +94,7 @@
}
#endif
- Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED);
+ Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
// Fill the bit-vector part with zeros.
for (int i = 0; i < slot_kinds_length; i++) {
@@ -85,9 +103,37 @@
Handle<TypeFeedbackMetadata> metadata =
Handle<TypeFeedbackMetadata>::cast(array);
+
+ // Add names to NamesTable.
+ const int name_count = spec->name_count();
+
+ Handle<FixedArray> names =
+ name_count == 0
+ ? factory->empty_fixed_array()
+ : factory->NewFixedArray(name_count * kNameTableEntrySize);
+ int name_index = 0;
for (int i = 0; i < slot_count; i++) {
- metadata->SetKind(FeedbackVectorSlot(i), spec->GetKind(i));
+ FeedbackVectorSlotKind kind = spec->GetKind(i);
+ metadata->SetKind(FeedbackVectorSlot(i), kind);
+ if (SlotRequiresName(kind)) {
+ Handle<String> name = spec->GetName(name_index);
+ DCHECK(!name.is_null());
+ int entry = name_index * kNameTableEntrySize;
+ names->set(entry + kNameTableSlotIndex, Smi::FromInt(i));
+ names->set(entry + kNameTableNameIndex, *name);
+ name_index++;
+ }
}
+ DCHECK_EQ(name_count, name_index);
+ metadata->set(kNamesTableIndex, *names);
+
+ // It's important that the TypeFeedbackMetadata have a COW map, since it's
+ // pointed to by both a SharedFunctionInfo and indirectly by closures through
+ // the TypeFeedbackVector. The serializer uses the COW map type to decide
+ // this object belongs in the startup snapshot and not the partial
+ // snapshot(s).
+ metadata->set_map(isolate->heap()->fixed_cow_array_map());
+
return metadata;
}
@@ -99,14 +145,51 @@
}
int slots = slot_count();
- for (int i = 0; i < slots; i++) {
- if (GetKind(FeedbackVectorSlot(i)) != other_spec->GetKind(i)) {
+ int name_index = 0;
+ for (int i = 0; i < slots;) {
+ FeedbackVectorSlot slot(i);
+ FeedbackVectorSlotKind kind = GetKind(slot);
+ int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
+
+ if (kind != other_spec->GetKind(i)) {
return true;
}
+ if (SlotRequiresName(kind)) {
+ String* name = GetName(slot);
+ DCHECK(name != GetHeap()->empty_string());
+ String* other_name = *other_spec->GetName(name_index++);
+ if (name != other_name) {
+ return true;
+ }
+ }
+ i += entry_size;
}
return false;
}
+bool TypeFeedbackMetadata::DiffersFrom(
+ const TypeFeedbackMetadata* other_metadata) const {
+ if (other_metadata->slot_count() != slot_count()) {
+ return true;
+ }
+
+ int slots = slot_count();
+ for (int i = 0; i < slots;) {
+ FeedbackVectorSlot slot(i);
+ FeedbackVectorSlotKind kind = GetKind(slot);
+ int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
+ if (GetKind(slot) != other_metadata->GetKind(slot)) {
+ return true;
+ }
+ if (SlotRequiresName(kind)) {
+ if (GetName(slot) != other_metadata->GetName(slot)) {
+ return true;
+ }
+ }
+ i += entry_size;
+ }
+ return false;
+}
const char* TypeFeedbackMetadata::Kind2String(FeedbackVectorSlotKind kind) {
switch (kind) {
@@ -116,6 +199,8 @@
return "CALL_IC";
case FeedbackVectorSlotKind::LOAD_IC:
return "LOAD_IC";
+ case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
+ return "LOAD_GLOBAL_IC";
case FeedbackVectorSlotKind::KEYED_LOAD_IC:
return "KEYED_LOAD_IC";
case FeedbackVectorSlotKind::STORE_IC:
@@ -131,6 +216,16 @@
return "?";
}
+FeedbackVectorSlotKind TypeFeedbackVector::GetKind(
+ FeedbackVectorSlot slot) const {
+ DCHECK(!is_empty());
+ return metadata()->GetKind(slot);
+}
+
+String* TypeFeedbackVector::GetName(FeedbackVectorSlot slot) const {
+ DCHECK(!is_empty());
+ return metadata()->GetName(slot);
+}
// static
Handle<TypeFeedbackVector> TypeFeedbackVector::New(
@@ -146,13 +241,29 @@
Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
array->set(kMetadataIndex, *metadata);
+ DisallowHeapAllocation no_gc;
+
// Ensure we can skip the write barrier
Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
DCHECK_EQ(*factory->uninitialized_symbol(), *uninitialized_sentinel);
- for (int i = kReservedIndexCount; i < length; i++) {
- array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
- }
+ for (int i = 0; i < slot_count;) {
+ FeedbackVectorSlot slot(i);
+ FeedbackVectorSlotKind kind = metadata->GetKind(slot);
+ int index = TypeFeedbackVector::GetIndex(slot);
+ int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
+ Object* value;
+ if (kind == FeedbackVectorSlotKind::LOAD_GLOBAL_IC) {
+ value = *factory->empty_weak_cell();
+ } else {
+ value = *uninitialized_sentinel;
+ }
+ array->set(index, value, SKIP_WRITE_BARRIER);
+ for (int j = 1; j < entry_size; j++) {
+ array->set(index + j, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
+ }
+ i += entry_size;
+ }
return Handle<TypeFeedbackVector>::cast(array);
}
@@ -208,6 +319,11 @@
nexus.Clear(shared->code());
break;
}
+ case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: {
+ LoadGlobalICNexus nexus(this, slot);
+ nexus.Clear(shared->code());
+ break;
+ }
case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
KeyedLoadICNexus nexus(this, slot);
nexus.Clear(shared->code());
@@ -251,8 +367,28 @@
SharedFunctionInfo::Iterator iterator(isolate);
SharedFunctionInfo* shared;
while ((shared = iterator.Next())) {
- TypeFeedbackVector* vector = shared->feedback_vector();
- vector->ClearKeyedStoreICs(shared);
+ if (!shared->OptimizedCodeMapIsCleared()) {
+ FixedArray* optimized_code_map = shared->optimized_code_map();
+ int length = optimized_code_map->length();
+ for (int i = SharedFunctionInfo::kEntriesStart; i < length;
+ i += SharedFunctionInfo::kEntryLength) {
+ Object* lits =
+ optimized_code_map->get(i + SharedFunctionInfo::kLiteralsOffset);
+ TypeFeedbackVector* vector = nullptr;
+ if (lits->IsWeakCell()) {
+ WeakCell* cell = WeakCell::cast(lits);
+ if (cell->value()->IsLiteralsArray()) {
+ vector = LiteralsArray::cast(cell->value())->feedback_vector();
+ }
+ } else {
+ DCHECK(lits->IsLiteralsArray());
+ vector = LiteralsArray::cast(lits)->feedback_vector();
+ }
+ if (vector != nullptr) {
+ vector->ClearKeyedStoreICs(shared);
+ }
+ }
+ }
}
}
@@ -389,6 +525,17 @@
return UNINITIALIZED;
}
+InlineCacheState LoadGlobalICNexus::StateFromFeedback() const {
+ Isolate* isolate = GetIsolate();
+ Object* feedback = GetFeedback();
+
+ Object* extra = GetFeedbackExtra();
+ if (!WeakCell::cast(feedback)->cleared() ||
+ extra != *TypeFeedbackVector::UninitializedSentinel(isolate)) {
+ return MONOMORPHIC;
+ }
+ return UNINITIALIZED;
+}
InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
@@ -488,7 +635,7 @@
int CallICNexus::ExtractCallCount() {
Object* call_count = GetFeedbackExtra();
if (call_count->IsSmi()) {
- int value = Smi::cast(call_count)->value() / 2;
+ int value = Smi::cast(call_count)->value();
return value;
}
return -1;
@@ -505,14 +652,14 @@
GetIsolate()->factory()->NewAllocationSite();
SetFeedback(*new_site);
}
- SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
}
void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) {
Handle<WeakCell> new_cell = GetIsolate()->factory()->NewWeakCell(function);
SetFeedback(*new_cell);
- SetFeedbackExtra(Smi::FromInt(kCallCountIncrement), SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(Smi::FromInt(1), SKIP_WRITE_BARRIER);
}
@@ -524,8 +671,7 @@
void CallICNexus::ConfigureMegamorphic(int call_count) {
SetFeedback(*TypeFeedbackVector::MegamorphicSentinel(GetIsolate()),
SKIP_WRITE_BARRIER);
- SetFeedbackExtra(Smi::FromInt(call_count * kCallCountIncrement),
- SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(Smi::FromInt(call_count), SKIP_WRITE_BARRIER);
}
@@ -536,6 +682,24 @@
SetFeedbackExtra(*handler);
}
+void LoadGlobalICNexus::ConfigureUninitialized() {
+ Isolate* isolate = GetIsolate();
+ SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+ SKIP_WRITE_BARRIER);
+}
+
+void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
+ Isolate* isolate = GetIsolate();
+ SetFeedback(*isolate->factory()->NewWeakCell(cell));
+ SetFeedbackExtra(*TypeFeedbackVector::UninitializedSentinel(isolate),
+ SKIP_WRITE_BARRIER);
+}
+
+void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Code> handler) {
+ SetFeedback(GetIsolate()->heap()->empty_weak_cell());
+ SetFeedbackExtra(*handler);
+}
void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
Handle<Map> receiver_map,
@@ -587,7 +751,6 @@
SKIP_WRITE_BARRIER);
}
-
void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
MapHandleList* maps,
CodeHandleList* handlers) {
@@ -781,6 +944,9 @@
void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
+void LoadGlobalICNexus::Clear(Code* host) {
+ LoadGlobalIC::Clear(GetIsolate(), host, this);
+}
void KeyedLoadICNexus::Clear(Code* host) {
KeyedLoadIC::Clear(GetIsolate(), host, this);