Version 3.25.14 (based on bleeding_edge revision r19965)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@19966 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index ec1613a..98753e4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-03-17: Version 3.25.14
+
+        Performance and stability improvements on all platforms.
+
+
+2014-03-17: Version 3.25.14
+
+        Performance and stability improvements on all platforms.
+
+
 2014-03-17: Version 3.25.13
 
         Move profiler callback interfaces from v8.h to v8-profiler.h.
diff --git a/src/a64/full-codegen-a64.cc b/src/a64/full-codegen-a64.cc
index a5f7311..dcab182 100644
--- a/src/a64/full-codegen-a64.cc
+++ b/src/a64/full-codegen-a64.cc
@@ -129,6 +129,8 @@
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
 
+  InitializeFeedbackVector();
+
   profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
@@ -1160,8 +1162,12 @@
   // We got a fixed array in register x0. Iterate through that.
   __ Bind(&fixed_array);
 
+  Handle<Object> feedback = Handle<Object>(
+      Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
+      isolate());
+  StoreFeedbackVectorSlot(slot, feedback);
   __ LoadObject(x1, FeedbackVector());
-  __ Mov(x10, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
+  __ Mov(x10, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
   __ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(slot)));
 
   __ Mov(x1, Operand(Smi::FromInt(1)));  // Smi indicates slow check.
@@ -2408,6 +2414,9 @@
   // Record source position for debugger.
   SetSourcePosition(expr->position());
 
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
   __ LoadObject(x2, FeedbackVector());
   __ Mov(x3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
 
@@ -2604,6 +2613,9 @@
   __ Peek(x1, arg_count * kXRegSize);
 
   // Record call targets in unoptimized code.
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
   __ LoadObject(x2, FeedbackVector());
   __ Mov(x3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
 
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index bad1003..8672ccb 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -131,6 +131,8 @@
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
 
+  InitializeFeedbackVector();
+
   profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
@@ -1164,8 +1166,12 @@
   Label non_proxy;
   __ bind(&fixed_array);
 
+  Handle<Object> feedback = Handle<Object>(
+      Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
+      isolate());
+  StoreFeedbackVectorSlot(slot, feedback);
   __ Move(r1, FeedbackVector());
-  __ mov(r2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
+  __ mov(r2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
   __ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot)));
 
   __ mov(r1, Operand(Smi::FromInt(1)));  // Smi indicates slow check
@@ -2705,6 +2711,9 @@
   // Record source position for debugger.
   SetSourcePosition(expr->position());
 
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
   __ Move(r2, FeedbackVector());
   __ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
 
@@ -2891,6 +2900,9 @@
   __ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
 
   // Record call targets in unoptimized code.
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
   __ Move(r2, FeedbackVector());
   __ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
 
diff --git a/src/compiler.cc b/src/compiler.cc
index 69b794d..fdee097 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -249,17 +249,6 @@
   ASSERT(scope_ == NULL);
   scope_ = scope;
   function()->ProcessFeedbackSlots(isolate_);
-  int length = function()->slot_count();
-  // Allocate the feedback vector too.
-  feedback_vector_ = isolate()->factory()->NewFixedArray(length, TENURED);
-  // Ensure we can skip the write barrier
-  ASSERT_EQ(isolate()->heap()->uninitialized_symbol(),
-            *TypeFeedbackInfo::UninitializedSentinel(isolate()));
-  for (int i = 0; i < length; i++) {
-    feedback_vector_->set(i,
-        *TypeFeedbackInfo::UninitializedSentinel(isolate()),
-        SKIP_WRITE_BARRIER);
-  }
 }
 
 
@@ -581,8 +570,6 @@
   shared->ReplaceCode(*code);
   if (shared->optimization_disabled()) code->set_optimizable(false);
 
-  shared->set_feedback_vector(*info->feedback_vector());
-
   // Set the expected number of properties for instances.
   FunctionLiteral* lit = info->function();
   int expected = lit->expected_property_count();
@@ -836,8 +823,7 @@
         lit->materialized_literal_count(),
         lit->is_generator(),
         info->code(),
