Version 3.24.6

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@18396 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 9a68f63..1f5b165 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2487,13 +2487,7 @@
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) return true;
   if (obj->IsNumber()) {
-    double value = obj->Number();
-    static const i::DoubleRepresentation minus_zero(-0.0);
-    i::DoubleRepresentation rep(value);
-    if (rep.bits == minus_zero.bits) {
-      return false;
-    }
-    return i::FastI2D(i::FastD2I(value)) == value;
+    return i::IsInt32Double(obj->Number());
   }
   return false;
 }
@@ -2504,12 +2498,10 @@
   if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
   if (obj->IsNumber()) {
     double value = obj->Number();
-    static const i::DoubleRepresentation minus_zero(-0.0);
-    i::DoubleRepresentation rep(value);
-    if (rep.bits == minus_zero.bits) {
-      return false;
-    }
-    return i::FastUI2D(i::FastD2UI(value)) == value;
+    return !i::IsMinusZero(value) &&
+           value >= 0 &&
+           value <= i::kMaxUInt32 &&
+           value == i::FastUI2D(i::FastD2UI(value));
   }
   return false;
 }
@@ -6500,6 +6492,17 @@
 }
 
 
+void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
+  reinterpret_cast<i::Isolate*>(this)->stack_guard()->RequestInterrupt(
+      callback, data);
+}
+
+
+void Isolate::ClearInterrupt() {
+  reinterpret_cast<i::Isolate*>(this)->stack_guard()->ClearInterrupt();
+}
+
+
 Isolate* Isolate::GetCurrent() {
   i::Isolate* isolate = i::Isolate::UncheckedCurrent();
   return reinterpret_cast<Isolate*>(isolate);
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 4b65845..d95b746 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -803,7 +803,7 @@
   //   r1 - isolate
   FrameScope scope(masm, StackFrame::MANUAL);
   __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
-  __ PrepareCallCFunction(1, 0, r2);
+  __ PrepareCallCFunction(2, 0, r2);
   __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
   __ CallCFunction(
       ExternalReference::get_make_code_young_function(masm->isolate()), 2);
@@ -836,7 +836,7 @@
   //   r1 - isolate
   FrameScope scope(masm, StackFrame::MANUAL);
   __ stm(db_w, sp, r0.bit() | r1.bit() | fp.bit() | lr.bit());
-  __ PrepareCallCFunction(1, 0, r2);
+  __ PrepareCallCFunction(2, 0, r2);
   __ mov(r1, Operand(ExternalReference::isolate_address(masm->isolate())));
   __ CallCFunction(ExternalReference::get_mark_code_as_executed_function(
         masm->isolate()), 2);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 5f6076b..1e36b35 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -815,11 +815,11 @@
                           const Register scratch) {
   static const DoubleRepresentation minus_zero(-0.0);
   static const DoubleRepresentation zero(0.0);
-  DoubleRepresentation value(imm);
+  DoubleRepresentation value_rep(imm);
   // Handle special values first.
-  if (value.bits == zero.bits) {
+  if (value_rep == zero) {
     vmov(dst, kDoubleRegZero);
-  } else if (value.bits == minus_zero.bits) {
+  } else if (value_rep == minus_zero) {
     vneg(dst, kDoubleRegZero);
   } else {
     vmov(dst, imm, scratch);
diff --git a/src/ast.h b/src/ast.h
index cf3ef92..f8de9be 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -39,7 +39,6 @@
 #include "small-pointer-list.h"
 #include "smart-pointers.h"
 #include "token.h"
-#include "type-info.h"  // TODO(rossberg): this should eventually be removed
 #include "types.h"
 #include "utils.h"
 #include "variables.h"
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 0a9fdcb..c47bdf5 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -545,7 +545,7 @@
     map->AppendDescriptor(&d, witness);
   }
   {  // Add name.
-    CallbacksDescriptor d(*factory()->name_string(), *name, rw_attribs);
+    CallbacksDescriptor d(*factory()->name_string(), *name, ro_attribs);
     map->AppendDescriptor(&d, witness);
   }
   {  // Add arguments.
diff --git a/src/codegen.h b/src/codegen.h
index b271d21..d160f13 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -30,7 +30,6 @@
 
 #include "code-stubs.h"
 #include "runtime.h"
-#include "type-info.h"
 
 // Include the declaration of the architecture defined class CodeGenerator.
 // The contract  to the shared code is that the the CodeGenerator is a subclass
diff --git a/src/conversions.h b/src/conversions.h
index 7aa2d3f..f850f58 100644
--- a/src/conversions.h
+++ b/src/conversions.h
@@ -72,7 +72,7 @@
 // The result is unspecified if x is infinite or NaN, or if the rounded
 // integer value is outside the range of type int.
 inline int FastD2I(double x) {
-  return static_cast<int>(x);
+  return static_cast<int32_t>(x);
 }
 
 inline unsigned int FastD2UI(double x);
diff --git a/src/execution.cc b/src/execution.cc
index c0e9a64..a9f72b3 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -540,6 +540,48 @@
 }
 
 
+void StackGuard::RequestInterrupt(InterruptCallback callback, void* data) {
+  ExecutionAccess access(isolate_);
+  thread_local_.interrupt_flags_ |= API_INTERRUPT;
+  thread_local_.interrupt_callback_ = callback;
+  thread_local_.interrupt_callback_data_ = data;
+  set_interrupt_limits(access);
+}
+
+
+void StackGuard::ClearInterrupt() {
+  thread_local_.interrupt_callback_ = 0;
+  thread_local_.interrupt_callback_data_ = 0;
+  Continue(API_INTERRUPT);
+}
+
+
+bool StackGuard::IsAPIInterrupt() {
+  ExecutionAccess access(isolate_);
+  return thread_local_.interrupt_flags_ & API_INTERRUPT;
+}
+
+
+void StackGuard::InvokeInterruptCallback() {
+  InterruptCallback callback = 0;
+  void* data = 0;
+
+  {
+    ExecutionAccess access(isolate_);
+    callback = thread_local_.interrupt_callback_;
+    data = thread_local_.interrupt_callback_data_;
+    thread_local_.interrupt_callback_ = NULL;
+    thread_local_.interrupt_callback_data_ = NULL;
+  }
+
+  if (callback != NULL) {
+    VMState<EXTERNAL> state(isolate_);
+    HandleScope handle_scope(isolate_);
+    callback(reinterpret_cast<v8::Isolate*>(isolate_), data);
+  }
+}
+
+
 char* StackGuard::ArchiveStackGuard(char* to) {
   ExecutionAccess access(isolate_);
   OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
@@ -581,6 +623,8 @@
   nesting_ = 0;
   postpone_interrupts_nesting_ = 0;
   interrupt_flags_ = 0;
+  interrupt_callback_ = NULL;
+  interrupt_callback_data_ = NULL;
 }
 
 
@@ -601,6 +645,8 @@
   nesting_ = 0;
   postpone_interrupts_nesting_ = 0;
   interrupt_flags_ = 0;
+  interrupt_callback_ = NULL;
+  interrupt_callback_data_ = NULL;
   return should_set_stack_limits;
 }
 
@@ -936,6 +982,11 @@
     return isolate->heap()->undefined_value();
   }
 
