2013-11-22: Version 3.23.10

Remove preemption thread and API. (issue 3004)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@17998 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index a448e19..adc3e7a 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5045,6 +5045,24 @@
 // --- E n v i r o n m e n t ---
 
 
+void v8::V8::InitializePlatform(Platform* platform) {
+#ifdef V8_USE_DEFAULT_PLATFORM
+  FATAL("Can't override v8::Platform when using default implementation");
+#else
+  i::V8::InitializePlatform(platform);
+#endif
+}
+
+
+void v8::V8::ShutdownPlatform() {
+#ifdef V8_USE_DEFAULT_PLATFORM
+  FATAL("Can't override v8::Platform when using default implementation");
+#else
+  i::V8::ShutdownPlatform();
+#endif
+}
+
+
 bool v8::V8::Initialize() {
   i::Isolate* isolate = i::Isolate::UncheckedCurrent();
   if (isolate != NULL && isolate->IsInitialized()) {
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index bc52fa8..322df91 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -40,6 +40,7 @@
 #include "objects-visiting.h"
 #include "platform.h"
 #include "snapshot.h"
+#include "trig-table.h"
 #include "extensions/externalize-string-extension.h"
 #include "extensions/gc-extension.h"
 #include "extensions/statistics-extension.h"
@@ -2635,6 +2636,44 @@
   InitializeExperimentalGlobal();
   if (!InstallExperimentalNatives()) return;
 
+  if (!Serializer::enabled()) {
+    Handle<JSBuiltinsObject> builtins(native_context()->builtins());
+    // Initialize trigonometric lookup tables and constants.
+    // The snapshot cannot contain typed arrays, and we don't need it to.
+    const int table_num_bytes = TrigonometricLookupTable::table_num_bytes();
+    v8::Local<v8::ArrayBuffer> sin_buffer = v8::ArrayBuffer::New(
+        TrigonometricLookupTable::sin_table(), table_num_bytes);
+    v8::Local<v8::ArrayBuffer> cos_buffer = v8::ArrayBuffer::New(
+        TrigonometricLookupTable::cos_x_interval_table(), table_num_bytes);
+    v8::Local<v8::Float64Array> sin_table = v8::Float64Array::New(
+        sin_buffer, 0, TrigonometricLookupTable::table_size());
+    v8::Local<v8::Float64Array> cos_table = v8::Float64Array::New(
+        cos_buffer, 0, TrigonometricLookupTable::table_size());
+
+    ForceSetProperty(builtins,
+                     factory()->InternalizeOneByteString(
+                         STATIC_ASCII_VECTOR("kSinTable")),
+                     Utils::OpenHandle(*sin_table),
+                     NONE);
+    ForceSetProperty(builtins,
+                     factory()->InternalizeOneByteString(
+                         STATIC_ASCII_VECTOR("kCosXIntervalTable")),
+                     Utils::OpenHandle(*cos_table),
+                     NONE);
+    ForceSetProperty(builtins,
+                     factory()->InternalizeOneByteString(
+                         STATIC_ASCII_VECTOR("kSamples")),
+                     factory()->NewHeapNumber(
+                         TrigonometricLookupTable::samples()),
+                     NONE);
+    ForceSetProperty(builtins,
+                     factory()->InternalizeOneByteString(
+                         STATIC_ASCII_VECTOR("kIndexConvert")),
+                     factory()->NewHeapNumber(
+                         TrigonometricLookupTable::samples_over_pi_half()),
+                     NONE);
+  }
+
   // Initially seed the per-context random number generator
   // using the per-isolate random number generator.
   uint32_t* state = reinterpret_cast<uint32_t*>(
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 62e19e1..3d42483 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -511,6 +511,22 @@
                             AllocationSite::kNestedSiteOffset),
                         graph()->GetConstant0());
 
+  // Pretenuring calculation fields.
+  Add<HStoreNamedField>(object,
+                        HObjectAccess::ForAllocationSiteOffset(
+                            AllocationSite::kMementoFoundCountOffset),
+                        graph()->GetConstant0());
+
+  Add<HStoreNamedField>(object,
+                        HObjectAccess::ForAllocationSiteOffset(
+                            AllocationSite::kMementoCreateCountOffset),
+                        graph()->GetConstant0());
+
+  Add<HStoreNamedField>(object,
+                        HObjectAccess::ForAllocationSiteOffset(
+                            AllocationSite::kPretenureDecisionOffset),
+                        graph()->GetConstant0());
+
   // Store an empty fixed array for the code dependency.
   HConstant* empty_fixed_array =
     Add<HConstant>(isolate()->factory()->empty_fixed_array());
@@ -992,16 +1008,10 @@
 
   // Make sure that both arguments are strings if not known in advance.
   if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) {
-    IfBuilder if_leftnotstring(this);
-    if_leftnotstring.IfNot<HIsStringAndBranch>(left);
-    if_leftnotstring.Then();
-    if_leftnotstring.Deopt("Expected string for LHS of string addition");
+    left = BuildCheckString(left);
   }
   if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) {
-    IfBuilder if_rightnotstring(this);
-    if_rightnotstring.IfNot<HIsStringAndBranch>(right);
-    if_rightnotstring.Then();
-    if_rightnotstring.Deopt("Expected string for RHS of string addition");
+    right = BuildCheckString(right);
   }
 
   return BuildStringAdd(left, right, pretenure_flag);