-        ScopeInfo::Create(info->scope(), info->zone()),
-        info->feedback_vector());
+        ScopeInfo::Create(info->scope(), info->zone()));
 
     ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
     SetFunctionInfo(result, lit, true, script);
@@ -1036,8 +1022,7 @@
                                      literal->materialized_literal_count(),
                                      literal->is_generator(),
                                      info.code(),
-                                     scope_info,
-                                     info.feedback_vector());
+                                     scope_info);
   SetFunctionInfo(result, literal, false, script);
   RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
   result->set_allows_lazy_compilation(allow_lazy);
diff --git a/src/compiler.h b/src/compiler.h
index e4ade7b..f63475c 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -175,9 +175,6 @@
     ASSERT(global_scope_ == NULL);
     global_scope_ = global_scope;
   }
-  Handle<FixedArray> feedback_vector() const {
-    return feedback_vector_;
-  }
   void SetCode(Handle<Code> code) { code_ = code; }
   void SetExtension(v8::Extension* extension) {
     ASSERT(!is_lazy());
@@ -406,9 +403,6 @@
   // global script. Will be a null handle otherwise.
   Handle<Context> context_;
 
-  // Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
-  Handle<FixedArray> feedback_vector_;
-
   // Compilation mode flag and whether deoptimization is allowed.
   Mode mode_;
   BailoutId osr_ast_id_;
diff --git a/src/factory.cc b/src/factory.cc
index 6f86647..4dd7f77 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1542,12 +1542,10 @@
     int number_of_literals,
     bool is_generator,
     Handle<Code> code,
-    Handle<ScopeInfo> scope_info,
-    Handle<FixedArray> feedback_vector) {
+    Handle<ScopeInfo> scope_info) {
   Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
   shared->set_code(*code);
   shared->set_scope_info(*scope_info);
-  shared->set_feedback_vector(*feedback_vector);
   int literals_array_size = number_of_literals;
   // If the function contains object, regexp or array literals,
   // allocate extra space for a literals array prefix containing the
diff --git a/src/factory.h b/src/factory.h
index 558ff85..a87af1d 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -517,8 +517,7 @@
       int number_of_literals,
       bool is_generator,
       Handle<Code> code,
-      Handle<ScopeInfo> scope_info,
-      Handle<FixedArray> feedback_vector);
+      Handle<ScopeInfo> scope_info);
   Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
 
   Handle<JSMessageObject> NewJSMessageObject(
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 165d007..2170b84 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -386,6 +386,18 @@
 }
 
 
+void FullCodeGenerator::InitializeFeedbackVector() {
+  int length = info_->function()->slot_count();
+  feedback_vector_ = isolate()->factory()->NewFixedArray(length, TENURED);
+  Handle<Object> sentinel = TypeFeedbackInfo::UninitializedSentinel(isolate());
+  // Ensure that it's safe to set without using a write barrier.
+  ASSERT_EQ(isolate()->heap()->uninitialized_symbol(), *sentinel);
+  for (int i = 0; i < length; i++) {
+    feedback_vector_->set(i, *sentinel, SKIP_WRITE_BARRIER);
+  }
+}
+
+
 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
   // Fill in the deoptimization information.
   ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
@@ -404,6 +416,7 @@
 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
   Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
   info->set_ic_total_count(ic_total_count_);
+  info->set_feedback_vector(*FeedbackVector());
   ASSERT(!isolate()->heap()->InNewSpace(*info));
   code->set_type_feedback_info(*info);
 }
@@ -1605,8 +1618,7 @@
   bool is_generator = false;
   Handle<SharedFunctionInfo> shared =
       isolate()->factory()->NewSharedFunctionInfo(name, literals, is_generator,
-          code, Handle<ScopeInfo>(fun->shared()->scope_info()),
-          Handle<FixedArray>(fun->shared()->feedback_vector()));
+          code, Handle<ScopeInfo>(fun->shared()->scope_info()));
   shared->set_construct_stub(*construct_stub);
 
   // Copy the function data to the shared function info.
diff --git a/src/full-codegen.h b/src/full-codegen.h
index f2e39de..7d03527 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -437,8 +437,12 @@
   // Feedback slot support. The feedback vector will be cleared during gc and
   // collected by the type-feedback oracle.
   Handle<FixedArray> FeedbackVector() {
-    return info_->feedback_vector();
+    return feedback_vector_;
   }
