Index: src/type-feedback-vector.cc |
diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc |
index dcae7c72e657bacba67c4ee206fb28c57365098f..641f8b66e8f75166e1bb19ecd8097f33ca2d9ad0 100644 |
--- a/src/type-feedback-vector.cc |
+++ b/src/type-feedback-vector.cc |
@@ -4,6 +4,7 @@ |
#include "src/v8.h" |
+#include "src/ic/ic.h" |
#include "src/ic/ic-state.h" |
#include "src/objects.h" |
#include "src/type-feedback-vector-inl.h" |
@@ -12,10 +13,69 @@ namespace v8 { |
namespace internal { |
// static |
+TypeFeedbackVector::VectorICKind TypeFeedbackVector::FromCodeKind( |
+ Code::Kind kind) { |
+ if (kind == Code::CALL_IC) { |
+ return KindCallIC; |
+ } else if (kind == Code::LOAD_IC) { |
+ return KindLoadIC; |
+ } else if (kind == Code::KEYED_LOAD_IC) { |
+ return KindKeyedLoadIC; |
+ } |
+ |
+ // Shouldn't get here. |
+ UNREACHABLE(); |
+ return KindUnused; |
+} |
+ |
+ |
+// static |
+Code::Kind TypeFeedbackVector::FromVectorICKind(VectorICKind kind) { |
+ if (kind == KindCallIC) |
+ return Code::CALL_IC; |
+ else if (kind == KindLoadIC) |
+ return Code::LOAD_IC; |
+ else if (kind == KindKeyedLoadIC) |
+ return Code::KEYED_LOAD_IC; |
+ DCHECK(kind == KindUnused); |
+ return Code::NUMBER_OF_KINDS; // Sentinel for no information. |
+} |
+ |
+ |
+Code::Kind TypeFeedbackVector::GetKind(FeedbackVectorICSlot slot) const { |
+ if (!FLAG_vector_ics) { |
+ // We only have CALL_ICs |
+ return Code::CALL_IC; |
+ } |
+ |
+ int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
+ int data = Smi::cast(get(index))->value(); |
+ VectorICKind b = VectorICComputer::decode(data, slot.ToInt()); |
+ return FromVectorICKind(b); |
+} |
+ |
+ |
+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); |
+ int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt()); |
+ int data = Smi::cast(get(index))->value(); |
+ int new_data = VectorICComputer::encode(data, slot.ToInt(), b); |
+ set(index, Smi::FromInt(new_data)); |
+} |
+ |
+ |
+// static |
Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, |
int slot_count, |
int ic_slot_count) { |
- int length = slot_count + ic_slot_count + kReservedIndexCount; |
+ int index_count = |
+ FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0; |
+ int length = slot_count + ic_slot_count + index_count + kReservedIndexCount; |
if (length == kReservedIndexCount) { |
return Handle<TypeFeedbackVector>::cast( |
isolate->factory()->empty_fixed_array()); |
@@ -24,17 +84,21 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate, |
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length, TENURED); |
if (ic_slot_count > 0) { |
array->set(kFirstICSlotIndex, |
- Smi::FromInt(slot_count + kReservedIndexCount)); |
+ 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(kReservedIndexCount + i, Smi::FromInt(0)); |
+ } |
// 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; i < length; i++) { |
+ for (int i = kReservedIndexCount + index_count; i < length; i++) { |
array->set(i, *uninitialized_sentinel, SKIP_WRITE_BARRIER); |
} |
return Handle<TypeFeedbackVector>::cast(array); |
@@ -82,9 +146,142 @@ void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) { |
FeedbackVectorICSlot slot(i); |
Object* obj = Get(slot); |
if (obj != uninitialized_sentinel) { |
- ICUtility::Clear(isolate, Code::CALL_IC, host, this, slot); |
+ // TODO(mvstanton): To make this code work with --vector-ics, |
+ // additional Nexus types must be created. |
+ DCHECK(!FLAG_vector_ics); |
+ DCHECK(GetKind(slot) == Code::CALL_IC); |
+ CallICNexus nexus(this, slot); |
+ ICUtility::Clear(isolate, Code::CALL_IC, host, &nexus); |
+ } |
+ } |
+} |
+ |
+ |
+Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) { |
+ Isolate* isolate = GetIsolate(); |
+ Handle<Object> feedback = handle(GetFeedback(), isolate); |
+ if (!feedback->IsFixedArray() || |
+ FixedArray::cast(*feedback)->length() != length) { |
+ Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); |
+ SetFeedback(*array); |
+ return array; |
+ } |
+ return Handle<FixedArray>::cast(feedback); |
+} |
+ |
+ |
+void FeedbackNexus::InstallHandlers(int start_index, TypeHandleList* types, |
+ CodeHandleList* handlers) { |
+ Isolate* isolate = GetIsolate(); |
+ FixedArray* array = FixedArray::cast(GetFeedback()); |
+ 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); |
+ array->set(start_index + (current * 2), *map); |
+ array->set(start_index + (current * 2 + 1), *handlers->at(current)); |
+ } |
+} |
+ |
+ |
+InlineCacheState CallICNexus::StateFromFeedback() const { |
+ Isolate* isolate = GetIsolate(); |
+ InlineCacheState state = UNINITIALIZED; |
+ Object* feedback = GetFeedback(); |
+ |
+ if (feedback == *vector()->MegamorphicSentinel(isolate)) { |
+ state = GENERIC; |
+ } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) { |
+ state = MONOMORPHIC; |
+ } else { |
+ CHECK(feedback == *vector()->UninitializedSentinel(isolate)); |
+ } |
+ |
+ return state; |
+} |
+ |
+ |
+void CallICNexus::ConfigureGeneric() { |
+ SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER); |
+} |
+ |
+ |
+void CallICNexus::ConfigureMonomorphicArray() { |
+ Object* feedback = GetFeedback(); |
+ if (!feedback->IsAllocationSite()) { |
+ Handle<AllocationSite> new_site = |
+ GetIsolate()->factory()->NewAllocationSite(); |
+ SetFeedback(*new_site); |
+ } |
+} |
+ |
+ |
+void CallICNexus::ConfigureUninitialized() { |
+ SetFeedback(*vector()->UninitializedSentinel(GetIsolate()), |
+ SKIP_WRITE_BARRIER); |
+} |
+ |
+ |
+void CallICNexus::ConfigureMonomorphic(Handle<JSFunction> function) { |
+ SetFeedback(*function); |
+} |
+ |
+ |
+int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const { |
+ Isolate* isolate = GetIsolate(); |
+ Object* feedback = GetFeedback(); |
+ if (feedback->IsFixedArray()) { |
+ 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) { |
+ Map* map = Map::cast(array->get(i)); |
+ maps->Add(handle(map, isolate)); |
+ } |
+ return (array->length() - start_index) / 2; |
+ } |
+ |
+ return 0; |
+} |
+ |
+ |
+MaybeHandle<Code> FeedbackNexus::FindHandlerForMap(int start_index, |
+ Handle<Map> map) const { |
+ Object* feedback = GetFeedback(); |
+ if (feedback->IsFixedArray()) { |
+ FixedArray* array = FixedArray::cast(feedback); |
+ for (int i = start_index; i < array->length(); i += 2) { |
+ Map* array_map = Map::cast(array->get(i)); |
+ if (array_map == *map) { |
+ Code* code = Code::cast(array->get(i + 1)); |
+ DCHECK(code->kind() == Code::HANDLER); |
+ return handle(code); |
+ } |
+ } |
+ } |
+ |
+ return MaybeHandle<Code>(); |
+} |
+ |
+ |
+bool FeedbackNexus::FindHandlers(int start_index, CodeHandleList* code_list, |
+ int length) const { |
+ Object* feedback = GetFeedback(); |
+ int count = 0; |
+ if (feedback->IsFixedArray()) { |
+ 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) { |
+ Code* code = Code::cast(array->get(i + 1)); |
+ DCHECK(code->kind() == Code::HANDLER); |
+ code_list->Add(handle(code)); |
+ count++; |
} |
} |
+ return count == length; |
} |
} |
} // namespace v8::internal |