diff --git a/src/d8.cc b/src/d8.cc
index 5b128c0..41b08bc 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1379,43 +1379,6 @@
     } else if (strcmp(argv[i], "--send-idle-notification") == 0) {
       options.send_idle_notification = true;
       argv[i] = NULL;
-    } else if (strcmp(argv[i], "--preemption") == 0) {
-#ifdef V8_SHARED
-      printf("D8 with shared library does not support multi-threading\n");
-      return false;
-#else
-      options.use_preemption = true;
-      argv[i] = NULL;
-#endif  // V8_SHARED
-    } else if (strcmp(argv[i], "--nopreemption") == 0) {
-#ifdef V8_SHARED
-      printf("D8 with shared library does not support multi-threading\n");
-      return false;
-#else
-      options.use_preemption = false;
-      argv[i] = NULL;
-#endif  // V8_SHARED
-    } else if (strcmp(argv[i], "--preemption-interval") == 0) {
-#ifdef V8_SHARED
-      printf("D8 with shared library does not support multi-threading\n");
-      return false;
-#else
-      if (++i < argc) {
-        argv[i-1] = NULL;
-        char* end = NULL;
-        options.preemption_interval = strtol(argv[i], &end, 10);  // NOLINT
-        if (options.preemption_interval <= 0
-            || *end != '\0'
-            || errno == ERANGE) {
-          printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
-          return false;
-        }
-        argv[i] = NULL;
-      } else {
-        printf("Missing value for --preemption-interval\n");
-        return false;
-      }
-#endif  // V8_SHARED
     } else if (strcmp(argv[i], "-f") == 0) {
       // Ignore any -f flags for compatibility with other stand-alone
       // JavaScript engines.
@@ -1554,14 +1517,6 @@
         V8::IdleNotification(kLongIdlePauseInMs);
       }
     }
-
-#ifndef V8_SHARED
-    // Start preemption if threads have been created and preemption is enabled.
-    if (threads.length() > 0
-        && options.use_preemption) {
-      Locker::StartPreemption(isolate, options.preemption_interval);
-    }
-#endif  // V8_SHARED
   }
 
 #ifndef V8_SHARED
@@ -1574,11 +1529,6 @@
     thread->Join();
     delete thread;
   }
-
-  if (threads.length() > 0 && options.use_preemption) {
-    Locker lock(isolate);
-    Locker::StopPreemption(isolate);
-  }
 #endif  // V8_SHARED
   return 0;
 }
diff --git a/src/d8.h b/src/d8.h
index 8c1687e..761276e 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -219,8 +219,6 @@
  public:
   ShellOptions() :
 #ifndef V8_SHARED
-     use_preemption(true),
-     preemption_interval(10),
      num_parallel_files(0),
      parallel_files(NULL),
 #endif  // V8_SHARED
@@ -245,8 +243,6 @@
   }
 
 #ifndef V8_SHARED
-  bool use_preemption;
-  int preemption_interval;
   int num_parallel_files;
   char** parallel_files;
 #endif  // V8_SHARED
diff --git a/src/default-platform.cc b/src/default-platform.cc
new file mode 100644
index 0000000..ef3c4eb
--- /dev/null
+++ b/src/default-platform.cc
@@ -0,0 +1,56 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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"
+
+namespace v8 {
+namespace internal {
+
+
+DefaultPlatform::DefaultPlatform() {}
+
+
+DefaultPlatform::~DefaultPlatform() {}
+
+void DefaultPlatform::CallOnBackgroundThread(Task *task,
+                                             ExpectedRuntime expected_runtime) {
+  // TODO(jochen): implement.
+  task->Run();
+  delete task;
+}
+
+
+void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
+  // TODO(jochen): implement.
+  task->Run();
+  delete task;
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/default-platform.h b/src/default-platform.h
new file mode 100644
index 0000000..fe1bf8e
--- /dev/null
+++ b/src/default-platform.h
@@ -0,0 +1,55 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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_
+
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+class DefaultPlatform : public Platform {
+ public:
+  DefaultPlatform();
+  virtual ~DefaultPlatform();
+
+  // v8::Platform implementation.
+  virtual void CallOnBackgroundThread(
+      Task *task, ExpectedRuntime expected_runtime) V8_OVERRIDE;
+  virtual void CallOnForegroundThread(v8::Isolate *isolate,
+                                      Task *task) V8_OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
+};
+
+
+} }  // namespace v8::internal
+
+
+#endif  // V8_DEFAULT_PLATFORM_H_
diff --git a/src/execution.cc b/src/execution.cc
index 8febbbf..32c616f 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -814,8 +814,6 @@
   // Clear the preempt request flag.
   isolate->stack_guard()->Continue(PREEMPT);
 
-  ContextSwitcher::PreemptionReceived();
-
 #ifdef ENABLE_DEBUGGER_SUPPORT
   if (isolate->debug()->InDebugger()) {
     // If currently in the debugger don't do any actual preemption but record
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 62cb307..1c95885 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -611,10 +611,6 @@
 DEFINE_bool(profile_deserialization, false,
             "Print the time it takes to deserialize the snapshot.")
 
-// v8.cc
-DEFINE_bool(preemption, false,
-            "activate a 100ms timer that switches between V8 threads")
-
 // Regexp
 DEFINE_bool(regexp_optimization, true, "generate optimized regexp code")
 
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index b7b7f22..7e74d86 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1526,6 +1526,15 @@
                        AllocationSite::kTransitionInfoOffset);
   SetInternalReference(site, entry, "nested_site", site->nested_site(),
                        AllocationSite::kNestedSiteOffset);
+  SetInternalReference(site, entry, "memento_found_count",
+                       site->memento_found_count(),
+                       AllocationSite::kMementoFoundCountOffset);
+  SetInternalReference(site, entry, "memento_create_count",
+                       site->memento_create_count(),
+                       AllocationSite::kMementoCreateCountOffset);
+  SetInternalReference(site, entry, "pretenure_decision",
+                       site->pretenure_decision(),
+                       AllocationSite::kPretenureDecisionOffset);
   SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
                        AllocationSite::kDependentCodeOffset);
 }
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index f7b3100..fd93ce3 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1273,17 +1273,14 @@
 }
 
 