+  void StoreFeedbackVectorSlot(int slot, Handle<Object> object) {
+    feedback_vector_->set(slot, *object);
+  }
+  void InitializeFeedbackVector();
 
   // Record a call's return site offset, used to rebuild the frame if the
   // called function was inlined at the site.
@@ -840,6 +844,7 @@
   ZoneList<BackEdgeEntry> back_edges_;
   int ic_total_count_;
   Handle<FixedArray> handler_table_;
+  Handle<FixedArray> feedback_vector_;
   Handle<Cell> profiling_counter_;
   bool generate_debug_code_;
 
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index a7c1c2e..10e177d 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1398,9 +1398,6 @@
   SetInternalReference(obj, entry,
                        "optimized_code_map", shared->optimized_code_map(),
                        SharedFunctionInfo::kOptimizedCodeMapOffset);
-  SetInternalReference(obj, entry,
-                       "feedback_vector", shared->feedback_vector(),
-                       SharedFunctionInfo::kFeedbackVectorOffset);
   SetWeakReference(obj, entry,
                    "initial_map", shared->initial_map(),
                    SharedFunctionInfo::kInitialMapOffset);
diff --git a/src/heap.cc b/src/heap.cc
index aa5c3a9..f33d6d3 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2687,6 +2687,7 @@
     if (!maybe_info->To(&info)) return maybe_info;
   }
   info->initialize_storage();
+  info->set_feedback_vector(empty_fixed_array(), SKIP_WRITE_BARRIER);
   return info;
 }
 
@@ -3808,7 +3809,6 @@
   share->set_script(undefined_value(), SKIP_WRITE_BARRIER);
   share->set_debug_info(undefined_value(), SKIP_WRITE_BARRIER);
   share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
-  share->set_feedback_vector(empty_fixed_array(), SKIP_WRITE_BARRIER);
   share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
   share->set_ast_node_count(0);
   share->set_counters(0);
diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
index a7c45ac..52a5492 100644
--- a/src/hydrogen-check-elimination.cc
+++ b/src/hydrogen-check-elimination.cc
@@ -88,6 +88,10 @@
         ReduceCompareMap(HCompareMap::cast(instr));
         break;
       }
+      case HValue::kCompareObjectEqAndBranch: {
+        ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch::cast(instr));
+        break;
+      }
       case HValue::kTransitionElementsKind: {
         ReduceTransitionElementsKind(
             HTransitionElementsKind::cast(instr));
@@ -479,6 +483,23 @@
     instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
   }
 
+  void ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch* instr) {
+    MapSet maps_left = FindMaps(instr->left()->ActualValue());
+    if (maps_left == NULL) return;
+    MapSet maps_right = FindMaps(instr->right()->ActualValue());
+    if (maps_right == NULL) return;
+    MapSet intersection = maps_left->Intersect(maps_right, phase_->zone());
+    if (intersection->size() > 0) return;
+
+    TRACE(("Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n",
+        instr->id(), instr->block()->block_id()));
+    int succ = 1;
+    instr->set_known_successor_index(succ);
+
+    int unreachable_succ = 1 - succ;
+    instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
+  }
+
   void ReduceTransitionElementsKind(HTransitionElementsKind* instr) {
     MapSet maps = FindMaps(instr->object()->ActualValue());
     // Can only learn more about an object that already has a known set of maps.
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 2b64f89..b2f1708 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -3098,6 +3098,10 @@
 
 
 bool HCompareObjectEqAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
+  if (known_successor_index() != kNoKnownSuccessorIndex) {
+    *block = SuccessorAt(known_successor_index());
+    return true;
+  }
   if (FLAG_fold_constants && left()->IsConstant() && right()->IsConstant()) {
     *block = HConstant::cast(left())->DataEquals(HConstant::cast(right()))
         ? FirstSuccessor() : SecondSuccessor();
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index c70ac73..5a6f4c2 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -4288,6 +4288,12 @@
 
   virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
 
+  static const int kNoKnownSuccessorIndex = -1;
+  int known_successor_index() const { return known_successor_index_; }
+  void set_known_successor_index(int known_successor_index) {
+    known_successor_index_ = known_successor_index;
+  }
+
   HValue* left() { return OperandAt(0); }
   HValue* right() { return OperandAt(1); }
 
@@ -4307,7 +4313,8 @@
   HCompareObjectEqAndBranch(HValue* left,
                             HValue* right,
                             HBasicBlock* true_target = NULL,
-                            HBasicBlock* false_target = NULL) {
+                            HBasicBlock* false_target = NULL)
+      : known_successor_index_(kNoKnownSuccessorIndex) {
     ASSERT(!left->IsConstant() ||
            (!HConstant::cast(left)->HasInteger32Value() ||
             HConstant::cast(left)->HasSmiValue()));
@@ -4319,6 +4326,8 @@
     SetSuccessorAt(0, true_target);
     SetSuccessorAt(1, false_target);
   }
+
+  int known_successor_index_;
 };
 
 
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 2881e90..04a045b 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -7206,7 +7206,6 @@
       target_shared->set_scope_info(*target_scope_info);
     }
     target_shared->EnableDeoptimizationSupport(*target_info.code());