+  if (stack_guard->IsAPIInterrupt()) {
+    stack_guard->InvokeInterruptCallback();
+    stack_guard->Continue(API_INTERRUPT);
+  }
+
   if (stack_guard->IsGCRequest()) {
     isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
                                        "StackGuard GC request");
diff --git a/src/execution.h b/src/execution.h
index eda416c..3e62d87 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -43,7 +43,8 @@
   TERMINATE = 1 << 4,
   GC_REQUEST = 1 << 5,
   FULL_DEOPT = 1 << 6,
-  INSTALL_CODE = 1 << 7
+  INSTALL_CODE = 1 << 7,
+  API_INTERRUPT = 1 << 8
 };
 
 
@@ -222,6 +223,11 @@
   void FullDeopt();
   void Continue(InterruptFlag after_what);
 
+  void RequestInterrupt(InterruptCallback callback, void* data);
+  void ClearInterrupt();
+  bool IsAPIInterrupt();
+  void InvokeInterruptCallback();
+
   // This provides an asynchronous read of the stack limits for the current
   // thread.  There are no locks protecting this, but it is assumed that you
   // have the global V8 lock if you are using multiple V8 threads.
@@ -307,6 +313,9 @@
     int nesting_;
     int postpone_interrupts_nesting_;
     int interrupt_flags_;
+
+    InterruptCallback interrupt_callback_;
+    void* interrupt_callback_data_;
   };
 
   // TODO(isolates): Technically this could be calculated directly from a
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 1230801..7489df7 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -534,8 +534,8 @@
             "trace progress of the incremental marking")
 DEFINE_bool(track_gc_object_stats, false,
             "track object counts and memory usage")
-DEFINE_bool(parallel_sweeping, true, "enable parallel sweeping")
-DEFINE_bool(concurrent_sweeping, false, "enable concurrent sweeping")
+DEFINE_bool(parallel_sweeping, false, "enable parallel sweeping")
+DEFINE_bool(concurrent_sweeping, true, "enable concurrent sweeping")
 DEFINE_int(sweeper_threads, 0,
            "number of parallel and concurrent sweeping threads")
 #ifdef VERIFY_HEAP
diff --git a/src/heap-snapshot-generator-inl.h b/src/heap-snapshot-generator-inl.h
index 43002d2..582de32 100644
--- a/src/heap-snapshot-generator-inl.h
+++ b/src/heap-snapshot-generator-inl.h
@@ -59,7 +59,10 @@
 
 HeapGraphEdge** HeapEntry::children_arr() {
   ASSERT(children_index_ >= 0);
-  return &snapshot_->children()[children_index_];
+  SLOW_ASSERT(children_index_ < snapshot_->children().length() ||
+      (children_index_ == snapshot_->children().length() &&
+       children_count_ == 0));
+  return &snapshot_->children().first() + children_index_;
 }
 
 
diff --git a/src/heap.cc b/src/heap.cc
index c42c445..7477450 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -49,6 +49,7 @@
 #include "snapshot.h"
 #include "store-buffer.h"
 #include "utils/random-number-generator.h"
+#include "v8conversions.h"
 #include "v8threads.h"
 #include "v8utils.h"
 #include "vm-state-inl.h"
@@ -3689,6 +3690,7 @@
   }
 }
 