-HValue* HGraphBuilder::BuildCheckString(
-    HValue* object, const char* failure_reason) {
-  if (!object->type().IsString()) {
-    ASSERT(!object->IsConstant() ||
-           !HConstant::cast(object)->HasStringValue());
-    IfBuilder if_isstring(this);
-    if_isstring.If<HIsStringAndBranch>(object);
-    if_isstring.Then();
-    if_isstring.ElseDeopt(failure_reason);
+HValue* HGraphBuilder::BuildCheckString(HValue* string) {
+  if (!string->type().IsString()) {
+    ASSERT(!string->IsConstant() ||
+           !HConstant::cast(string)->HasStringValue());
+    BuildCheckHeapObject(string);
+    return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
   }
-  return object;
+  return string;
 }
 
 
@@ -8657,14 +8654,12 @@
       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
     // Validate type feedback for left argument.
     if (left_type->Is(Type::String())) {
-      left = BuildCheckString(
-          left, "Expected string for LHS of binary operation");
+      left = BuildCheckString(left);
     }
 
     // Validate type feedback for right argument.
     if (right_type->Is(Type::String())) {
-      right = BuildCheckString(
-          right, "Expected string for RHS of binary operation");
+      right = BuildCheckString(right);
     }
 
     // Convert left argument as necessary.
diff --git a/src/hydrogen.h b/src/hydrogen.h
index a117c55..d11fbc0 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1256,7 +1256,7 @@
 
   HValue* BuildCheckHeapObject(HValue* object);
   HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
-  HValue* BuildCheckString(HValue* object, const char* failure_reason);
+  HValue* BuildCheckString(HValue* string);
   HValue* BuildWrapReceiver(HValue* object, HValue* function);
 
   // Building common constructs
diff --git a/src/isolate.cc b/src/isolate.cc
index 7250246..2acc59a 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1549,7 +1549,6 @@
       write_iterator_(NULL),
       global_handles_(NULL),
       eternal_handles_(NULL),
-      context_switcher_(NULL),
       thread_manager_(NULL),
       fp_stubs_generated_(false),
       has_installed_extensions_(false),
@@ -1690,10 +1689,6 @@
 
     delete deoptimizer_data_;
     deoptimizer_data_ = NULL;
-    if (FLAG_preemption) {
-      v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
-      v8::Locker::StopPreemption(reinterpret_cast<v8::Isolate*>(this));
-    }
     builtins_.TearDown();
     bootstrapper_->TearDown();
 
@@ -1805,8 +1800,6 @@
   delete write_iterator_;
   write_iterator_ = NULL;
 
-  delete context_switcher_;
-  context_switcher_ = NULL;
   delete thread_manager_;
   thread_manager_ = NULL;
 
@@ -2038,11 +2031,6 @@
     }
   }
 
-  if (FLAG_preemption) {
-    v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
-    v8::Locker::StartPreemption(reinterpret_cast<v8::Isolate*>(this), 100);
-  }
-
 #ifdef ENABLE_DEBUGGER_SUPPORT
   debug_->SetUp(create_heap_objects);
 #endif
diff --git a/src/isolate.h b/src/isolate.h
index ed568b7..f280ee8 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -58,7 +58,6 @@
 class CodeTracer;
 class CompilationCache;
 class ContextSlotCache;
-class ContextSwitcher;
 class Counters;
 class CpuFeatures;
 class CpuProfiler;
@@ -919,12 +918,6 @@
 
   ThreadManager* thread_manager() { return thread_manager_; }
 
-  ContextSwitcher* context_switcher() { return context_switcher_; }
-
-  void set_context_switcher(ContextSwitcher* switcher) {
-    context_switcher_ = switcher;
-  }
-
   StringTracker* string_tracker() { return string_tracker_; }
 
   unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
@@ -1293,7 +1286,6 @@
   ConsStringIteratorOp* write_iterator_;
   GlobalHandles* global_handles_;
   EternalHandles* eternal_handles_;
-  ContextSwitcher* context_switcher_;
   ThreadManager* thread_manager_;
   RuntimeState runtime_state_;
   bool fp_stubs_generated_;
diff --git a/src/math.js b/src/math.js
index 2df0ec2..c163d9a 100644
--- a/src/math.js
+++ b/src/math.js
@@ -79,7 +79,8 @@
 
 // ECMA 262 - 15.8.2.7
 function MathCos(x) {
-  return MathCosImpl(x);
+  x = MathAbs(x);  // Convert to number and get rid of -0.
+  return TrigonometricInterpolation(x, 1);
 }
 
 // ECMA 262 - 15.8.2.8
@@ -179,7 +180,9 @@
 
 // ECMA 262 - 15.8.2.16
 function MathSin(x) {
-  return MathSinImpl(x);
+  x = x * 1;  // Convert to number and deal with -0.
+  if (%_IsMinusZero(x)) return x;
+  return TrigonometricInterpolation(x, 0);
 }
 
 // ECMA 262 - 15.8.2.17
@@ -189,7 +192,7 @@
 
 // ECMA 262 - 15.8.2.18
 function MathTan(x) {
-  return MathSinImpl(x) / MathCosImpl(x);
+  return MathSin(x) / MathCos(x);
 }
 
 // Non-standard extension.
@@ -198,119 +201,73 @@
 }
 
 