-    target_shared->set_feedback_vector(*target_info.feedback_vector());
     Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
                                         &target_info,
                                         target_shared);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 06da7ba..096e2ed 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -119,6 +119,8 @@
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
 
+  InitializeFeedbackVector();
+
   profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
@@ -1102,10 +1104,15 @@
   Label non_proxy;
   __ bind(&fixed_array);
 
+  Handle<Object> feedback = Handle<Object>(
+      Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
+      isolate());
+  StoreFeedbackVectorSlot(slot, feedback);
+
   // No need for a write barrier, we are storing a Smi in the feedback vector.
   __ LoadHeapObject(ebx, FeedbackVector());
   __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
-         Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
+         Immediate(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
 
   __ mov(ebx, Immediate(Smi::FromInt(1)));  // Smi indicates slow check
   __ mov(ecx, Operand(esp, 0 * kPointerSize));  // Get enumerated object
@@ -2658,6 +2665,9 @@
   // Record source position for debugger.
   SetSourcePosition(expr->position());
 
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
   __ LoadHeapObject(ebx, FeedbackVector());
   __ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
 
@@ -2835,6 +2845,9 @@
   __ mov(edi, Operand(esp, arg_count * kPointerSize));
 
   // Record call targets in unoptimized code.
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
   __ LoadHeapObject(ebx, FeedbackVector());
   __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
 
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 8250ce0..02a890a 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -139,6 +139,8 @@
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
 
+  InitializeFeedbackVector();
+
   profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
@@ -1174,8 +1176,12 @@
   Label non_proxy;
   __ bind(&fixed_array);
 
+  Handle<Object> feedback = Handle<Object>(
+      Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
+      isolate());
+  StoreFeedbackVectorSlot(slot, feedback);
   __ li(a1, FeedbackVector());
-  __ li(a2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
+  __ li(a2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
   __ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot)));
 
   __ li(a1, Operand(Smi::FromInt(1)));  // Smi indicates slow check
@@ -2729,6 +2735,9 @@
   // Record source position for debugger.
   SetSourcePosition(expr->position());
 
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
   __ li(a2, FeedbackVector());
   __ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
 
@@ -2913,6 +2922,9 @@
   __ lw(a1, MemOperand(sp, arg_count * kPointerSize));
 
   // Record call targets in unoptimized code.
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
   __ li(a2, FeedbackVector());
   __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
 
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 4fafc15..5ca07d5 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -368,6 +368,7 @@
 void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
   VerifyObjectField(kStorage1Offset);
   VerifyObjectField(kStorage2Offset);
+  VerifyHeapPointer(feedback_vector());
 }
 
 
@@ -551,7 +552,6 @@
   VerifyObjectField(kNameOffset);
   VerifyObjectField(kCodeOffset);
   VerifyObjectField(kOptimizedCodeMapOffset);