+
 Heap::RootListIndex Heap::RootIndexForEmptyExternalArray(
     ElementsKind elementsKind) {
   switch (elementsKind) {
@@ -3723,16 +3725,11 @@
 }
 
 
-
-
 MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) {
   // We need to distinguish the minus zero value and this cannot be
   // done after conversion to int. Doing this by comparing bit
   // patterns is faster than using fpclassify() et al.
-  static const DoubleRepresentation minus_zero(-0.0);
-
-  DoubleRepresentation rep(value);
-  if (rep.bits == minus_zero.bits) {
+  if (IsMinusZero(value)) {
     return AllocateHeapNumber(-0.0, pretenure);
   }
 
diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
index bbd3042..ae11042 100644
--- a/src/hydrogen-check-elimination.cc
+++ b/src/hydrogen-check-elimination.cc
@@ -127,9 +127,14 @@
       new_entry->check_ = NULL;
       new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
     }
-    if (succ->predecessors()->length() == 1) {
-      HControlInstruction* end = succ->predecessors()->at(0)->end();
-      if (end->IsCompareMap() && end->SuccessorAt(0) == succ) {
+    copy->cursor_ = cursor_;
+    copy->size_ = size_;
+
+    // Branch-sensitive analysis for certain comparisons may add more facts
+    // to the state for the successor on the true branch.
+    HControlInstruction* end = succ->predecessors()->at(0)->end();
+    if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) {
+      if (end->IsCompareMap()) {
         // Learn on the true branch of if(CompareMap(x)).
         HCompareMap* cmp = HCompareMap::cast(end);
         HValue* object = cmp->value()->ActualValue();
@@ -141,9 +146,29 @@
           list->Add(cmp->map(), phase_->zone());
           entry->maps_ = list;
         }
+      } else if (end->IsCompareObjectEqAndBranch()) {
+        // Learn on the true branch of if(CmpObjectEq(x, y)).
+        HCompareObjectEqAndBranch* cmp =
+          HCompareObjectEqAndBranch::cast(end);
+        HValue* left = cmp->left()->ActualValue();
+        HValue* right = cmp->right()->ActualValue();
+        HCheckTableEntry* le = copy->Find(left);
+        HCheckTableEntry* re = copy->Find(right);
+        if (le == NULL) {
+          if (re != NULL) {
+            copy->Insert(left, NULL, re->maps_->Copy(zone));
+          }
+        } else if (re == NULL) {
+          copy->Insert(right, NULL, le->maps_->Copy(zone));
+        } else {
+          MapSet intersect = le->maps_->Intersect(re->maps_, zone);
+          le->maps_ = intersect;
+          re->maps_ = intersect->Copy(zone);
+        }
       }
-      // TODO(titzer): is it worthwhile to learn on false branch too?
+      // Learning on false branches requires storing negative facts.
     }
+
     return copy;
   }
 
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 46893e8..6e17397 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1377,7 +1377,7 @@
     HConstant* c = HConstant::cast(value);
     if (c->HasNumberValue()) {
       double double_res = c->DoubleValue();
-      if (TypeInfo::IsInt32Double(double_res)) {
+      if (IsInt32Double(double_res)) {
         return HConstant::New(zone, context,
                               static_cast<int32_t>(double_res),
                               required_representation);
@@ -3794,7 +3794,7 @@
     HConstant* c_right = HConstant::cast(right);                               \
     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {             \
       double double_res = c_left->DoubleValue() op c_right->DoubleValue();     \
-      if (TypeInfo::IsInt32Double(double_res)) {                               \
+      if (IsInt32Double(double_res)) {                                         \
         return H_CONSTANT_INT(double_res);                                     \
       }                                                                        \
       return H_CONSTANT_DOUBLE(double_res);                                    \
@@ -3990,7 +3990,7 @@
     if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
       if (c_right->DoubleValue() != 0) {
         double double_res = c_left->DoubleValue() / c_right->DoubleValue();
-        if (TypeInfo::IsInt32Double(double_res)) {
+        if (IsInt32Double(double_res)) {
           return H_CONSTANT_INT(double_res);
         }
         return H_CONSTANT_DOUBLE(double_res);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index fde3abc..1e270ab 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1245,7 +1245,7 @@
   virtual void Verify() V8_OVERRIDE;
 #endif
 
-  virtual bool IsCall() { return false; }
+  virtual bool HasStackCheck() { return false; }
 
   DECLARE_ABSTRACT_INSTRUCTION(Instruction)
 
@@ -2243,8 +2243,6 @@
     return -argument_count();
   }
 
-  virtual bool IsCall() V8_FINAL V8_OVERRIDE { return true; }
-
  private:
   int argument_count_;
 };
@@ -2300,6 +2298,9 @@
         known_function_(known_function) {
     formal_parameter_count_ = known_function.is_null()
         ? 0 : known_function->shared()->formal_parameter_count();
+    has_stack_check_ = !known_function.is_null() &&
+        (known_function->code()->kind() == Code::FUNCTION ||
+         known_function->code()->kind() == Code::OPTIMIZED_FUNCTION);
   }
 
   static HInvokeFunction* New(Zone* zone,
@@ -2316,15 +2317,21 @@
   Handle<JSFunction> known_function() { return known_function_; }
   int formal_parameter_count() const { return formal_parameter_count_; }
 
+  virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+    return has_stack_check_;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
 
  private:
   HInvokeFunction(HValue* context, HValue* function, int argument_count)
-      : HBinaryCall(context, function, argument_count) {
+      : HBinaryCall(context, function, argument_count),
+        has_stack_check_(false) {
   }
 
   Handle<JSFunction> known_function_;
   int formal_parameter_count_;
+  bool has_stack_check_;
 };
 
 
@@ -2348,16 +2355,24 @@
     return Representation::None();
   }
 
+  virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+    return has_stack_check_;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction)
 
  private:
   HCallConstantFunction(Handle<JSFunction> function, int argument_count)
       : HCall<0>(argument_count),
         function_(function),
-        formal_parameter_count_(function->shared()->formal_parameter_count()) {}
+        formal_parameter_count_(function->shared()->formal_parameter_count()),
+        has_stack_check_(
+            function->code()->kind() == Code::FUNCTION ||
+            function->code()->kind() == Code::OPTIMIZED_FUNCTION) {}
 
   Handle<JSFunction> function_;
   int formal_parameter_count_;
+  bool has_stack_check_;
 };
 
 
@@ -2465,16 +2480,24 @@
     return Representation::None();
   }
 
+  virtual bool HasStackCheck() V8_FINAL V8_OVERRIDE {
+    return has_stack_check_;
+  }
+
   DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal)
 
  private:
   HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
       : HCall<0>(argument_count),
         target_(target),
-        formal_parameter_count_(target->shared()->formal_parameter_count()) { }
+        formal_parameter_count_(target->shared()->formal_parameter_count()),
+        has_stack_check_(
+            target->code()->kind() == Code::FUNCTION ||
+            target->code()->kind() == Code::OPTIMIZED_FUNCTION) {}
 
   Handle<JSFunction> target_;
   int formal_parameter_count_;
+  bool has_stack_check_;
 };
 
 