-var MathSinImpl = function(x) {
-  InitTrigonometricFunctions();
-  return MathSinImpl(x);
-}
+var kInversePiHalf      = 0.636619772367581343;      // 2 / pi
+var kInversePiHalfS26   = 9.48637384723993156e-9;    // 2 / pi / (2^26)
+var kS26                = 1 << 26;
+var kTwoStepThreshold   = 1 << 27;
+// pi / 2 rounded up
+var kPiHalf             = 1.570796326794896780;      // 0x192d4454fb21f93f
+// We use two parts for pi/2 to emulate a higher precision.
+// pi_half_1 only has 26 significant bits for mantissa.
+// Note that pi_half > pi_half_1 + pi_half_2
+var kPiHalf1            = 1.570796325802803040;      // 0x00000054fb21f93f
+var kPiHalf2            = 9.920935796805404252e-10;  // 0x3326a611460b113e
 
+var kSamples;            // Initialized to a number during genesis.
+var kIndexConvert;       // Initialized to kSamples / (pi/2) during genesis.
+var kSinTable;           // Initialized to a Float64Array during genesis.
+var kCosXIntervalTable;  // Initialized to a Float64Array during genesis.
 
-var MathCosImpl = function(x) {
-  InitTrigonometricFunctions();
-  return MathCosImpl(x);
-}
-
-
-var InitTrigonometricFunctions;
-
-
-// Define constants and interpolation functions.
-// Also define the initialization function that populates the lookup table
-// and then wires up the function definitions.
-function SetupTrigonometricFunctions() {
-  var samples = 1800;   // Table size.  Do not change arbitrarily.
-  var inverse_pi_half      = 0.636619772367581343;      // 2 / pi
-  var inverse_pi_half_s_26 = 9.48637384723993156e-9;    // 2 / pi / (2^26)
-  var s_26 = 1 << 26;
-  var two_step_threshold   = 1 << 27;
-  var index_convert        = 1145.915590261646418;      // samples / (pi / 2)
-  // pi / 2 rounded up
-  var pi_half              = 1.570796326794896780;      // 0x192d4454fb21f93f
-  // We use two parts for pi/2 to emulate a higher precision.
-  // pi_half_1 only has 26 significant bits for mantissa.
-  // Note that pi_half > pi_half_1 + pi_half_2
-  var pi_half_1            = 1.570796325802803040;      // 0x00000054fb21f93f
-  var pi_half_2            = 9.920935796805404252e-10;  // 0x3326a611460b113e
-  var table_sin;
-  var table_cos_interval;
-
-  // This implements sine using the following algorithm.
-  // 1) Multiplication takes care of to-number conversion.
-  // 2) Reduce x to the first quadrant [0, pi/2].
-  //    Conveniently enough, in case of +/-Infinity, we get NaN.
-  //    Note that we try to use only 26 instead of 52 significant bits for
-  //    mantissa to avoid rounding errors when multiplying.  For very large
-  //    input we therefore have additional steps.
-  // 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant.
-  // 4) Do a table lookup for the closest samples to the left and right of x.
-  // 5) Find the derivatives at those sampling points by table lookup:
-  //    dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2].
-  // 6) Use cubic spline interpolation to approximate sin(x).
-  // 7) Negate the result if x was in the 3rd or 4th quadrant.
-  // 8) Get rid of -0 by adding 0.
-  var Interpolation = function(x, phase) {
-    if (x < 0 || x > pi_half) {
-      var multiple;
-      while (x < -two_step_threshold || x > two_step_threshold) {
-        // Let's assume this loop does not terminate.
-        // All numbers x in each loop forms a set S.
-        // (1) abs(x) > 2^27 for all x in S.
-        // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1
-        // (3) multiple is rounded down in 2^26 steps, so the rounding error is
-        //     at most max(ulp, 2^26).
-        // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least
-        //     (1-pi/4)x
-        // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4.
-        //     Note that this difference cannot be simply rounded off.
-        // Set S cannot exist since (5) violates (1).  Loop must terminate.
-        multiple = MathFloor(x * inverse_pi_half_s_26) * s_26;
-        x = x - multiple * pi_half_1 - multiple * pi_half_2;
-      }
-      multiple = MathFloor(x * inverse_pi_half);
-      x = x - multiple * pi_half_1 - multiple * pi_half_2;
-      phase += multiple;
+// This implements sine using the following algorithm.
+// 1) Multiplication takes care of to-number conversion.
+// 2) Reduce x to the first quadrant [0, pi/2].
+//    Conveniently enough, in case of +/-Infinity, we get NaN.
+//    Note that we try to use only 26 instead of 52 significant bits for
+//    mantissa to avoid rounding errors when multiplying.  For very large
+//    input we therefore have additional steps.
+// 3) Replace x by (pi/2-x) if x was in the 2nd or 4th quadrant.
+// 4) Do a table lookup for the closest samples to the left and right of x.
+// 5) Find the derivatives at those sampling points by table lookup:
+//    dsin(x)/dx = cos(x) = sin(pi/2-x) for x in [0, pi/2].
+// 6) Use cubic spline interpolation to approximate sin(x).
+// 7) Negate the result if x was in the 3rd or 4th quadrant.
+// 8) Get rid of -0 by adding 0.
+function TrigonometricInterpolation(x, phase) {
+  if (x < 0 || x > kPiHalf) {
+    var multiple;
+    while (x < -kTwoStepThreshold || x > kTwoStepThreshold) {
+      // Let's assume this loop does not terminate.
+      // All numbers x in each loop forms a set S.
+      // (1) abs(x) > 2^27 for all x in S.
+      // (2) abs(multiple) != 0 since (2^27 * inverse_pi_half_s26) > 1
+      // (3) multiple is rounded down in 2^26 steps, so the rounding error is
+      //     at most max(ulp, 2^26).
+      // (4) so for x > 2^27, we subtract at most (1+pi/4)x and at least
+      //     (1-pi/4)x
+      // (5) The subtraction results in x' so that abs(x') <= abs(x)*pi/4.
+      //     Note that this difference cannot be simply rounded off.
+      // Set S cannot exist since (5) violates (1).  Loop must terminate.
+      multiple = MathFloor(x * kInversePiHalfS26) * kS26;
+      x = x - multiple * kPiHalf1 - multiple * kPiHalf2;
     }
-    var double_index = x * index_convert;
-    if (phase & 1) double_index = samples - double_index;
-    var index = double_index | 0;
-    var t1 = double_index - index;
-    var t2 = 1 - t1;
-    var y1 = table_sin[index];
-    var y2 = table_sin[index + 1];
-    var dy = y2 - y1;
-    return (t2 * y1 + t1 * y2 +
-                t1 * t2 * ((table_cos_interval[index] - dy) * t2 +
-                           (dy - table_cos_interval[index + 1]) * t1))
-           * (1 - (phase & 2)) + 0;
+    multiple = MathFloor(x * kInversePiHalf);
+    x = x - multiple * kPiHalf1 - multiple * kPiHalf2;
+    phase += multiple;
   }
-
-  var MathSinInterpolation = function(x) {
-    x = x * 1;  // Convert to number and deal with -0.
-    if (%_IsMinusZero(x)) return x;
-    return Interpolation(x, 0);
-  }
-
-  // Cosine is sine with a phase offset.
-  var MathCosInterpolation = function(x) {
-    x = MathAbs(x);  // Convert to number and get rid of -0.
-    return Interpolation(x, 1);
-  };
-
-  %SetInlineBuiltinFlag(Interpolation);
-  %SetInlineBuiltinFlag(MathSinInterpolation);
-  %SetInlineBuiltinFlag(MathCosInterpolation);
-
-  InitTrigonometricFunctions = function() {
-    table_sin = new global.Float64Array(samples + 2);
-    table_cos_interval = new global.Float64Array(samples + 2);
-    %PopulateTrigonometricTable(table_sin, table_cos_interval, samples);
-    MathSinImpl = MathSinInterpolation;
-    MathCosImpl = MathCosInterpolation;
-  }
+  var double_index = x * kIndexConvert;
+  if (phase & 1) double_index = kSamples - double_index;
+  var index = double_index | 0;
+  var t1 = double_index - index;
+  var t2 = 1 - t1;
+  var y1 = kSinTable[index];
+  var y2 = kSinTable[index + 1];
+  var dy = y2 - y1;
+  return (t2 * y1 + t1 * y2 +
+              t1 * t2 * ((kCosXIntervalTable[index] - dy) * t2 +
+                         (dy - kCosXIntervalTable[index + 1]) * t1))
+         * (1 - (phase & 2)) + 0;
 }
 
-SetupTrigonometricFunctions();
-
-
 // -------------------------------------------------------------------
 
 function SetUpMath() {
@@ -387,6 +344,7 @@
   %SetInlineBuiltinFlag(MathSin);
   %SetInlineBuiltinFlag(MathCos);
   %SetInlineBuiltinFlag(MathTan);
+  %SetInlineBuiltinFlag(TrigonometricInterpolation);
 }
 
 SetUpMath();
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index bc5d62a..43d83bd 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -3037,22 +3037,44 @@
 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
   Register arguments = ToRegister(instr->arguments());
   Register result = ToRegister(instr->result());
-  if (instr->length()->IsConstantOperand() &&
-      instr->index()->IsConstantOperand()) {
-    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+  // There are two words between the frame pointer and the last argument.
+  // Subtracting from length accounts for one of them add one more.
+  if (instr->length()->IsConstantOperand()) {
     int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
-    int index = (const_length - const_index) + 1;
-    __ lw(result, MemOperand(arguments, index * kPointerSize));
+    if (instr->index()->IsConstantOperand()) {
+      int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+      int index = (const_length - const_index) + 1;
+      __ lw(result, MemOperand(arguments, index * kPointerSize));
+    } else {
+      Register index = ToRegister(instr->index());
+      __ li(at, Operand(const_length + 1));
+      __ Subu(result, at, index);
+      __ sll(at, result, kPointerSizeLog2);
+      __ Addu(at, arguments, at);
+      __ lw(result, MemOperand(at));
+    }
+  } else if (instr->index()->IsConstantOperand()) {
+    Register length = ToRegister(instr->length());
+    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
+    int loc = const_index - 1;
+    if (loc != 0) {
+      __ Subu(result, length, Operand(loc));
+      __ sll(at, result, kPointerSizeLog2);
+      __ Addu(at, arguments, at);
+      __ lw(result, MemOperand(at));
+    } else {
+      __ sll(at, length, kPointerSizeLog2);
+      __ Addu(at, arguments, at);
+      __ lw(result, MemOperand(at));
+    }
   } else {
     Register length = ToRegister(instr->length());
     Register index = ToRegister(instr->index());
-    // There are two words between the frame pointer and the last argument.
-    // Subtracting from length accounts for one of them, add one more.
-    __ subu(length, length, index);
-    __ Addu(length, length, Operand(1));
-    __ sll(length, length, kPointerSizeLog2);
-    __ Addu(at, arguments, Operand(length));
-    __ lw(result, MemOperand(at, 0));
+    __ Subu(result, length, index);
+    __ Addu(result, result, 1);
+    __ sll(at, result, kPointerSizeLog2);
+    __ Addu(at, arguments, at);
+    __ lw(result, MemOperand(at));
   }
 }
 
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index abdc3e6..5dbef8d 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -2472,15 +2472,8 @@
 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
   info()->MarkAsRequiresFrame();
   LOperand* args = UseRegister(instr->arguments());
-  LOperand* length;
-  LOperand* index;
-  if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
-    length = UseRegisterOrConstant(instr->length());
-    index = UseOrConstant(instr->index());
-  } else {
-    length = UseTempRegister(instr->length());
-    index = UseRegisterAtStart(instr->index());
-  }
+  LOperand* length = UseRegisterOrConstantAtStart(instr->length());
+  LOperand* index = UseRegisterOrConstantAtStart(instr->index());
   return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
 }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 2e8c0ad..7064ea9 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1314,6 +1314,9 @@
   set_transition_info(Smi::FromInt(0));
   SetElementsKind(GetInitialFastElementsKind());
   set_nested_site(Smi::FromInt(0));
+  set_memento_create_count(Smi::FromInt(0));
+  set_memento_found_count(Smi::FromInt(0));
+  set_pretenure_decision(Smi::FromInt(0));
   set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
                      SKIP_WRITE_BARRIER);
 }
