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