diff --git a/src/hydrogen-load-elimination.cc b/src/hydrogen-load-elimination.cc
index f3b5748..f2e993b 100644
--- a/src/hydrogen-load-elimination.cc
+++ b/src/hydrogen-load-elimination.cc
@@ -43,7 +43,6 @@
 class HFieldApproximation : public ZoneObject {
  public:  // Just a data blob.
   HValue* object_;
-  HLoadNamedField* last_load_;
   HValue* last_value_;
   HFieldApproximation* next_;
 
@@ -52,7 +51,6 @@
     if (this == NULL) return NULL;
     HFieldApproximation* copy = new(zone) HFieldApproximation();
     copy->object_ = this->object_;
-    copy->last_load_ = this->last_load_;
     copy->last_value_ = this->last_value_;
     copy->next_ = this->next_->Copy(zone);
     return copy;
@@ -197,7 +195,6 @@
 
     if (approx->last_value_ == NULL) {
       // Load is not redundant. Fill out a new entry.
-      approx->last_load_ = instr;
       approx->last_value_ = instr;
       return instr;
     } else {
@@ -217,12 +214,14 @@
     HValue* object = instr->object()->ActualValue();
     HValue* value = instr->value();
 
-    // Kill non-equivalent may-alias entries.
-    KillFieldInternal(object, field, value);
     if (instr->has_transition()) {
-      // A transition store alters the map of the object.
-      // TODO(titzer): remember the new map (a constant) for the object.
+      // A transition introduces a new field and alters the map of the object.
+      // Since the field in the object is new, it cannot alias existing entries.
+      // TODO(titzer): introduce a constant for the new map and remember it.
       KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
+    } else {
+      // Kill non-equivalent may-alias entries.
+      KillFieldInternal(object, field, value);
     }
     HFieldApproximation* approx = FindOrCreate(object, field);
 
@@ -231,7 +230,6 @@
       return NULL;
     } else {
       // The store is not redundant. Update the entry.
-      approx->last_load_ = NULL;
       approx->last_value_ = value;
       return instr;
     }
@@ -314,7 +312,6 @@
 
     // Insert the entry at the head of the list.
     approx->object_ = object;
-    approx->last_load_ = NULL;
     approx->last_value_ = NULL;
     approx->next_ = fields_[field];
     fields_[field] = approx;
@@ -397,7 +394,6 @@
       PrintF("  field %d: ", i);
       for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
         PrintF("[o%d =", a->object_->id());
-        if (a->last_load_ != NULL) PrintF(" L%d", a->last_load_->id());
         if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
         PrintF("] ");
       }