@@ -3874,33 +3877,14 @@
 
 
 int Code::major_key() {
-  ASSERT(kind() == STUB ||
-         kind() == HANDLER ||
-         kind() == BINARY_OP_IC ||
-         kind() == COMPARE_IC ||
-         kind() == COMPARE_NIL_IC ||
-         kind() == STORE_IC ||
-         kind() == LOAD_IC ||
-         kind() == KEYED_LOAD_IC ||
-         kind() == KEYED_CALL_IC ||
-         kind() == TO_BOOLEAN_IC);
+  ASSERT(has_major_key());
   return StubMajorKeyField::decode(
       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
 }
 
 
 void Code::set_major_key(int major) {
-  ASSERT(kind() == STUB ||
-         kind() == HANDLER ||
-         kind() == BINARY_OP_IC ||
-         kind() == COMPARE_IC ||
-         kind() == COMPARE_NIL_IC ||
-         kind() == LOAD_IC ||
-         kind() == KEYED_LOAD_IC ||
-         kind() == STORE_IC ||
-         kind() == KEYED_STORE_IC ||
-         kind() == KEYED_CALL_IC ||
-         kind() == TO_BOOLEAN_IC);
+  ASSERT(has_major_key());
   ASSERT(0 <= major && major < 256);
   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
   int updated = StubMajorKeyField::update(previous, major);
@@ -3908,6 +3892,21 @@
 }
 
 
+bool Code::has_major_key() {
+  return kind() == STUB ||
+      kind() == HANDLER ||
+      kind() == BINARY_OP_IC ||
+      kind() == COMPARE_IC ||
+      kind() == COMPARE_NIL_IC ||
+      kind() == LOAD_IC ||
+      kind() == KEYED_LOAD_IC ||
+      kind() == STORE_IC ||
+      kind() == KEYED_STORE_IC ||
+      kind() == KEYED_CALL_IC ||
+      kind() == TO_BOOLEAN_IC;
+}
+
+
 bool Code::is_pregenerated() {
   return (kind() == STUB && IsPregeneratedField::decode(flags()));
 }
@@ -4552,6 +4551,10 @@
 
 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
 ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
+ACCESSORS_TO_SMI(AllocationSite, memento_found_count, kMementoFoundCountOffset)
+ACCESSORS_TO_SMI(AllocationSite, memento_create_count,
+                 kMementoCreateCountOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_decision, kPretenureDecisionOffset)
 ACCESSORS(AllocationSite, dependent_code, DependentCode,
           kDependentCodeOffset)
 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 5260193..9f1b939 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -1125,6 +1125,12 @@
   dependent_code()->ShortPrint(out);
   PrintF(out, "\n - nested site: ");
   nested_site()->ShortPrint(out);
+  PrintF(out, "\n - memento found count: ");
+  memento_found_count()->ShortPrint(out);
+  PrintF(out, "\n - memento create count: ");
+  memento_create_count()->ShortPrint(out);
+  PrintF(out, "\n - pretenure decision: ");
+  pretenure_decision()->ShortPrint(out);
   PrintF(out, "\n - transition_info: ");
   if (transition_info()->IsSmi()) {
     ElementsKind kind = GetElementsKind();
diff --git a/src/objects.cc b/src/objects.cc
index c874ee3..2b38b1d 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -33,6 +33,7 @@
 #include "arguments.h"
 #include "bootstrapper.h"
 #include "codegen.h"
+#include "code-stubs.h"
 #include "cpu-profiler.h"
 #include "debug.h"
 #include "deoptimizer.h"
@@ -11135,6 +11136,10 @@
 
 void Code::Disassemble(const char* name, FILE* out) {
   PrintF(out, "kind = %s\n", Kind2String(kind()));
+  if (has_major_key()) {
+    PrintF(out, "major_key = %s\n",
+           CodeStub::MajorName(CodeStub::GetMajorKey(this), true));
+  }
   if (is_inline_cache_stub()) {
     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
     PrintExtraICState(out, kind(), needs_extended_extra_ic_state(kind()) ?
diff --git a/src/objects.h b/src/objects.h
index 352edaa..cf4c80b 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5141,6 +5141,7 @@
   // [major_key]: For kind STUB or BINARY_OP_IC, the major key.
   inline int major_key();
   inline void set_major_key(int value);
+  inline bool has_major_key();
 
   // For kind STUB or ICs, tells whether or not a code object was generated by
   // the optimizing compiler (but it may not be an optimized function).
@@ -8110,6 +8111,9 @@
   // walked in a particular order. So [[1, 2], 1, 2] will have one
   // nested_site, but [[1, 2], 3, [4]] will have a list of two.
   DECL_ACCESSORS(nested_site, Object)
+  DECL_ACCESSORS(memento_found_count, Smi)
+  DECL_ACCESSORS(memento_create_count, Smi)
+  DECL_ACCESSORS(pretenure_decision, Smi)
   DECL_ACCESSORS(dependent_code, DependentCode)
   DECL_ACCESSORS(weak_next, Object)
 
@@ -8177,7 +8181,13 @@
 
   static const int kTransitionInfoOffset = HeapObject::kHeaderSize;
   static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize;
-  static const int kDependentCodeOffset = kNestedSiteOffset + kPointerSize;
+  static const int kMementoFoundCountOffset = kNestedSiteOffset + kPointerSize;
+  static const int kMementoCreateCountOffset =
+      kMementoFoundCountOffset + kPointerSize;
+  static const int kPretenureDecisionOffset =
+      kMementoCreateCountOffset + kPointerSize;
+  static const int kDependentCodeOffset =
+      kPretenureDecisionOffset + kPointerSize;
   static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize;
   static const int kSize = kWeakNextOffset + kPointerSize;
 
diff --git a/src/runtime.cc b/src/runtime.cc
index f546629..c11a005 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -7848,35 +7848,6 @@
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, Runtime_PopulateTrigonometricTable) {
-  HandleScope scope(isolate);
-  ASSERT(args.length() == 3);
-  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, sin_table, 0);
-  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, cos_table, 1);
-  CONVERT_SMI_ARG_CHECKED(samples, 2);
-  RUNTIME_ASSERT(sin_table->type() == kExternalDoubleArray);
-  RUNTIME_ASSERT(cos_table->type() == kExternalDoubleArray);
-  double* sin_buffer = reinterpret_cast<double*>(
-      JSArrayBuffer::cast(sin_table->buffer())->backing_store());
-  double* cos_buffer = reinterpret_cast<double*>(
-      JSArrayBuffer::cast(cos_table->buffer())->backing_store());
-
-  static const double pi_half = 3.1415926535897932 / 2;
-  double interval = pi_half / samples;
-  for (int i = 0; i < samples + 1; i++) {
-    double sample = sin(i * interval);
-    sin_buffer[i] = sample;
-    cos_buffer[samples - i] = sample * interval;
-  }
-
-  // Fill this to catch out of bound accesses when calculating Math.sin(pi/2).
-  sin_buffer[samples + 1] = sin(pi_half + interval);
-  cos_buffer[samples + 1] = cos(pi_half + interval) * interval;
-
-  return isolate->heap()->undefined_value();
-}
-
-
 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 2);
diff --git a/src/runtime.h b/src/runtime.h
index 4872ab5..0e09200 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -190,7 +190,6 @@
   F(Math_sin, 1, 1) \
   F(Math_sqrt, 1, 1) \
   F(Math_tan, 1, 1) \
-  F(PopulateTrigonometricTable, 3, 1) \
   \
   /* Regular expressions */ \
   F(RegExpCompile, 3, 1) \
diff --git a/src/trig-table.h b/src/trig-table.h
new file mode 100644
index 0000000..081c038
--- /dev/null
+++ b/src/trig-table.h
@@ -0,0 +1,61 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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_TRIG_TABLE_H_
+#define V8_TRIG_TABLE_H_
+
+
+namespace v8 {
+namespace internal {
+
+class TrigonometricLookupTable : public AllStatic {
+ public:
+  // Casting away const-ness to use as argument for typed array constructor.
+  static void* sin_table() {
+    return const_cast<double*>(&kSinTable[0]);
+  }
+
+  static void* cos_x_interval_table() {
+    return const_cast<double*>(&kCosXIntervalTable[0]);
+  }
+
+  static double samples_over_pi_half() { return kSamplesOverPiHalf; }
+  static int samples() { return kSamples; }
+  static int table_num_bytes() { return kTableSize * sizeof(*kSinTable); }
+  static int table_size() { return kTableSize; }
+
+ private:
+  static const double kSinTable[];
+  static const double kCosXIntervalTable[];
+  static const int kSamples;
+  static const int kTableSize;
+  static const double kSamplesOverPiHalf;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_TRIG_TABLE_H_
diff --git a/src/v8.cc b/src/v8.cc
index 17007a2..c56c82a 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -32,6 +32,9 @@
 #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"
@@ -52,6 +55,7 @@
 
 List<CallCompletedCallback>* V8::call_completed_callbacks_ = NULL;
 v8::ArrayBuffer::Allocator* V8::array_buffer_allocator_ = NULL;
+v8::Platform* V8::platform_ = NULL;
 
 
 bool V8::Initialize(Deserializer* des) {
@@ -100,6 +104,12 @@
   call_completed_callbacks_ = NULL;
 
   Sampler::TearDown();
+
+#ifdef V8_USE_DEFAULT_PLATFORM
+  DefaultPlatform* platform = static_cast<DefaultPlatform*>(platform_);
+  platform_ = NULL;
+  delete platform;
+#endif
 }
 
 
@@ -179,6 +189,9 @@
     FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
   }
 
+#ifdef V8_USE_DEFAULT_PLATFORM
+  platform_ = new DefaultPlatform;
+#endif
   Sampler::SetUp();
   CPU::SetUp();
   OS::PostSetUp();
@@ -194,4 +207,23 @@
   CallOnce(&init_once, &InitializeOncePerProcessImpl);
 }
 
+
+void V8::InitializePlatform(v8::Platform* platform) {
+  ASSERT(!platform_);
+  ASSERT(platform);
+  platform_ = platform;
+}
+
+
+void V8::ShutdownPlatform() {
+  ASSERT(platform_);
+  platform_ = NULL;
+}
+
+
+v8::Platform* V8::GetCurrentPlatform() {
+  ASSERT(platform_);
+  return platform_;
+}
+
 } }  // namespace v8::internal