-  VerifyObjectField(kFeedbackVectorOffset);
   VerifyObjectField(kScopeInfoOffset);
   VerifyObjectField(kInstanceClassNameOffset);
   VerifyObjectField(kFunctionDataOffset);
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 49fd9d4..75ff839 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1481,7 +1481,7 @@
 AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
                                            ElementsKind to) {
   if (IsFastSmiElementsKind(from) &&
-       IsMoreGeneralElementsKindTransition(from, to)) {
+      IsMoreGeneralElementsKindTransition(from, to)) {
     return TRACK_ALLOCATION_SITE;
   }
 
@@ -4980,8 +4980,6 @@
 ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
                  kOptimizedCodeMapOffset)
 ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
-ACCESSORS(SharedFunctionInfo, feedback_vector, FixedArray,
-          kFeedbackVectorOffset)
 ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
 ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
           kInstanceClassNameOffset)
@@ -6654,6 +6652,10 @@
 }
 
 
+ACCESSORS(TypeFeedbackInfo, feedback_vector, FixedArray,
+          kFeedbackVectorOffset)
+
+
 SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)
 
 
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index e287691..518167c 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -566,6 +566,8 @@
   HeapObject::PrintHeader(out, "TypeFeedbackInfo");
   PrintF(out, " - ic_total_count: %d, ic_with_type_info_count: %d\n",
          ic_total_count(), ic_with_type_info_count());
+  PrintF(out, " - feedback_vector: ");
+  feedback_vector()->FixedArrayPrint(out);
 }
 
 
@@ -879,8 +881,6 @@
   PrintF(out, "\n - length = %d", length());
   PrintF(out, "\n - optimized_code_map = ");
   optimized_code_map()->ShortPrint(out);