diff --git a/src/hydrogen-sce.cc b/src/hydrogen-sce.cc
index a6995f6..70b0a0c 100644
--- a/src/hydrogen-sce.cc
+++ b/src/hydrogen-sce.cc
@@ -43,7 +43,7 @@
       HBasicBlock* dominator = back_edge;
       while (true) {
         for (HInstructionIterator it(dominator); !it.Done(); it.Advance()) {
-          if (it.Current()->IsCall()) {
+          if (it.Current()->HasStackCheck()) {
             block->loop_information()->stack_check()->Eliminate();
             break;
           }
diff --git a/src/ic.cc b/src/ic.cc
index 25f875a..dd7df98 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -35,6 +35,7 @@
 #include "ic-inl.h"
 #include "runtime.h"
 #include "stub-cache.h"
+#include "v8conversions.h"
 
 namespace v8 {
 namespace internal {
@@ -2674,7 +2675,7 @@
     new_kind = SMI;
   } else if (object->IsHeapNumber()) {
     double value = Handle<HeapNumber>::cast(object)->value();
-    new_kind = TypeInfo::IsInt32Double(value) ? INT32 : NUMBER;
+    new_kind = IsInt32Double(value) ? INT32 : NUMBER;
   } else if (object->IsString() && op() == Token::ADD) {
     new_kind = STRING;
   }
diff --git a/src/ic.h b/src/ic.h
index fa7ed6d..d1d2b61 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -29,12 +29,14 @@
 #define V8_IC_H_
 
 #include "macro-assembler.h"
-#include "type-info.h"
 
 namespace v8 {
 namespace internal {
 
 
+const int kMaxKeyedPolymorphism = 4;
+
+
 // IC_UTIL_LIST defines all utility functions called from generated
 // inline caching code. The argument for the macro, ICU, is the function name.
 #define IC_UTIL_LIST(ICU)                             \
@@ -296,6 +298,12 @@
 };
 
 
+enum StringStubFeedback {
+  DEFAULT_STRING_STUB = 0,
+  STRING_INDEX_OUT_OF_BOUNDS = 1
+};
+
+
 class CallICBase: public IC {
  public:
   // ExtraICState bits
diff --git a/src/isolate.h b/src/isolate.h
index 31a0af8..5c3bbb3 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1082,6 +1082,10 @@
   bool IsDeferredHandle(Object** location);
 #endif  // DEBUG
 
+  int max_available_threads() const {
+    return max_available_threads_;
+  }
+
   void set_max_available_threads(int value) {
     max_available_threads_ = value;
   }
diff --git a/src/default-platform.cc b/src/libplatform/default-platform.cc
similarity index 64%
copy from src/default-platform.cc
copy to src/libplatform/default-platform.cc
index ef3c4eb..1e21ca4 100644
--- a/src/default-platform.cc
+++ b/src/libplatform/default-platform.cc
@@ -25,24 +25,58 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "v8.h"
-
 #include "default-platform.h"
 
+#include <queue>
+
+// TODO(jochen): We should have our own version of checks.h.
+#include "../checks.h"
+// TODO(jochen): Why is cpu.h not in platform/?
+#include "../cpu.h"
+#include "worker-thread.h"
+
 namespace v8 {
 namespace internal {
 
 
-DefaultPlatform::DefaultPlatform() {}
+DefaultPlatform::DefaultPlatform()
+    : initialized_(false), thread_pool_size_(0) {}
 
 
-DefaultPlatform::~DefaultPlatform() {}
+DefaultPlatform::~DefaultPlatform() {
+  LockGuard<Mutex> guard(&lock_);
+  queue_.Terminate();
+  if (initialized_) {
+    for (std::vector<WorkerThread*>::iterator i = thread_pool_.begin();
+         i != thread_pool_.end(); ++i) {
+      delete *i;
+    }
+  }
+}
+
+
+void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
+  LockGuard<Mutex> guard(&lock_);
+  ASSERT(thread_pool_size >= 0);
+  if (thread_pool_size < 1)
+    thread_pool_size = CPU::NumberOfProcessorsOnline();
+  thread_pool_size_ = Max(Min(thread_pool_size, kMaxThreadPoolSize), 1);
+}
+
+
+void DefaultPlatform::EnsureInitialized() {
+  LockGuard<Mutex> guard(&lock_);
+  if (initialized_) return;
+  initialized_ = true;
+
+  for (int i = 0; i < thread_pool_size_; ++i)
+    thread_pool_.push_back(new WorkerThread(&queue_));
+}
 
 void DefaultPlatform::CallOnBackgroundThread(Task *task,
                                              ExpectedRuntime expected_runtime) {
-  // TODO(jochen): implement.
-  task->Run();
-  delete task;
+  EnsureInitialized();
+  queue_.Append(task);
 }
 
 
@@ -52,5 +86,4 @@
   delete task;
 }
 
-
 } }  // namespace v8::internal
diff --git a/src/default-platform.h b/src/libplatform/default-platform.h
similarity index 76%
rename from src/default-platform.h
rename to src/libplatform/default-platform.h
index fe1bf8e..877b3a6 100644
--- a/src/default-platform.h
+++ b/src/libplatform/default-platform.h
@@ -25,19 +25,31 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef V8_DEFAULT_PLATFORM_H_
-#define V8_DEFAULT_PLATFORM_H_
+#ifndef V8_LIBPLATFORM_DEFAULT_PLATFORM_H_
+#define V8_LIBPLATFORM_DEFAULT_PLATFORM_H_
 
-#include "v8.h"
+#include <vector>
+
+#include "../../include/v8-platform.h"
+// TODO(jochen): We should have our own version of globals.h.
+#include "../globals.h"
+#include "../platform/mutex.h"
+#include "task-queue.h"
 
 namespace v8 {
 namespace internal {
 
+class TaskQueue;
+class Thread;
+class WorkerThread;
+
 class DefaultPlatform : public Platform {
  public:
   DefaultPlatform();
   virtual ~DefaultPlatform();
 
+  void SetThreadPoolSize(int thread_pool_size);
+
   // v8::Platform implementation.
   virtual void CallOnBackgroundThread(
       Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
@@ -45,6 +57,16 @@
                                       Task *task) V8_OVERRIDE;
 
  private:
+  static const int kMaxThreadPoolSize = 4;
+
+  void EnsureInitialized();
+
+  Mutex lock_;
+  bool initialized_;
+  int thread_pool_size_;
+  std::vector<WorkerThread*> thread_pool_;
+  TaskQueue queue_;
+
   DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
 };
 
@@ -52,4 +74,4 @@
 } }  // namespace v8::internal
 
 
-#endif  // V8_DEFAULT_PLATFORM_H_
+#endif  // V8_LIBPLATFORM_DEFAULT_PLATFORM_H_
diff --git a/src/default-platform.cc b/src/libplatform/task-queue.cc
similarity index 62%
copy from src/default-platform.cc
copy to src/libplatform/task-queue.cc
index ef3c4eb..1ea31eb 100644
--- a/src/default-platform.cc
+++ b/src/libplatform/task-queue.cc
@@ -25,32 +25,56 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "v8.h"
+#include "task-queue.h"
 
-#include "default-platform.h"
+// TODO(jochen): We should have our own version of checks.h.
+#include "../checks.h"
 
 namespace v8 {
 namespace internal {
 
-
-DefaultPlatform::DefaultPlatform() {}
+TaskQueue::TaskQueue() : process_queue_semaphore_(0), terminated_(false) {}
 
 
-DefaultPlatform::~DefaultPlatform() {}
-
-void DefaultPlatform::CallOnBackgroundThread(Task *task,
-                                             ExpectedRuntime expected_runtime) {
-  // TODO(jochen): implement.
-  task->Run();
-  delete task;
+TaskQueue::~TaskQueue() {
+  LockGuard<Mutex> guard(&lock_);
+  ASSERT(terminated_);
+  ASSERT(task_queue_.empty());
 }
 
 
-void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
-  // TODO(jochen): implement.
-  task->Run();
-  delete task;
+void TaskQueue::Append(Task* task) {
+  LockGuard<Mutex> guard(&lock_);
+  ASSERT(!terminated_);
+  task_queue_.push(task);
+  process_queue_semaphore_.Signal();
 }
 
 
+Task* TaskQueue::GetNext() {
+  for (;;) {
+    {
+      LockGuard<Mutex> guard(&lock_);
+      if (!task_queue_.empty()) {
+        Task* result = task_queue_.front();
+        task_queue_.pop();
+        return result;
+      }
+      if (terminated_) {
+        process_queue_semaphore_.Signal();
+        return NULL;
+      }
+    }
+    process_queue_semaphore_.Wait();
+  }
+}
+
+
+void TaskQueue::Terminate() {
+  LockGuard<Mutex> guard(&lock_);
+  ASSERT(!terminated_);
+  terminated_ = true;
+  process_queue_semaphore_.Signal();
+}
+
 } }  // namespace v8::internal
diff --git a/src/default-platform.h b/src/libplatform/task-queue.h
similarity index 68%
copy from src/default-platform.h
copy to src/libplatform/task-queue.h
index fe1bf8e..a3182d3 100644
--- a/src/default-platform.h
+++ b/src/libplatform/task-queue.h
@@ -25,31 +25,47 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef V8_DEFAULT_PLATFORM_H_
-#define V8_DEFAULT_PLATFORM_H_
+#ifndef V8_LIBPLATFORM_TASK_QUEUE_H_
+#define V8_LIBPLATFORM_TASK_QUEUE_H_
 
-#include "v8.h"
+#include <queue>
+
+// TODO(jochen): We should have our own version of globals.h.
+#include "../globals.h"
+#include "../platform/mutex.h"
+#include "../platform/semaphore.h"
 
 namespace v8 {
+
+class Task;
+
 namespace internal {
 
-class DefaultPlatform : public Platform {
+class TaskQueue {
  public:
-  DefaultPlatform();
-  virtual ~DefaultPlatform();
+  TaskQueue();
+  ~TaskQueue();
 
-  // v8::Platform implementation.
-  virtual void CallOnBackgroundThread(
-      Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
-  virtual void CallOnForegroundThread(v8::Isolate *isolate,
-                                      Task *task) V8_OVERRIDE;
+  // Appends a task to the queue. The queue takes ownership of |task|.
+  void Append(Task* task);
+
+  // Returns the next task to process. Blocks if no task is available. Returns
+  // NULL if the queue is terminated.
+  Task* GetNext();
+
+  // Terminate the queue.
+  void Terminate();
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
-};
+  Mutex lock_;
+  Semaphore process_queue_semaphore_;
+  std::queue<Task*> task_queue_;
+  bool terminated_;
 
+  DISALLOW_COPY_AND_ASSIGN(TaskQueue);
+};
 
 } }  // namespace v8::internal
 
 
-#endif  // V8_DEFAULT_PLATFORM_H_
+#endif  // V8_LIBPLATFORM_TASK_QUEUE_H_
diff --git a/src/default-platform.cc b/src/libplatform/worker-thread.cc
similarity index 77%
rename from src/default-platform.cc
rename to src/libplatform/worker-thread.cc
index ef3c4eb..cca8a97 100644
--- a/src/default-platform.cc
+++ b/src/libplatform/worker-thread.cc
@@ -25,32 +25,32 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include "v8.h"
+#include "worker-thread.h"
 
-#include "default-platform.h"
+// TODO(jochen): We should have our own version of checks.h.
+#include "../checks.h"
+#include "../../include/v8-platform.h"
+#include "task-queue.h"
 
 namespace v8 {
 namespace internal {
 
-
-DefaultPlatform::DefaultPlatform() {}
-
-
-DefaultPlatform::~DefaultPlatform() {}
-
-void DefaultPlatform::CallOnBackgroundThread(Task *task,
-                                             ExpectedRuntime expected_runtime) {
-  // TODO(jochen): implement.
-  task->Run();
-  delete task;
+WorkerThread::WorkerThread(TaskQueue* queue)
+    : Thread("V8 WorkerThread"), queue_(queue) {
+  Start();
 }
 
 
-void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
-  // TODO(jochen): implement.
-  task->Run();
-  delete task;
+WorkerThread::~WorkerThread() {
+  Join();
 }
 
 
+void WorkerThread::Run() {
+  while (Task* task = queue_->GetNext()) {
+    task->Run();
+    delete task;
+  }
+}
+
 } }  // namespace v8::internal
diff --git a/src/default-platform.h b/src/libplatform/worker-thread.h
similarity index 75%
copy from src/default-platform.h
copy to src/libplatform/worker-thread.h
index fe1bf8e..f0b9019 100644
--- a/src/default-platform.h
+++ b/src/libplatform/worker-thread.h
@@ -25,31 +25,38 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef V8_DEFAULT_PLATFORM_H_
-#define V8_DEFAULT_PLATFORM_H_
+#ifndef V8_LIBPLATFORM_WORKER_THREAD_H_
+#define V8_LIBPLATFORM_WORKER_THREAD_H_
 
-#include "v8.h"
+#include <queue>
+
+// TODO(jochen): We should have our own version of globals.h.
+#include "../globals.h"
+#include "../platform.h"
 
 namespace v8 {
+
 namespace internal {
 
-class DefaultPlatform : public Platform {
- public:
-  DefaultPlatform();
-  virtual ~DefaultPlatform();
+class TaskQueue;
 
-  // v8::Platform implementation.
-  virtual void CallOnBackgroundThread(
-      Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
-  virtual void CallOnForegroundThread(v8::Isolate *isolate,
-                                      Task *task) V8_OVERRIDE;
+class WorkerThread : public Thread {
+ public:
+  explicit WorkerThread(TaskQueue* queue);
+  virtual ~WorkerThread();
+
+  // Thread implementation.
+  virtual void Run() V8_OVERRIDE;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
-};
+  friend class QuitTask;
 
+  TaskQueue* queue_;
+
+  DISALLOW_COPY_AND_ASSIGN(WorkerThread);
+};
 
 } }  // namespace v8::internal
 
 
-#endif  // V8_DEFAULT_PLATFORM_H_
+#endif  // V8_LIBPLATFORM_WORKER_THREAD_H_
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 40cc99f..ae8e3e7 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -825,7 +825,7 @@
       (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
   FrameScope scope(masm, StackFrame::MANUAL);
   __ MultiPush(saved_regs);
-  __ PrepareCallCFunction(1, 0, a2);
+  __ PrepareCallCFunction(2, 0, a2);
   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
   __ CallCFunction(
       ExternalReference::get_make_code_young_function(masm->isolate()), 2);
@@ -864,7 +864,7 @@
       (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit();
   FrameScope scope(masm, StackFrame::MANUAL);
   __ MultiPush(saved_regs);
-  __ PrepareCallCFunction(1, 0, a2);
+  __ PrepareCallCFunction(2, 0, a2);
   __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate())));
   __ CallCFunction(
       ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index bc981cb..4e3ab32 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -1228,12 +1228,12 @@
 void MacroAssembler::Move(FPURegister dst, double imm) {
   static const DoubleRepresentation minus_zero(-0.0);
   static const DoubleRepresentation zero(0.0);
-  DoubleRepresentation value(imm);
+  DoubleRepresentation value_rep(imm);
   // Handle special values first.
   bool force_load = dst.is(kDoubleRegZero);
-  if (value.bits == zero.bits && !force_load) {
+  if (value_rep == zero && !force_load) {
     mov_d(dst, kDoubleRegZero);
-  } else if (value.bits == minus_zero.bits && !force_load) {
+  } else if (value_rep == minus_zero && !force_load) {
     neg_d(dst, kDoubleRegZero);
   } else {
     uint32_t lo, hi;
diff --git a/src/property-details.h b/src/property-details.h
index 617e9b2..753eeee 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -113,8 +113,6 @@
 
   static Representation FromKind(Kind kind) { return Representation(kind); }
 
-  // TODO(rossberg): this should die eventually.
-  static Representation FromType(TypeInfo info);
   static Representation FromType(Handle<Type> type);
 
   bool Equals(const Representation& other) const {
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 6e68314..dc2c340 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -35,6 +35,7 @@
 #include "gdb-jit.h"
 #include "ic-inl.h"
 #include "stub-cache.h"
+#include "type-info.h"
 #include "vm-state-inl.h"
 
 namespace v8 {
diff --git a/src/type-info.cc b/src/type-info.cc
index 73d8c75..3cdcf8e 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -42,20 +42,6 @@
 namespace internal {
 
 
-TypeInfo TypeInfo::FromValue(Handle<Object> value) {
-  if (value->IsSmi()) {
-    return TypeInfo::Smi();
-  } else if (value->IsHeapNumber()) {
-    return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value())
-        ? TypeInfo::Integer32()
-        : TypeInfo::Double();
-  } else if (value->IsString()) {
-    return TypeInfo::String();
-  }
-  return TypeInfo::Unknown();
-}
-
-
 TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
                                        Handle<Context> native_context,
                                        Isolate* isolate,
@@ -586,14 +572,4 @@
 }
 
 
-Representation Representation::FromType(TypeInfo info) {
-  if (info.IsUninitialized()) return Representation::None();
-  if (info.IsSmi()) return Representation::Smi();
-  if (info.IsInteger32()) return Representation::Integer32();
-  if (info.IsDouble()) return Representation::Double();
-  if (info.IsNumber()) return Representation::Double();
-  return Representation::Tagged();
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/type-info.h b/src/type-info.h
index 8bad5c0..635be1a 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -36,189 +36,7 @@
 namespace v8 {
 namespace internal {
 
-const int kMaxKeyedPolymorphism = 4;
-
-//         Unknown
-//           |   \____________
-//           |                |
-//      Primitive       Non-primitive
-//           |   \_______     |
-//           |           |    |
-//        Number       String |
-//         /   \         |    |
-//    Double  Integer32  |   /
-//        |      |      /   /
-//        |     Smi    /   /
-//        |      |    / __/
-//        Uninitialized.
-
-class TypeInfo {
- public:
-  TypeInfo() : type_(kUninitialized) { }
-
-  static TypeInfo Unknown() { return TypeInfo(kUnknown); }
-  // We know it's a primitive type.
-  static TypeInfo Primitive() { return TypeInfo(kPrimitive); }
-  // We know it's a number of some sort.
-  static TypeInfo Number() { return TypeInfo(kNumber); }
-  // We know it's a signed 32 bit integer.
-  static TypeInfo Integer32() { return TypeInfo(kInteger32); }
-  // We know it's a Smi.
-  static TypeInfo Smi() { return TypeInfo(kSmi); }
-  // We know it's a heap number.
-  static TypeInfo Double() { return TypeInfo(kDouble); }
-  // We know it's a string.
-  static TypeInfo String() { return TypeInfo(kString); }
-  // We know it's an internalized string.
-  static TypeInfo InternalizedString() { return TypeInfo(kInternalizedString); }
-  // We know it's a non-primitive (object) type.
-  static TypeInfo NonPrimitive() { return TypeInfo(kNonPrimitive); }
-  // We haven't started collecting info yet.
-  static TypeInfo Uninitialized() { return TypeInfo(kUninitialized); }
-
-  int ToInt() {
-    return type_;
-  }
-
-  static TypeInfo FromInt(int bit_representation) {
-    Type t = static_cast<Type>(bit_representation);
-    ASSERT(t == kUnknown ||
-           t == kPrimitive ||
-           t == kNumber ||
-           t == kInteger32 ||
-           t == kSmi ||
-           t == kDouble ||
-           t == kString ||
-           t == kNonPrimitive);
-    return TypeInfo(t);
-  }
-
-  // Return the weakest (least precise) common type.
-  static TypeInfo Combine(TypeInfo a, TypeInfo b) {
-    return TypeInfo(static_cast<Type>(a.type_ & b.type_));
-  }
-
-
-  // Integer32 is an integer that can be represented as a signed
-  // 32-bit integer. It has to be
-  // in the range [-2^31, 2^31 - 1]. We also have to check for negative 0
-  // as it is not an Integer32.
-  static inline bool IsInt32Double(double value) {
-    const DoubleRepresentation minus_zero(-0.0);
-    DoubleRepresentation rep(value);
-    if (rep.bits == minus_zero.bits) return false;
-    if (value >= kMinInt && value <= kMaxInt &&
-        value == static_cast<int32_t>(value)) {
-      return true;
-    }
-    return false;
-  }
-
-  static TypeInfo FromValue(Handle<Object> value);
-
-  bool Equals(const TypeInfo& other) {
-    return type_ == other.type_;
-  }
-
-  inline bool IsUnknown() {
-    ASSERT(type_ != kUninitialized);
-    return type_ == kUnknown;
-  }
-
-  inline bool IsPrimitive() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kPrimitive) == kPrimitive);
-  }
-
-  inline bool IsNumber() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kNumber) == kNumber);
-  }
-
-  inline bool IsSmi() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kSmi) == kSmi);
-  }
-
-  inline bool IsInternalizedString() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kInternalizedString) == kInternalizedString);
-  }
-
-  inline bool IsNonInternalizedString() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kInternalizedString) == kString);
-  }
-
-  inline bool IsInteger32() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kInteger32) == kInteger32);
-  }
-
-  inline bool IsDouble() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kDouble) == kDouble);
-  }
-
-  inline bool IsString() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kString) == kString);
-  }
-
-  inline bool IsNonPrimitive() {
-    ASSERT(type_ != kUninitialized);
-    return ((type_ & kNonPrimitive) == kNonPrimitive);
-  }
-
-  inline bool IsUninitialized() {
-    return type_ == kUninitialized;
-  }
-
-  const char* ToString() {
-    switch (type_) {
-      case kUnknown: return "Unknown";
-      case kPrimitive: return "Primitive";
-      case kNumber: return "Number";
-      case kInteger32: return "Integer32";
-      case kSmi: return "Smi";
-      case kInternalizedString: return "InternalizedString";
-      case kDouble: return "Double";
-      case kString: return "String";
-      case kNonPrimitive: return "Object";
-      case kUninitialized: return "Uninitialized";
-    }
-    UNREACHABLE();
-    return "Unreachable code";
-  }
-
- private:
-  enum Type {
-    kUnknown = 0,                // 0000000
-    kPrimitive = 0x10,           // 0010000
-    kNumber = 0x11,              // 0010001
-    kInteger32 = 0x13,           // 0010011
-    kSmi = 0x17,                 // 0010111
-    kDouble = 0x19,              // 0011001
-    kString = 0x30,              // 0110000
-    kInternalizedString = 0x32,  // 0110010
-    kNonPrimitive = 0x40,        // 1000000
-    kUninitialized = 0x7f        // 1111111
-  };
-
-  explicit inline TypeInfo(Type t) : type_(t) { }
-
-  Type type_;
-};
-
-
-enum StringStubFeedback {
-  DEFAULT_STRING_STUB = 0,
-  STRING_INDEX_OUT_OF_BOUNDS = 1
-};
-
-
 // Forward declarations.