diff --git a/src/v8.h b/src/v8.h
index 01362ab..6f2633a 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -50,6 +50,7 @@
 
 // Basic includes
 #include "../include/v8.h"
+#include "../include/v8-platform.h"
 #include "v8globals.h"
 #include "v8checks.h"
 #include "allocation.h"
@@ -111,6 +112,10 @@
     array_buffer_allocator_ = allocator;
   }
 
+  static void InitializePlatform(v8::Platform* platform);
+  static void ShutdownPlatform();
+  static v8::Platform* GetCurrentPlatform();
+
  private:
   static void InitializeOncePerProcessImpl();
   static void InitializeOncePerProcess();
@@ -119,6 +124,8 @@
   static List<CallCompletedCallback>* call_completed_callbacks_;
   // Allocator for external array buffers.
   static v8::ArrayBuffer::Allocator* array_buffer_allocator_;
+  // v8::Platform to use.
+  static v8::Platform* platform_;
 };
 
 
diff --git a/src/v8threads.cc b/src/v8threads.cc
index cc4f439..1de9d4f 100644
--- a/src/v8threads.cc
+++ b/src/v8threads.cc
@@ -133,18 +133,6 @@
 }
 
 
-void Locker::StartPreemption(v8::Isolate* isolate, int every_n_ms) {
-  v8::internal::ContextSwitcher::StartPreemption(
-      reinterpret_cast<i::Isolate*>(isolate), every_n_ms);
-}
-
-
-void Locker::StopPreemption(v8::Isolate* isolate) {
-  v8::internal::ContextSwitcher::StopPreemption(
-      reinterpret_cast<i::Isolate*>(isolate));
-}
-
-
 namespace internal {
 
 
@@ -419,63 +407,5 @@
 }
 
 
-ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
-  : Thread("v8:CtxtSwitcher"),
-    keep_going_(true),
-    sleep_ms_(every_n_ms),
-    isolate_(isolate) {
-}
-
-
-// Set the scheduling interval of V8 threads. This function starts the
-// ContextSwitcher thread if needed.
-void ContextSwitcher::StartPreemption(Isolate* isolate, int every_n_ms) {
-  ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
-  if (isolate->context_switcher() == NULL) {
-    // If the ContextSwitcher thread is not running at the moment start it now.
-    isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
-    isolate->context_switcher()->Start();
-  } else {
-    // ContextSwitcher thread is already running, so we just change the
-    // scheduling interval.
-    isolate->context_switcher()->sleep_ms_ = every_n_ms;
-  }
-}
-
-
-// Disable preemption of V8 threads. If multiple threads want to use V8 they
-// must cooperatively schedule amongst them from this point on.
-void ContextSwitcher::StopPreemption(Isolate* isolate) {
-  ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
-  if (isolate->context_switcher() != NULL) {
-    // The ContextSwitcher thread is running. We need to stop it and release
-    // its resources.
-    isolate->context_switcher()->keep_going_ = false;
-    // Wait for the ContextSwitcher thread to exit.
-    isolate->context_switcher()->Join();
-    // Thread has exited, now we can delete it.
-    delete(isolate->context_switcher());
-    isolate->set_context_switcher(NULL);
-  }
-}
-
-
-// Main loop of the ContextSwitcher thread: Preempt the currently running V8
-// thread at regular intervals.
-void ContextSwitcher::Run() {
-  while (keep_going_) {
-    OS::Sleep(sleep_ms_);
-    isolate()->stack_guard()->Preempt();
-  }
-}
-
-
-// Acknowledge the preemption by the receiving thread.
-void ContextSwitcher::PreemptionReceived() {
-  // There is currently no accounting being done for this. But could be in the
-  // future, which is why we leave this in.
-}
-
-
 }  // namespace internal
 }  // namespace v8