-  PrintF(out, "\n - feedback_vector = ");
-  feedback_vector()->FixedArrayPrint(out);
   PrintF(out, "\n");
 }
 
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index db84664..4f14988 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -427,6 +427,9 @@
     Map* map, HeapObject* object) {
   Heap* heap = map->GetHeap();
   Code* code = Code::cast(object);
+  if (FLAG_cleanup_code_caches_at_gc) {
+    code->ClearTypeFeedbackInfo(heap);
+  }
   if (FLAG_age_code && !Serializer::enabled()) {
     code->MakeOlder(heap->mark_compact_collector()->marking_parity());
   }
@@ -442,9 +445,6 @@
   if (shared->ic_age() != heap->global_ic_age()) {
     shared->ResetForNewContext(heap->global_ic_age());
   }
-  if (FLAG_cleanup_code_caches_at_gc) {
-    shared->ClearTypeFeedbackInfo(heap);
-  }
   if (FLAG_cache_optimized_code &&
       FLAG_flush_optimized_code_cache &&
       !shared->optimized_code_map()->IsSmi()) {
diff --git a/src/objects.cc b/src/objects.cc
index 92e4dc4..b1251e1 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -10642,16 +10642,19 @@
 }
 
 
-void SharedFunctionInfo::ClearTypeFeedbackInfo(Heap* heap) {
-  FixedArray* vector = feedback_vector();
-  for (int i = 0; i < vector->length(); i++) {
-    Object* obj = vector->get(i);
-    if (!obj->IsAllocationSite()) {
-      // The assert verifies we can skip the write barrier.
-      ASSERT(heap->uninitialized_symbol() ==
-             TypeFeedbackInfo::RawUninitializedSentinel(heap));
-      vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap),
-                  SKIP_WRITE_BARRIER);
+void Code::ClearTypeFeedbackInfo(Heap* heap) {
+  if (kind() != FUNCTION) return;
+  Object* raw_info = type_feedback_info();
+  if (raw_info->IsTypeFeedbackInfo()) {
+    FixedArray* feedback_vector =
+        TypeFeedbackInfo::cast(raw_info)->feedback_vector();
+    for (int i = 0; i < feedback_vector->length(); i++) {
+      Object* obj = feedback_vector->get(i);
+      if (!obj->IsAllocationSite()) {
+        // TODO(mvstanton): Can't I avoid a write barrier for this sentinel?
+        feedback_vector->set(i,
+                             TypeFeedbackInfo::RawUninitializedSentinel(heap));
+      }
     }
   }
 }
diff --git a/src/objects.h b/src/objects.h
index c772578..7a1ae26 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5497,6 +5497,8 @@
   void ClearInlineCaches();
   void ClearInlineCaches(Kind kind);
 
+  void ClearTypeFeedbackInfo(Heap* heap);
+
   BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset);
   uint32_t TranslateAstIdToPcOffset(BailoutId ast_id);
 
@@ -6692,8 +6694,6 @@
   // Removed a specific optimized code object from the optimized code map.
   void EvictFromOptimizedCodeMap(Code* optimized_code, const char* reason);
 
-  void ClearTypeFeedbackInfo(Heap* heap);
-
   // Trims the optimized code map after entries have been removed.
   void TrimOptimizedCodeMap(int shrink_by);
 
@@ -6802,12 +6802,6 @@
   inline int construction_count();
   inline void set_construction_count(int value);
 
-  // [feedback_vector] - accumulates ast node feedback from full-codegen and
-  // (increasingly) from crankshafted code where sufficient feedback isn't
-  // available. Currently the field is duplicated in
-  // TypeFeedbackInfo::feedback_vector, but the allocation is done here.
-  DECL_ACCESSORS(feedback_vector, FixedArray)
-
   // [initial_map]: initial map of the first function called as a constructor.
   // Saved for the duration of the tracking phase.
   // This is a weak link (GC resets it to undefined_value if no other live
@@ -7088,10 +7082,8 @@
   static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
   static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
   static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
-  static const int kFeedbackVectorOffset =
-      kInferredNameOffset + kPointerSize;
   static const int kInitialMapOffset =
-      kFeedbackVectorOffset + kPointerSize;
+      kInferredNameOffset + kPointerSize;
   // ast_node_count is a Smi field. It could be grouped with another Smi field
   // into a PSEUDO_SMI_ACCESSORS pair (on x64), if one becomes available.
   static const int kAstNodeCountOffset =
@@ -8177,6 +8169,8 @@
   inline void set_inlined_type_change_checksum(int checksum);
   inline bool matches_inlined_type_change_checksum(int checksum);
 
+  DECL_ACCESSORS(feedback_vector, FixedArray)
+
   static inline TypeFeedbackInfo* cast(Object* obj);
 
   // Dispatched behavior.
@@ -8185,9 +8179,10 @@
 
   static const int kStorage1Offset = HeapObject::kHeaderSize;
   static const int kStorage2Offset = kStorage1Offset + kPointerSize;
-  static const int kSize = kStorage2Offset + kPointerSize;
+  static const int kFeedbackVectorOffset =
+      kStorage2Offset + kPointerSize;
+  static const int kSize = kFeedbackVectorOffset + kPointerSize;
 
-  // TODO(mvstanton): move these sentinel declarations to shared function info.
   // The object that indicates an uninitialized cache.
   static inline Handle<Object> UninitializedSentinel(Isolate* isolate);
 
@@ -8203,6 +8198,9 @@
   // garbage collection (e.g., for patching the cache).
   static inline Object* RawUninitializedSentinel(Heap* heap);
 
+  static const int kForInFastCaseMarker = 0;
+  static const int kForInSlowCaseMarker = 1;
+
  private:
   static const int kTypeChangeChecksumBits = 7;
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 02be8a6..4bca2c7 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2929,7 +2929,6 @@
   // Set the code, scope info, formal parameter count, and the length
   // of the target shared function info.
   target_shared->ReplaceCode(source_shared->code());
-  target_shared->set_feedback_vector(source_shared->feedback_vector());
   target_shared->set_scope_info(source_shared->scope_info());
   target_shared->set_length(source_shared->length());
   target_shared->set_formal_parameter_count(
@@ -8478,10 +8477,10 @@
   HandleScope scope(isolate);
   ASSERT(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
-  function->shared()->ClearTypeFeedbackInfo(isolate->heap());
   Code* unoptimized = function->shared()->code();
   if (unoptimized->kind() == Code::FUNCTION) {
     unoptimized->ClearInlineCaches();
+    unoptimized->ClearTypeFeedbackInfo(isolate->heap());
   }
   return isolate->heap()->undefined_value();
 }
diff --git a/src/type-info.cc b/src/type-info.cc
index 6282ef6..35beb18 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -43,12 +43,16 @@
 
 
 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
-                                       Handle<FixedArray> feedback_vector,
                                        Handle<Context> native_context,
                                        Zone* zone)
     : native_context_(native_context),
-      zone_(zone),
-      feedback_vector_(feedback_vector) {
+      zone_(zone) {
+  Object* raw_info = code->type_feedback_info();
+  if (raw_info->IsTypeFeedbackInfo()) {
+    feedback_vector_ = Handle<FixedArray>(TypeFeedbackInfo::cast(raw_info)->
+                                          feedback_vector());
+  }
+
   BuildDictionary(code);
   ASSERT(dictionary_->IsDictionary());
 }
@@ -128,9 +132,9 @@
 
 byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) {
   Handle<Object> value = GetInfo(feedback_vector_slot);
-  return value.is_identical_to(
-      TypeFeedbackInfo::UninitializedSentinel(isolate()))
-      ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN;
+  return value->IsSmi() &&
+      Smi::cast(*value)->value() == TypeFeedbackInfo::kForInFastCaseMarker
+          ? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN;
 }
 
 
diff --git a/src/type-info.h b/src/type-info.h
index 8494424..5bf653f 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -44,7 +44,6 @@
 class TypeFeedbackOracle: public ZoneObject {
  public:
   TypeFeedbackOracle(Handle<Code> code,
-                     Handle<FixedArray> feedback_vector,
                      Handle<Context> native_context,
                      Zone* zone);
 
diff --git a/src/typing.cc b/src/typing.cc
index b9d0ba3..a88ca8c 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -40,7 +40,6 @@
     : info_(info),
       oracle_(
           Handle<Code>(info->closure()->shared()->code()),
-          Handle<FixedArray>(info->closure()->shared()->feedback_vector()),
           Handle<Context>(info->closure()->context()->native_context()),
           info->zone()),
       store_(info->zone()) {
diff --git a/src/version.cc b/src/version.cc
index d7908e3..6988b14 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     25
-#define BUILD_NUMBER      13
+#define BUILD_NUMBER      14
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index b146809..b40ee92 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -119,6 +119,8 @@
   handler_table_ =
       isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
 
+  InitializeFeedbackVector();
+
   profiling_counter_ = isolate()->factory()->NewCell(
       Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
   SetFunctionPosition(function());
@@ -1125,10 +1127,15 @@
   Label non_proxy;
   __ bind(&fixed_array);
 
+  Handle<Object> feedback = Handle<Object>(
+      Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
+      isolate());
+  StoreFeedbackVectorSlot(slot, feedback);
+
   // No need for a write barrier, we are storing a Smi in the feedback vector.
   __ Move(rbx, FeedbackVector());
   __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
-          TypeFeedbackInfo::MegamorphicSentinel(isolate()));
+          Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker));
   __ Move(rbx, Smi::FromInt(1));  // Smi indicates slow check
   __ movp(rcx, Operand(rsp, 0 * kPointerSize));  // Get enumerated object
   STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
@@ -2641,6 +2648,9 @@
   // Record source position for debugger.
   SetSourcePosition(expr->position());
 
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
   __ Move(rbx, FeedbackVector());
   __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
 
@@ -2818,6 +2828,9 @@
   __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
 
   // Record call targets in unoptimized code, but not in the snapshot.
+  Handle<Object> uninitialized =
+      TypeFeedbackInfo::UninitializedSentinel(isolate());
+  StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
   __ Move(rbx, FeedbackVector());
   __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
 
diff --git a/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc
index 00f29d4..120a053 100644
--- a/test/cctest/test-compiler.cc
+++ b/test/cctest/test-compiler.cc
@@ -312,43 +312,6 @@
 }
 
 