-class CompilationInfo;
 class ICStub;
 class SmallMapList;
 
diff --git a/src/unique.h b/src/unique.h
index a93b046..a2f29e4 100644
--- a/src/unique.h
+++ b/src/unique.h
@@ -278,7 +278,7 @@
     return out;
   }
 
-  // Makes an exact copy of this set. O(|this| + |that|).
+  // Makes an exact copy of this set. O(|this|).
   UniqueSet<T>* Copy(Zone* zone) const {
     UniqueSet<T>* copy = new(zone) UniqueSet<T>();
     copy->size_ = this->size_;
diff --git a/src/v8.cc b/src/v8.cc
index 265f0a6..76a6cb7 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -32,13 +32,13 @@
 #include "elements.h"
 #include "bootstrapper.h"
 #include "debug.h"
-#ifdef V8_USE_DEFAULT_PLATFORM
-#include "default-platform.h"
-#endif
 #include "deoptimizer.h"
 #include "frames.h"
 #include "heap-profiler.h"
 #include "hydrogen.h"
+#ifdef V8_USE_DEFAULT_PLATFORM
+#include "libplatform/default-platform.h"
+#endif
 #include "lithium-allocator.h"
 #include "objects.h"
 #include "once.h"
@@ -79,6 +79,11 @@
   if (isolate->IsDead()) return false;
   if (isolate->IsInitialized()) return true;
 
+#ifdef V8_USE_DEFAULT_PLATFORM
+  DefaultPlatform* platform = static_cast<DefaultPlatform*>(platform_);
+  platform->SetThreadPoolSize(isolate->max_available_threads());
+#endif
+
   return isolate->Init(des);
 }
 