diff --git a/src/v8threads.h b/src/v8threads.h
index 1edacfc..a20700a 100644
--- a/src/v8threads.h
+++ b/src/v8threads.h
@@ -139,34 +139,6 @@
 };
 
 
-// The ContextSwitcher thread is used to schedule regular preemptions to
-// multiple running V8 threads. Generally it is necessary to call
-// StartPreemption if there is more than one thread running. If not, a single
-// JavaScript can take full control of V8 and not allow other threads to run.
-class ContextSwitcher: public Thread {
- public:
-  // Set the preemption interval for the ContextSwitcher thread.
-  static void StartPreemption(Isolate* isolate, int every_n_ms);
-
-  // Stop sending preemption requests to threads.
-  static void StopPreemption(Isolate* isolate);
-
-  // Preempted thread needs to call back to the ContextSwitcher to acknowledge
-  // the handling of a preemption request.
-  static void PreemptionReceived();
-
- private:
-  ContextSwitcher(Isolate* isolate, int every_n_ms);
-
-  Isolate* isolate() const { return isolate_; }
-
-  void Run();
-
-  bool keep_going_;
-  int sleep_ms_;
-  Isolate* isolate_;
-};
-
 } }  // namespace v8::internal
 
 #endif  // V8_V8THREADS_H_
diff --git a/src/version.cc b/src/version.cc
index 8ee0430..c76c1b2 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     23
-#define BUILD_NUMBER      9
+#define BUILD_NUMBER      10
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)