-TEST(FeedbackVectorRecreatedOnScopeChanges) {
-  if (i::FLAG_always_opt || !i::FLAG_lazy) return;
-  CcTest::InitializeVM();
-  v8::HandleScope scope(CcTest::isolate());
-
-  CompileRun("function builder() {"
-             "  call_target = function() { return 3; };"
-             "  return (function() {"
-             "    eval('');"
-             "    return function() {"
-             "      'use strict';"
-             "      call_target();"
-             "    }"
-             "  })();"
-             "}"
-             "morphing_call = builder();");
-
-  Handle<JSFunction> f =
-      v8::Utils::OpenHandle(
-          *v8::Handle<v8::Function>::Cast(
-              CcTest::global()->Get(v8_str("morphing_call"))));
-
-  // morphing_call should have one feedback vector slot for the call to
-  // call_target(), scoping analysis having been performed.
-  CHECK_EQ(1, f->shared()->feedback_vector()->length());
-  // And yet it's not compiled.
-  CHECK(!f->shared()->is_compiled());
-
-  CompileRun("morphing_call();");
-
-  // On scoping analysis after lazy compile, the call is now a global
-  // call which needs no feedback vector slot.
-  CHECK_EQ(0, f->shared()->feedback_vector()->length());
-  CHECK(f->shared()->is_compiled());
-}
-
-
 // Test that optimized code for different closures is actually shared
 // immediately by the FastNewClosureStub when run in the same context.
 TEST(OptimizedCodeSharing) {
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 07828a9..d8af3d1 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -2857,7 +2857,8 @@
           *v8::Handle<v8::Function>::Cast(
               CcTest::global()->Get(v8_str("f"))));
 