diff --git a/src/v8conversions.h b/src/v8conversions.h
index 68107de..f2568c0 100644
--- a/src/v8conversions.h
+++ b/src/v8conversions.h
@@ -33,6 +33,24 @@
 namespace v8 {
 namespace internal {
 
+
+static inline bool IsMinusZero(double value) {
+  static const DoubleRepresentation minus_zero(-0.0);
+  return DoubleRepresentation(value) == minus_zero;
+}
+
+
+// Integer32 is an integer that can be represented as a signed 32-bit
+// integer. It has to be in the range [-2^31, 2^31 - 1].
+// We also have to check for negative 0 as it is not an Integer32.
+static inline bool IsInt32Double(double value) {
+  return !IsMinusZero(value) &&
+         value >= kMinInt &&
+         value <= kMaxInt &&
+         value == FastI2D(FastD2I(value));
+}
+
+
 // Convert from Number object to C integer.
 inline int32_t NumberToInt32(Object* number) {
   if (number->IsSmi()) return Smi::cast(number)->value();
diff --git a/src/v8globals.h b/src/v8globals.h
index 4910cb7..a9980e5 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -322,6 +322,9 @@
   double  value;
   int64_t bits;
   DoubleRepresentation(double x) { value = x; }
+  bool operator==(const DoubleRepresentation& other) const {
+    return bits == other.bits;
+  }
 };
 
 
diff --git a/src/version.cc b/src/version.cc
index 37f29c5..eb320a9 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     24
-#define BUILD_NUMBER      5
+#define BUILD_NUMBER      6
 #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/builtins-x64.cc b/src/x64/builtins-x64.cc
index aef9164..f2c955c 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -604,9 +604,9 @@
   __ movq(arg_reg_1, Operand(rsp, kNumSafepointRegisters * kPointerSize));
   {  // NOLINT
     FrameScope scope(masm, StackFrame::MANUAL);
-    __ PrepareCallCFunction(1);
+    __ PrepareCallCFunction(2);
     __ CallCFunction(
-        ExternalReference::get_make_code_young_function(masm->isolate()), 1);
+        ExternalReference::get_make_code_young_function(masm->isolate()), 2);
   }
   __ Popad();
   __ ret(0);
@@ -637,10 +637,10 @@
   __ subq(arg_reg_1, Immediate(Assembler::kShortCallInstructionLength));
   {  // NOLINT
     FrameScope scope(masm, StackFrame::MANUAL);
-    __ PrepareCallCFunction(1);
+    __ PrepareCallCFunction(2);
     __ CallCFunction(
         ExternalReference::get_mark_code_as_executed_function(masm->isolate()),
-        1);
+        2);
   }
   __ Popad();
 
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index 3c5666e..6586a27 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -29,7 +29,6 @@
 #define V8_X64_CODE_STUBS_X64_H_
 
 #include "ic-inl.h"
-#include "type-info.h"
 
 namespace v8 {
 namespace internal {