diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc
index a3fe070..c51d987 100644
--- a/src/type-feedback-vector.cc
+++ b/src/type-feedback-vector.cc
@@ -4,6 +4,8 @@
 
 #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"
 
@@ -11,6 +13,114 @@
 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
+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;
+}
+
+
+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, 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;
+  if (length == kReservedIndexCount) {
+    return Handle<TypeFeedbackVector>::cast(
+        isolate->factory()->empty_fixed_array());
+  }
+
+  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(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 + index_count; 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;
+}
+
+
+// static
 Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
     Isolate* isolate, Handle<TypeFeedbackVector> vector) {
   Handle<TypeFeedbackVector> result;
@@ -18,5 +128,389 @@
       isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
   return result;
 }
+
+
+// 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;
+}
+
+
+void TypeFeedbackVector::ClearSlots(SharedFunctionInfo* shared) {
+  int slots = Slots();
+  Isolate* isolate = GetIsolate();
+  Object* uninitialized_sentinel =
+      TypeFeedbackVector::RawUninitializedSentinel(isolate->heap());
+
+  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);
+      }
+    }
+  }
+
+  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);
+        }
+      } else if (kind == Code::LOAD_IC) {
+        LoadICNexus nexus(this, slot);
+        if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
+          nexus.Clear(host);
+        }
+      } else if (kind == Code::KEYED_LOAD_IC) {
+        KeyedLoadICNexus nexus(this, slot);
+        if (ClearLogic(heap, ic_age, kind, nexus.StateFromFeedback())) {
+          nexus.Clear(host);
+        }
+      }
+    }
+  }
+}
+
+
+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();
+  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));
+  }
+}
+
+
+InlineCacheState LoadICNexus::StateFromFeedback() const {
+  Isolate* isolate = GetIsolate();
+  Object* feedback = GetFeedback();
+  if (feedback == *vector()->UninitializedSentinel(isolate)) {
+    return UNINITIALIZED;
+  } else if (feedback == *vector()->MegamorphicSentinel(isolate)) {
+    return MEGAMORPHIC;
+  } else if (feedback == *vector()->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 UNINITIALIZED;
+}
+
+
+InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
+  Isolate* isolate = GetIsolate();
+  Object* feedback = GetFeedback();
+  if (feedback == *vector()->UninitializedSentinel(isolate)) {
+    return UNINITIALIZED;
+  } else if (feedback == *vector()->PremonomorphicSentinel(isolate)) {
+    return PREMONOMORPHIC;
+  } else if (feedback == *vector()->GenericSentinel(isolate)) {
+    return GENERIC;
+  } 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 UNINITIALIZED;
+}
+
+
+InlineCacheState CallICNexus::StateFromFeedback() const {
+  Isolate* isolate = GetIsolate();
+  Object* feedback = GetFeedback();
+
+  if (feedback == *vector()->MegamorphicSentinel(isolate)) {
+    return GENERIC;
+  } else if (feedback->IsAllocationSite() || feedback->IsJSFunction()) {
+    return MONOMORPHIC;
+  }
+
+  CHECK(feedback == *vector()->UninitializedSentinel(isolate));
+  return UNINITIALIZED;
+}
+
+
+void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
+
+
+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);
+}
+
+
+void KeyedLoadICNexus::ConfigureGeneric() {
+  SetFeedback(*vector()->GenericSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
+}
+
+
+void LoadICNexus::ConfigureMegamorphic() {
+  SetFeedback(*vector()->MegamorphicSentinel(GetIsolate()), SKIP_WRITE_BARRIER);
+}
+
+
+void LoadICNexus::ConfigurePremonomorphic() {
+  SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()),
+              SKIP_WRITE_BARRIER);
+}
+
+
+void KeyedLoadICNexus::ConfigurePremonomorphic() {
+  SetFeedback(*vector()->PremonomorphicSentinel(GetIsolate()),
+              SKIP_WRITE_BARRIER);
+}
+
+
+void LoadICNexus::ConfigureMonomorphic(Handle<HeapType> type,
+                                       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);
+}
+
+
+void KeyedLoadICNexus::ConfigureMonomorphic(Handle<Name> name,
+                                            Handle<HeapType> type,
+                                            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);
+}
+
+
+void LoadICNexus::ConfigurePolymorphic(TypeHandleList* types,
+                                       CodeHandleList* handlers) {
+  int receiver_count = types->length();
+  EnsureArrayOfSize(receiver_count * 2);
+  InstallHandlers(0, types, handlers);
+}
+
+
+void KeyedLoadICNexus::ConfigurePolymorphic(Handle<Name> name,
+                                            TypeHandleList* types,
+                                            CodeHandleList* handlers) {
+  int receiver_count = types->length();
+  Handle<FixedArray> array = EnsureArrayOfSize(1 + receiver_count * 2);
+  if (name.is_null()) {
+    array->set(0, Smi::FromInt(0));
+  } else {
+    array->set(0, *name);
+  }
+  InstallHandlers(1, types, handlers);
+}
+
+
+int FeedbackNexus::ExtractMaps(int start_index, MapHandleList* maps) const {
+  Isolate* isolate = GetIsolate();
+  Object* feedback = GetFeedback();
+  if (feedback->IsFixedArray()) {
+    int found = 0;
+    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) {
+      WeakCell* cell = WeakCell::cast(array->get(i));
+      if (!cell->cleared()) {
+        Map* map = Map::cast(cell->value());
+        maps->Add(handle(map, isolate));
+        found++;
+      }
+    }
+    return found;
+  }
+
+  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) {
+      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));
+          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, ... ]. 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) {
+      WeakCell* cell = WeakCell::cast(array->get(i));
+      if (!cell->cleared()) {
+        Code* code = Code::cast(array->get(i + 1));
+        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); }
+
+
+void KeyedLoadICNexus::Clear(Code* host) {
+  KeyedLoadIC::Clear(GetIsolate(), host, this);
+}
+
+
+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);
+  }
+  return NULL;
+}
 }
 }  // namespace v8::internal