-  Handle<FixedArray> feedback_vector(f->shared()->feedback_vector());
+  Handle<FixedArray> feedback_vector(TypeFeedbackInfo::cast(
+      f->shared()->code()->type_feedback_info())->feedback_vector());
 
   CHECK_EQ(2, feedback_vector->length());
   CHECK(feedback_vector->get(0)->IsJSFunction());
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 8a2fef9..e6ebe48 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -221,6 +221,8 @@
   'regexp-global': [SKIP],
   'compiler/alloc-numbers': [SKIP],
   'harmony/symbols': [SKIP],
+  # Issue 3219:
+  'getters-on-elements': [PASS, ['gc_stress == True', FAIL]],
 }],  # 'arch == a64 and mode == debug and simulator_run == True'
 
 ##############################################################################
diff --git a/test/mjsunit/regress/regress-351257.js b/test/mjsunit/regress/regress-351257.js
deleted file mode 100644
index 40714fa..0000000
--- a/test/mjsunit/regress/regress-351257.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --stress-opt --always-opt
-
-function foo(x) { return x; }
-function container() {
-  x = 0;
-  eval('"use strict"; var x = 9;');
-  (function() {
-    "use strict";
-    foo(x);
-  })();
-}
-
-container();
diff --git a/test/mjsunit/regress/regress-crbug-352058.js b/test/mjsunit/regress/regress-crbug-352058.js
new file mode 100644
index 0000000..e270d83
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-352058.js
@@ -0,0 +1,17 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --check-elimination --stress-opt
+
+var v0 = this;
+var v2 = this;
+function f() {
+  v2 = [1.2, 2.3];
+  v0 = [12, 23];
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/tools/push-to-trunk/git_recipes.py b/tools/push-to-trunk/git_recipes.py
index 6b54510..4358258 100644
--- a/tools/push-to-trunk/git_recipes.py
+++ b/tools/push-to-trunk/git_recipes.py
@@ -65,7 +65,7 @@
 
   def GitCheckoutFile(self, name):
     assert name
-    self.Git(MakeArgs(["checkout --", name]))
+    self.Git(MakeArgs(["checkout -f --", name]))
 
   @Strip
   def GitCurrentBranch(self):
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index cff0a9a..d2a29da 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -741,7 +741,7 @@
       Git("checkout -b %s svn/trunk" % TEST_CONFIG[TRUNKBRANCH], "",
           cb=ResetChangeLog),
       Git("apply --index --reject \"%s\"" % TEST_CONFIG[PATCH_FILE], ""),
-      Git("checkout -- %s" % TEST_CONFIG[CHANGELOG_FILE], "",
+      Git("checkout -f -- %s" % TEST_CONFIG[CHANGELOG_FILE], "",
           cb=ResetChangeLog),
       Git("add \"%s\"" % TEST_CONFIG[VERSION_FILE], ""),
       Git("commit -aF \"%s\"" % TEST_CONFIG[COMMITMSG_FILE], "",