Version 3.21.4

Lowered kInitialMaxFastElementArray constant to 95K (issue 2790).

Use signals for cpu profiling on Mac OS X (issue 2814).

Deprecated CpuProfileNode::GetSelfSamplesCount (Chromium issue 267595).

Added support for higher CPU profiler sampling rate on posix systems (issue 2814).

Worked around 'inlining failed' build error with older GCC 4.x releases.

Added source map support to tick processor.

Stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@16338 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 5d81c7a..37763eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2013-08-26: Version 3.21.4
+
+        Lowered kInitialMaxFastElementArray constant to 95K (issue 2790).
+
+        Use signals for cpu profiling on Mac OS X (issue 2814).
+
+        Deprecated CpuProfileNode::GetSelfSamplesCount (Chromium issue 267595).
+
+        Added support for higher CPU profiler sampling rate on posix systems
+        (issue 2814).
+
+        Worked around 'inlining failed' build error with older GCC 4.x releases.
+
+        Added source map support to tick processor.
+
+        Stability improvements on all platforms.
+
+
 2013-08-23: Version 3.21.3
 
         Temporarily disabled optimization for StringWrappers to use native
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index e538f4a..936ea59 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -75,7 +75,7 @@
   /** DEPRECATED. Please use GetHitCount instead.
     * Returns the count of samples where function was currently executing.
     */
-  double GetSelfSamplesCount() const;
+  V8_DEPRECATED(double GetSelfSamplesCount() const);
 
   /**
     * Returns the count of samples where the function was currently executing.
diff --git a/include/v8.h b/include/v8.h
index 93b55dd..dbf2b08 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -120,6 +120,7 @@
 class Value;
 template <class T> class Handle;
 template <class T> class Local;
+template <class T> class Eternal;
 template <class T> class Persistent;
 class FunctionTemplate;
 class ObjectTemplate;
@@ -370,11 +371,6 @@
 };
 
 
-// A value which will never be returned by Local::Eternalize
-// Useful for static initialization
-const int kUninitializedEternalIndex = -1;
-
-
 /**
  * A light-weight stack-allocated object handle.  All operations
  * that return objects from within v8 return them in local handles.  They
@@ -420,11 +416,6 @@
     return Local<S>::Cast(*this);
   }
 
-  // Keep this Local alive for the lifetime of the Isolate.
-  // It remains retrievable via the returned index,
-  V8_INLINE(int Eternalize(Isolate* isolate));
-  V8_INLINE(static Local<T> GetEternal(Isolate* isolate, int index));
-
   /**
    * Create a local handle for the content of another handle.
    * The referee is kept alive by the local handle even when
@@ -445,6 +436,7 @@
 
  private:
   friend class Utils;
+  template<class F> friend class Eternal;
   template<class F> friend class Persistent;
   template<class F> friend class Handle;
   friend class Arguments;
@@ -460,6 +452,28 @@
   V8_INLINE(static Local<T> New(Isolate* isolate, T* that));
 };
 
+
+// Eternal handles are set-once handles that live for the life of the isolate.
+template <class T> class Eternal {
+ public:
+  V8_INLINE(Eternal()) : index_(kInitialValue) { }
+  template<class S>
+  V8_INLINE(Eternal(Isolate* isolate, Local<S> handle))
+      : index_(kInitialValue) {
+    Set(isolate, handle);
+  }
+  // Can only be safely called if already set.
+  V8_INLINE(Local<T> Get(Isolate* isolate));
+  V8_INLINE(bool IsEmpty()) { return index_ != kInitialValue; }
+  template<class S>
+  V8_INLINE(void Set(Isolate* isolate, Local<S> handle));
+
+ private:
+  static const int kInitialValue = -1;
+  int index_;
+};
+
+
 /**
  * An object reference that is independent of any handle scope.  Where
  * a Local handle only lives as long as the HandleScope in which it was
@@ -2968,6 +2982,14 @@
   void Set(Handle<String> name, Handle<Data> value,
            PropertyAttribute attributes = None);
   V8_INLINE(void Set(const char* name, Handle<Data> value));
+
+  void SetAccessorProperty(
+     Local<String> name,
+     Local<FunctionTemplate> getter = Local<FunctionTemplate>(),
+     Local<FunctionTemplate> setter = Local<FunctionTemplate>(),
+     PropertyAttribute attribute = None,
+     AccessControl settings = DEFAULT);
+
  private:
   Template();
 
@@ -4788,12 +4810,14 @@
                        void* data,
                        RevivableCallback weak_reference_callback);
   static void ClearWeak(internal::Object** global_handle);
-  static int Eternalize(internal::Isolate* isolate,
-                        internal::Object** handle);
-  static internal::Object** GetEternal(internal::Isolate* isolate, int index);
+  static void Eternalize(Isolate* isolate,
+                         Value* handle,
+                         int* index);
+  static Local<Value> GetEternal(Isolate* isolate, int index);
 
   template <class T> friend class Handle;
   template <class T> friend class Local;
+  template <class T> friend class Eternal;
   template <class T> friend class Persistent;
   friend class Context;
 };
@@ -5655,17 +5679,16 @@
 
 
 template<class T>
-int Local<T>::Eternalize(Isolate* isolate) {
-  return V8::Eternalize(reinterpret_cast<internal::Isolate*>(isolate),
-                        reinterpret_cast<internal::Object**>(this->val_));
+template<class S>
+void Eternal<T>::Set(Isolate* isolate, Local<S> handle) {
+  TYPE_CHECK(T, S);
+  V8::Eternalize(isolate, Value::Cast(*handle), &this->index_);
 }
 
 
 template<class T>
-Local<T> Local<T>::GetEternal(Isolate* isolate, int index) {
-  internal::Object** handle =
-      V8::GetEternal(reinterpret_cast<internal::Isolate*>(isolate), index);
-  return Local<T>(T::Cast(reinterpret_cast<Value*>(handle)));
+Local<T> Eternal<T>::Get(Isolate* isolate) {
+  return Local<T>::Cast(V8::GetEternal(isolate, index_));
 }
 
 
diff --git a/include/v8config.h b/include/v8config.h
index fe72c95..25eb480 100644
--- a/include/v8config.h
+++ b/include/v8config.h
@@ -97,6 +97,7 @@
 // C++11 feature detection
 //
 //  V8_HAS_CXX11_ALIGNAS        - alignas specifier supported
+//  V8_HAS_CXX11_ALIGNOF        - alignof(type) operator supported
 //  V8_HAS_CXX11_STATIC_ASSERT  - static_assert() supported
 //  V8_HAS_CXX11_DELETE         - deleted functions supported
 //  V8_HAS_CXX11_FINAL          - final marker supported
@@ -104,7 +105,9 @@
 //
 // Compiler-specific feature detection
 //
-//  V8_HAS_ATTRIBUTE___ALIGNED__    - __attribute__((__aligned__(n))) supported
+//  V8_HAS___ALIGNOF                - __alignof(type) operator supported
+//  V8_HAS___ALIGNOF__              - __alignof__(type) operator supported
+//  V8_HAS_ATTRIBUTE_ALIGNED        - __attribute__((aligned(n))) supported
 //  V8_HAS_ATTRIBUTE_ALWAYS_INLINE  - __attribute__((always_inline)) supported
 //  V8_HAS_ATTRIBUTE_DEPRECATED     - __attribute__((deprecated)) supported
 //  V8_HAS_ATTRIBUTE_VISIBILITY     - __attribute__((visibility)) supported
@@ -122,7 +125,11 @@
 
 # define V8_CC_CLANG 1
 
-# define V8_HAS_ATTRIBUTE___ALIGNED__ (__has_attribute(__aligned__))
+// Clang defines __alignof__ as alias for __alignof
+# define V8_HAS___ALIGNOF 1
+# define V8_HAS___ALIGNOF__ V8_HAS___ALIGNOF
+
+# define V8_HAS_ATTRIBUTE_ALIGNED (__has_attribute(aligned))
 # define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline))
 # define V8_HAS_ATTRIBUTE_DEPRECATED (__has_attribute(deprecated))
 # define V8_HAS_ATTRIBUTE_VISIBILITY (__has_attribute(visibility))
@@ -146,8 +153,13 @@
 #  define V8_CC_MINGW 1
 # endif
 
-# define V8_HAS_ATTRIBUTE___ALIGNED__ (V8_GNUC_PREREQ(2, 95, 0))
-# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (V8_GNUC_PREREQ(4, 0, 0))
+# define V8_HAS___ALIGNOF__ (V8_GNUC_PREREQ(4, 3, 0))
+
+# define V8_HAS_ATTRIBUTE_ALIGNED (V8_GNUC_PREREQ(2, 95, 0))
+// always_inline is available in gcc 4.0 but not very reliable until 4.4.
+// Works around "sorry, unimplemented: inlining failed" build errors with
+// older compilers.
+# define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (V8_GNUC_PREREQ(4, 4, 0))
 # define V8_HAS_ATTRIBUTE_DEPRECATED (V8_GNUC_PREREQ(3, 4, 0))
 # define V8_HAS_ATTRIBUTE_VISIBILITY (V8_GNUC_PREREQ(4, 3, 0))
 
@@ -161,6 +173,7 @@
 // both for forward compatibility.
 # if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
 #  define V8_HAS_CXX11_ALIGNAS (V8_GNUC_PREREQ(4, 8, 0))
+#  define V8_HAS_CXX11_ALIGNOF (V8_GNUC_PREREQ(4, 8, 0))
 #  define V8_HAS_CXX11_STATIC_ASSERT (V8_GNUC_PREREQ(4, 3, 0))
 #  define V8_HAS_CXX11_DELETE (V8_GNUC_PREREQ(4, 4, 0))
 #  define V8_HAS_CXX11_OVERRIDE (V8_GNUC_PREREQ(4, 7, 0))
@@ -176,6 +189,8 @@
 
 # define V8_CC_MSVC 1
 
+# define V8_HAS___ALIGNOF 1
+
 // Override control was added with Visual Studio 2005, but
 // Visual Studio 2010 and earlier spell "final" as "sealed".
 # define V8_HAS_CXX11_FINAL (_MSC_VER >= 1700)
@@ -272,16 +287,54 @@
 
 // This macro allows to specify memory alignment for structs, classes, etc.
 // Use like:
-//   class V8_ALIGNAS(16) MyClass { ... };
-//   V8_ALIGNAS(32) int array[42];
+//   class V8_ALIGNED(16) MyClass { ... };
+//   V8_ALIGNED(32) int array[42];
 #if V8_HAS_CXX11_ALIGNAS
-# define V8_ALIGNAS(n) alignas(n)
-#elif V8_HAS_ATTRIBUTE___ALIGNED__
-# define V8_ALIGNAS(n) __attribute__((__aligned__(n)))
+# define V8_ALIGNED(n) alignas(n)
+#elif V8_HAS_ATTRIBUTE_ALIGNED
+# define V8_ALIGNED(n) __attribute__((aligned(n)))
 #elif V8_HAS_DECLSPEC_ALIGN
-# define V8_ALIGNAS(n) __declspec(align(n))
+# define V8_ALIGNED(n) __declspec(align(n))
 #else
-# define V8_ALIGNAS(n) /* NOT SUPPORTED */
+# define V8_ALIGNED(n) /* NOT SUPPORTED */
+#endif
+
+
+// This macro is similar to V8_ALIGNED(), but takes a type instead of size
+// in bytes. If the compiler does not supports using the alignment of the
+// |type|, it will align according to the |alignment| instead. For example,
+// Visual Studio C++ cannot combine __declspec(align) and __alignof. The
+// |alignment| must be a literal that is used as a kind of worst-case fallback
+// alignment.
+// Use like:
+//   struct V8_ALIGNAS(AnotherClass, 16) NewClass { ... };
+//   V8_ALIGNAS(double, 8) int array[100];
+#if V8_HAS_CXX11_ALIGNAS
+# define V8_ALIGNAS(type, alignment) alignas(type)
+#elif V8_HAS___ALIGNOF__ && V8_HAS_ATTRIBUTE_ALIGNED
+# define V8_ALIGNAS(type, alignment) __attribute__((aligned(__alignof__(type))))
+#else
+# define V8_ALIGNAS(type, alignment) V8_ALIGNED(alignment)
+#endif
+
+
+// This macro returns alignment in bytes (an integer power of two) required for
+// any instance of the given type, which is either complete type, an array type,
+// or a reference type.
+// Use like:
+//   size_t alignment = V8_ALIGNOF(double);
+#if V8_HAS_CXX11_ALIGNOF
+# define V8_ALIGNOF(type) alignof(type)
+#elif V8_HAS___ALIGNOF
+# define V8_ALIGNOF(type) __alignof(type)
+#elif V8_HAS___ALIGNOF__
+# define V8_ALIGNOF(type) __alignof__(type)
+#else
+// Note that alignment of a type within a struct can be less than the
+// alignment of the type stand-alone (because of ancient ABIs), so this
+// should only be used as a last resort.
+namespace v8 { template <typename T> class AlignOfHelper { char c; T t; }; }
+# define V8_ALIGNOF(type) (sizeof(::v8::AlignOfHelper<type>) - sizeof(type))
 #endif
 
 #endif  // V8CONFIG_H_
diff --git a/src/api.cc b/src/api.cc
index 0eb139f..61cc520 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -399,6 +399,9 @@
   kSnapshotContext,
   kLibraries,
   kExperimentalLibraries,
+#if defined(V8_I18N_SUPPORT)
+  kI18NExtension,
+#endif
   kCompressedStartupDataCount
 };
 
@@ -439,6 +442,17 @@
       exp_libraries_source.length();
   compressed_data[kExperimentalLibraries].raw_size =
       i::ExperimentalNatives::GetRawScriptsSize();
+
+#if defined(V8_I18N_SUPPORT)
+  i::Vector<const ii:byte> i18n_extension_source =
+      i::I18NNatives::GetScriptsSource();
+  compressed_data[kI18NExtension].data =
+      reinterpret_cast<const char*>(i18n_extension_source.start());
+  compressed_data[kI18NExtension].compressed_size =
+      i18n_extension_source.length();
+  compressed_data[kI18NExtension].raw_size =
+      i::I18NNatives::GetRawScriptsSize();
+#endif
 #endif
 }
 
@@ -468,6 +482,15 @@
       decompressed_data[kExperimentalLibraries].data,
       decompressed_data[kExperimentalLibraries].raw_size);
   i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source);
+
+#if defined(V8_I18N_SUPPORT)
+  ASSERT_EQ(i::I18NNatives::GetRawScriptsSize(),
+            decompressed_data[kI18NExtension].raw_size);
+  i::Vector<const char> i18n_extension_source(
+      decompressed_data[kI18NExtension].data,
+      decompressed_data[kI18NExtension].raw_size);
+  i::I18NNatives::SetRawScriptsSource(i18n_extension_source);
+#endif
 #endif
 }
 
@@ -653,13 +676,16 @@
 }
 
 
-int V8::Eternalize(i::Isolate* isolate, i::Object** handle) {
-  return isolate->eternal_handles()->Create(isolate, *handle);
+void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  i::Object* object = *Utils::OpenHandle(value);
+  isolate->eternal_handles()->Create(isolate, object, index);
 }
 
 
-i::Object** V8::GetEternal(i::Isolate* isolate, int index) {
-  return isolate->eternal_handles()->Get(index).location();
+Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  return Utils::ToLocal(isolate->eternal_handles()->Get(index));
 }
 
 
@@ -932,21 +958,62 @@
 }
 
 
-void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
+static void TemplateSet(i::Isolate* isolate,
+                        v8::Template* templ,
+                        int length,
+                        v8::Handle<v8::Data>* data) {
+  i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
+  if (list->IsUndefined()) {
+    list = NeanderArray().value();
+    Utils::OpenHandle(templ)->set_property_list(*list);
+  }
+  NeanderArray array(list);
+  array.add(Utils::OpenHandle(*v8::Integer::New(length)));
+  for (int i = 0; i < length; i++) {
+    i::Handle<i::Object> value = data[i].IsEmpty() ?
+        i::Handle<i::Object>(isolate->factory()->undefined_value()) :
+        Utils::OpenHandle(*data[i]);
+    array.add(value);
+  }
+}
+
+
+void Template::Set(v8::Handle<String> name,
+                   v8::Handle<Data> value,
                    v8::PropertyAttribute attribute) {
   i::Isolate* isolate = i::Isolate::Current();
   if (IsDeadCheck(isolate, "v8::Template::Set()")) return;
   ENTER_V8(isolate);
   i::HandleScope scope(isolate);
-  i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list(), isolate);
-  if (list->IsUndefined()) {
-    list = NeanderArray().value();
-    Utils::OpenHandle(this)->set_property_list(*list);
-  }
-  NeanderArray array(list);
-  array.add(Utils::OpenHandle(*name));
-  array.add(Utils::OpenHandle(*value));
-  array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
+  const int kSize = 3;
+  v8::Handle<v8::Data> data[kSize] = {
+      name,
+      value,
+      v8::Integer::New(attribute)};
+  TemplateSet(isolate, this, kSize, data);
+}
+
+
+void Template::SetAccessorProperty(
+    v8::Local<v8::String> name,
+    v8::Local<FunctionTemplate> getter,
+    v8::Local<FunctionTemplate> setter,
+    v8::PropertyAttribute attribute,
+    v8::AccessControl access_control) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::Template::SetAccessor()")) return;
+  ENTER_V8(isolate);
+  ASSERT(!name.IsEmpty());
+  ASSERT(!getter.IsEmpty() || !setter.IsEmpty());
+  i::HandleScope scope(isolate);
+  const int kSize = 5;
+  v8::Handle<v8::Data> data[kSize] = {
+      name,
+      getter,
+      setter,
+      v8::Integer::New(attribute),
+      v8::Integer::New(access_control)};
+  TemplateSet(isolate, this, kSize, data);
 }
 
 
diff --git a/src/apinatives.js b/src/apinatives.js
index ccbedd6..ace882b 100644
--- a/src/apinatives.js
+++ b/src/apinatives.js
@@ -104,19 +104,32 @@
 
 function ConfigureTemplateInstance(obj, data) {
   var properties = %GetTemplateField(data, kApiPropertyListOffset);
-  if (properties) {
-    // Disable access checks while instantiating the object.
-    var requires_access_checks = %DisableAccessChecks(obj);
-    try {
-      for (var i = 0; i < properties[0]; i += 3) {
+  if (!properties) return;
+  // Disable access checks while instantiating the object.
+  var requires_access_checks = %DisableAccessChecks(obj);
+  try {
+    for (var i = 1; i < properties[0];) {
+      var length = properties[i];
+      if (length == 3) {
         var name = properties[i + 1];
         var prop_data = properties[i + 2];
         var attributes = properties[i + 3];
         var value = Instantiate(prop_data, name);
         %SetProperty(obj, name, value, attributes);
+      } else if (length == 5) {
+        var name = properties[i + 1];
+        var getter = properties[i + 2];
+        var setter = properties[i + 3];
+        var attribute = properties[i + 4];
+        var access_control = properties[i + 5];
+        %SetAccessorProperty(
+            obj, name, getter, setter, attribute, access_control);
+      } else {
+        throw "Bad properties array";
       }
-    } finally {
-      if (requires_access_checks) %EnableAccessChecks(obj);
+      i += length + 1;
     }
+  } finally {
+    if (requires_access_checks) %EnableAccessChecks(obj);
   }
 }
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index a9db5a5..ae6db3a 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -152,7 +152,8 @@
 
 #else  // __arm__
   // Probe for additional features not already known to be available.
-  if (!IsSupported(VFP3) && FLAG_enable_vfp3 && OS::ArmCpuHasFeature(VFP3)) {
+  CPU cpu;
+  if (!IsSupported(VFP3) && FLAG_enable_vfp3 && cpu.has_vfp3()) {
     // This implementation also sets the VFP flags if runtime
     // detection of VFP returns true. VFPv3 implies ARMv7, see ARM DDI
     // 0406B, page A1-6.
@@ -161,38 +162,40 @@
         static_cast<uint64_t>(1) << ARMv7;
   }
 
-  if (!IsSupported(NEON) && FLAG_enable_neon && OS::ArmCpuHasFeature(NEON)) {
+  if (!IsSupported(NEON) && FLAG_enable_neon && cpu.has_neon()) {
     found_by_runtime_probing_only_ |= 1u << NEON;
   }
 
-  if (!IsSupported(ARMv7) && FLAG_enable_armv7 && OS::ArmCpuHasFeature(ARMv7)) {
+  if (!IsSupported(ARMv7) && FLAG_enable_armv7 && cpu.architecture() >= 7) {
     found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << ARMv7;
   }
 
-  if (!IsSupported(SUDIV) && FLAG_enable_sudiv && OS::ArmCpuHasFeature(SUDIV)) {
+  if (!IsSupported(SUDIV) && FLAG_enable_sudiv && cpu.has_idiva()) {
     found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << SUDIV;
   }
 
   if (!IsSupported(UNALIGNED_ACCESSES) && FLAG_enable_unaligned_accesses
-      && OS::ArmCpuHasFeature(ARMv7)) {
+      && cpu.architecture() >= 7) {
     found_by_runtime_probing_only_ |=
         static_cast<uint64_t>(1) << UNALIGNED_ACCESSES;
   }
 
-  CpuImplementer implementer = OS::GetCpuImplementer();
-  if (implementer == QUALCOMM_IMPLEMENTER &&
-      FLAG_enable_movw_movt && OS::ArmCpuHasFeature(ARMv7)) {
+  // Use movw/movt for QUALCOMM ARMv7 cores.
+  if (cpu.implementer() == CPU::QUALCOMM &&
+      cpu.architecture() >= 7 &&
+      FLAG_enable_movw_movt) {
     found_by_runtime_probing_only_ |=
         static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS;
   }
 
-  CpuPart part = OS::GetCpuPart(implementer);
-  if ((part == CORTEX_A9) || (part == CORTEX_A5)) {
+  // ARM Cortex-A9 and Cortex-A5 have 32 byte cachelines.
+  if (cpu.implementer() == CPU::ARM &&
+      (cpu.part() == CPU::ARM_CORTEX_A5 ||
+       cpu.part() == CPU::ARM_CORTEX_A9)) {
     cache_line_size_ = 32;
   }
 
-  if (!IsSupported(VFP32DREGS) && FLAG_enable_32dregs
-      && OS::ArmCpuHasFeature(VFP32DREGS)) {
+  if (!IsSupported(VFP32DREGS) && FLAG_enable_32dregs && cpu.has_vfp3_d32()) {
     found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP32DREGS;
   }
 
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 98a835f..3dbdb2f 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -634,6 +634,111 @@
 }
 
 
+void DoubleToIStub::Generate(MacroAssembler* masm) {
+  Label out_of_range, only_low, negate, done;
+  Register input_reg = source();
+  Register result_reg = destination();
+
+  int double_offset = offset();
+  // Account for saved regs if input is sp.
+  if (input_reg.is(sp)) double_offset += 2 * kPointerSize;
+
+  // Immediate values for this stub fit in instructions, so it's safe to use ip.
+  Register scratch = ip;
+  Register scratch_low =
+      GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch);
+  Register scratch_high =
+      GetRegisterThatIsNotOneOf(input_reg, result_reg, scratch, scratch_low);
+  LowDwVfpRegister double_scratch = kScratchDoubleReg;
+
+  __ Push(scratch_high, scratch_low);
+
+  if (!skip_fastpath()) {
+    // Load double input.
+    __ vldr(double_scratch, MemOperand(input_reg, double_offset));
+    __ vmov(scratch_low, scratch_high, double_scratch);
+
+    // Do fast-path convert from double to int.
+    __ vcvt_s32_f64(double_scratch.low(), double_scratch);
+    __ vmov(result_reg, double_scratch.low());
+
+    // If result is not saturated (0x7fffffff or 0x80000000), we are done.
+    __ sub(scratch, result_reg, Operand(1));
+    __ cmp(scratch, Operand(0x7ffffffe));
+    __ b(lt, &done);
+  } else {
+    // We've already done MacroAssembler::TryFastTruncatedDoubleToILoad, so we
+    // know exponent > 31, so we can skip the vcvt_s32_f64 which will saturate.
+    if (double_offset == 0) {
+      __ ldm(ia, input_reg, scratch_low.bit() | scratch_high.bit());
+    } else {
+      __ ldr(scratch_low, MemOperand(input_reg, double_offset));
+      __ ldr(scratch_high, MemOperand(input_reg, double_offset + kIntSize));
+    }
+  }
+
+  __ Ubfx(scratch, scratch_high,
+         HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+  // Load scratch with exponent - 1. This is faster than loading
+  // with exponent because Bias + 1 = 1024 which is an *ARM* immediate value.
+  STATIC_ASSERT(HeapNumber::kExponentBias + 1 == 1024);
+  __ sub(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
+  // If exponent is greater than or equal to 84, the 32 less significant
+  // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
+  // the result is 0.
+  // Compare exponent with 84 (compare exponent - 1 with 83).
+  __ cmp(scratch, Operand(83));
+  __ b(ge, &out_of_range);
+
+  // If we reach this code, 31 <= exponent <= 83.
+  // So, we don't have to handle cases where 0 <= exponent <= 20 for
+  // which we would need to shift right the high part of the mantissa.
+  // Scratch contains exponent - 1.
+  // Load scratch with 52 - exponent (load with 51 - (exponent - 1)).
+  __ rsb(scratch, scratch, Operand(51), SetCC);
+  __ b(ls, &only_low);
+  // 21 <= exponent <= 51, shift scratch_low and scratch_high
+  // to generate the result.
+  __ mov(scratch_low, Operand(scratch_low, LSR, scratch));
+  // Scratch contains: 52 - exponent.
+  // We needs: exponent - 20.
+  // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20.
+  __ rsb(scratch, scratch, Operand(32));
+  __ Ubfx(result_reg, scratch_high,
+          0, HeapNumber::kMantissaBitsInTopWord);
+  // Set the implicit 1 before the mantissa part in scratch_high.
+  __ orr(result_reg, result_reg,
+         Operand(1 << HeapNumber::kMantissaBitsInTopWord));
+  __ orr(result_reg, scratch_low, Operand(result_reg, LSL, scratch));
+  __ b(&negate);
+
+  __ bind(&out_of_range);
+  __ mov(result_reg, Operand::Zero());
+  __ b(&done);
+
+  __ bind(&only_low);
+  // 52 <= exponent <= 83, shift only scratch_low.
+  // On entry, scratch contains: 52 - exponent.
+  __ rsb(scratch, scratch, Operand::Zero());
+  __ mov(result_reg, Operand(scratch_low, LSL, scratch));
+
+  __ bind(&negate);
+  // If input was positive, scratch_high ASR 31 equals 0 and
+  // scratch_high LSR 31 equals zero.
+  // New result = (result eor 0) + 0 = result.
+  // If the input was negative, we have to negate the result.
+  // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1.
+  // New result = (result eor 0xffffffff) + 1 = 0 - result.
+  __ eor(result_reg, result_reg, Operand(scratch_high, ASR, 31));
+  __ add(result_reg, result_reg, Operand(scratch_high, LSR, 31));
+
+  __ bind(&done);
+
+  __ Pop(scratch_high, scratch_low);
+  __ Ret();
+}
+
+
 bool WriteInt32ToHeapNumberStub::IsPregenerated() {
   // These variants are compiled ahead of time.  See next method.
   if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) {
@@ -1591,7 +1696,6 @@
   Register right = r0;
   Register scratch1 = r6;
   Register scratch2 = r7;
-  Register scratch3 = r4;
 
   ASSERT(smi_operands || (not_numbers != NULL));
   if (smi_operands) {
@@ -1689,12 +1793,8 @@
         __ SmiUntag(r2, right);
       } else {
         // Convert operands to 32-bit integers. Right in r2 and left in r3.
-        __ ConvertNumberToInt32(
-          left, r3, heap_number_map,
-          scratch1, scratch2, scratch3, d0, d1, not_numbers);
-        __ ConvertNumberToInt32(
-          right, r2, heap_number_map,
-          scratch1, scratch2, scratch3, d0, d1, not_numbers);
+        __ TruncateNumberToI(left, r3, heap_number_map, scratch1, not_numbers);
+        __ TruncateNumberToI(right, r2, heap_number_map, scratch1, not_numbers);
       }
 
       Label result_not_a_smi;
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index 6eab8d1..bee3e1e 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -376,7 +376,7 @@
           address_(address),
           scratch0_(scratch0) {
       ASSERT(!AreAliased(scratch0, object, address, no_reg));
-      scratch1_ = GetRegThatIsNotOneOf(object_, address_, scratch0_);
+      scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_);
     }
 
     void Save(MacroAssembler* masm) {
@@ -419,19 +419,6 @@
     Register scratch0_;
     Register scratch1_;
 
-    Register GetRegThatIsNotOneOf(Register r1,
-                                  Register r2,
-                                  Register r3) {
-      for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
-        Register candidate = Register::FromAllocationIndex(i);
-        if (candidate.is(r1)) continue;
-        if (candidate.is(r2)) continue;
-        if (candidate.is(r3)) continue;
-        return candidate;
-      }
-      UNREACHABLE();
-      return no_reg;
-    }
     friend class RecordWriteStub;
   };
 
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 12a6290..7c02a62 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1915,13 +1915,10 @@
       } else {
         value = UseRegister(instr->value());
         LOperand* temp1 = TempRegister();
-        LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
-                                                      : NULL;
-        LOperand* temp3 = FixedTemp(d11);
+        LOperand* temp2 = FixedTemp(d11);
         res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
                                                        temp1,
-                                                       temp2,
-                                                       temp3));
+                                                       temp2));
         res = AssignEnvironment(res);
       }
       return res;
@@ -1941,14 +1938,12 @@
       return AssignPointerMap(result);
     } else if (to.IsSmi()) {
       LOperand* value = UseRegister(instr->value());
-      return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToSmi(value,
-          TempRegister(), TempRegister())));
+      return AssignEnvironment(
+          DefineAsRegister(new(zone()) LDoubleToSmi(value)));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
-      LOperand* temp1 = TempRegister();
-      LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL;
-      LDoubleToI* res = new(zone()) LDoubleToI(value, temp1, temp2);
+      LDoubleToI* res = new(zone()) LDoubleToI(value);
       return AssignEnvironment(DefineAsRegister(res));
     }
   } else if (from.IsInteger32()) {
@@ -2440,6 +2435,9 @@
 
 
 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
+  HEnvironment* env = current_block_->last_environment();
+  instr->ReplayEnvironment(env);
+
   // There are no real uses of a captured object.
   return NULL;
 }
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 9a6c395..316df7d 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -2045,17 +2045,13 @@
 };
 
 
-class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 2> {
+class LDoubleToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
-  LDoubleToSmi(LOperand* value, LOperand* temp, LOperand* temp2) {
+  explicit LDoubleToSmi(LOperand* value) {
     inputs_[0] = value;
-    temps_[0] = temp;
-    temps_[1] = temp2;
   }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
@@ -2065,17 +2061,13 @@
 
 
 // Sometimes truncating conversion from a tagged value to an int32.
-class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
+class LDoubleToI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
  public:
-  LDoubleToI(LOperand* value, LOperand* temp, LOperand* temp2) {
+  explicit LDoubleToI(LOperand* value) {
     inputs_[0] = value;
-    temps_[0] = temp;
-    temps_[1] = temp2;
   }
 
   LOperand* value() { return inputs_[0]; }
-  LOperand* temp() { return temps_[0]; }
-  LOperand* temp2() { return temps_[1]; }
 
   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
@@ -2085,22 +2077,19 @@
 
 
 // Truncating conversion from a tagged value to an int32.
-class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 3> {
+class LTaggedToI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
  public:
   LTaggedToI(LOperand* value,
              LOperand* temp,
-             LOperand* temp2,
-             LOperand* temp3) {
+             LOperand* temp2) {
     inputs_[0] = value;
     temps_[0] = temp;
     temps_[1] = temp2;
-    temps_[2] = temp3;
   }
 
   LOperand* value() { return inputs_[0]; }
   LOperand* temp() { return temps_[0]; }
   LOperand* temp2() { return temps_[1]; }
-  LOperand* temp3() { return temps_[2]; }
 
   DECLARE_CONCRETE_INSTRUCTION(TaggedToI, "tagged-to-i")
   DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 6dae6db..f3f8b50 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -4908,7 +4908,7 @@
   Register scratch1 = scratch0();
   Register scratch2 = ToRegister(instr->temp());
   LowDwVfpRegister double_scratch = double_scratch0();
-  DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3());
+  DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp2());
 
   ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
   ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
@@ -4919,18 +4919,14 @@
   // The carry flag is set when we reach this deferred code as we just executed
   // SmiUntag(heap_object, SetCC)
   STATIC_ASSERT(kHeapObjectTag == 1);
-  __ adc(input_reg, input_reg, Operand(input_reg));
+  __ adc(scratch2, input_reg, Operand(input_reg));
 
   // Heap number map check.
-  __ ldr(scratch1, FieldMemOperand(input_reg, HeapObject::kMapOffset));
+  __ ldr(scratch1, FieldMemOperand(scratch2, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
   __ cmp(scratch1, Operand(ip));
 
   if (instr->truncating()) {
-    Register scratch3 = ToRegister(instr->temp2());
-    ASSERT(!scratch3.is(input_reg) &&
-           !scratch3.is(scratch1) &&
-           !scratch3.is(scratch2));
     // Performs a truncating conversion of a floating point number as used by
     // the JS bitwise operations.
     Label heap_number;
@@ -4938,23 +4934,18 @@
     // Check for undefined. Undefined is converted to zero for truncating
     // conversions.
     __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
-    __ cmp(input_reg, Operand(ip));
+    __ cmp(scratch2, Operand(ip));
     DeoptimizeIf(ne, instr->environment());
     __ mov(input_reg, Operand::Zero());
     __ b(&done);
 
     __ bind(&heap_number);
-    __ sub(scratch1, input_reg, Operand(kHeapObjectTag));
-    __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
-
-    __ ECMAToInt32(input_reg, double_scratch2,
-                   scratch1, scratch2, scratch3, double_scratch);
-
+    __ TruncateHeapNumberToI(input_reg, scratch2);
   } else {
     // Deoptimize if we don't have a heap number.
     DeoptimizeIf(ne, instr->environment());
 
-    __ sub(ip, input_reg, Operand(kHeapObjectTag));
+    __ sub(ip, scratch2, Operand(kHeapObjectTag));
     __ vldr(double_scratch2, ip, HeapNumber::kValueOffset);
     __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch);
     DeoptimizeIf(ne, instr->environment());
@@ -5026,14 +5017,11 @@
 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
   Register result_reg = ToRegister(instr->result());
   Register scratch1 = scratch0();
-  Register scratch2 = ToRegister(instr->temp());
   DwVfpRegister double_input = ToDoubleRegister(instr->value());
   LowDwVfpRegister double_scratch = double_scratch0();
 
   if (instr->truncating()) {
-    Register scratch3 = ToRegister(instr->temp2());
-    __ ECMAToInt32(result_reg, double_input,
-                   scratch1, scratch2, scratch3, double_scratch);
+    __ TruncateDoubleToI(result_reg, double_input);
   } else {
     __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
     // Deoptimize if the input wasn't a int32 (inside a double).
@@ -5054,14 +5042,11 @@
 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
   Register result_reg = ToRegister(instr->result());
   Register scratch1 = scratch0();
-  Register scratch2 = ToRegister(instr->temp());
   DwVfpRegister double_input = ToDoubleRegister(instr->value());
   LowDwVfpRegister double_scratch = double_scratch0();
 
   if (instr->truncating()) {
-    Register scratch3 = ToRegister(instr->temp2());
-    __ ECMAToInt32(result_reg, double_input,
-                   scratch1, scratch2, scratch3, double_scratch);
+    __ TruncateDoubleToI(result_reg, double_input);
   } else {
     __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
     // Deoptimize if the input wasn't a int32 (inside a double).
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 190e868..16ba89c 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -829,26 +829,6 @@
 }
 
 
-void MacroAssembler::ConvertNumberToInt32(Register object,
-                                          Register dst,
-                                          Register heap_number_map,
-                                          Register scratch1,
-                                          Register scratch2,
-                                          Register scratch3,
-                                          DwVfpRegister double_scratch1,
-                                          LowDwVfpRegister double_scratch2,
-                                          Label* not_number) {
-  Label done;
-  UntagAndJumpIfSmi(dst, object, &done);
-  JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
-  vldr(double_scratch1, FieldMemOperand(object, HeapNumber::kValueOffset));
-  ECMAToInt32(dst, double_scratch1,
-              scratch1, scratch2, scratch3, double_scratch2);
-
-  bind(&done);
-}
-
-
 void MacroAssembler::LoadNumber(Register object,
                                 LowDwVfpRegister dst,
                                 Register heap_number_map,
@@ -2538,84 +2518,76 @@
   bind(&exception);
 }
 
-
-void MacroAssembler::ECMAToInt32(Register result,
-                                 DwVfpRegister double_input,
-                                 Register scratch,
-                                 Register scratch_high,
-                                 Register scratch_low,
-                                 LowDwVfpRegister double_scratch) {
-  ASSERT(!scratch_high.is(result));
-  ASSERT(!scratch_low.is(result));
-  ASSERT(!scratch_low.is(scratch_high));
-  ASSERT(!scratch.is(result) &&
-         !scratch.is(scratch_high) &&
-         !scratch.is(scratch_low));
-  ASSERT(!double_input.is(double_scratch));
-
-  Label out_of_range, only_low, negate, done;
-
+void MacroAssembler::TryInlineTruncateDoubleToI(Register result,
+                                                DwVfpRegister double_input,
+                                                Label* done) {
+  LowDwVfpRegister double_scratch = kScratchDoubleReg;
   vcvt_s32_f64(double_scratch.low(), double_input);
   vmov(result, double_scratch.low());
 
   // If result is not saturated (0x7fffffff or 0x80000000), we are done.
-  sub(scratch, result, Operand(1));
-  cmp(scratch, Operand(0x7ffffffe));
-  b(lt, &done);
+  sub(ip, result, Operand(1));
+  cmp(ip, Operand(0x7ffffffe));
+  b(lt, done);
+}
 
-  vmov(scratch_low, scratch_high, double_input);
-  Ubfx(scratch, scratch_high,
-       HeapNumber::kExponentShift, HeapNumber::kExponentBits);
-  // Load scratch with exponent - 1. This is faster than loading
-  // with exponent because Bias + 1 = 1024 which is an *ARM* immediate value.
-  sub(scratch, scratch, Operand(HeapNumber::kExponentBias + 1));
-  // If exponent is greater than or equal to 84, the 32 less significant
-  // bits are 0s (2^84 = 1, 52 significant bits, 32 uncoded bits),
-  // the result is 0.
-  // Compare exponent with 84 (compare exponent - 1 with 83).
-  cmp(scratch, Operand(83));
-  b(ge, &out_of_range);
 
-  // If we reach this code, 31 <= exponent <= 83.
-  // So, we don't have to handle cases where 0 <= exponent <= 20 for
-  // which we would need to shift right the high part of the mantissa.
-  // Scratch contains exponent - 1.
-  // Load scratch with 52 - exponent (load with 51 - (exponent - 1)).
-  rsb(scratch, scratch, Operand(51), SetCC);
-  b(ls, &only_low);
-  // 21 <= exponent <= 51, shift scratch_low and scratch_high
-  // to generate the result.
-  mov(scratch_low, Operand(scratch_low, LSR, scratch));
-  // Scratch contains: 52 - exponent.
-  // We needs: exponent - 20.
-  // So we use: 32 - scratch = 32 - 52 + exponent = exponent - 20.
-  rsb(scratch, scratch, Operand(32));
-  Ubfx(result, scratch_high,
-       0, HeapNumber::kMantissaBitsInTopWord);
-  // Set the implicit 1 before the mantissa part in scratch_high.
-  orr(result, result, Operand(1 << HeapNumber::kMantissaBitsInTopWord));
-  orr(result, scratch_low, Operand(result, LSL, scratch));
-  b(&negate);
+void MacroAssembler::TruncateDoubleToI(Register result,
+                                       DwVfpRegister double_input) {
+  Label done;
 
-  bind(&out_of_range);
-  mov(result, Operand::Zero());
-  b(&done);
+  TryInlineTruncateDoubleToI(result, double_input, &done);
 
-  bind(&only_low);
-  // 52 <= exponent <= 83, shift only scratch_low.
-  // On entry, scratch contains: 52 - exponent.
-  rsb(scratch, scratch, Operand::Zero());
-  mov(result, Operand(scratch_low, LSL, scratch));
+  // If we fell through then inline version didn't succeed - call stub instead.
+  push(lr);
+  sub(sp, sp, Operand(kDoubleSize));  // Put input on stack.
+  vstr(double_input, MemOperand(sp, 0));
 
-  bind(&negate);
-  // If input was positive, scratch_high ASR 31 equals 0 and
-  // scratch_high LSR 31 equals zero.
-  // New result = (result eor 0) + 0 = result.
-  // If the input was negative, we have to negate the result.
-  // Input_high ASR 31 equals 0xffffffff and scratch_high LSR 31 equals 1.
-  // New result = (result eor 0xffffffff) + 1 = 0 - result.
-  eor(result, result, Operand(scratch_high, ASR, 31));
-  add(result, result, Operand(scratch_high, LSR, 31));
+  DoubleToIStub stub(sp, result, 0, true, true);
+  CallStub(&stub);
+
+  add(sp, sp, Operand(kDoubleSize));
+  pop(lr);
+
+  bind(&done);
+}
+
+
+void MacroAssembler::TruncateHeapNumberToI(Register result,
+                                           Register object) {
+  Label done;
+  LowDwVfpRegister double_scratch = kScratchDoubleReg;
+  ASSERT(!result.is(object));
+
+  vldr(double_scratch,
+       MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag));
+  TryInlineTruncateDoubleToI(result, double_scratch, &done);
+
+  // If we fell through then inline version didn't succeed - call stub instead.
+  push(lr);
+  DoubleToIStub stub(object,
+                     result,
+                     HeapNumber::kValueOffset - kHeapObjectTag,
+                     true,
+                     true);
+  CallStub(&stub);
+  pop(lr);
+
+  bind(&done);
+}
+
+
+void MacroAssembler::TruncateNumberToI(Register object,
+                                       Register result,
+                                       Register heap_number_map,
+                                       Register scratch1,
+                                       Label* not_number) {
+  Label done;
+  ASSERT(!result.is(object));
+
+  UntagAndJumpIfSmi(result, object, &done);
+  JumpIfNotHeapNumber(object, heap_number_map, scratch1, not_number);
+  TruncateHeapNumberToI(result, object);
 
   bind(&done);
 }
@@ -2847,6 +2819,11 @@
     RecordComment("Abort message: ");
     RecordComment(msg);
   }
+
+  if (FLAG_trap_on_abort) {
+    stop(msg);
+    return;
+  }
 #endif
 
   mov(r0, Operand(p0));
@@ -3830,6 +3807,30 @@
 }
 
 
+Register GetRegisterThatIsNotOneOf(Register reg1,
+                                   Register reg2,
+                                   Register reg3,
+                                   Register reg4,
+                                   Register reg5,
+                                   Register reg6) {
+  RegList regs = 0;
+  if (reg1.is_valid()) regs |= reg1.bit();
+  if (reg2.is_valid()) regs |= reg2.bit();
+  if (reg3.is_valid()) regs |= reg3.bit();
+  if (reg4.is_valid()) regs |= reg4.bit();
+  if (reg5.is_valid()) regs |= reg5.bit();
+  if (reg6.is_valid()) regs |= reg6.bit();
+
+  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+    Register candidate = Register::FromAllocationIndex(i);
+    if (regs & candidate.bit()) continue;
+    return candidate;
+  }
+  UNREACHABLE();
+  return no_reg;
+}
+
+
 #ifdef DEBUG
 bool AreAliased(Register reg1,
                 Register reg2,
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 8b9fa2b..f3716c2 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -62,6 +62,14 @@
 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
 
 
+Register GetRegisterThatIsNotOneOf(Register reg1,
+                                   Register reg2 = no_reg,
+                                   Register reg3 = no_reg,
+                                   Register reg4 = no_reg,
+                                   Register reg5 = no_reg,
+                                   Register reg6 = no_reg);
+
+
 #ifdef DEBUG
 bool AreAliased(Register reg1,
                 Register reg2,
@@ -491,19 +499,6 @@
   void VmovLow(Register dst, DwVfpRegister src);
   void VmovLow(DwVfpRegister dst, Register src);
 
-  // Converts the smi or heap number in object to an int32 using the rules
-  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
-  // and brought into the range -2^31 .. +2^31 - 1.
-  void ConvertNumberToInt32(Register object,
-                            Register dst,
-                            Register heap_number_map,
-                            Register scratch1,
-                            Register scratch2,
-                            Register scratch3,
-                            DwVfpRegister double_scratch1,
-                            LowDwVfpRegister double_scratch2,
-                            Label* not_int32);
-
   // Loads the number from object into dst register.
   // If |object| is neither smi nor heap number, |not_number| is jumped to
   // with |object| still intact.
@@ -989,15 +984,34 @@
                      Label* exact);
 
   // Performs a truncating conversion of a floating point number as used by
+  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
+  // succeeds, otherwise falls through if result is saturated. On return
+  // 'result' either holds answer, or is clobbered on fall through.
+  //
+  // Only public for the test code in test-code-stubs-arm.cc.
+  void TryInlineTruncateDoubleToI(Register result,
+                                  DwVfpRegister input,
+                                  Label* done);
+
+  // Performs a truncating conversion of a floating point number as used by
   // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
-  // Double_scratch must be between d0 and d15.
-  // Exits with 'result' holding the answer and all other registers clobbered.
-  void ECMAToInt32(Register result,
-                   DwVfpRegister double_input,
-                   Register scratch,
-                   Register scratch_high,
-                   Register scratch_low,
-                   LowDwVfpRegister double_scratch);
+  // Exits with 'result' holding the answer.
+  void TruncateDoubleToI(Register result, DwVfpRegister double_input);
+
+  // Performs a truncating conversion of a heap number as used by
+  // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
+  // must be different registers.  Exits with 'result' holding the answer.
+  void TruncateHeapNumberToI(Register result, Register object);
+
+  // Converts the smi or heap number in object to an int32 using the rules
+  // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
+  // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
+  // different registers.
+  void TruncateNumberToI(Register object,
+                         Register result,
+                         Register heap_number_map,
+                         Register scratch1,
+                         Label* not_int32);
 
   // Check whether d16-d31 are available on the CPU. The result is given by the
   // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise.
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 85a11e7..85c2a7c 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -45,6 +45,10 @@
 #include "extensions/statistics-extension.h"
 #include "code-stubs.h"
 
+#if defined(V8_I18N_SUPPORT)
+#include "extensions/i18n/i18n-extension.h"
+#endif
+
 namespace v8 {
 namespace internal {
 
@@ -102,6 +106,9 @@
   GCExtension::Register();
   ExternalizeStringExtension::Register();
   StatisticsExtension::Register();
+#if defined(V8_I18N_SUPPORT)
+  v8_i18n::Extension::Register();
+#endif
 }
 
 
@@ -2288,6 +2295,12 @@
     InstallExtension(isolate, "v8/statistics", &extension_states);
   }
 
+#if defined(V8_I18N_SUPPORT)
+  if (FLAG_enable_i18n) {
+    InstallExtension(isolate, "v8/i18n", &extension_states);
+  }
+#endif
+
   if (extensions == NULL) return true;
   // Install required extensions
   int count = v8::ImplementationUtilities::GetNameCount(extensions);
diff --git a/src/circular-queue.h b/src/circular-queue.h
index efbacd5..c7797b3 100644
--- a/src/circular-queue.h
+++ b/src/circular-queue.h
@@ -70,7 +70,7 @@
              // completely processed by the consumer.
   };
 
-  struct V8_ALIGNAS(PROCESSOR_CACHE_LINE_SIZE) Entry {
+  struct V8_ALIGNED(PROCESSOR_CACHE_LINE_SIZE) Entry {
     Entry() : marker(kEmpty) {}
     T record;
     Atomic32 marker;
@@ -79,8 +79,8 @@
   Entry* Next(Entry* entry);
 
   Entry buffer_[Length];
-  V8_ALIGNAS(PROCESSOR_CACHE_LINE_SIZE) Entry* enqueue_pos_;
-  V8_ALIGNAS(PROCESSOR_CACHE_LINE_SIZE) Entry* dequeue_pos_;
+  V8_ALIGNED(PROCESSOR_CACHE_LINE_SIZE) Entry* enqueue_pos_;
+  V8_ALIGNED(PROCESSOR_CACHE_LINE_SIZE) Entry* dequeue_pos_;
 
   DISALLOW_COPY_AND_ASSIGN(SamplingCircularQueue);
 };
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 9bbab9a..3e18138 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -495,7 +495,7 @@
 template <>
 HValue* CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
-      GetParameter(0), GetParameter(1), NULL, NULL,
+      GetParameter(0), GetParameter(1), NULL,
       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
       false, NEVER_RETURN_HOLE, STANDARD_STORE);
   return load;
@@ -540,7 +540,7 @@
 template <>
 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() {
   BuildUncheckedMonomorphicElementAccess(
-      GetParameter(0), GetParameter(1), GetParameter(2), NULL,
+      GetParameter(0), GetParameter(1), GetParameter(2),
       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
       true, NEVER_RETURN_HOLE, casted_stub()->store_mode());
 
@@ -888,11 +888,11 @@
                                 casted_stub()->to_kind(),
                                 casted_stub()->is_jsarray());
 
-    BuildUncheckedMonomorphicElementAccess(object, key, value, NULL,
-                                          casted_stub()->is_jsarray(),
-                                          casted_stub()->to_kind(),
-                                          true, ALLOW_RETURN_HOLE,
-                                          casted_stub()->store_mode());
+    BuildUncheckedMonomorphicElementAccess(object, key, value,
+                                           casted_stub()->is_jsarray(),
+                                           casted_stub()->to_kind(),
+                                           true, ALLOW_RETURN_HOLE,
+                                           casted_stub()->store_mode());
   }
 
   return value;
diff --git a/src/code-stubs.h b/src/code-stubs.h
index c58acd6..4be914d 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -1704,11 +1704,13 @@
   DoubleToIStub(Register source,
                 Register destination,
                 int offset,
-                bool is_truncating) : bit_field_(0) {
+                bool is_truncating,
+                bool skip_fastpath = false) : bit_field_(0) {
     bit_field_ = SourceRegisterBits::encode(source.code_) |
       DestinationRegisterBits::encode(destination.code_) |
       OffsetBits::encode(offset) |
-      IsTruncatingBits::encode(is_truncating);
+      IsTruncatingBits::encode(is_truncating) |
+      SkipFastPathBits::encode(skip_fastpath);
   }
 
   Register source() {
@@ -1725,12 +1727,18 @@
     return IsTruncatingBits::decode(bit_field_);
   }
 
+  bool skip_fastpath() {
+    return SkipFastPathBits::decode(bit_field_);
+  }
+
   int offset() {
     return OffsetBits::decode(bit_field_);
   }
 
   void Generate(MacroAssembler* masm);
 
+  virtual bool SometimesSetsUpAFrame() { return false; }
+
  private:
   static const int kBitsPerRegisterNumber = 6;
   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
@@ -1743,6 +1751,8 @@
       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
   class OffsetBits:
       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
+  class SkipFastPathBits:
+      public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
 
   Major MajorKey() { return DoubleToI; }
   int MinorKey() { return bit_field_; }
diff --git a/src/compiler.cc b/src/compiler.cc
index 0460da1..c14234f 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -362,7 +362,7 @@
   }
 
   // Take --hydrogen-filter into account.
-  if (!info()->closure()->PassesHydrogenFilter()) {
+  if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) {
     info()->AbortOptimization();
     return SetLastStatus(BAILED_OUT);
   }
@@ -1209,6 +1209,8 @@
     if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
       return;
     int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
+    int column_num =
+        GetScriptColumnNumber(script, shared->start_position()) + 1;
     USE(line_num);
     if (script->name()->IsString()) {
       PROFILE(info->isolate(),
@@ -1217,7 +1219,8 @@
                               *shared,
                               info,
                               String::cast(script->name()),
-                              line_num));
+                              line_num,
+                              column_num));
     } else {
       PROFILE(info->isolate(),
               CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
@@ -1225,7 +1228,8 @@
                               *shared,
                               info,
                               info->isolate()->heap()->empty_string(),
-                              line_num));
+                              line_num,
+                              column_num));
     }
   }
 
@@ -1258,9 +1262,10 @@
 bool CompilationPhase::ShouldProduceTraceOutput() const {
   // Trace if the appropriate trace flag is set and the phase name's first
   // character is in the FLAG_trace_phase command line parameter.
-  bool tracing_on = info()->IsStub() ?
-      FLAG_trace_hydrogen_stubs :
-      FLAG_trace_hydrogen;
+  bool tracing_on = info()->IsStub()
+      ? FLAG_trace_hydrogen_stubs
+      : (FLAG_trace_hydrogen &&
+         info()->closure()->PassesFilter(FLAG_trace_hydrogen_filter));
   return (tracing_on &&
       OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL);
 }
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index ed7d5a9..f8698b3 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -43,10 +43,15 @@
 static const int kProfilerStackSize = 64 * KB;
 
 
-ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
+ProfilerEventsProcessor::ProfilerEventsProcessor(
+    ProfileGenerator* generator,
+    Sampler* sampler,
+    int period_in_useconds)
     : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
       generator_(generator),
+      sampler_(sampler),
       running_(true),
+      period_in_useconds_(period_in_useconds),
       last_code_event_id_(0), last_processed_code_event_id_(0) {
 }
 
@@ -118,15 +123,39 @@
 }
 
 
-void ProfilerEventsProcessor::Run() {
-  while (running_) {
-    // Process ticks until we have any.
+void ProfilerEventsProcessor::ProcessEventsAndDoSample() {
+  int64_t stop_time = OS::Ticks() + period_in_useconds_;
+  // Keep processing existing events until we need to do next sample.
+  while (OS::Ticks() < stop_time) {
     if (ProcessTicks()) {
-      // All ticks of the current last_processed_code_event_id_ are processed,
+      // All ticks of the current dequeue_order are processed,
       // proceed to the next code event.
       ProcessCodeEvent();
     }
-    YieldCPU();
+  }
+  // Schedule next sample. sampler_ is NULL in tests.
+  if (sampler_) sampler_->DoSample();
+}
+
+
+void ProfilerEventsProcessor::ProcessEventsAndYield() {
+  // Process ticks until we have any.
+  if (ProcessTicks()) {
+    // All ticks of the current dequeue_order are processed,
+    // proceed to the next code event.
+    ProcessCodeEvent();
+  }
+  YieldCPU();
+}
+
+
+void ProfilerEventsProcessor::Run() {
+  while (running_) {
+    if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
+      ProcessEventsAndDoSample();
+    } else {
+      ProcessEventsAndYield();
+    }
   }
 
   // Process remaining tick events.
@@ -403,9 +432,10 @@
     saved_logging_nesting_ = logger->logging_nesting_;
     logger->logging_nesting_ = 0;
     generator_ = new ProfileGenerator(profiles_);
-    processor_ = new ProfilerEventsProcessor(generator_);
+    Sampler* sampler = logger->sampler();
+    processor_ = new ProfilerEventsProcessor(
+        generator_, sampler, FLAG_cpu_profiler_sampling_interval);
     is_profiling_ = true;
-    processor_->StartSynchronously();
     // Enumerate stuff we already have in the heap.
     ASSERT(isolate_->heap()->HasBeenSetUp());
     if (!FLAG_prof_browser_mode) {
@@ -415,12 +445,15 @@
     logger->LogAccessorCallbacks();
     LogBuiltins();
     // Enable stack sampling.
-    Sampler* sampler = logger->sampler();
+    if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
+      sampler->SetHasProcessingThread(true);
+    }
     sampler->IncreaseProfilingDepth();
     if (!sampler->IsActive()) {
       sampler->Start();
       need_to_stop_sampler_ = true;
     }
+    processor_->StartSynchronously();
   }
 }
 
@@ -453,16 +486,19 @@
   Logger* logger = isolate_->logger();
   Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
   sampler->DecreaseProfilingDepth();
-  if (need_to_stop_sampler_) {
-    sampler->Stop();
-    need_to_stop_sampler_ = false;
-  }
   is_profiling_ = false;
   processor_->StopSynchronously();
   delete processor_;
   delete generator_;
   processor_ = NULL;
   generator_ = NULL;
+  if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
+    sampler->SetHasProcessingThread(false);
+  }
+  if (need_to_stop_sampler_) {
+    sampler->Stop();
+    need_to_stop_sampler_ = false;
+  }
   logger->logging_nesting_ = saved_logging_nesting_;
 }
 
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index ddd27a8..84e34e4 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -136,7 +136,9 @@
 // methods called by event producers: VM and stack sampler threads.
 class ProfilerEventsProcessor : public Thread {
  public:
-  explicit ProfilerEventsProcessor(ProfileGenerator* generator);
+  ProfilerEventsProcessor(ProfileGenerator* generator,
+                          Sampler* sampler,
+                          int period_in_useconds);
   virtual ~ProfilerEventsProcessor() {}
 
   // Thread control.
@@ -160,8 +162,14 @@
   bool ProcessCodeEvent();
   bool ProcessTicks();
 
+  void ProcessEventsAndDoSample();
+  void ProcessEventsAndYield();
+
   ProfileGenerator* generator_;
+  Sampler* sampler_;
   bool running_;
+  // Sampling period in microseconds.
+  const int period_in_useconds_;
   UnboundQueue<CodeEventsContainer> events_buffer_;
   static const size_t kTickSampleBufferSize = 1 * MB;
   static const size_t kTickSampleQueueLength =
diff --git a/src/cpu.cc b/src/cpu.cc
new file mode 100644
index 0000000..d7c32dd
--- /dev/null
+++ b/src/cpu.cc
@@ -0,0 +1,446 @@
+// 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 "cpu.h"
+
+#include <algorithm>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "checks.h"
+
+namespace v8 {
+namespace internal {
+
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+
+#if V8_CC_MSVC
+
+#include <intrin.h>  // NOLINT
+
+#elif defined(__i386__) && defined(__pic__)
+
+static V8_INLINE(void __cpuid(int cpu_info[4], int info_type)) {
+  __asm__ volatile (
+    "mov %%ebx, %%edi\n"
+    "cpuid\n"
+    "xchg %%edi, %%ebx\n"
+    : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
+    : "a"(info_type)
+  );
+}
+
+#else  // !V8_CC_MSVC || (!defined(__i386__) && !defined(__pic__))
+
+static void V8_INLINE(__cpuid(int cpu_info[4], int info_type)) {
+  __asm__ volatile (
+    "cpuid \n\t"
+    : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
+    : "a"(info_type)
+  );
+}
+
+#endif
+
+#elif V8_HOST_ARCH_ARM || V8_HOST_ARCH_MIPS
+
+#if V8_HOST_ARCH_ARM
+
+// See <uapi/asm/hwcap.h> kernel header.
+/*
+ * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP
+ */
+#define HWCAP_SWP (1 << 0)
+#define HWCAP_HALF  (1 << 1)
+#define HWCAP_THUMB (1 << 2)
+#define HWCAP_26BIT (1 << 3)  /* Play it safe */
+#define HWCAP_FAST_MULT (1 << 4)
+#define HWCAP_FPA (1 << 5)
+#define HWCAP_VFP (1 << 6)
+#define HWCAP_EDSP  (1 << 7)
+#define HWCAP_JAVA  (1 << 8)
+#define HWCAP_IWMMXT  (1 << 9)
+#define HWCAP_CRUNCH  (1 << 10)
+#define HWCAP_THUMBEE (1 << 11)
+#define HWCAP_NEON  (1 << 12)
+#define HWCAP_VFPv3 (1 << 13)
+#define HWCAP_VFPv3D16  (1 << 14) /* also set for VFPv4-D16 */
+#define HWCAP_TLS (1 << 15)
+#define HWCAP_VFPv4 (1 << 16)
+#define HWCAP_IDIVA (1 << 17)
+#define HWCAP_IDIVT (1 << 18)
+#define HWCAP_VFPD32  (1 << 19) /* set if VFP has 32 regs (not 16) */
+#define HWCAP_IDIV  (HWCAP_IDIVA | HWCAP_IDIVT)
+#define HWCAP_LPAE  (1 << 20)
+
+#define AT_HWCAP 16
+
+// Read the ELF HWCAP flags by parsing /proc/self/auxv.
+static uint32_t ReadELFHWCaps() {
+  uint32_t result = 0;
+  FILE* fp = fopen("/proc/self/auxv", "r");
+  if (fp != NULL) {
+    struct { uint32_t tag; uint32_t value; } entry;
+    for (;;) {
+      size_t n = fread(&entry, sizeof(entry), 1, fp);
+      if (n == 0 || (entry.tag == 0 && entry.value == 0)) {
+        break;
+      }
+      if (entry.tag == AT_HWCAP) {
+        result = entry.value;
+        break;
+      }
+    }
+    fclose(fp);
+  }
+  return result;
+}
+
+#endif  // V8_HOST_ARCH_ARM
+
+// Extract the information exposed by the kernel via /proc/cpuinfo.
+class CPUInfo V8_FINAL BASE_EMBEDDED {
+ public:
+  CPUInfo() : datalen_(0) {
+    // Get the size of the cpuinfo file by reading it until the end. This is
+    // required because files under /proc do not always return a valid size
+    // when using fseek(0, SEEK_END) + ftell(). Nor can the be mmap()-ed.
+    static const char PATHNAME[] = "/proc/cpuinfo";
+    FILE* fp = fopen(PATHNAME, "r");
+    if (fp != NULL) {
+      for (;;) {
+        char buffer[256];
+        size_t n = fread(buffer, 1, sizeof(buffer), fp);
+        if (n == 0) {
+          break;
+        }
+        datalen_ += n;
+      }
+      fclose(fp);
+    }
+
+    // Read the contents of the cpuinfo file.
+    data_ = new char[datalen_ + 1];
+    fp = fopen(PATHNAME, "r");
+    if (fp != NULL) {
+      for (size_t offset = 0; offset < datalen_; ) {
+        size_t n = fread(data_ + offset, 1, datalen_ - offset, fp);
+        if (n == 0) {
+          break;
+        }
+        offset += n;
+      }
+      fclose(fp);
+    }
+
+    // Zero-terminate the data.
+    data_[datalen_] = '\0';
+  }
+
+  ~CPUInfo() {
+    delete[] data_;
+  }
+
+  // Extract the content of a the first occurence of a given field in
+  // the content of the cpuinfo file and return it as a heap-allocated
+  // string that must be freed by the caller using delete[].
+  // Return NULL if not found.
+  char* ExtractField(const char* field) const {
+    ASSERT(field != NULL);
+
+    // Look for first field occurence, and ensure it starts the line.
+    size_t fieldlen = strlen(field);
+    char* p = data_;
+    for (;;) {
+      p = strstr(p, field);
+      if (p == NULL) {
+        return NULL;
+      }
+      if (p == data_ || p[-1] == '\n') {
+        break;
+      }
+      p += fieldlen;
+    }
+
+    // Skip to the first colon followed by a space.
+    p = strchr(p + fieldlen, ':');
+    if (p == NULL || !isspace(p[1])) {
+      return NULL;
+    }
+    p += 2;
+
+    // Find the end of the line.
+    char* q = strchr(p, '\n');
+    if (q == NULL) {
+      q = data_ + datalen_;
+    }
+
+    // Copy the line into a heap-allocated buffer.
+    size_t len = q - p;
+    char* result = new char[len + 1];
+    if (result != NULL) {
+      memcpy(result, p, len);
+      result[len] = '\0';
+    }
+    return result;
+  }
+
+ private:
+  char* data_;
+  size_t datalen_;
+};
+
+
+// Checks that a space-separated list of items contains one given 'item'.
+static bool HasListItem(const char* list, const char* item) {
+  ssize_t item_len = strlen(item);
+  const char* p = list;
+  if (p != NULL) {
+    while (*p != '\0') {
+      // Skip whitespace.
+      while (isspace(*p)) ++p;
+
+      // Find end of current list item.
+      const char* q = p;
+      while (*q != '\0' && !isspace(*q)) ++q;
+
+      if (item_len == q - p && memcmp(p, item, item_len) == 0) {
+        return true;
+      }
+
+      // Skip to next item.
+      p = q;
+    }
+  }
+  return false;
+}
+
+#endif  // V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+
+CPU::CPU() : stepping_(0),
+             model_(0),
+             ext_model_(0),
+             family_(0),
+             ext_family_(0),
+             type_(0),
+             implementer_(0),
+             architecture_(0),
+             part_(0),
+             has_fpu_(false),
+             has_cmov_(false),
+             has_sahf_(false),
+             has_mmx_(false),
+             has_sse_(false),
+             has_sse2_(false),
+             has_sse3_(false),
+             has_ssse3_(false),
+             has_sse41_(false),
+             has_sse42_(false),
+             has_idiva_(false),
+             has_neon_(false),
+             has_thumbee_(false),
+             has_vfp_(false),
+             has_vfp3_(false),
+             has_vfp3_d32_(false) {
+  memcpy(vendor_, "Unknown", 8);
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+  int cpu_info[4];
+
+  // __cpuid with an InfoType argument of 0 returns the number of
+  // valid Ids in CPUInfo[0] and the CPU identification string in
+  // the other three array elements. The CPU identification string is
+  // not in linear order. The code below arranges the information
+  // in a human readable form. The human readable order is CPUInfo[1] |
+  // CPUInfo[3] | CPUInfo[2]. CPUInfo[2] and CPUInfo[3] are swapped
+  // before using memcpy to copy these three array elements to cpu_string.
+  __cpuid(cpu_info, 0);
+  unsigned num_ids = cpu_info[0];
+  std::swap(cpu_info[2], cpu_info[3]);
+  memcpy(vendor_, cpu_info + 1, 12);
+  vendor_[12] = '\0';
+
+  // Interpret CPU feature information.
+  if (num_ids > 0) {
+    __cpuid(cpu_info, 1);
+    stepping_ = cpu_info[0] & 0xf;
+    model_ = ((cpu_info[0] >> 4) & 0xf) + ((cpu_info[0] >> 12) & 0xf0);
+    family_ = (cpu_info[0] >> 8) & 0xf;
+    type_ = (cpu_info[0] >> 12) & 0x3;
+    ext_model_ = (cpu_info[0] >> 16) & 0xf;
+    ext_family_ = (cpu_info[0] >> 20) & 0xff;
+    has_fpu_ = (cpu_info[3] & 0x00000001) != 0;
+    has_cmov_ = (cpu_info[3] & 0x00008000) != 0;
+    has_mmx_ = (cpu_info[3] & 0x00800000) != 0;
+    has_sse_ = (cpu_info[3] & 0x02000000) != 0;
+    has_sse2_ = (cpu_info[3] & 0x04000000) != 0;
+    has_sse3_ = (cpu_info[2] & 0x00000001) != 0;
+    has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
+    has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
+    has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
+  }
+
+  // Query extended IDs.
+  __cpuid(cpu_info, 0x80000000);
+  unsigned num_ext_ids = cpu_info[0];
+
+  // Interpret extended CPU feature information.
+  if (num_ext_ids > 0x80000000) {
+    __cpuid(cpu_info, 0x80000001);
+    // SAHF is always available in compat/legacy mode,
+    // but must be probed in long mode.
+#if V8_HOST_ARCH_IA32
+    has_sahf_ = true;
+#else
+    has_sahf_ = (cpu_info[2] & 0x00000001) != 0;
+#endif
+  }
+#elif V8_HOST_ARCH_ARM
+  CPUInfo cpu_info;
+
+  // Extract implementor from the "CPU implementer" field.
+  char* implementer = cpu_info.ExtractField("CPU implementer");
+  if (implementer != NULL) {
+    char* end ;
+    implementer_ = strtol(implementer, &end, 0);
+    if (end == implementer) {
+      implementer_ = 0;
+    }
+    delete[] implementer;
+  }
+
+  // Extract part number from the "CPU part" field.
+  char* part = cpu_info.ExtractField("CPU part");
+  if (part != NULL) {
+    char* end ;
+    part_ = strtol(part, &end, 0);
+    if (end == part) {
+      part_ = 0;
+    }
+    delete[] part;
+  }
+
+  // Extract architecture from the "CPU Architecture" field.
+  // The list is well-known, unlike the the output of
+  // the 'Processor' field which can vary greatly.
+  // See the definition of the 'proc_arch' array in
+  // $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
+  // same file.
+  char* architecture = cpu_info.ExtractField("CPU architecture");
+  if (architecture != NULL) {
+    char* end;
+    architecture_ = strtol(architecture, &end, 10);
+    if (end == architecture) {
+      architecture_ = 0;
+    }
+    delete[] architecture;
+
+    // Unfortunately, it seems that certain ARMv6-based CPUs
+    // report an incorrect architecture number of 7!
+    //
+    // See http://code.google.com/p/android/issues/detail?id=10812
+    //
+    // We try to correct this by looking at the 'elf_format'
+    // field reported by the 'Processor' field, which is of the
+    // form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
+    // an ARMv6-one. For example, the Raspberry Pi is one popular
+    // ARMv6 device that reports architecture 7.
+    if (architecture_ == 7) {
+      char* processor = cpu_info.ExtractField("Processor");
+      if (HasListItem(processor, "(v6l)")) {
+        architecture_ = 6;
+      }
+      delete[] processor;
+    }
+  }
+
+  // Try to extract the list of CPU features from ELF hwcaps.
+  uint32_t hwcaps = ReadELFHWCaps();
+  if (hwcaps != 0) {
+    has_idiva_ = (hwcaps & HWCAP_IDIVA) != 0;
+    has_neon_ = (hwcaps & HWCAP_NEON) != 0;
+    has_thumbee_ = (hwcaps & HWCAP_THUMBEE) != 0;
+    has_vfp_ = (hwcaps & HWCAP_VFP) != 0;
+    has_vfp3_ = (hwcaps & (HWCAP_VFPv3 | HWCAP_VFPv3D16 | HWCAP_VFPv4)) != 0;
+    has_vfp3_d32_ = (has_vfp3_ && ((hwcaps & HWCAP_VFPv3D16) == 0 ||
+                                   (hwcaps & HWCAP_VFPD32) != 0));
+  } else {
+    // Try to fallback to "Features" CPUInfo field.
+    char* features = cpu_info.ExtractField("Features");
+    has_idiva_ = HasListItem(features, "idiva");
+    has_neon_ = HasListItem(features, "neon");
+    has_thumbee_ = HasListItem(features, "thumbee");
+    has_vfp_ = HasListItem(features, "vfp");
+    if (HasListItem(features, "vfpv3")) {
+      has_vfp3_ = true;
+      has_vfp3_d32_ = true;
+    } else if (HasListItem(features, "vfpv3d16")) {
+      has_vfp3_ = true;
+    }
+    delete[] features;
+  }
+
+  // Some old kernels will report vfp not vfpv3. Here we make an attempt
+  // to detect vfpv3 by checking for vfp *and* neon, since neon is only
+  // available on architectures with vfpv3. Checking neon on its own is
+  // not enough as it is possible to have neon without vfp.
+  if (has_vfp_ && has_neon_) {
+    has_vfp3_ = true;
+  }
+
+  // VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
+  if (architecture_ < 7 && has_vfp3_) {
+    architecture_ = 7;
+  }
+
+  // ARMv7 implies ThumbEE.
+  if (architecture_ >= 7) {
+    has_thumbee_ = true;
+  }
+
+  // The earliest architecture with ThumbEE is ARMv6T2.
+  if (has_thumbee_ && architecture_ < 6) {
+    architecture_ = 6;
+  }
+
+  // We don't support any FPUs other than VFP.
+  has_fpu_ = has_vfp_;
+#elif V8_HOST_ARCH_MIPS
+  // Simple detection of FPU at runtime for Linux.
+  // It is based on /proc/cpuinfo, which reveals hardware configuration
+  // to user-space applications.  According to MIPS (early 2010), no similar
+  // facility is universally available on the MIPS architectures,
+  // so it's up to individual OSes to provide such.
+  CPUInfo cpu_info;
+  char* cpu_model = cpu_info.ExtractField("cpu model");
+  has_fpu_ = HasListItem(cpu_model, "FPU");
+  delete[] cpu_model;
+#endif
+}
+
+} }  // namespace v8::internal
diff --git a/src/cpu.h b/src/cpu.h
index f8d33e4..ef58b4c 100644
--- a/src/cpu.h
+++ b/src/cpu.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-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:
@@ -44,14 +44,61 @@
 // ----------------------------------------------------------------------------
 // CPU
 //
-// This class has static methods for the architecture specific functions. Add
-// methods here to cope with differences between the supported architectures.
+// Query information about the processor.
 //
-// For each architecture the file cpu_<arch>.cc contains the implementation of
-// these functions.
+// This class also has static methods for the architecture specific functions.
+// Add methods here to cope with differences between the supported
+// architectures. For each architecture the file cpu_<arch>.cc contains the
+// implementation of these static functions.
 
-class CPU : public AllStatic {
+class CPU V8_FINAL BASE_EMBEDDED {
  public:
+  CPU();
+
+  // x86 CPUID information
+  const char* vendor() const { return vendor_; }
+  int stepping() const { return stepping_; }
+  int model() const { return model_; }
+  int ext_model() const { return ext_model_; }
+  int family() const { return family_; }
+  int ext_family() const { return ext_family_; }
+  int type() const { return type_; }
+
+  // arm implementer/part information
+  int implementer() const { return implementer_; }
+  static const int ARM = 0x41;
+  static const int QUALCOMM = 0x51;
+  int architecture() const { return architecture_; }
+  int part() const { return part_; }
+  static const int ARM_CORTEX_A5 = 0xc05;
+  static const int ARM_CORTEX_A7 = 0xc07;
+  static const int ARM_CORTEX_A8 = 0xc08;
+  static const int ARM_CORTEX_A9 = 0xc09;
+  static const int ARM_CORTEX_A12 = 0xc0c;
+  static const int ARM_CORTEX_A15 = 0xc0f;
+
+  // General features
+  bool has_fpu() const { return has_fpu_; }
+
+  // x86 features
+  bool has_cmov() const { return has_cmov_; }
+  bool has_sahf() const { return has_sahf_; }
+  bool has_mmx() const { return has_mmx_; }
+  bool has_sse() const { return has_sse_; }
+  bool has_sse2() const { return has_sse2_; }
+  bool has_sse3() const { return has_sse3_; }
+  bool has_ssse3() const { return has_ssse3_; }
+  bool has_sse41() const { return has_sse41_; }
+  bool has_sse42() const { return has_sse42_; }
+
+  // arm features
+  bool has_idiva() const { return has_idiva_; }
+  bool has_neon() const { return has_neon_; }
+  bool has_thumbee() const { return has_thumbee_; }
+  bool has_vfp() const { return has_vfp_; }
+  bool has_vfp3() const { return has_vfp3_; }
+  bool has_vfp3_d32() const { return has_vfp3_d32_; }
+
   // Initializes the cpu architecture support. Called once at VM startup.
   static void SetUp();
 
@@ -59,6 +106,34 @@
 
   // Flush instruction cache.
   static void FlushICache(void* start, size_t size);
+
+ private:
+  char vendor_[13];
+  int stepping_;
+  int model_;
+  int ext_model_;
+  int family_;
+  int ext_family_;
+  int type_;
+  int implementer_;
+  int architecture_;
+  int part_;
+  bool has_fpu_;
+  bool has_cmov_;
+  bool has_sahf_;
+  bool has_mmx_;
+  bool has_sse_;
+  bool has_sse2_;
+  bool has_sse3_;
+  bool has_ssse3_;
+  bool has_sse41_;
+  bool has_sse42_;
+  bool has_idiva_;
+  bool has_neon_;
+  bool has_thumbee_;
+  bool has_vfp_;
+  bool has_vfp3_;
+  bool has_vfp3_d32_;
 };
 
 } }  // namespace v8::internal
diff --git a/src/extensions/i18n/break-iterator.js b/src/extensions/i18n/break-iterator.js
new file mode 100644
index 0000000..898bd5d
--- /dev/null
+++ b/src/extensions/i18n/break-iterator.js
@@ -0,0 +1,190 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+/**
+ * Initializes the given object so it's a valid BreakIterator instance.
+ * Useful for subclassing.
+ */
+function initializeBreakIterator(iterator, locales, options) {
+  if (iterator.hasOwnProperty('__initializedIntlObject')) {
+    throw new TypeError('Trying to re-initialize v8BreakIterator object.');
+  }
+
+  if (options === undefined) {
+    options = {};
+  }
+
+  var getOption = getGetOption(options, 'breakiterator');
+
+  var internalOptions = {};
+
+  defineWEProperty(internalOptions, 'type', getOption(
+    'type', 'string', ['character', 'word', 'sentence', 'line'], 'word'));
+
+  var locale = resolveLocale('breakiterator', locales, options);
+  var resolved = Object.defineProperties({}, {
+    requestedLocale: {value: locale.locale, writable: true},
+    type: {value: internalOptions.type, writable: true},
+    locale: {writable: true}
+  });
+
+  var internalIterator = %CreateBreakIterator(locale.locale,
+                                              internalOptions,
+                                              resolved);
+
+  Object.defineProperty(iterator, 'iterator', {value: internalIterator});
+  Object.defineProperty(iterator, 'resolved', {value: resolved});
+  Object.defineProperty(iterator, '__initializedIntlObject',
+                        {value: 'breakiterator'});
+
+  return iterator;
+}
+
+
+/**
+ * Constructs Intl.v8BreakIterator object given optional locales and options
+ * parameters.
+ *
+ * @constructor
+ */
+%SetProperty(Intl, 'v8BreakIterator', function() {
+    var locales = arguments[0];
+    var options = arguments[1];
+
+    if (!this || this === Intl) {
+      // Constructor is called as a function.
+      return new Intl.v8BreakIterator(locales, options);
+    }
+
+    return initializeBreakIterator(toObject(this), locales, options);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+
+
+/**
+ * BreakIterator resolvedOptions method.
+ */
+%SetProperty(Intl.v8BreakIterator.prototype, 'resolvedOptions', function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    if (!this || typeof this !== 'object' ||
+        this.__initializedIntlObject !== 'breakiterator') {
+      throw new TypeError('resolvedOptions method called on a non-object or ' +
+          'on a object that is not Intl.v8BreakIterator.');
+    }
+
+    var segmenter = this;
+    var locale = getOptimalLanguageTag(segmenter.resolved.requestedLocale,
+                                       segmenter.resolved.locale);
+
+    return {
+      locale: locale,
+      type: segmenter.resolved.type
+    };
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.v8BreakIterator.prototype.resolvedOptions,
+                 'resolvedOptions');
+%FunctionRemovePrototype(Intl.v8BreakIterator.prototype.resolvedOptions);
+%SetNativeFlag(Intl.v8BreakIterator.prototype.resolvedOptions);
+
+
+/**
+ * Returns the subset of the given locale list for which this locale list
+ * has a matching (possibly fallback) locale. Locales appear in the same
+ * order in the returned list as in the input list.
+ * Options are optional parameter.
+ */
+%SetProperty(Intl.v8BreakIterator, 'supportedLocalesOf', function(locales) {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    return supportedLocalesOf('breakiterator', locales, arguments[1]);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.v8BreakIterator.supportedLocalesOf, 'supportedLocalesOf');
+%FunctionRemovePrototype(Intl.v8BreakIterator.supportedLocalesOf);
+%SetNativeFlag(Intl.v8BreakIterator.supportedLocalesOf);
+
+
+/**
+ * Adopts text to segment using the iterator. Old text, if present,
+ * gets discarded.
+ */
+function adoptText(iterator, text) {
+  %BreakIteratorAdoptText(iterator.iterator, String(text));
+}
+
+
+/**
+ * Returns index of the first break in the string and moves current pointer.
+ */
+function first(iterator) {
+  return %BreakIteratorFirst(iterator.iterator);
+}
+
+
+/**
+ * Returns the index of the next break and moves the pointer.
+ */
+function next(iterator) {
+  return %BreakIteratorNext(iterator.iterator);
+}
+
+
+/**
+ * Returns index of the current break.
+ */
+function current(iterator) {
+  return %BreakIteratorCurrent(iterator.iterator);
+}
+
+
+/**
+ * Returns type of the current break.
+ */
+function breakType(iterator) {
+  return %BreakIteratorBreakType(iterator.iterator);
+}
+
+
+addBoundMethod(Intl.v8BreakIterator, 'adoptText', adoptText, 1);
+addBoundMethod(Intl.v8BreakIterator, 'first', first, 0);
+addBoundMethod(Intl.v8BreakIterator, 'next', next, 0);
+addBoundMethod(Intl.v8BreakIterator, 'current', current, 0);
+addBoundMethod(Intl.v8BreakIterator, 'breakType', breakType, 0);
diff --git a/src/extensions/i18n/collator.js b/src/extensions/i18n/collator.js
new file mode 100644
index 0000000..d8d247b
--- /dev/null
+++ b/src/extensions/i18n/collator.js
@@ -0,0 +1,209 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+/**
+ * Initializes the given object so it's a valid Collator instance.
+ * Useful for subclassing.
+ */
+function initializeCollator(collator, locales, options) {
+  if (collator.hasOwnProperty('__initializedIntlObject')) {
+    throw new TypeError('Trying to re-initialize Collator object.');
+  }
+
+  if (options === undefined) {
+    options = {};
+  }
+
+  var getOption = getGetOption(options, 'collator');
+
+  var internalOptions = {};
+
+  defineWEProperty(internalOptions, 'usage', getOption(
+    'usage', 'string', ['sort', 'search'], 'sort'));
+
+  var sensitivity = getOption('sensitivity', 'string',
+                              ['base', 'accent', 'case', 'variant']);
+  if (sensitivity === undefined && internalOptions.usage === 'sort') {
+    sensitivity = 'variant';
+  }
+  defineWEProperty(internalOptions, 'sensitivity', sensitivity);
+
+  defineWEProperty(internalOptions, 'ignorePunctuation', getOption(
+    'ignorePunctuation', 'boolean', undefined, false));
+
+  var locale = resolveLocale('collator', locales, options);
+
+  // ICU can't take kb, kc... parameters through localeID, so we need to pass
+  // them as options.
+  // One exception is -co- which has to be part of the extension, but only for
+  // usage: sort, and its value can't be 'standard' or 'search'.
+  var extensionMap = parseExtension(locale.extension);
+  setOptions(
+      options, extensionMap, COLLATOR_KEY_MAP, getOption, internalOptions);
+
+  var collation = 'default';
+  var extension = '';
+  if (extensionMap.hasOwnProperty('co') && internalOptions.usage === 'sort') {
+    if (ALLOWED_CO_VALUES.indexOf(extensionMap.co) !== -1) {
+      extension = '-u-co-' + extensionMap.co;
+      // ICU can't tell us what the collation is, so save user's input.
+      collation = extensionMap.co;
+    }
+  } else if (internalOptions.usage === 'search') {
+    extension = '-u-co-search';
+  }
+  defineWEProperty(internalOptions, 'collation', collation);
+
+  var requestedLocale = locale.locale + extension;
+
+  // We define all properties C++ code may produce, to prevent security
+  // problems. If malicious user decides to redefine Object.prototype.locale
+  // we can't just use plain x.locale = 'us' or in C++ Set("locale", "us").
+  // Object.defineProperties will either succeed defining or throw an error.
+  var resolved = Object.defineProperties({}, {
+    caseFirst: {writable: true},
+    collation: {value: internalOptions.collation, writable: true},
+    ignorePunctuation: {writable: true},
+    locale: {writable: true},
+    numeric: {writable: true},
+    requestedLocale: {value: requestedLocale, writable: true},
+    sensitivity: {writable: true},
+    strength: {writable: true},
+    usage: {value: internalOptions.usage, writable: true}
+  });
+
+  var internalCollator = %CreateCollator(requestedLocale,
+                                         internalOptions,
+                                         resolved);
+
+  // Writable, configurable and enumerable are set to false by default.
+  Object.defineProperty(collator, 'collator', {value: internalCollator});
+  Object.defineProperty(collator, '__initializedIntlObject',
+                        {value: 'collator'});
+  Object.defineProperty(collator, 'resolved', {value: resolved});
+
+  return collator;
+}
+
+
+/**
+ * Constructs Intl.Collator object given optional locales and options
+ * parameters.
+ *
+ * @constructor
+ */
+%SetProperty(Intl, 'Collator', function() {
+    var locales = arguments[0];
+    var options = arguments[1];
+
+    if (!this || this === Intl) {
+      // Constructor is called as a function.
+      return new Intl.Collator(locales, options);
+    }
+
+    return initializeCollator(toObject(this), locales, options);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+
+
+/**
+ * Collator resolvedOptions method.
+ */
+%SetProperty(Intl.Collator.prototype, 'resolvedOptions', function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    if (!this || typeof this !== 'object' ||
+        this.__initializedIntlObject !== 'collator') {
+      throw new TypeError('resolvedOptions method called on a non-object ' +
+                          'or on a object that is not Intl.Collator.');
+    }
+
+    var coll = this;
+    var locale = getOptimalLanguageTag(coll.resolved.requestedLocale,
+                                       coll.resolved.locale);
+
+    return {
+      locale: locale,
+      usage: coll.resolved.usage,
+      sensitivity: coll.resolved.sensitivity,
+      ignorePunctuation: coll.resolved.ignorePunctuation,
+      numeric: coll.resolved.numeric,
+      caseFirst: coll.resolved.caseFirst,
+      collation: coll.resolved.collation
+    };
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.Collator.prototype.resolvedOptions, 'resolvedOptions');
+%FunctionRemovePrototype(Intl.Collator.prototype.resolvedOptions);
+%SetNativeFlag(Intl.Collator.prototype.resolvedOptions);
+
+
+/**
+ * Returns the subset of the given locale list for which this locale list
+ * has a matching (possibly fallback) locale. Locales appear in the same
+ * order in the returned list as in the input list.
+ * Options are optional parameter.
+ */
+%SetProperty(Intl.Collator, 'supportedLocalesOf', function(locales) {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    return supportedLocalesOf('collator', locales, arguments[1]);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.Collator.supportedLocalesOf, 'supportedLocalesOf');
+%FunctionRemovePrototype(Intl.Collator.supportedLocalesOf);
+%SetNativeFlag(Intl.Collator.supportedLocalesOf);
+
+
+/**
+ * When the compare method is called with two arguments x and y, it returns a
+ * Number other than NaN that represents the result of a locale-sensitive
+ * String comparison of x with y.
+ * The result is intended to order String values in the sort order specified
+ * by the effective locale and collation options computed during construction
+ * of this Collator object, and will be negative, zero, or positive, depending
+ * on whether x comes before y in the sort order, the Strings are equal under
+ * the sort order, or x comes after y in the sort order, respectively.
+ */
+function compare(collator, x, y) {
+  return %InternalCompare(collator.collator, String(x), String(y));
+};
+
+
+addBoundMethod(Intl.Collator, 'compare', compare, 2);
diff --git a/src/extensions/i18n/date-format.js b/src/extensions/i18n/date-format.js
new file mode 100644
index 0000000..b1d28e5
--- /dev/null
+++ b/src/extensions/i18n/date-format.js
@@ -0,0 +1,474 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+/**
+ * Returns a string that matches LDML representation of the options object.
+ */
+function toLDMLString(options) {
+  var getOption = getGetOption(options, 'dateformat');
+
+  var ldmlString = '';
+
+  var option = getOption('weekday', 'string', ['narrow', 'short', 'long']);
+  ldmlString += appendToLDMLString(
+      option, {narrow: 'EEEEE', short: 'EEE', long: 'EEEE'});
+
+  option = getOption('era', 'string', ['narrow', 'short', 'long']);
+  ldmlString += appendToLDMLString(
+      option, {narrow: 'GGGGG', short: 'GGG', long: 'GGGG'});
+
+  option = getOption('year', 'string', ['2-digit', 'numeric']);
+  ldmlString += appendToLDMLString(option, {'2-digit': 'yy', 'numeric': 'y'});
+
+  option = getOption('month', 'string',
+                     ['2-digit', 'numeric', 'narrow', 'short', 'long']);
+  ldmlString += appendToLDMLString(option, {'2-digit': 'MM', 'numeric': 'M',
+          'narrow': 'MMMMM', 'short': 'MMM', 'long': 'MMMM'});
+
+  option = getOption('day', 'string', ['2-digit', 'numeric']);
+  ldmlString += appendToLDMLString(
+      option, {'2-digit': 'dd', 'numeric': 'd'});
+
+  var hr12 = getOption('hour12', 'boolean');
+  option = getOption('hour', 'string', ['2-digit', 'numeric']);
+  if (hr12 === undefined) {
+    ldmlString += appendToLDMLString(option, {'2-digit': 'jj', 'numeric': 'j'});
+  } else if (hr12 === true) {
+    ldmlString += appendToLDMLString(option, {'2-digit': 'hh', 'numeric': 'h'});
+  } else {
+    ldmlString += appendToLDMLString(option, {'2-digit': 'HH', 'numeric': 'H'});
+  }
+
+  option = getOption('minute', 'string', ['2-digit', 'numeric']);
+  ldmlString += appendToLDMLString(option, {'2-digit': 'mm', 'numeric': 'm'});
+
+  option = getOption('second', 'string', ['2-digit', 'numeric']);
+  ldmlString += appendToLDMLString(option, {'2-digit': 'ss', 'numeric': 's'});
+
+  option = getOption('timeZoneName', 'string', ['short', 'long']);
+  ldmlString += appendToLDMLString(option, {short: 'v', long: 'vv'});
+
+  return ldmlString;
+}
+
+
+/**
+ * Returns either LDML equivalent of the current option or empty string.
+ */
+function appendToLDMLString(option, pairs) {
+  if (option !== undefined) {
+    return pairs[option];
+  } else {
+    return '';
+  }
+}
+
+
+/**
+ * Returns object that matches LDML representation of the date.
+ */
+function fromLDMLString(ldmlString) {
+  // First remove '' quoted text, so we lose 'Uhr' strings.
+  ldmlString = ldmlString.replace(QUOTED_STRING_RE, '');
+
+  var options = {};
+  var match = ldmlString.match(/E{3,5}/g);
+  options = appendToDateTimeObject(
+      options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'});
+
+  match = ldmlString.match(/G{3,5}/g);
+  options = appendToDateTimeObject(
+      options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'});
+
+  match = ldmlString.match(/y{1,2}/g);
+  options = appendToDateTimeObject(
+      options, 'year', match, {y: 'numeric', yy: '2-digit'});
+
+  match = ldmlString.match(/M{1,5}/g);
+  options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit',
+      M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'});
+
+  // Sometimes we get L instead of M for month - standalone name.
+  match = ldmlString.match(/L{1,5}/g);
+  options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit',
+      L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'});
+
+  match = ldmlString.match(/d{1,2}/g);
+  options = appendToDateTimeObject(
+      options, 'day', match, {d: 'numeric', dd: '2-digit'});
+
+  match = ldmlString.match(/h{1,2}/g);
+  if (match !== null) {
+    options['hour12'] = true;
+  }
+  options = appendToDateTimeObject(
+      options, 'hour', match, {h: 'numeric', hh: '2-digit'});
+
+  match = ldmlString.match(/H{1,2}/g);
+  if (match !== null) {
+    options['hour12'] = false;
+  }
+  options = appendToDateTimeObject(
+      options, 'hour', match, {H: 'numeric', HH: '2-digit'});
+
+  match = ldmlString.match(/m{1,2}/g);
+  options = appendToDateTimeObject(
+      options, 'minute', match, {m: 'numeric', mm: '2-digit'});
+
+  match = ldmlString.match(/s{1,2}/g);
+  options = appendToDateTimeObject(
+      options, 'second', match, {s: 'numeric', ss: '2-digit'});
+
+  match = ldmlString.match(/v{1,2}/g);
+  options = appendToDateTimeObject(
+      options, 'timeZoneName', match, {v: 'short', vv: 'long'});
+
+  return options;
+}
+
+
+function appendToDateTimeObject(options, option, match, pairs) {
+  if (match === null) {
+    if (!options.hasOwnProperty(option)) {
+      defineWEProperty(options, option, undefined);
+    }
+    return options;
+  }
+
+  var property = match[0];
+  defineWEProperty(options, option, pairs[property]);
+
+  return options;
+}
+
+
+/**
+ * Returns options with at least default values in it.
+ */
+function toDateTimeOptions(options, required, defaults) {
+  if (options === undefined) {
+    options = null;
+  } else {
+    options = toObject(options);
+  }
+
+  options = Object.apply(this, [options]);
+
+  var needsDefault = true;
+  if ((required === 'date' || required === 'any') &&
+      (options.weekday !== undefined || options.year !== undefined ||
+       options.month !== undefined || options.day !== undefined)) {
+    needsDefault = false;
+  }
+
+  if ((required === 'time' || required === 'any') &&
+      (options.hour !== undefined || options.minute !== undefined ||
+       options.second !== undefined)) {
+    needsDefault = false;
+  }
+
+  if (needsDefault && (defaults === 'date' || defaults === 'all')) {
+    Object.defineProperty(options, 'year', {value: 'numeric',
+                                            writable: true,
+                                            enumerable: true,
+                                            configurable: true});
+    Object.defineProperty(options, 'month', {value: 'numeric',
+                                             writable: true,
+                                             enumerable: true,
+                                             configurable: true});
+    Object.defineProperty(options, 'day', {value: 'numeric',
+                                           writable: true,
+                                           enumerable: true,
+                                           configurable: true});
+  }
+
+  if (needsDefault && (defaults === 'time' || defaults === 'all')) {
+    Object.defineProperty(options, 'hour', {value: 'numeric',
+                                            writable: true,
+                                            enumerable: true,
+                                            configurable: true});
+    Object.defineProperty(options, 'minute', {value: 'numeric',
+                                              writable: true,
+                                              enumerable: true,
+                                              configurable: true});
+    Object.defineProperty(options, 'second', {value: 'numeric',
+                                              writable: true,
+                                              enumerable: true,
+                                              configurable: true});
+  }
+
+  return options;
+}
+
+
+/**
+ * Initializes the given object so it's a valid DateTimeFormat instance.
+ * Useful for subclassing.
+ */
+function initializeDateTimeFormat(dateFormat, locales, options) {
+
+  if (dateFormat.hasOwnProperty('__initializedIntlObject')) {
+    throw new TypeError('Trying to re-initialize DateTimeFormat object.');
+  }
+
+  if (options === undefined) {
+    options = {};
+  }
+
+  var locale = resolveLocale('dateformat', locales, options);
+
+  options = toDateTimeOptions(options, 'any', 'date');
+
+  var getOption = getGetOption(options, 'dateformat');
+
+  // We implement only best fit algorithm, but still need to check
+  // if the formatMatcher values are in range.
+  var matcher = getOption('formatMatcher', 'string',
+                          ['basic', 'best fit'], 'best fit');
+
+  // Build LDML string for the skeleton that we pass to the formatter.
+  var ldmlString = toLDMLString(options);
+
+  // Filter out supported extension keys so we know what to put in resolved
+  // section later on.
+  // We need to pass calendar and number system to the method.
+  var tz = canonicalizeTimeZoneID(options.timeZone);
+
+  // ICU prefers options to be passed using -u- extension key/values, so
+  // we need to build that.
+  var internalOptions = {};
+  var extensionMap = parseExtension(locale.extension);
+  var extension = setOptions(options, extensionMap, DATETIME_FORMAT_KEY_MAP,
+                             getOption, internalOptions);
+
+  var requestedLocale = locale.locale + extension;
+  var resolved = Object.defineProperties({}, {
+    calendar: {writable: true},
+    day: {writable: true},
+    era: {writable: true},
+    hour12: {writable: true},
+    hour: {writable: true},
+    locale: {writable: true},
+    minute: {writable: true},
+    month: {writable: true},
+    numberingSystem: {writable: true},
+    pattern: {writable: true},
+    requestedLocale: {value: requestedLocale, writable: true},
+    second: {writable: true},
+    timeZone: {writable: true},
+    timeZoneName: {writable: true},
+    tz: {value: tz, writable: true},
+    weekday: {writable: true},
+    year: {writable: true}
+  });
+
+  var formatter = %CreateDateTimeFormat(
+    requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved);
+
+  if (tz !== undefined && tz !== resolved.timeZone) {
+    throw new RangeError('Unsupported time zone specified ' + tz);
+  }
+
+  Object.defineProperty(dateFormat, 'formatter', {value: formatter});
+  Object.defineProperty(dateFormat, 'resolved', {value: resolved});
+  Object.defineProperty(dateFormat, '__initializedIntlObject',
+                        {value: 'dateformat'});
+
+  return dateFormat;
+}
+
+
+/**
+ * Constructs Intl.DateTimeFormat object given optional locales and options
+ * parameters.
+ *
+ * @constructor
+ */
+%SetProperty(Intl, 'DateTimeFormat', function() {
+    var locales = arguments[0];
+    var options = arguments[1];
+
+    if (!this || this === Intl) {
+      // Constructor is called as a function.
+      return new Intl.DateTimeFormat(locales, options);
+    }
+
+    return initializeDateTimeFormat(toObject(this), locales, options);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+
+
+/**
+ * DateTimeFormat resolvedOptions method.
+ */
+%SetProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    if (!this || typeof this !== 'object' ||
+        this.__initializedIntlObject !== 'dateformat') {
+      throw new TypeError('resolvedOptions method called on a non-object or ' +
+          'on a object that is not Intl.DateTimeFormat.');
+    }
+
+    var format = this;
+    var fromPattern = fromLDMLString(format.resolved.pattern);
+    var userCalendar = ICU_CALENDAR_MAP[format.resolved.calendar];
+    if (userCalendar === undefined) {
+      // Use ICU name if we don't have a match. It shouldn't happen, but
+      // it would be too strict to throw for this.
+      userCalendar = format.resolved.calendar;
+    }
+
+    var locale = getOptimalLanguageTag(format.resolved.requestedLocale,
+                                       format.resolved.locale);
+
+    var result = {
+      locale: locale,
+      numberingSystem: format.resolved.numberingSystem,
+      calendar: userCalendar,
+      timeZone: format.resolved.timeZone
+    };
+
+    addWECPropertyIfDefined(result, 'timeZoneName', fromPattern.timeZoneName);
+    addWECPropertyIfDefined(result, 'era', fromPattern.era);
+    addWECPropertyIfDefined(result, 'year', fromPattern.year);
+    addWECPropertyIfDefined(result, 'month', fromPattern.month);
+    addWECPropertyIfDefined(result, 'day', fromPattern.day);
+    addWECPropertyIfDefined(result, 'weekday', fromPattern.weekday);
+    addWECPropertyIfDefined(result, 'hour12', fromPattern.hour12);
+    addWECPropertyIfDefined(result, 'hour', fromPattern.hour);
+    addWECPropertyIfDefined(result, 'minute', fromPattern.minute);
+    addWECPropertyIfDefined(result, 'second', fromPattern.second);
+
+    return result;
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.DateTimeFormat.prototype.resolvedOptions,
+                 'resolvedOptions');
+%FunctionRemovePrototype(Intl.DateTimeFormat.prototype.resolvedOptions);
+%SetNativeFlag(Intl.DateTimeFormat.prototype.resolvedOptions);
+
+
+/**
+ * Returns the subset of the given locale list for which this locale list
+ * has a matching (possibly fallback) locale. Locales appear in the same
+ * order in the returned list as in the input list.
+ * Options are optional parameter.
+ */
+%SetProperty(Intl.DateTimeFormat, 'supportedLocalesOf', function(locales) {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    return supportedLocalesOf('dateformat', locales, arguments[1]);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.DateTimeFormat.supportedLocalesOf, 'supportedLocalesOf');
+%FunctionRemovePrototype(Intl.DateTimeFormat.supportedLocalesOf);
+%SetNativeFlag(Intl.DateTimeFormat.supportedLocalesOf);
+
+
+/**
+ * Returns a String value representing the result of calling ToNumber(date)
+ * according to the effective locale and the formatting options of this
+ * DateTimeFormat.
+ */
+function formatDate(formatter, dateValue) {
+  var dateMs;
+  if (dateValue === undefined) {
+    dateMs = Date.now();
+  } else {
+    dateMs = Number(dateValue);
+  }
+
+  if (!isFinite(dateMs)) {
+    throw new RangeError('Provided date is not in valid range.');
+  }
+
+  return %InternalDateFormat(formatter.formatter, new Date(dateMs));
+}
+
+
+/**
+ * Returns a Date object representing the result of calling ToString(value)
+ * according to the effective locale and the formatting options of this
+ * DateTimeFormat.
+ * Returns undefined if date string cannot be parsed.
+ */
+function parseDate(formatter, value) {
+  return %InternalDateParse(formatter.formatter, String(value));
+}
+
+
+// 0 because date is optional argument.
+addBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0);
+addBoundMethod(Intl.DateTimeFormat, 'v8Parse', parseDate, 1);
+
+
+/**
+ * Returns canonical Area/Location name, or throws an exception if the zone
+ * name is invalid IANA name.
+ */
+function canonicalizeTimeZoneID(tzID) {
+  // Skip undefined zones.
+  if (tzID === undefined) {
+    return tzID;
+  }
+
+  // Special case handling (UTC, GMT).
+  var upperID = tzID.toUpperCase();
+  if (upperID === 'UTC' || upperID === 'GMT' ||
+      upperID === 'ETC/UTC' || upperID === 'ETC/GMT') {
+    return 'UTC';
+  }
+
+  // We expect only _ and / beside ASCII letters.
+  // All inputs should conform to Area/Location from now on.
+  var match = TIMEZONE_NAME_CHECK_RE.exec(tzID);
+  if (match === null) {
+    throw new RangeError('Expected Area/Location for time zone, got ' + tzID);
+  }
+
+  var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]);
+  var i = 3;
+  while (match[i] !== undefined && i < match.length) {
+    result = result + '_' + toTitleCaseWord(match[i]);
+    i++;
+  }
+
+  return result;
+}
diff --git a/src/extensions/i18n/footer.js b/src/extensions/i18n/footer.js
new file mode 100644
index 0000000..ac33f1e
--- /dev/null
+++ b/src/extensions/i18n/footer.js
@@ -0,0 +1,40 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+// Fix RegExp global state so we don't fail WebKit layout test:
+// fast/js/regexp-caching.html
+// It seems that 'g' or test() operations leave state changed.
+var CLEANUP_RE = new RegExp('');
+CLEANUP_RE.test('');
+
+return Intl;
+}());
diff --git a/src/extensions/i18n/globals.js b/src/extensions/i18n/globals.js
new file mode 100644
index 0000000..68fabe7
--- /dev/null
+++ b/src/extensions/i18n/globals.js
@@ -0,0 +1,168 @@
+// 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.
+// limitations under the License.
+
+
+/**
+ * List of available services.
+ */
+var AVAILABLE_SERVICES = ['collator',
+                          'numberformat',
+                          'dateformat',
+                          'breakiterator'];
+
+/**
+ * Caches available locales for each service.
+ */
+var AVAILABLE_LOCALES = {
+  'collator': undefined,
+  'numberformat': undefined,
+  'dateformat': undefined,
+  'breakiterator': undefined
+};
+
+/**
+ * Caches default ICU locale.
+ */
+var DEFAULT_ICU_LOCALE = undefined;
+
+/**
+ * Unicode extension regular expression.
+ */
+var UNICODE_EXTENSION_RE = new RegExp('-u(-[a-z0-9]{2,8})+', 'g');
+
+/**
+ * Matches any Unicode extension.
+ */
+var ANY_EXTENSION_RE = new RegExp('-[a-z0-9]{1}-.*', 'g');
+
+/**
+ * Replace quoted text (single quote, anything but the quote and quote again).
+ */
+var QUOTED_STRING_RE = new RegExp("'[^']+'", 'g');
+
+/**
+ * Matches valid service name.
+ */
+var SERVICE_RE =
+    new RegExp('^(collator|numberformat|dateformat|breakiterator)$');
+
+/**
+ * Validates a language tag against bcp47 spec.
+ * Actual value is assigned on first run.
+ */
+var LANGUAGE_TAG_RE = undefined;
+
+/**
+ * Helps find duplicate variants in the language tag.
+ */
+var LANGUAGE_VARIANT_RE = undefined;
+
+/**
+ * Helps find duplicate singletons in the language tag.
+ */
+var LANGUAGE_SINGLETON_RE = undefined;
+
+/**
+ * Matches valid IANA time zone names.
+ */
+var TIMEZONE_NAME_CHECK_RE =
+    new RegExp('^([A-Za-z]+)/([A-Za-z]+)(?:_([A-Za-z]+))*$');
+
+/**
+ * Maps ICU calendar names into LDML type.
+ */
+var ICU_CALENDAR_MAP = {
+  'gregorian': 'gregory',
+  'japanese': 'japanese',
+  'buddhist': 'buddhist',
+  'roc': 'roc',
+  'persian': 'persian',
+  'islamic-civil': 'islamicc',
+  'islamic': 'islamic',
+  'hebrew': 'hebrew',
+  'chinese': 'chinese',
+  'indian': 'indian',
+  'coptic': 'coptic',
+  'ethiopic': 'ethiopic',
+  'ethiopic-amete-alem': 'ethioaa'
+};
+
+/**
+ * Map of Unicode extensions to option properties, and their values and types,
+ * for a collator.
+ */
+var COLLATOR_KEY_MAP = {
+  'kn': {'property': 'numeric', 'type': 'boolean'},
+  'kf': {'property': 'caseFirst', 'type': 'string',
+         'values': ['false', 'lower', 'upper']}
+};
+
+/**
+ * Map of Unicode extensions to option properties, and their values and types,
+ * for a number format.
+ */
+var NUMBER_FORMAT_KEY_MAP = {
+  'nu': {'property': undefined, 'type': 'string'}
+};
+
+/**
+ * Map of Unicode extensions to option properties, and their values and types,
+ * for a date/time format.
+ */
+var DATETIME_FORMAT_KEY_MAP = {
+  'ca': {'property': undefined, 'type': 'string'},
+  'nu': {'property': undefined, 'type': 'string'}
+};
+
+/**
+ * Allowed -u-co- values. List taken from:
+ * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
+ */
+var ALLOWED_CO_VALUES = [
+  'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic',
+  'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin'
+];
+
+/**
+ * Object attributes (configurable, writable, enumerable).
+ * To combine attributes, OR them.
+ * Values/names are copied from v8/include/v8.h:PropertyAttribute
+ */
+var ATTRIBUTES = {
+  'NONE': 0,
+  'READ_ONLY': 1,
+  'DONT_ENUM': 2,
+  'DONT_DELETE': 4
+};
+
+/**
+ * Error message for when function object is created with new and it's not
+ * a constructor.
+ */
+var ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR =
+  'Function object that\'s not a constructor was created with new';
diff --git a/src/extensions/i18n/header.js b/src/extensions/i18n/header.js
new file mode 100644
index 0000000..1c0a2d8
--- /dev/null
+++ b/src/extensions/i18n/header.js
@@ -0,0 +1,41 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+/**
+ * Intl object is a single object that has some named properties,
+ * all of which are constructors.
+ */
+var Intl = (function() {
+
+'use strict';
+
+var Intl = {};
diff --git a/src/extensions/i18n/i18n-extension.cc b/src/extensions/i18n/i18n-extension.cc
new file mode 100644
index 0000000..b5f2863
--- /dev/null
+++ b/src/extensions/i18n/i18n-extension.cc
@@ -0,0 +1,51 @@
+// 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.
+// limitations under the License.
+
+#include "i18n-extension.h"
+
+#include "natives.h"
+
+using v8::internal::I18NNatives;
+
+namespace v8_i18n {
+
+Extension::Extension()
+    : v8::Extension("v8/i18n",
+                    reinterpret_cast<const char*>(
+                        I18NNatives::GetScriptsSource().start()),
+                    0,
+                    0,
+                    I18NNatives::GetScriptsSource().length()) {}
+
+
+void Extension::Register() {
+  static Extension i18n_extension;
+  static v8::DeclareExtension extension_declaration(&i18n_extension);
+}
+
+}  // namespace v8_i18n
diff --git a/src/extensions/i18n/i18n-extension.h b/src/extensions/i18n/i18n-extension.h
new file mode 100644
index 0000000..9e538cb
--- /dev/null
+++ b/src/extensions/i18n/i18n-extension.h
@@ -0,0 +1,48 @@
+// 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.
+// limitations under the License.
+
+#ifndef V8_EXTENSIONS_I18N_I18N_EXTENSION_H_
+#define V8_EXTENSIONS_I18N_I18N_EXTENSION_H_
+
+#include "v8.h"
+
+namespace v8_i18n {
+
+class Extension : public v8::Extension {
+ public:
+  Extension();
+
+  static void Register();
+
+ private:
+  static Extension* extension_;
+};
+
+}  // namespace v8_i18n
+
+#endif  // V8_EXTENSIONS_I18N_I18N_EXTENSION_H_
diff --git a/src/extensions/i18n/i18n-utils.js b/src/extensions/i18n/i18n-utils.js
new file mode 100644
index 0000000..545082e
--- /dev/null
+++ b/src/extensions/i18n/i18n-utils.js
@@ -0,0 +1,536 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+/**
+ * Adds bound method to the prototype of the given object.
+ */
+function addBoundMethod(obj, methodName, implementation, length) {
+  function getter() {
+    if (!this || typeof this !== 'object' ||
+        this.__initializedIntlObject === undefined) {
+        throw new TypeError('Method ' + methodName + ' called on a ' +
+                            'non-object or on a wrong type of object.');
+    }
+    var internalName = '__bound' + methodName + '__';
+    if (this[internalName] === undefined) {
+      var that = this;
+      var boundMethod;
+      if (length === undefined || length === 2) {
+        boundMethod = function(x, y) {
+          if (%_IsConstructCall()) {
+            throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+          }
+          return implementation(that, x, y);
+        }
+      } else if (length === 1) {
+        boundMethod = function(x) {
+          if (%_IsConstructCall()) {
+            throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+          }
+          return implementation(that, x);
+        }
+      } else {
+        boundMethod = function() {
+          if (%_IsConstructCall()) {
+            throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+          }
+          // DateTimeFormat.format needs to be 0 arg method, but can stil
+          // receive optional dateValue param. If one was provided, pass it
+          // along.
+          if (arguments.length > 0) {
+            return implementation(that, arguments[0]);
+          } else {
+            return implementation(that);
+          }
+        }
+      }
+      %FunctionSetName(boundMethod, internalName);
+      %FunctionRemovePrototype(boundMethod);
+      %SetNativeFlag(boundMethod);
+      this[internalName] = boundMethod;
+    }
+    return this[internalName];
+  }
+
+  %FunctionSetName(getter, methodName);
+  %FunctionRemovePrototype(getter);
+  %SetNativeFlag(getter);
+
+  Object.defineProperty(obj.prototype, methodName, {
+    get: getter,
+    enumerable: false,
+    configurable: true
+  });
+}
+
+
+/**
+ * Returns an intersection of locales and service supported locales.
+ * Parameter locales is treated as a priority list.
+ */
+function supportedLocalesOf(service, locales, options) {
+  if (service.match(SERVICE_RE) === null) {
+    throw new Error('Internal error, wrong service type: ' + service);
+  }
+
+  // Provide defaults if matcher was not specified.
+  if (options === undefined) {
+    options = {};
+  } else {
+    options = toObject(options);
+  }
+
+  var matcher = options.localeMatcher;
+  if (matcher !== undefined) {
+    matcher = String(matcher);
+    if (matcher !== 'lookup' && matcher !== 'best fit') {
+      throw new RangeError('Illegal value for localeMatcher:' + matcher);
+    }
+  } else {
+    matcher = 'best fit';
+  }
+
+  var requestedLocales = initializeLocaleList(locales);
+
+  // Cache these, they don't ever change per service.
+  if (AVAILABLE_LOCALES[service] === undefined) {
+    AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
+  }
+
+  // Use either best fit or lookup algorithm to match locales.
+  if (matcher === 'best fit') {
+    return initializeLocaleList(bestFitSupportedLocalesOf(
+        requestedLocales, AVAILABLE_LOCALES[service]));
+  }
+
+  return initializeLocaleList(lookupSupportedLocalesOf(
+      requestedLocales, AVAILABLE_LOCALES[service]));
+}
+
+
+/**
+ * Returns the subset of the provided BCP 47 language priority list for which
+ * this service has a matching locale when using the BCP 47 Lookup algorithm.
+ * Locales appear in the same order in the returned list as in the input list.
+ */
+function lookupSupportedLocalesOf(requestedLocales, availableLocales) {
+  var matchedLocales = [];
+  for (var i = 0; i < requestedLocales.length; ++i) {
+    // Remove -u- extension.
+    var locale = requestedLocales[i].replace(UNICODE_EXTENSION_RE, '');
+    do {
+      if (availableLocales[locale] !== undefined) {
+        // Push requested locale not the resolved one.
+        matchedLocales.push(requestedLocales[i]);
+        break;
+      }
+      // Truncate locale if possible, if not break.
+      var pos = locale.lastIndexOf('-');
+      if (pos === -1) {
+        break;
+      }
+      locale = locale.substring(0, pos);
+    } while (true);
+  }
+
+  return matchedLocales;
+}
+
+
+/**
+ * Returns the subset of the provided BCP 47 language priority list for which
+ * this service has a matching locale when using the implementation
+ * dependent algorithm.
+ * Locales appear in the same order in the returned list as in the input list.
+ */
+function bestFitSupportedLocalesOf(requestedLocales, availableLocales) {
+  // TODO(cira): implement better best fit algorithm.
+  return lookupSupportedLocalesOf(requestedLocales, availableLocales);
+}
+
+
+/**
+ * Returns a getOption function that extracts property value for given
+ * options object. If property is missing it returns defaultValue. If value
+ * is out of range for that property it throws RangeError.
+ */
+function getGetOption(options, caller) {
+  if (options === undefined) {
+    throw new Error('Internal ' + caller + ' error. ' +
+                    'Default options are missing.');
+  }
+
+  var getOption = function getOption(property, type, values, defaultValue) {
+    if (options[property] !== undefined) {
+      var value = options[property];
+      switch (type) {
+        case 'boolean':
+          value = Boolean(value);
+          break;
+        case 'string':
+          value = String(value);
+          break;
+        case 'number':
+          value = Number(value);
+          break;
+        default:
+          throw new Error('Internal error. Wrong value type.');
+      }
+      if (values !== undefined && values.indexOf(value) === -1) {
+        throw new RangeError('Value ' + value + ' out of range for ' + caller +
+                             ' options property ' + property);
+      }
+
+      return value;
+    }
+
+    return defaultValue;
+  }
+
+  return getOption;
+}
+
+
+/**
+ * Compares a BCP 47 language priority list requestedLocales against the locales
+ * in availableLocales and determines the best available language to meet the
+ * request. Two algorithms are available to match the locales: the Lookup
+ * algorithm described in RFC 4647 section 3.4, and an implementation dependent
+ * best-fit algorithm. Independent of the locale matching algorithm, options
+ * specified through Unicode locale extension sequences are negotiated
+ * separately, taking the caller's relevant extension keys and locale data as
+ * well as client-provided options into consideration. Returns an object with
+ * a locale property whose value is the language tag of the selected locale,
+ * and properties for each key in relevantExtensionKeys providing the selected
+ * value for that key.
+ */
+function resolveLocale(service, requestedLocales, options) {
+  requestedLocales = initializeLocaleList(requestedLocales);
+
+  var getOption = getGetOption(options, service);
+  var matcher = getOption('localeMatcher', 'string',
+                          ['lookup', 'best fit'], 'best fit');
+  var resolved;
+  if (matcher === 'lookup') {
+    resolved = lookupMatcher(service, requestedLocales);
+  } else {
+    resolved = bestFitMatcher(service, requestedLocales);
+  }
+
+  return resolved;
+}
+
+
+/**
+ * Returns best matched supported locale and extension info using basic
+ * lookup algorithm.
+ */
+function lookupMatcher(service, requestedLocales) {
+  if (service.match(SERVICE_RE) === null) {
+    throw new Error('Internal error, wrong service type: ' + service);
+  }
+
+  // Cache these, they don't ever change per service.
+  if (AVAILABLE_LOCALES[service] === undefined) {
+    AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
+  }
+
+  for (var i = 0; i < requestedLocales.length; ++i) {
+    // Remove all extensions.
+    var locale = requestedLocales[i].replace(ANY_EXTENSION_RE, '');
+    do {
+      if (AVAILABLE_LOCALES[service][locale] !== undefined) {
+        // Return the resolved locale and extension.
+        var extensionMatch = requestedLocales[i].match(UNICODE_EXTENSION_RE);
+        var extension = (extensionMatch === null) ? '' : extensionMatch[0];
+        return {'locale': locale, 'extension': extension, 'position': i};
+      }
+      // Truncate locale if possible.
+      var pos = locale.lastIndexOf('-');
+      if (pos === -1) {
+        break;
+      }
+      locale = locale.substring(0, pos);
+    } while (true);
+  }
+
+  // Didn't find a match, return default.
+  if (DEFAULT_ICU_LOCALE === undefined) {
+    DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
+  }
+
+  return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
+}
+
+
+/**
+ * Returns best matched supported locale and extension info using
+ * implementation dependend algorithm.
+ */
+function bestFitMatcher(service, requestedLocales) {
+  // TODO(cira): implement better best fit algorithm.
+  return lookupMatcher(service, requestedLocales);
+}
+
+
+/**
+ * Parses Unicode extension into key - value map.
+ * Returns empty object if the extension string is invalid.
+ * We are not concerned with the validity of the values at this point.
+ */
+function parseExtension(extension) {
+  var extensionSplit = extension.split('-');
+
+  // Assume ['', 'u', ...] input, but don't throw.
+  if (extensionSplit.length <= 2 ||
+      (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) {
+    return {};
+  }
+
+  // Key is {2}alphanum, value is {3,8}alphanum.
+  // Some keys may not have explicit values (booleans).
+  var extensionMap = {};
+  var previousKey = undefined;
+  for (var i = 2; i < extensionSplit.length; ++i) {
+    var length = extensionSplit[i].length;
+    var element = extensionSplit[i];
+    if (length === 2) {
+      extensionMap[element] = undefined;
+      previousKey = element;
+    } else if (length >= 3 && length <=8 && previousKey !== undefined) {
+      extensionMap[previousKey] = element;
+      previousKey = undefined;
+    } else {
+      // There is a value that's too long, or that doesn't have a key.
+      return {};
+    }
+  }
+
+  return extensionMap;
+}
+
+
+/**
+ * Converts parameter to an Object if possible.
+ */
+function toObject(value) {
+  if (value === undefined || value === null) {
+    throw new TypeError('Value cannot be converted to an Object.');
+  }
+
+  return Object(value);
+}
+
+
+/**
+ * Populates internalOptions object with boolean key-value pairs
+ * from extensionMap and options.
+ * Returns filtered extension (number and date format constructors use
+ * Unicode extensions for passing parameters to ICU).
+ * It's used for extension-option pairs only, e.g. kn-normalization, but not
+ * for 'sensitivity' since it doesn't have extension equivalent.
+ * Extensions like nu and ca don't have options equivalent, so we place
+ * undefined in the map.property to denote that.
+ */
+function setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) {
+  var extension = '';
+
+  var updateExtension = function updateExtension(key, value) {
+    return '-' + key + '-' + String(value);
+  }
+
+  var updateProperty = function updateProperty(property, type, value) {
+    if (type === 'boolean' && (typeof value === 'string')) {
+      value = (value === 'true') ? true : false;
+    }
+
+    if (property !== undefined) {
+      defineWEProperty(outOptions, property, value);
+    }
+  }
+
+  for (var key in keyValues) {
+    if (keyValues.hasOwnProperty(key)) {
+      var value = undefined;
+      var map = keyValues[key];
+      if (map.property !== undefined) {
+        // This may return true if user specifies numeric: 'false', since
+        // Boolean('nonempty') === true.
+        value = getOption(map.property, map.type, map.values);
+      }
+      if (value !== undefined) {
+        updateProperty(map.property, map.type, value);
+        extension += updateExtension(key, value);
+        continue;
+      }
+      // User options didn't have it, check Unicode extension.
+      // Here we want to convert strings 'true', 'false' into proper Boolean
+      // values (not a user error).
+      if (extensionMap.hasOwnProperty(key)) {
+        value = extensionMap[key];
+        if (value !== undefined) {
+          updateProperty(map.property, map.type, value);
+          extension += updateExtension(key, value);
+        } else if (map.type === 'boolean') {
+          // Boolean keys are allowed not to have values in Unicode extension.
+          // Those default to true.
+          updateProperty(map.property, map.type, true);
+          extension += updateExtension(key, true);
+        }
+      }
+    }
+  }
+
+  return extension === ''? '' : '-u' + extension;
+}
+
+
+/**
+ * Converts all OwnProperties into
+ * configurable: false, writable: false, enumerable: true.
+ */
+function freezeArray(array) {
+  array.forEach(function(element, index) {
+    Object.defineProperty(array, index, {value: element,
+                                         configurable: false,
+                                         writable: false,
+                                         enumerable: true});
+  });
+
+  Object.defineProperty(array, 'length', {value: array.length,
+                                          writable: false});
+
+  return array;
+}
+
+
+/**
+ * It's sometimes desireable to leave user requested locale instead of ICU
+ * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter
+ * one, if that was what user requested).
+ * This function returns user specified tag if its maximized form matches ICU
+ * resolved locale. If not we return ICU result.
+ */
+function getOptimalLanguageTag(original, resolved) {
+  // Returns Array<Object>, where each object has maximized and base properties.
+  // Maximized: zh -> zh-Hans-CN
+  // Base: zh-CN-u-ca-gregory -> zh-CN
+  // Take care of grandfathered or simple cases.
+  if (original === resolved) {
+    return original;
+  }
+
+  var locales = %GetLanguageTagVariants([original, resolved]);
+  if (locales[0].maximized !== locales[1].maximized) {
+    return resolved;
+  }
+
+  // Preserve extensions of resolved locale, but swap base tags with original.
+  var resolvedBase = new RegExp('^' + locales[1].base);
+  return resolved.replace(resolvedBase, locales[0].base);
+}
+
+
+/**
+ * Returns an Object that contains all of supported locales for a given
+ * service.
+ * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ
+ * that is supported. This is required by the spec.
+ */
+function getAvailableLocalesOf(service) {
+  var available = %AvailableLocalesOf(service);
+
+  for (var i in available) {
+    if (available.hasOwnProperty(i)) {
+      var parts = i.match(/^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/);
+      if (parts !== null) {
+        // Build xx-ZZ. We don't care about the actual value,
+        // as long it's not undefined.
+        available[parts[1] + '-' + parts[3]] = null;
+      }
+    }
+  }
+
+  return available;
+}
+
+
+/**
+ * Defines a property and sets writable and enumerable to true.
+ * Configurable is false by default.
+ */
+function defineWEProperty(object, property, value) {
+  Object.defineProperty(object, property,
+                        {value: value, writable: true, enumerable: true});
+}
+
+
+/**
+ * Adds property to an object if the value is not undefined.
+ * Sets configurable descriptor to false.
+ */
+function addWEPropertyIfDefined(object, property, value) {
+  if (value !== undefined) {
+    defineWEProperty(object, property, value);
+  }
+}
+
+
+/**
+ * Defines a property and sets writable, enumerable and configurable to true.
+ */
+function defineWECProperty(object, property, value) {
+  Object.defineProperty(object, property,
+                        {value: value,
+                         writable: true,
+                         enumerable: true,
+                         configurable: true});
+}
+
+
+/**
+ * Adds property to an object if the value is not undefined.
+ * Sets all descriptors to true.
+ */
+function addWECPropertyIfDefined(object, property, value) {
+  if (value !== undefined) {
+    defineWECProperty(object, property, value);
+  }
+}
+
+
+/**
+ * Returns titlecased word, aMeRricA -> America.
+ */
+function toTitleCaseWord(word) {
+  return word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase();
+}
diff --git a/src/extensions/i18n/locale.js b/src/extensions/i18n/locale.js
new file mode 100644
index 0000000..e478327
--- /dev/null
+++ b/src/extensions/i18n/locale.js
@@ -0,0 +1,190 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+/**
+ * Canonicalizes the language tag, or throws in case the tag is invalid.
+ */
+function canonicalizeLanguageTag(localeID) {
+  // null is typeof 'object' so we have to do extra check.
+  if (typeof localeID !== 'string' && typeof localeID !== 'object' ||
+      localeID === null) {
+    throw new TypeError('Language ID should be string or object.');
+  }
+
+  var localeString = String(localeID);
+
+  if (isValidLanguageTag(localeString) === false) {
+    throw new RangeError('Invalid language tag: ' + localeString);
+  }
+
+  // This call will strip -kn but not -kn-true extensions.
+  // ICU bug filled - http://bugs.icu-project.org/trac/ticket/9265.
+  // TODO(cira): check if -u-kn-true-kc-true-kh-true still throws after
+  // upgrade to ICU 4.9.
+  var tag = %CanonicalizeLanguageTag(localeString);
+  if (tag === 'invalid-tag') {
+    throw new RangeError('Invalid language tag: ' + localeString);
+  }
+
+  return tag;
+}
+
+
+/**
+ * Returns an array where all locales are canonicalized and duplicates removed.
+ * Throws on locales that are not well formed BCP47 tags.
+ */
+function initializeLocaleList(locales) {
+  var seen = [];
+  if (locales === undefined) {
+    // Constructor is called without arguments.
+    seen = [];
+  } else {
+    // We allow single string localeID.
+    if (typeof locales === 'string') {
+      seen.push(canonicalizeLanguageTag(locales));
+      return freezeArray(seen);
+    }
+
+    var o = toObject(locales);
+    // Converts it to UInt32 (>>> is shr on 32bit integers).
+    var len = o.length >>> 0;
+
+    for (var k = 0; k < len; k++) {
+      if (k in o) {
+        var value = o[k];
+
+        var tag = canonicalizeLanguageTag(value);
+
+        if (seen.indexOf(tag) === -1) {
+          seen.push(tag);
+        }
+      }
+    }
+  }
+
+  return freezeArray(seen);
+}
+
+
+/**
+ * Validates the language tag. Section 2.2.9 of the bcp47 spec
+ * defines a valid tag.
+ *
+ * ICU is too permissible and lets invalid tags, like
+ * hant-cmn-cn, through.
+ *
+ * Returns false if the language tag is invalid.
+ */
+function isValidLanguageTag(locale) {
+  // Check if it's well-formed, including grandfadered tags.
+  if (LANGUAGE_TAG_RE.test(locale) === false) {
+    return false;
+  }
+
+  // Just return if it's a x- form. It's all private.
+  if (locale.indexOf('x-') === 0) {
+    return true;
+  }
+
+  // Check if there are any duplicate variants or singletons (extensions).
+
+  // Remove private use section.
+  locale = locale.split(/-x-/)[0];
+
+  // Skip language since it can match variant regex, so we start from 1.
+  // We are matching i-klingon here, but that's ok, since i-klingon-klingon
+  // is not valid and would fail LANGUAGE_TAG_RE test.
+  var variants = [];
+  var extensions = [];
+  var parts = locale.split(/-/);
+  for (var i = 1; i < parts.length; i++) {
+    var value = parts[i];
+    if (LANGUAGE_VARIANT_RE.test(value) === true && extensions.length === 0) {
+      if (variants.indexOf(value) === -1) {
+        variants.push(value);
+      } else {
+        return false;
+      }
+    }
+
+    if (LANGUAGE_SINGLETON_RE.test(value) === true) {
+      if (extensions.indexOf(value) === -1) {
+        extensions.push(value);
+      } else {
+        return false;
+      }
+    }
+  }
+
+  return true;
+ }
+
+
+/**
+ * Builds a regular expresion that validates the language tag
+ * against bcp47 spec.
+ * Uses http://tools.ietf.org/html/bcp47, section 2.1, ABNF.
+ * Runs on load and initializes the global REs.
+ */
+(function() {
+  var alpha = '[a-zA-Z]';
+  var digit = '[0-9]';
+  var alphanum = '(' + alpha + '|' + digit + ')';
+  var regular = '(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|' +
+                'zh-min|zh-min-nan|zh-xiang)';
+  var irregular = '(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|' +
+                  'i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|' +
+                  'i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)';
+  var grandfathered = '(' + irregular + '|' + regular + ')';
+  var privateUse = '(x(-' + alphanum + '{1,8})+)';
+
+  var singleton = '(' + digit + '|[A-WY-Za-wy-z])';
+  LANGUAGE_SINGLETON_RE = new RegExp('^' + singleton + '$', 'i');
+
+  var extension = '(' + singleton + '(-' + alphanum + '{2,8})+)';
+
+  var variant = '(' + alphanum + '{5,8}|(' + digit + alphanum + '{3}))';
+  LANGUAGE_VARIANT_RE = new RegExp('^' + variant + '$', 'i');
+
+  var region = '(' + alpha + '{2}|' + digit + '{3})';
+  var script = '(' + alpha + '{4})';
+  var extLang = '(' + alpha + '{3}(-' + alpha + '{3}){0,2})';
+  var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' +
+                 alpha + '{5,8})';
+  var langTag = language + '(-' + script + ')?(-' + region + ')?(-' +
+                variant + ')*(-' + extension + ')*(-' + privateUse + ')?';
+
+  var languageTag =
+      '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$';
+  LANGUAGE_TAG_RE = new RegExp(languageTag, 'i');
+})();
diff --git a/src/extensions/i18n/number-format.js b/src/extensions/i18n/number-format.js
new file mode 100644
index 0000000..5722a5d
--- /dev/null
+++ b/src/extensions/i18n/number-format.js
@@ -0,0 +1,289 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+/**
+ * Verifies that the input is a well-formed ISO 4217 currency code.
+ * Don't uppercase to test. It could convert invalid code into a valid one.
+ * For example \u00DFP (Eszett+P) becomes SSP.
+ */
+function isWellFormedCurrencyCode(currency) {
+  return typeof currency == "string" &&
+      currency.length == 3 &&
+      currency.match(/[^A-Za-z]/) == null;
+}
+
+
+/**
+ * Returns the valid digit count for a property, or throws RangeError on
+ * a value out of the range.
+ */
+function getNumberOption(options, property, min, max, fallback) {
+  var value = options[property];
+  if (value !== undefined) {
+    value = Number(value);
+    if (isNaN(value) || value < min || value > max) {
+      throw new RangeError(property + ' value is out of range.');
+    }
+    return Math.floor(value);
+  }
+
+  return fallback;
+}
+
+
+/**
+ * Initializes the given object so it's a valid NumberFormat instance.
+ * Useful for subclassing.
+ */
+function initializeNumberFormat(numberFormat, locales, options) {
+  if (numberFormat.hasOwnProperty('__initializedIntlObject')) {
+    throw new TypeError('Trying to re-initialize NumberFormat object.');
+  }
+
+  if (options === undefined) {
+    options = {};
+  }
+
+  var getOption = getGetOption(options, 'numberformat');
+
+  var locale = resolveLocale('numberformat', locales, options);
+
+  var internalOptions = {};
+  defineWEProperty(internalOptions, 'style', getOption(
+    'style', 'string', ['decimal', 'percent', 'currency'], 'decimal'));
+
+  var currency = getOption('currency', 'string');
+  if (currency !== undefined && !isWellFormedCurrencyCode(currency)) {
+    throw new RangeError('Invalid currency code: ' + currency);
+  }
+
+  if (internalOptions.style === 'currency' && currency === undefined) {
+    throw new TypeError('Currency code is required with currency style.');
+  }
+
+  var currencyDisplay = getOption(
+      'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol');
+  if (internalOptions.style === 'currency') {
+    defineWEProperty(internalOptions, 'currency', currency.toUpperCase());
+    defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay);
+  }
+
+  // Digit ranges.
+  var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1);
+  defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
+
+  var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0);
+  defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
+
+  var mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, 3);
+  defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
+
+  var mnsd = options['minimumSignificantDigits'];
+  var mxsd = options['maximumSignificantDigits'];
+  if (mnsd !== undefined || mxsd !== undefined) {
+    mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 0);
+    defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
+
+    mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21);
+    defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
+  }
+
+  // Grouping.
+  defineWEProperty(internalOptions, 'useGrouping', getOption(
+    'useGrouping', 'boolean', undefined, true));
+
+  // ICU prefers options to be passed using -u- extension key/values for
+  // number format, so we need to build that.
+  var extensionMap = parseExtension(locale.extension);
+  var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP,
+                             getOption, internalOptions);
+
+  var requestedLocale = locale.locale + extension;
+  var resolved = Object.defineProperties({}, {
+    currency: {writable: true},
+    currencyDisplay: {writable: true},
+    locale: {writable: true},
+    maximumFractionDigits: {writable: true},
+    minimumFractionDigits: {writable: true},
+    minimumIntegerDigits: {writable: true},
+    numberingSystem: {writable: true},
+    requestedLocale: {value: requestedLocale, writable: true},
+    style: {value: internalOptions.style, writable: true},
+    useGrouping: {writable: true}
+  });
+  if (internalOptions.hasOwnProperty('minimumSignificantDigits')) {
+    defineWEProperty(resolved, 'minimumSignificantDigits', undefined);
+  }
+  if (internalOptions.hasOwnProperty('maximumSignificantDigits')) {
+    defineWEProperty(resolved, 'maximumSignificantDigits', undefined);
+  }
+  var formatter = %CreateNumberFormat(requestedLocale,
+                                      internalOptions,
+                                      resolved);
+
+  // We can't get information about number or currency style from ICU, so we
+  // assume user request was fulfilled.
+  if (internalOptions.style === 'currency') {
+    Object.defineProperty(resolved, 'currencyDisplay', {value: currencyDisplay,
+                                                        writable: true});
+  }
+
+  Object.defineProperty(numberFormat, 'formatter', {value: formatter});
+  Object.defineProperty(numberFormat, 'resolved', {value: resolved});
+  Object.defineProperty(numberFormat, '__initializedIntlObject',
+                        {value: 'numberformat'});
+
+  return numberFormat;
+}
+
+
+/**
+ * Constructs Intl.NumberFormat object given optional locales and options
+ * parameters.
+ *
+ * @constructor
+ */
+%SetProperty(Intl, 'NumberFormat', function() {
+    var locales = arguments[0];
+    var options = arguments[1];
+
+    if (!this || this === Intl) {
+      // Constructor is called as a function.
+      return new Intl.NumberFormat(locales, options);
+    }
+
+    return initializeNumberFormat(toObject(this), locales, options);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+
+
+/**
+ * NumberFormat resolvedOptions method.
+ */
+%SetProperty(Intl.NumberFormat.prototype, 'resolvedOptions', function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    if (!this || typeof this !== 'object' ||
+        this.__initializedIntlObject !== 'numberformat') {
+      throw new TypeError('resolvedOptions method called on a non-object' +
+          ' or on a object that is not Intl.NumberFormat.');
+    }
+
+    var format = this;
+    var locale = getOptimalLanguageTag(format.resolved.requestedLocale,
+                                       format.resolved.locale);
+
+    var result = {
+      locale: locale,
+      numberingSystem: format.resolved.numberingSystem,
+      style: format.resolved.style,
+      useGrouping: format.resolved.useGrouping,
+      minimumIntegerDigits: format.resolved.minimumIntegerDigits,
+      minimumFractionDigits: format.resolved.minimumFractionDigits,
+      maximumFractionDigits: format.resolved.maximumFractionDigits,
+    };
+
+    if (result.style === 'currency') {
+      defineWECProperty(result, 'currency', format.resolved.currency);
+      defineWECProperty(result, 'currencyDisplay',
+                        format.resolved.currencyDisplay);
+    }
+
+    if (format.resolved.hasOwnProperty('minimumSignificantDigits')) {
+      defineWECProperty(result, 'minimumSignificantDigits',
+                        format.resolved.minimumSignificantDigits);
+    }
+
+    if (format.resolved.hasOwnProperty('maximumSignificantDigits')) {
+      defineWECProperty(result, 'maximumSignificantDigits',
+                        format.resolved.maximumSignificantDigits);
+    }
+
+    return result;
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.NumberFormat.prototype.resolvedOptions,
+                 'resolvedOptions');
+%FunctionRemovePrototype(Intl.NumberFormat.prototype.resolvedOptions);
+%SetNativeFlag(Intl.NumberFormat.prototype.resolvedOptions);
+
+
+/**
+ * Returns the subset of the given locale list for which this locale list
+ * has a matching (possibly fallback) locale. Locales appear in the same
+ * order in the returned list as in the input list.
+ * Options are optional parameter.
+ */
+%SetProperty(Intl.NumberFormat, 'supportedLocalesOf', function(locales) {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    return supportedLocalesOf('numberformat', locales, arguments[1]);
+  },
+  ATTRIBUTES.DONT_ENUM
+);
+%FunctionSetName(Intl.NumberFormat.supportedLocalesOf, 'supportedLocalesOf');
+%FunctionRemovePrototype(Intl.NumberFormat.supportedLocalesOf);
+%SetNativeFlag(Intl.NumberFormat.supportedLocalesOf);
+
+
+/**
+ * Returns a String value representing the result of calling ToNumber(value)
+ * according to the effective locale and the formatting options of this
+ * NumberFormat.
+ */
+function formatNumber(formatter, value) {
+  // Spec treats -0 and +0 as 0.
+  var number = Number(value);
+  if (number === -0) {
+    number = 0;
+  }
+
+  return %InternalNumberFormat(formatter.formatter, number);
+}
+
+
+/**
+ * Returns a Number that represents string value that was passed in.
+ */
+function parseNumber(formatter, value) {
+  return %InternalNumberParse(formatter.formatter, String(value));
+}
+
+
+addBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1);
+addBoundMethod(Intl.NumberFormat, 'v8Parse', parseNumber, 1);
diff --git a/src/extensions/i18n/overrides.js b/src/extensions/i18n/overrides.js
new file mode 100644
index 0000000..b2d60b3
--- /dev/null
+++ b/src/extensions/i18n/overrides.js
@@ -0,0 +1,220 @@
+// 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.
+// limitations under the License.
+
+// ECMAScript 402 API implementation is broken into separate files for
+// each service. The build system combines them together into one
+// Intl namespace.
+
+
+// Save references to Intl objects and methods we use, for added security.
+var savedObjects = {
+  'collator': Intl.Collator,
+  'numberformat': Intl.NumberFormat,
+  'dateformatall': Intl.DateTimeFormat,
+  'dateformatdate': Intl.DateTimeFormat,
+  'dateformattime': Intl.DateTimeFormat
+};
+
+
+// Default (created with undefined locales and options parameters) collator,
+// number and date format instances. They'll be created as needed.
+var defaultObjects = {
+  'collator': undefined,
+  'numberformat': undefined,
+  'dateformatall': undefined,
+  'dateformatdate': undefined,
+  'dateformattime': undefined,
+};
+
+
+/**
+ * Returns cached or newly created instance of a given service.
+ * We cache only default instances (where no locales or options are provided).
+ */
+function cachedOrNewService(service, locales, options, defaults) {
+  var useOptions = (defaults === undefined) ? options : defaults;
+  if (locales === undefined && options === undefined) {
+    if (defaultObjects[service] === undefined) {
+      defaultObjects[service] = new savedObjects[service](locales, useOptions);
+    }
+    return defaultObjects[service];
+  }
+  return new savedObjects[service](locales, useOptions);
+}
+
+
+/**
+ * Compares this and that, and returns less than 0, 0 or greater than 0 value.
+ * Overrides the built-in method.
+ */
+Object.defineProperty(String.prototype, 'localeCompare', {
+  value: function(that) {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    if (this === undefined || this === null) {
+      throw new TypeError('Method invoked on undefined or null value.');
+    }
+
+    var locales = arguments[1];
+    var options = arguments[2];
+    var collator = cachedOrNewService('collator', locales, options);
+    return compare(collator, this, that);
+  },
+  writable: true,
+  configurable: true,
+  enumerable: false
+});
+%FunctionSetName(String.prototype.localeCompare, 'localeCompare');
+%FunctionRemovePrototype(String.prototype.localeCompare);
+%SetNativeFlag(String.prototype.localeCompare);
+
+
+/**
+ * Formats a Number object (this) using locale and options values.
+ * If locale or options are omitted, defaults are used.
+ */
+Object.defineProperty(Number.prototype, 'toLocaleString', {
+  value: function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    if (!(this instanceof Number) && typeof(this) !== 'number') {
+      throw new TypeError('Method invoked on an object that is not Number.');
+    }
+
+    var locales = arguments[0];
+    var options = arguments[1];
+    var numberFormat = cachedOrNewService('numberformat', locales, options);
+    return formatNumber(numberFormat, this);
+  },
+  writable: true,
+  configurable: true,
+  enumerable: false
+});
+%FunctionSetName(Number.prototype.toLocaleString, 'toLocaleString');
+%FunctionRemovePrototype(Number.prototype.toLocaleString);
+%SetNativeFlag(Number.prototype.toLocaleString);
+
+
+/**
+ * Returns actual formatted date or fails if date parameter is invalid.
+ */
+function toLocaleDateTime(date, locales, options, required, defaults, service) {
+  if (!(date instanceof Date)) {
+    throw new TypeError('Method invoked on an object that is not Date.');
+  }
+
+  if (isNaN(date)) {
+    return 'Invalid Date';
+  }
+
+  var internalOptions = toDateTimeOptions(options, required, defaults);
+
+  var dateFormat =
+      cachedOrNewService(service, locales, options, internalOptions);
+
+  return formatDate(dateFormat, date);
+}
+
+
+/**
+ * Formats a Date object (this) using locale and options values.
+ * If locale or options are omitted, defaults are used - both date and time are
+ * present in the output.
+ */
+Object.defineProperty(Date.prototype, 'toLocaleString', {
+  value: function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    var locales = arguments[0];
+    var options = arguments[1];
+    return toLocaleDateTime(
+        this, locales, options, 'any', 'all', 'dateformatall');
+  },
+  writable: true,
+  configurable: true,
+  enumerable: false
+});
+%FunctionSetName(Date.prototype.toLocaleString, 'toLocaleString');
+%FunctionRemovePrototype(Date.prototype.toLocaleString);
+%SetNativeFlag(Date.prototype.toLocaleString);
+
+
+/**
+ * Formats a Date object (this) using locale and options values.
+ * If locale or options are omitted, defaults are used - only date is present
+ * in the output.
+ */
+Object.defineProperty(Date.prototype, 'toLocaleDateString', {
+  value: function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    var locales = arguments[0];
+    var options = arguments[1];
+    return toLocaleDateTime(
+        this, locales, options, 'date', 'date', 'dateformatdate');
+  },
+  writable: true,
+  configurable: true,
+  enumerable: false
+});
+%FunctionSetName(Date.prototype.toLocaleDateString, 'toLocaleDateString');
+%FunctionRemovePrototype(Date.prototype.toLocaleDateString);
+%SetNativeFlag(Date.prototype.toLocaleDateString);
+
+
+/**
+ * Formats a Date object (this) using locale and options values.
+ * If locale or options are omitted, defaults are used - only time is present
+ * in the output.
+ */
+Object.defineProperty(Date.prototype, 'toLocaleTimeString', {
+  value: function() {
+    if (%_IsConstructCall()) {
+      throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
+    }
+
+    var locales = arguments[0];
+    var options = arguments[1];
+    return toLocaleDateTime(
+        this, locales, options, 'time', 'time', 'dateformattime');
+  },
+  writable: true,
+  configurable: true,
+  enumerable: false
+});
+%FunctionSetName(Date.prototype.toLocaleTimeString, 'toLocaleTimeString');
+%FunctionRemovePrototype(Date.prototype.toLocaleTimeString);
+%SetNativeFlag(Date.prototype.toLocaleTimeString);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index d3c322a..2d6863b 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -256,6 +256,7 @@
             "crankshaft harvests type feedback from stub cache")
 DEFINE_bool(hydrogen_stats, false, "print statistics for hydrogen")
 DEFINE_bool(trace_hydrogen, false, "trace generated hydrogen to file")
+DEFINE_string(trace_hydrogen_filter, "*", "hydrogen tracing filter")
 DEFINE_bool(trace_hydrogen_stubs, false, "trace generated hydrogen for stubs")
 DEFINE_string(trace_hydrogen_file, NULL, "trace hydrogen to given file name")
 DEFINE_string(trace_phase, "HLZ", "trace generated IR for specified phases")
@@ -331,15 +332,6 @@
 DEFINE_int(concurrent_recompilation_delay, 0,
            "artificial compilation delay in ms")
 
-// TODO(yangguo): to ease transitioning to the new naming scheme, we keep
-//                the old flags for now as aliases.  Remove soon.
-DEFINE_ALIAS_bool(parallel_recompilation, concurrent_recompilation)
-DEFINE_ALIAS_bool(trace_parallel_recompilation, trace_concurrent_recompilation)
-DEFINE_ALIAS_int(parallel_recompilation_queue_length,
-                 concurrent_recompilation_queue_length)
-DEFINE_ALIAS_int(parallel_recompilation_delay, concurrent_recompilation_delay)
-
-
 DEFINE_bool(omit_map_checks_for_leaf_maps, true,
             "do not emit check maps for constant values that have a leaf map, "
             "deoptimize the optimized code if the layout of the maps changes.")
@@ -407,6 +399,7 @@
             "enable use of constant pools for double immediate (ARM only)")
 
 // bootstrapper.cc
+DEFINE_bool(enable_i18n, true, "enable i18n extension")
 DEFINE_string(expose_natives_as, NULL, "expose natives in global object")
 DEFINE_string(expose_debug_as, NULL, "expose debug in global object")
 DEFINE_bool(expose_gc, false, "expose gc extension")
@@ -461,6 +454,18 @@
 
 DEFINE_bool(cache_prototype_transitions, true, "cache prototype transitions")
 
+// cpu-profiler.cc
+#if defined(ANDROID)
+// Phones and tablets have processors that are much slower than desktop
+// and laptop computers for which current heuristics are tuned.
+#define DEFAULT_INTERVAL 5000
+#else
+#define DEFAULT_INTERVAL 1000
+#endif
+DEFINE_int(cpu_profiler_sampling_interval, DEFAULT_INTERVAL,
+           "CPU profiler sampling interval in microseconds")
+#undef DEFAULT_INTERVAL
+
 // debug.cc
 DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
 DEFINE_bool(trace_js_array_abuse, false,
@@ -690,13 +695,14 @@
 DEFINE_bool(enable_slow_asserts, false,
             "enable asserts that are slow to execute")
 
-// codegen-ia32.cc / codegen-arm.cc
+// codegen-ia32.cc / codegen-arm.cc / macro-assembler-*.cc
 DEFINE_bool(print_source, false, "pretty print source code")
 DEFINE_bool(print_builtin_source, false,
             "pretty print source code for builtins")
 DEFINE_bool(print_ast, false, "print source AST")
 DEFINE_bool(print_builtin_ast, false, "print source AST for builtins")
 DEFINE_string(stop_at, "", "function name where to insert a breakpoint")
+DEFINE_bool(trap_on_abort, false, "replace aborts by breakpoints")
 
 // compiler.cc
 DEFINE_bool(print_builtin_scopes, false, "print scopes for builtins")
diff --git a/src/global-handles.cc b/src/global-handles.cc
index 5df9dd4..5632c7c 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -1020,7 +1020,6 @@
 
 
 EternalHandles::EternalHandles() : size_(0) {
-  STATIC_ASSERT(v8::kUninitializedEternalIndex == kInvalidIndex);
   for (unsigned i = 0; i < ARRAY_SIZE(singleton_handles_); i++) {
     singleton_handles_[i] = kInvalidIndex;
   }
@@ -1062,8 +1061,9 @@
 }
 
 
-int EternalHandles::Create(Isolate* isolate, Object* object) {
-  if (object == NULL) return kInvalidIndex;
+void EternalHandles::Create(Isolate* isolate, Object* object, int* index) {
+  ASSERT_EQ(kInvalidIndex, *index);
+  if (object == NULL) return;
   ASSERT_NE(isolate->heap()->the_hole_value(), object);
   int block = size_ >> kShift;
   int offset = size_ & kMask;
@@ -1079,7 +1079,7 @@
   if (isolate->heap()->InNewSpace(object)) {
     new_space_indices_.Add(size_);
   }
-  return size_++;
+  *index = size_++;
 }
 
 
diff --git a/src/global-handles.h b/src/global-handles.h
index 5a4ad13..57cf70e 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -346,8 +346,8 @@
 
   int NumberOfHandles() { return size_; }
 
-  // Create an EternalHandle, returning the index.
-  int Create(Isolate* isolate, Object* object);
+  // Create an EternalHandle, overwriting the index.
+  void Create(Isolate* isolate, Object* object, int* index);
 
   // Grab the handle for an existing EternalHandle.
   inline Handle<Object> Get(int index) {
@@ -369,8 +369,7 @@
   Handle<Object> CreateSingleton(Isolate* isolate,
                                  Object* object,
                                  SingletonHandle singleton) {
-    ASSERT(singleton_handles_[singleton] == kInvalidIndex);
-    singleton_handles_[singleton] = Create(isolate, object);
+    Create(isolate, object, &singleton_handles_[singleton]);
     return Get(singleton_handles_[singleton]);
   }
 
diff --git a/src/globals.h b/src/globals.h
index 478395a..2d072a0 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -30,19 +30,14 @@
 
 #include "../include/v8stdint.h"
 
-// Find a working V8_INFINITY.
-#if V8_CC_GNU
 // Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
 // warning flag and certain versions of GCC due to a bug:
 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
 // For now, we use the more involved template-based version from <limits>, but
 // only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
-# if V8_GNUC_PREREQ(2, 96, 0) && !V8_GNUC_PREREQ(4, 1, 0)
-#  include <limits>  // NOLINT
-#  define V8_INFINITY std::numeric_limits<double>::infinity()
-# else
-#  define V8_INFINITY INFINITY
-# endif
+#if V8_CC_GNU && V8_GNUC_PREREQ(2, 96, 0) && !V8_GNUC_PREREQ(4, 1, 0)
+# include <limits>  // NOLINT
+# define V8_INFINITY std::numeric_limits<double>::infinity()
 #elif V8_CC_MSVC
 # define V8_INFINITY HUGE_VAL
 #else
diff --git a/src/heap.cc b/src/heap.cc
index 1620435..ad352bc 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2429,6 +2429,7 @@
   }
   accessors->set_getter(the_hole_value(), SKIP_WRITE_BARRIER);
   accessors->set_setter(the_hole_value(), SKIP_WRITE_BARRIER);
+  accessors->set_access_flags(Smi::FromInt(0), SKIP_WRITE_BARRIER);
   return accessors;
 }
 
diff --git a/src/hydrogen-escape-analysis.cc b/src/hydrogen-escape-analysis.cc
index af77c16..311091b 100644
--- a/src/hydrogen-escape-analysis.cc
+++ b/src/hydrogen-escape-analysis.cc
@@ -65,7 +65,8 @@
 
 HCapturedObject* HEscapeAnalysisPhase::NewState(HInstruction* previous) {
   Zone* zone = graph()->zone();
-  HCapturedObject* state = new(zone) HCapturedObject(number_of_values_, zone);
+  HCapturedObject* state =
+      new(zone) HCapturedObject(number_of_values_, number_of_objects_, zone);
   state->InsertAfter(previous);
   return state;
 }
@@ -183,18 +184,9 @@
           }
           break;
         }
-        case HValue::kSimulate: {
-          HSimulate* simulate = HSimulate::cast(instr);
-          // TODO(mstarzinger): This doesn't track deltas for values on the
-          // operand stack yet. Find a repro test case and fix this.
-          for (int i = 0; i < simulate->OperandCount(); i++) {
-            if (simulate->OperandAt(i) != allocate) continue;
-            simulate->SetOperandAt(i, state);
-          }
-          break;
-        }
         case HValue::kArgumentsObject:
-        case HValue::kCapturedObject: {
+        case HValue::kCapturedObject:
+        case HValue::kSimulate: {
           for (int i = 0; i < instr->OperandCount(); i++) {
             if (instr->OperandAt(i) != allocate) continue;
             instr->SetOperandAt(i, state);
@@ -212,14 +204,8 @@
           if (mapcheck->value() != allocate) continue;
           // TODO(mstarzinger): This approach breaks if the tracked map value
           // is not a HConstant. Find a repro test case and fix this.
-          for (HUseIterator it(mapcheck->uses()); !it.Done(); it.Advance()) {
-            if (!it.value()->IsLoadNamedField()) continue;
-            HLoadNamedField* load = HLoadNamedField::cast(it.value());
-            load->ClearTypeCheck();
-          }
-          ASSERT(mapcheck->HasNoUses());
-
-          mapcheck->DeleteAndReplaceWith(NULL);
+          ASSERT(mapcheck->ActualValue() == allocate);
+          mapcheck->DeleteAndReplaceWith(mapcheck->ActualValue());
           break;
         }
         default:
@@ -280,6 +266,7 @@
     if (!allocate->size()->IsInteger32Constant()) continue;
     int size_in_bytes = allocate->size()->GetInteger32Constant();
     number_of_values_ = size_in_bytes / kPointerSize;
+    number_of_objects_++;
     block_states_.Clear();
 
     // Perform actual analysis steps.
diff --git a/src/hydrogen-escape-analysis.h b/src/hydrogen-escape-analysis.h
index 123da21..2d425e2 100644
--- a/src/hydrogen-escape-analysis.h
+++ b/src/hydrogen-escape-analysis.h
@@ -40,6 +40,7 @@
   explicit HEscapeAnalysisPhase(HGraph* graph)
       : HPhase("H_Escape analysis", graph),
         captured_(0, zone()),
+        number_of_objects_(0),
         number_of_values_(0),
         cumulative_values_(0),
         block_states_(graph->blocks()->length(), zone()) { }
@@ -73,6 +74,9 @@
   // List of allocations captured during collection phase.
   ZoneList<HInstruction*> captured_;
 
+  // Number of captured objects on which scalar replacement was done.
+  int number_of_objects_;
+
   // Number of scalar values tracked during scalar replacement phase.
   int number_of_values_;
   int cumulative_values_;
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index b0045b8..7c419dc 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -2289,6 +2289,23 @@
 }
 
 
+// Replay captured objects by replacing all captured objects with the
+// same capture id in the current and all outer environments.
+void HCapturedObject::ReplayEnvironment(HEnvironment* env) {
+  ASSERT(env != NULL);
+  while (env != NULL) {
+    for (int i = 0; i < env->length(); ++i) {
+      HValue* value = env->values()->at(i);
+      if (value->IsCapturedObject() &&
+          HCapturedObject::cast(value)->capture_id() == this->capture_id()) {
+        env->SetValueAt(i, this);
+      }
+    }
+    env = env->outer();
+  }
+}
+
+
 void HEnterInlined::RegisterReturnTarget(HBasicBlock* return_target,
                                          Zone* zone) {
   ASSERT(return_target->IsInlineReturnTarget());
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 685a5e8..47bd758 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -3208,8 +3208,8 @@
 
 class HCapturedObject V8_FINAL : public HDematerializedObject {
  public:
-  HCapturedObject(int length, Zone* zone)
-      : HDematerializedObject(length, zone) {
+  HCapturedObject(int length, int id, Zone* zone)
+      : HDematerializedObject(length, zone), capture_id_(id) {
     set_representation(Representation::Tagged());
     values_.AddBlock(NULL, length, zone);  // Resize list.
   }
@@ -3219,8 +3219,15 @@
   // properties or elements backing store are not tracked here.
   const ZoneList<HValue*>* values() const { return &values_; }
   int length() const { return values_.length(); }
+  int capture_id() const { return capture_id_; }
+
+  // Replay effects of this instruction on the given environment.
+  void ReplayEnvironment(HEnvironment* env);
 
   DECLARE_CONCRETE_INSTRUCTION(CapturedObject)
+
+ private:
+  int capture_id_;
 };
 
 
@@ -5599,7 +5606,6 @@
 
   HValue* object() { return OperandAt(0); }
   bool HasTypeCheck() { return object()->IsCheckMaps(); }
-  void ClearTypeCheck() { SetOperandAt(0, object()->ActualValue()); }
   HObjectAccess access() const { return access_; }
   Representation field_representation() const {
       return access_.representation();
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 1961e40..95090d5 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1219,10 +1219,9 @@
 
 
 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
-    HValue* object,
+    HValue* checked_object,
     HValue* key,
     HValue* val,
-    HCheckMaps* checked_object,
     bool is_js_array,
     ElementsKind elements_kind,
     bool is_store,
@@ -1237,14 +1236,12 @@
   // generated store code.
   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
       (elements_kind == FAST_ELEMENTS && is_store)) {
-    if (checked_object != NULL) {
-      checked_object->ClearGVNFlag(kDependsOnElementsKind);
-    }
+    checked_object->ClearGVNFlag(kDependsOnElementsKind);
   }
-  if (checked_object != NULL) object = checked_object;
+
   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
   bool fast_elements = IsFastObjectElementsKind(elements_kind);
-  HValue* elements = AddLoadElements(object);
+  HValue* elements = AddLoadElements(checked_object);
   if (is_store && (fast_elements || fast_smi_only_elements) &&
       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
     HCheckMaps* check_cow_map = Add<HCheckMaps>(
@@ -1254,7 +1251,7 @@
   HInstruction* length = NULL;
   if (is_js_array) {
     length = Add<HLoadNamedField>(
-        object, HObjectAccess::ForArrayLength(elements_kind));
+        checked_object, HObjectAccess::ForArrayLength(elements_kind));
   } else {
     length = AddLoadFixedArrayLength(elements);
   }
@@ -1301,8 +1298,9 @@
 
   if (IsGrowStoreMode(store_mode)) {
     NoObservableSideEffectsScope no_effects(this);
-    elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
-                                         length, key, is_js_array);
+    elements = BuildCheckForCapacityGrow(checked_object, elements,
+                                         elements_kind, length, key,
+                                         is_js_array);
     checked_key = key;
   } else {
     checked_key = Add<HBoundsCheck>(key, length);
@@ -1310,9 +1308,8 @@
     if (is_store && (fast_elements || fast_smi_only_elements)) {
       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
         NoObservableSideEffectsScope no_effects(this);
-
-        elements = BuildCopyElementsOnWrite(object, elements, elements_kind,
-                                            length);
+        elements = BuildCopyElementsOnWrite(checked_object, elements,
+                                            elements_kind, length);
       } else {
         HCheckMaps* check_cow_map = Add<HCheckMaps>(
             elements, isolate()->factory()->fixed_array_map(),
@@ -4443,7 +4440,7 @@
 
 
 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
-    HValue* object,
+    HValue* checked_object,
     Handle<String> name,
     HValue* value,
     Handle<Map> map,
@@ -4495,11 +4492,12 @@
       AddStoreMapConstant(heap_number, isolate()->factory()->heap_number_map());
       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
                             value);
-      instr = New<HStoreNamedField>(object, heap_number_access,
-                                           heap_number);
+      instr = New<HStoreNamedField>(checked_object->ActualValue(),
+                                    heap_number_access,
+                                    heap_number);
     } else {
       // Already holds a HeapNumber; load the box and write its value field.
-      HInstruction* heap_number = Add<HLoadNamedField>(object,
+      HInstruction* heap_number = Add<HLoadNamedField>(checked_object,
                                                        heap_number_access);
       heap_number->set_type(HType::HeapNumber());
       instr = New<HStoreNamedField>(heap_number,
@@ -4508,7 +4506,9 @@
     }
   } else {
     // This is a normal store.
-    instr = New<HStoreNamedField>(object, field_access, value);
+    instr = New<HStoreNamedField>(checked_object->ActualValue(),
+                                  field_access,
+                                  value);
   }
 
   if (transition_to_field) {
@@ -4545,8 +4545,8 @@
   // Handle a store to a known field.
   LookupResult lookup(isolate());
   if (ComputeLoadStoreField(map, name, &lookup, true)) {
-    AddCheckMap(object, map);
-    return BuildStoreNamedField(object, name, value, map, &lookup);
+    HCheckMaps* checked_object = AddCheckMap(object, map);
+    return BuildStoreNamedField(checked_object, name, value, map, &lookup);
   }
 
   // No luck, do a generic store.
@@ -4808,11 +4808,11 @@
 
   // Everything matched; can use monomorphic store.
   BuildCheckHeapObject(object);
-  Add<HCheckMaps>(object, types);
+  HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
   HInstruction* store;
   CHECK_ALIVE_OR_RETURN(
       store = BuildStoreNamedField(
-          object, name, store_value, types->at(count - 1), &lookup),
+          checked_object, name, store_value, types->at(count - 1), &lookup),
       true);
   if (!ast_context()->IsEffect()) Push(result_value);
   store->set_position(position);
@@ -4861,7 +4861,7 @@
       set_current_block(if_true);
       HInstruction* instr;
       CHECK_ALIVE(instr = BuildStoreNamedField(
-          object, name, store_value, map, &lookup));
+          compare, name, store_value, map, &lookup));
       instr->set_position(position);
       // Goto will add the HSimulate for the store.
       AddInstruction(instr);
@@ -5498,19 +5498,7 @@
 }
 
 
-HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
-    HValue* object,
-    HValue* key,
-    HValue* val,
-    HValue* dependency,
-    Handle<Map> map,
-    bool is_store,
-    KeyedAccessStoreMode store_mode) {
-  HCheckMaps* mapcheck = Add<HCheckMaps>(object, map, top_info(), dependency);
-  if (dependency) {
-    mapcheck->ClearGVNFlag(kDependsOnElementsKind);
-  }
-
+LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
   // Loads from a "stock" fast holey double arrays can elide the hole check.
   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
@@ -5522,10 +5510,30 @@
     graph()->MarkDependsOnEmptyArrayProtoElements();
   }
 
+  return load_mode;
+}
+
+
+HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
+    HValue* object,
+    HValue* key,
+    HValue* val,
+    HValue* dependency,
+    Handle<Map> map,
+    bool is_store,
+    KeyedAccessStoreMode store_mode) {
+  HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
+                                               dependency);
+  if (dependency) {
+    checked_object->ClearGVNFlag(kDependsOnElementsKind);
+  }
+
+  LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   return BuildUncheckedMonomorphicElementAccess(
-      object, key, val,
-      mapcheck, map->instance_type() == JS_ARRAY_TYPE,
-      map->elements_kind(), is_store, load_mode, store_mode);
+      checked_object, key, val,
+      map->instance_type() == JS_ARRAY_TYPE,
+      map->elements_kind(), is_store,
+      load_mode, store_mode);
 }
 
 
@@ -5579,14 +5587,14 @@
   }
   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
 
-  HCheckMaps* check_maps = Add<HCheckMaps>(object, maps);
+  HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
   ElementsKind consolidated_elements_kind = has_seen_holey_elements
       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
       : most_general_consolidated_map->elements_kind();
   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
-      object, key, val, check_maps,
+      checked_object, key, val,
       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
       consolidated_elements_kind,
       false, NEVER_RETURN_HOLE, STANDARD_STORE);
@@ -5675,12 +5683,8 @@
     return is_store ? NULL : instr;
   }
 
-  HInstruction* checked_object =
-      AddInstruction(HCheckInstanceType::NewIsSpecObject(object, zone()));
   HBasicBlock* join = graph()->CreateBasicBlock();
 
-  HInstruction* elements = AddLoadElements(checked_object);
-
   for (int i = 0; i < untransitionable_maps.length(); ++i) {
     Handle<Map> map = untransitionable_maps[i];
     ElementsKind elements_kind = map->elements_kind();
@@ -5691,40 +5695,22 @@
     current_block()->Finish(mapcompare);
 
     set_current_block(this_map);
-    HInstruction* checked_key = NULL;
     HInstruction* access = NULL;
-    if (IsFastElementsKind(elements_kind)) {
-      if (is_store && !IsFastDoubleElementsKind(elements_kind)) {
-        Add<HCheckMaps>(
-            elements, isolate()->factory()->fixed_array_map(),
-            top_info(), mapcompare);
-      }
-      if (map->instance_type() == JS_ARRAY_TYPE) {
-        HInstruction* length = Add<HLoadNamedField>(
-            mapcompare, HObjectAccess::ForArrayLength(elements_kind));
-        checked_key = Add<HBoundsCheck>(key, length);
-      } else {
-        HInstruction* length = AddLoadFixedArrayLength(elements);
-        checked_key = Add<HBoundsCheck>(key, length);
-      }
-      access = AddFastElementAccess(
-          elements, checked_key, val, mapcompare,
-          elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE);
-    } else if (IsDictionaryElementsKind(elements_kind)) {
-      if (is_store) {
-        access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
-      } else {
-        access = AddInstruction(BuildLoadKeyedGeneric(object, key));
-      }
+    if (IsDictionaryElementsKind(elements_kind)) {
+      access = is_store
+          ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
+          : AddInstruction(BuildLoadKeyedGeneric(object, key));
     } else {
-      ASSERT(IsExternalArrayElementsKind(elements_kind));
-      HInstruction* length = AddLoadFixedArrayLength(elements);
-      checked_key = Add<HBoundsCheck>(key, length);
-      HLoadExternalArrayPointer* external_elements =
-          Add<HLoadExternalArrayPointer>(elements);
-      access = AddExternalArrayElementAccess(
-          external_elements, checked_key, val,
-          mapcompare, elements_kind, is_store);
+      ASSERT(IsFastElementsKind(elements_kind) ||
+             IsExternalArrayElementsKind(elements_kind));
+      LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
+      // Happily, mapcompare is a checked object.
+      access = BuildUncheckedMonomorphicElementAccess(
+          mapcompare, key, val,
+          map->instance_type() == JS_ARRAY_TYPE,
+          elements_kind, is_store,
+          load_mode,
+          store_mode);
     }
     *has_side_effects |= access->HasObservableSideEffects();
     // The caller will use has_side_effects and add a correct Simulate.
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 6128942..2b9fd96 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1225,10 +1225,9 @@
                                    bool is_jsarray);
 
   HInstruction* BuildUncheckedMonomorphicElementAccess(
-      HValue* object,
+      HValue* checked_object,
       HValue* key,
       HValue* val,
-      HCheckMaps* mapcheck,
       bool is_js_array,
       ElementsKind elements_kind,
       bool is_store,
@@ -1982,6 +1981,8 @@
                                                 HValue* val,
                                                 SmallMapList* maps);
 
+  LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map);
+
   HInstruction* BuildMonomorphicElementAccess(HValue* object,
                                               HValue* key,
                                               HValue* val,
diff --git a/src/i18n.js b/src/i18n.js
deleted file mode 100644
index 882d43f..0000000
--- a/src/i18n.js
+++ /dev/null
@@ -1,2116 +0,0 @@
-// 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.
-// limitations under the License.
-
-// ECMAScript 402 API implementation.
-
-/**
- * Intl object is a single object that has some named properties,
- * all of which are constructors.
- */
-$Object.defineProperty(global, "Intl", { enumerable: false, value: (function() {
-
-'use strict';
-
-var Intl = {};
-
-var undefined = global.undefined;
-
-var AVAILABLE_SERVICES = ['collator',
-                          'numberformat',
-                          'dateformat',
-                          'breakiterator'];
-
-/**
- * Caches available locales for each service.
- */
-var AVAILABLE_LOCALES = {
-  'collator': undefined,
-  'numberformat': undefined,
-  'dateformat': undefined,
-  'breakiterator': undefined
-};
-
-/**
- * Caches default ICU locale.
- */
-var DEFAULT_ICU_LOCALE = undefined;
-
-/**
- * Unicode extension regular expression.
- */
-var UNICODE_EXTENSION_RE = undefined;
-
-function GetUnicodeExtensionRE() {
-  if (UNICODE_EXTENSION_RE === undefined) {
-    UNICODE_EXTENSION_RE = new $RegExp('-u(-[a-z0-9]{2,8})+', 'g');
-  }
-  return UNICODE_EXTENSION_RE;
-}
-
-/**
- * Matches any Unicode extension.
- */
-var ANY_EXTENSION_RE = undefined;
-
-function GetAnyExtensionRE() {
-  if (ANY_EXTENSION_RE === undefined) {
-    ANY_EXTENSION_RE = new $RegExp('-[a-z0-9]{1}-.*', 'g');
-  }
-  return ANY_EXTENSION_RE;
-}
-
-/**
- * Replace quoted text (single quote, anything but the quote and quote again).
- */
-var QUOTED_STRING_RE = undefined;
-
-function GetQuotedStringRE() {
-  if (QUOTED_STRING_RE === undefined) {
-    QUOTED_STRING_RE = new $RegExp("'[^']+'", 'g');
-  }
-  return QUOTED_STRING_RE;
-}
-
-/**
- * Matches valid service name.
- */
-var SERVICE_RE = undefined;
-
-function GetServiceRE() {
-  if (SERVICE_RE === undefined) {
-    SERVICE_RE =
-        new $RegExp('^(collator|numberformat|dateformat|breakiterator)$');
-  }
-  return SERVICE_RE;
-}
-
-/**
- * Validates a language tag against bcp47 spec.
- * Actual value is assigned on first run.
- */
-var LANGUAGE_TAG_RE = undefined;
-
-function GetLanguageTagRE() {
-  if (LANGUAGE_TAG_RE === undefined) {
-    BuildLanguageTagREs();
-  }
-  return LANGUAGE_TAG_RE;
-}
-
-/**
- * Helps find duplicate variants in the language tag.
- */
-var LANGUAGE_VARIANT_RE = undefined;
-
-function GetLanguageVariantRE() {
-  if (LANGUAGE_VARIANT_RE === undefined) {
-    BuildLanguageTagREs();
-  }
-  return LANGUAGE_VARIANT_RE;
-}
-
-/**
- * Helps find duplicate singletons in the language tag.
- */
-var LANGUAGE_SINGLETON_RE = undefined;
-
-function GetLanguageSingletonRE() {
-  if (LANGUAGE_SINGLETON_RE === undefined) {
-    BuildLanguageTagREs();
-  }
-  return LANGUAGE_SINGLETON_RE;
-}
-
-/**
- * Matches valid IANA time zone names.
- */
-var TIMEZONE_NAME_CHECK_RE = undefined;
-
-function GetTimezoneNameCheckRE() {
-  if (TIMEZONE_NAME_CHECK_RE === undefined) {
-    TIMEZONE_NAME_CHECK_RE =
-        new $RegExp('^([A-Za-z]+)/([A-Za-z]+)(?:_([A-Za-z]+))*$');
-  }
-  return TIMEZONE_NAME_CHECK_RE;
-}
-
-/**
- * Maps ICU calendar names into LDML type.
- */
-var ICU_CALENDAR_MAP = {
-  'gregorian': 'gregory',
-  'japanese': 'japanese',
-  'buddhist': 'buddhist',
-  'roc': 'roc',
-  'persian': 'persian',
-  'islamic-civil': 'islamicc',
-  'islamic': 'islamic',
-  'hebrew': 'hebrew',
-  'chinese': 'chinese',
-  'indian': 'indian',
-  'coptic': 'coptic',
-  'ethiopic': 'ethiopic',
-  'ethiopic-amete-alem': 'ethioaa'
-};
-
-/**
- * Map of Unicode extensions to option properties, and their values and types,
- * for a collator.
- */
-var COLLATOR_KEY_MAP = {
-  'kn': {'property': 'numeric', 'type': 'boolean'},
-  'kf': {'property': 'caseFirst', 'type': 'string',
-         'values': ['false', 'lower', 'upper']}
-};
-
-/**
- * Map of Unicode extensions to option properties, and their values and types,
- * for a number format.
- */
-var NUMBER_FORMAT_KEY_MAP = {
-  'nu': {'property': undefined, 'type': 'string'}
-};
-
-/**
- * Map of Unicode extensions to option properties, and their values and types,
- * for a date/time format.
- */
-var DATETIME_FORMAT_KEY_MAP = {
-  'ca': {'property': undefined, 'type': 'string'},
-  'nu': {'property': undefined, 'type': 'string'}
-};
-
-/**
- * Allowed -u-co- values. List taken from:
- * http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
- */
-var ALLOWED_CO_VALUES = [
-  'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic',
-  'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin'
-];
-
-/**
- * Error message for when function object is created with new and it's not
- * a constructor.
- */
-var ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR =
-  'Function object that\'s not a constructor was created with new';
-
-
-/**
- * Adds bound method to the prototype of the given object.
- */
-function addBoundMethod(obj, methodName, implementation, length) {
-  function getter() {
-    if (!this || typeof this !== 'object' ||
-        this.__initializedIntlObject === undefined) {
-        throw new $TypeError('Method ' + methodName + ' called on a ' +
-                            'non-object or on a wrong type of object.');
-    }
-    var internalName = '__bound' + methodName + '__';
-    if (this[internalName] === undefined) {
-      var that = this;
-      var boundMethod;
-      if (length === undefined || length === 2) {
-        boundMethod = function(x, y) {
-          if (%_IsConstructCall()) {
-            throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-          }
-          return implementation(that, x, y);
-        }
-      } else if (length === 1) {
-        boundMethod = function(x) {
-          if (%_IsConstructCall()) {
-            throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-          }
-          return implementation(that, x);
-        }
-      } else {
-        boundMethod = function() {
-          if (%_IsConstructCall()) {
-            throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-          }
-          // DateTimeFormat.format needs to be 0 arg method, but can stil
-          // receive optional dateValue param. If one was provided, pass it
-          // along.
-          if (arguments.length > 0) {
-            return implementation(that, arguments[0]);
-          } else {
-            return implementation(that);
-          }
-        }
-      }
-      %FunctionSetName(boundMethod, internalName);
-      %FunctionRemovePrototype(boundMethod);
-      %SetNativeFlag(boundMethod);
-      this[internalName] = boundMethod;
-    }
-    return this[internalName];
-  }
-
-  %FunctionSetName(getter, methodName);
-  %FunctionRemovePrototype(getter);
-  %SetNativeFlag(getter);
-
-  $Object.defineProperty(obj.prototype, methodName, {
-    get: getter,
-    enumerable: false,
-    configurable: true
-  });
-}
-
-
-/**
- * Returns an intersection of locales and service supported locales.
- * Parameter locales is treated as a priority list.
- */
-function supportedLocalesOf(service, locales, options) {
-  if (service.match(GetServiceRE()) === null) {
-    throw new $Error('Internal error, wrong service type: ' + service);
-  }
-
-  // Provide defaults if matcher was not specified.
-  if (options === undefined) {
-    options = {};
-  } else {
-    options = toObject(options);
-  }
-
-  var matcher = options.localeMatcher;
-  if (matcher !== undefined) {
-    matcher = $String(matcher);
-    if (matcher !== 'lookup' && matcher !== 'best fit') {
-      throw new $RangeError('Illegal value for localeMatcher:' + matcher);
-    }
-  } else {
-    matcher = 'best fit';
-  }
-
-  var requestedLocales = initializeLocaleList(locales);
-
-  // Cache these, they don't ever change per service.
-  if (AVAILABLE_LOCALES[service] === undefined) {
-    AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
-  }
-
-  // Use either best fit or lookup algorithm to match locales.
-  if (matcher === 'best fit') {
-    return initializeLocaleList(bestFitSupportedLocalesOf(
-        requestedLocales, AVAILABLE_LOCALES[service]));
-  }
-
-  return initializeLocaleList(lookupSupportedLocalesOf(
-      requestedLocales, AVAILABLE_LOCALES[service]));
-}
-
-
-/**
- * Returns the subset of the provided BCP 47 language priority list for which
- * this service has a matching locale when using the BCP 47 Lookup algorithm.
- * Locales appear in the same order in the returned list as in the input list.
- */
-function lookupSupportedLocalesOf(requestedLocales, availableLocales) {
-  var matchedLocales = [];
-  for (var i = 0; i < requestedLocales.length; ++i) {
-    // Remove -u- extension.
-    var locale = requestedLocales[i].replace(GetUnicodeExtensionRE(), '');
-    do {
-      if (availableLocales[locale] !== undefined) {
-        // Push requested locale not the resolved one.
-        matchedLocales.push(requestedLocales[i]);
-        break;
-      }
-      // Truncate locale if possible, if not break.
-      var pos = locale.lastIndexOf('-');
-      if (pos === -1) {
-        break;
-      }
-      locale = locale.substring(0, pos);
-    } while (true);
-  }
-
-  return matchedLocales;
-}
-
-
-/**
- * Returns the subset of the provided BCP 47 language priority list for which
- * this service has a matching locale when using the implementation
- * dependent algorithm.
- * Locales appear in the same order in the returned list as in the input list.
- */
-function bestFitSupportedLocalesOf(requestedLocales, availableLocales) {
-  // TODO(cira): implement better best fit algorithm.
-  return lookupSupportedLocalesOf(requestedLocales, availableLocales);
-}
-
-
-/**
- * Returns a getOption function that extracts property value for given
- * options object. If property is missing it returns defaultValue. If value
- * is out of range for that property it throws RangeError.
- */
-function getGetOption(options, caller) {
-  if (options === undefined) {
-    throw new $Error('Internal ' + caller + ' error. ' +
-                    'Default options are missing.');
-  }
-
-  var getOption = function getOption(property, type, values, defaultValue) {
-    if (options[property] !== undefined) {
-      var value = options[property];
-      switch (type) {
-        case 'boolean':
-          value = Boolean(value);
-          break;
-        case 'string':
-          value = $String(value);
-          break;
-        case 'number':
-          value = $Number(value);
-          break;
-        default:
-          throw new $Error('Internal error. Wrong value type.');
-      }
-      if (values !== undefined && values.indexOf(value) === -1) {
-        throw new $RangeError('Value ' + value + ' out of range for ' + caller +
-                             ' options property ' + property);
-      }
-
-      return value;
-    }
-
-    return defaultValue;
-  }
-
-  return getOption;
-}
-
-
-/**
- * Compares a BCP 47 language priority list requestedLocales against the locales
- * in availableLocales and determines the best available language to meet the
- * request. Two algorithms are available to match the locales: the Lookup
- * algorithm described in RFC 4647 section 3.4, and an implementation dependent
- * best-fit algorithm. Independent of the locale matching algorithm, options
- * specified through Unicode locale extension sequences are negotiated
- * separately, taking the caller's relevant extension keys and locale data as
- * well as client-provided options into consideration. Returns an object with
- * a locale property whose value is the language tag of the selected locale,
- * and properties for each key in relevantExtensionKeys providing the selected
- * value for that key.
- */
-function resolveLocale(service, requestedLocales, options) {
-  requestedLocales = initializeLocaleList(requestedLocales);
-
-  var getOption = getGetOption(options, service);
-  var matcher = getOption('localeMatcher', 'string',
-                          ['lookup', 'best fit'], 'best fit');
-  var resolved;
-  if (matcher === 'lookup') {
-    resolved = lookupMatcher(service, requestedLocales);
-  } else {
-    resolved = bestFitMatcher(service, requestedLocales);
-  }
-
-  return resolved;
-}
-
-
-/**
- * Returns best matched supported locale and extension info using basic
- * lookup algorithm.
- */
-function lookupMatcher(service, requestedLocales) {
-  if (service.match(GetServiceRE()) === null) {
-    throw new $Error('Internal error, wrong service type: ' + service);
-  }
-
-  // Cache these, they don't ever change per service.
-  if (AVAILABLE_LOCALES[service] === undefined) {
-    AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
-  }
-
-  for (var i = 0; i < requestedLocales.length; ++i) {
-    // Remove all extensions.
-    var locale = requestedLocales[i].replace(GetAnyExtensionRE(), '');
-    do {
-      if (AVAILABLE_LOCALES[service][locale] !== undefined) {
-        // Return the resolved locale and extension.
-        var extensionMatch = requestedLocales[i].match(GetUnicodeExtensionRE());
-        var extension = (extensionMatch === null) ? '' : extensionMatch[0];
-        return {'locale': locale, 'extension': extension, 'position': i};
-      }
-      // Truncate locale if possible.
-      var pos = locale.lastIndexOf('-');
-      if (pos === -1) {
-        break;
-      }
-      locale = locale.substring(0, pos);
-    } while (true);
-  }
-
-  // Didn't find a match, return default.
-  if (DEFAULT_ICU_LOCALE === undefined) {
-    DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
-  }
-
-  return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
-}
-
-
-/**
- * Returns best matched supported locale and extension info using
- * implementation dependend algorithm.
- */
-function bestFitMatcher(service, requestedLocales) {
-  // TODO(cira): implement better best fit algorithm.
-  return lookupMatcher(service, requestedLocales);
-}
-
-
-/**
- * Parses Unicode extension into key - value map.
- * Returns empty object if the extension string is invalid.
- * We are not concerned with the validity of the values at this point.
- */
-function parseExtension(extension) {
-  var extensionSplit = extension.split('-');
-
-  // Assume ['', 'u', ...] input, but don't throw.
-  if (extensionSplit.length <= 2 ||
-      (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) {
-    return {};
-  }
-
-  // Key is {2}alphanum, value is {3,8}alphanum.
-  // Some keys may not have explicit values (booleans).
-  var extensionMap = {};
-  var previousKey = undefined;
-  for (var i = 2; i < extensionSplit.length; ++i) {
-    var length = extensionSplit[i].length;
-    var element = extensionSplit[i];
-    if (length === 2) {
-      extensionMap[element] = undefined;
-      previousKey = element;
-    } else if (length >= 3 && length <=8 && previousKey !== undefined) {
-      extensionMap[previousKey] = element;
-      previousKey = undefined;
-    } else {
-      // There is a value that's too long, or that doesn't have a key.
-      return {};
-    }
-  }
-
-  return extensionMap;
-}
-
-
-/**
- * Converts parameter to an Object if possible.
- */
-function toObject(value) {
-  if (value === undefined || value === null) {
-    throw new $TypeError('Value cannot be converted to an Object.');
-  }
-
-  return $Object(value);
-}
-
-
-/**
- * Populates internalOptions object with boolean key-value pairs
- * from extensionMap and options.
- * Returns filtered extension (number and date format constructors use
- * Unicode extensions for passing parameters to ICU).
- * It's used for extension-option pairs only, e.g. kn-normalization, but not
- * for 'sensitivity' since it doesn't have extension equivalent.
- * Extensions like nu and ca don't have options equivalent, so we place
- * undefined in the map.property to denote that.
- */
-function setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) {
-  var extension = '';
-
-  var updateExtension = function updateExtension(key, value) {
-    return '-' + key + '-' + $String(value);
-  }
-
-  var updateProperty = function updateProperty(property, type, value) {
-    if (type === 'boolean' && (typeof value === 'string')) {
-      value = (value === 'true') ? true : false;
-    }
-
-    if (property !== undefined) {
-      defineWEProperty(outOptions, property, value);
-    }
-  }
-
-  for (var key in keyValues) {
-    if (keyValues.hasOwnProperty(key)) {
-      var value = undefined;
-      var map = keyValues[key];
-      if (map.property !== undefined) {
-        // This may return true if user specifies numeric: 'false', since
-        // Boolean('nonempty') === true.
-        value = getOption(map.property, map.type, map.values);
-      }
-      if (value !== undefined) {
-        updateProperty(map.property, map.type, value);
-        extension += updateExtension(key, value);
-        continue;
-      }
-      // User options didn't have it, check Unicode extension.
-      // Here we want to convert strings 'true', 'false' into proper Boolean
-      // values (not a user error).
-      if (extensionMap.hasOwnProperty(key)) {
-        value = extensionMap[key];
-        if (value !== undefined) {
-          updateProperty(map.property, map.type, value);
-          extension += updateExtension(key, value);
-        } else if (map.type === 'boolean') {
-          // Boolean keys are allowed not to have values in Unicode extension.
-          // Those default to true.
-          updateProperty(map.property, map.type, true);
-          extension += updateExtension(key, true);
-        }
-      }
-    }
-  }
-
-  return extension === ''? '' : '-u' + extension;
-}
-
-
-/**
- * Converts all OwnProperties into
- * configurable: false, writable: false, enumerable: true.
- */
-function freezeArray(array) {
-  array.forEach(function(element, index) {
-    $Object.defineProperty(array, index, {value: element,
-                                          configurable: false,
-                                          writable: false,
-                                          enumerable: true});
-  });
-
-  $Object.defineProperty(array, 'length', {value: array.length,
-                                           writable: false});
-
-  return array;
-}
-
-
-/**
- * It's sometimes desireable to leave user requested locale instead of ICU
- * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter
- * one, if that was what user requested).
- * This function returns user specified tag if its maximized form matches ICU
- * resolved locale. If not we return ICU result.
- */
-function getOptimalLanguageTag(original, resolved) {
-  // Returns Array<Object>, where each object has maximized and base properties.
-  // Maximized: zh -> zh-Hans-CN
-  // Base: zh-CN-u-ca-gregory -> zh-CN
-  // Take care of grandfathered or simple cases.
-  if (original === resolved) {
-    return original;
-  }
-
-  var locales = %GetLanguageTagVariants([original, resolved]);
-  if (locales[0].maximized !== locales[1].maximized) {
-    return resolved;
-  }
-
-  // Preserve extensions of resolved locale, but swap base tags with original.
-  var resolvedBase = new $RegExp('^' + locales[1].base);
-  return resolved.replace(resolvedBase, locales[0].base);
-}
-
-
-/**
- * Returns an Object that contains all of supported locales for a given
- * service.
- * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ
- * that is supported. This is required by the spec.
- */
-function getAvailableLocalesOf(service) {
-  var available = %AvailableLocalesOf(service);
-
-  for (var i in available) {
-    if (available.hasOwnProperty(i)) {
-      var parts = i.match(/^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/);
-      if (parts !== null) {
-        // Build xx-ZZ. We don't care about the actual value,
-        // as long it's not undefined.
-        available[parts[1] + '-' + parts[3]] = null;
-      }
-    }
-  }
-
-  return available;
-}
-
-
-/**
- * Defines a property and sets writable and enumerable to true.
- * Configurable is false by default.
- */
-function defineWEProperty(object, property, value) {
-  $Object.defineProperty(object, property,
-                         {value: value, writable: true, enumerable: true});
-}
-
-
-/**
- * Adds property to an object if the value is not undefined.
- * Sets configurable descriptor to false.
- */
-function addWEPropertyIfDefined(object, property, value) {
-  if (value !== undefined) {
-    defineWEProperty(object, property, value);
-  }
-}
-
-
-/**
- * Defines a property and sets writable, enumerable and configurable to true.
- */
-function defineWECProperty(object, property, value) {
-  $Object.defineProperty(object, property,
-                         {value: value,
-                          writable: true,
-                          enumerable: true,
-                          configurable: true});
-}
-
-
-/**
- * Adds property to an object if the value is not undefined.
- * Sets all descriptors to true.
- */
-function addWECPropertyIfDefined(object, property, value) {
-  if (value !== undefined) {
-    defineWECProperty(object, property, value);
-  }
-}
-
-
-/**
- * Returns titlecased word, aMeRricA -> America.
- */
-function toTitleCaseWord(word) {
-  return word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase();
-}
-
-/**
- * Canonicalizes the language tag, or throws in case the tag is invalid.
- */
-function canonicalizeLanguageTag(localeID) {
-  // null is typeof 'object' so we have to do extra check.
-  if (typeof localeID !== 'string' && typeof localeID !== 'object' ||
-      localeID === null) {
-    throw new $TypeError('Language ID should be string or object.');
-  }
-
-  var localeString = $String(localeID);
-
-  if (isValidLanguageTag(localeString) === false) {
-    throw new $RangeError('Invalid language tag: ' + localeString);
-  }
-
-  // This call will strip -kn but not -kn-true extensions.
-  // ICU bug filled - http://bugs.icu-project.org/trac/ticket/9265.
-  // TODO(cira): check if -u-kn-true-kc-true-kh-true still throws after
-  // upgrade to ICU 4.9.
-  var tag = %CanonicalizeLanguageTag(localeString);
-  if (tag === 'invalid-tag') {
-    throw new $RangeError('Invalid language tag: ' + localeString);
-  }
-
-  return tag;
-}
-
-
-/**
- * Returns an array where all locales are canonicalized and duplicates removed.
- * Throws on locales that are not well formed BCP47 tags.
- */
-function initializeLocaleList(locales) {
-  var seen = [];
-  if (locales === undefined) {
-    // Constructor is called without arguments.
-    seen = [];
-  } else {
-    // We allow single string localeID.
-    if (typeof locales === 'string') {
-      seen.push(canonicalizeLanguageTag(locales));
-      return freezeArray(seen);
-    }
-
-    var o = toObject(locales);
-    // Converts it to UInt32 (>>> is shr on 32bit integers).
-    var len = o.length >>> 0;
-
-    for (var k = 0; k < len; k++) {
-      if (k in o) {
-        var value = o[k];
-
-        var tag = canonicalizeLanguageTag(value);
-
-        if (seen.indexOf(tag) === -1) {
-          seen.push(tag);
-        }
-      }
-    }
-  }
-
-  return freezeArray(seen);
-}
-
-
-/**
- * Validates the language tag. Section 2.2.9 of the bcp47 spec
- * defines a valid tag.
- *
- * ICU is too permissible and lets invalid tags, like
- * hant-cmn-cn, through.
- *
- * Returns false if the language tag is invalid.
- */
-function isValidLanguageTag(locale) {
-  // Check if it's well-formed, including grandfadered tags.
-  if (GetLanguageTagRE().test(locale) === false) {
-    return false;
-  }
-
-  // Just return if it's a x- form. It's all private.
-  if (locale.indexOf('x-') === 0) {
-    return true;
-  }
-
-  // Check if there are any duplicate variants or singletons (extensions).
-
-  // Remove private use section.
-  locale = locale.split(/-x-/)[0];
-
-  // Skip language since it can match variant regex, so we start from 1.
-  // We are matching i-klingon here, but that's ok, since i-klingon-klingon
-  // is not valid and would fail LANGUAGE_TAG_RE test.
-  var variants = [];
-  var extensions = [];
-  var parts = locale.split(/-/);
-  for (var i = 1; i < parts.length; i++) {
-    var value = parts[i];
-    if (GetLanguageVariantRE().test(value) === true && extensions.length === 0) {
-      if (variants.indexOf(value) === -1) {
-        variants.push(value);
-      } else {
-        return false;
-      }
-    }
-
-    if (GetLanguageSingletonRE().test(value) === true) {
-      if (extensions.indexOf(value) === -1) {
-        extensions.push(value);
-      } else {
-        return false;
-      }
-    }
-  }
-
-  return true;
- }
-
-
-/**
- * Builds a regular expresion that validates the language tag
- * against bcp47 spec.
- * Uses http://tools.ietf.org/html/bcp47, section 2.1, ABNF.
- * Runs on load and initializes the global REs.
- */
-function BuildLanguageTagREs() {
-  var alpha = '[a-zA-Z]';
-  var digit = '[0-9]';
-  var alphanum = '(' + alpha + '|' + digit + ')';
-  var regular = '(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|' +
-                'zh-min|zh-min-nan|zh-xiang)';
-  var irregular = '(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|' +
-                  'i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|' +
-                  'i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)';
-  var grandfathered = '(' + irregular + '|' + regular + ')';
-  var privateUse = '(x(-' + alphanum + '{1,8})+)';
-
-  var singleton = '(' + digit + '|[A-WY-Za-wy-z])';
-  LANGUAGE_SINGLETON_RE = new $RegExp('^' + singleton + '$', 'i');
-
-  var extension = '(' + singleton + '(-' + alphanum + '{2,8})+)';
-
-  var variant = '(' + alphanum + '{5,8}|(' + digit + alphanum + '{3}))';
-  LANGUAGE_VARIANT_RE = new $RegExp('^' + variant + '$', 'i');
-
-  var region = '(' + alpha + '{2}|' + digit + '{3})';
-  var script = '(' + alpha + '{4})';
-  var extLang = '(' + alpha + '{3}(-' + alpha + '{3}){0,2})';
-  var language = '(' + alpha + '{2,3}(-' + extLang + ')?|' + alpha + '{4}|' +
-                 alpha + '{5,8})';
-  var langTag = language + '(-' + script + ')?(-' + region + ')?(-' +
-                variant + ')*(-' + extension + ')*(-' + privateUse + ')?';
-
-  var languageTag =
-      '^(' + langTag + '|' + privateUse + '|' + grandfathered + ')$';
-  LANGUAGE_TAG_RE = new $RegExp(languageTag, 'i');
-}
-
-/**
- * Initializes the given object so it's a valid Collator instance.
- * Useful for subclassing.
- */
-function initializeCollator(collator, locales, options) {
-  if (collator.hasOwnProperty('__initializedIntlObject')) {
-    throw new $TypeError('Trying to re-initialize Collator object.');
-  }
-
-  if (options === undefined) {
-    options = {};
-  }
-
-  var getOption = getGetOption(options, 'collator');
-
-  var internalOptions = {};
-
-  defineWEProperty(internalOptions, 'usage', getOption(
-    'usage', 'string', ['sort', 'search'], 'sort'));
-
-  var sensitivity = getOption('sensitivity', 'string',
-                              ['base', 'accent', 'case', 'variant']);
-  if (sensitivity === undefined && internalOptions.usage === 'sort') {
-    sensitivity = 'variant';
-  }
-  defineWEProperty(internalOptions, 'sensitivity', sensitivity);
-
-  defineWEProperty(internalOptions, 'ignorePunctuation', getOption(
-    'ignorePunctuation', 'boolean', undefined, false));
-
-  var locale = resolveLocale('collator', locales, options);
-
-  // ICU can't take kb, kc... parameters through localeID, so we need to pass
-  // them as options.
-  // One exception is -co- which has to be part of the extension, but only for
-  // usage: sort, and its value can't be 'standard' or 'search'.
-  var extensionMap = parseExtension(locale.extension);
-  setOptions(
-      options, extensionMap, COLLATOR_KEY_MAP, getOption, internalOptions);
-
-  var collation = 'default';
-  var extension = '';
-  if (extensionMap.hasOwnProperty('co') && internalOptions.usage === 'sort') {
-    if (ALLOWED_CO_VALUES.indexOf(extensionMap.co) !== -1) {
-      extension = '-u-co-' + extensionMap.co;
-      // ICU can't tell us what the collation is, so save user's input.
-      collation = extensionMap.co;
-    }
-  } else if (internalOptions.usage === 'search') {
-    extension = '-u-co-search';
-  }
-  defineWEProperty(internalOptions, 'collation', collation);
-
-  var requestedLocale = locale.locale + extension;
-
-  // We define all properties C++ code may produce, to prevent security
-  // problems. If malicious user decides to redefine Object.prototype.locale
-  // we can't just use plain x.locale = 'us' or in C++ Set("locale", "us").
-  // Object.defineProperties will either succeed defining or throw an error.
-  var resolved = $Object.defineProperties({}, {
-    caseFirst: {writable: true},
-    collation: {value: internalOptions.collation, writable: true},
-    ignorePunctuation: {writable: true},
-    locale: {writable: true},
-    numeric: {writable: true},
-    requestedLocale: {value: requestedLocale, writable: true},
-    sensitivity: {writable: true},
-    strength: {writable: true},
-    usage: {value: internalOptions.usage, writable: true}
-  });
-
-  var internalCollator = %CreateCollator(requestedLocale,
-                                         internalOptions,
-                                         resolved);
-
-  // Writable, configurable and enumerable are set to false by default.
-  $Object.defineProperty(collator, 'collator', {value: internalCollator});
-  $Object.defineProperty(collator, '__initializedIntlObject',
-                         {value: 'collator'});
-  $Object.defineProperty(collator, 'resolved', {value: resolved});
-
-  return collator;
-}
-
-
-/**
- * Constructs Intl.Collator object given optional locales and options
- * parameters.
- *
- * @constructor
- */
-%SetProperty(Intl, 'Collator', function() {
-    var locales = arguments[0];
-    var options = arguments[1];
-
-    if (!this || this === Intl) {
-      // Constructor is called as a function.
-      return new Intl.Collator(locales, options);
-    }
-
-    return initializeCollator(toObject(this), locales, options);
-  },
-  DONT_ENUM
-);
-
-
-/**
- * Collator resolvedOptions method.
- */
-%SetProperty(Intl.Collator.prototype, 'resolvedOptions', function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    if (!this || typeof this !== 'object' ||
-        this.__initializedIntlObject !== 'collator') {
-      throw new $TypeError('resolvedOptions method called on a non-object ' +
-                           'or on a object that is not Intl.Collator.');
-    }
-
-    var coll = this;
-    var locale = getOptimalLanguageTag(coll.resolved.requestedLocale,
-                                       coll.resolved.locale);
-
-    return {
-      locale: locale,
-      usage: coll.resolved.usage,
-      sensitivity: coll.resolved.sensitivity,
-      ignorePunctuation: coll.resolved.ignorePunctuation,
-      numeric: coll.resolved.numeric,
-      caseFirst: coll.resolved.caseFirst,
-      collation: coll.resolved.collation
-    };
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.Collator.prototype.resolvedOptions, 'resolvedOptions');
-%FunctionRemovePrototype(Intl.Collator.prototype.resolvedOptions);
-%SetNativeFlag(Intl.Collator.prototype.resolvedOptions);
-
-
-/**
- * Returns the subset of the given locale list for which this locale list
- * has a matching (possibly fallback) locale. Locales appear in the same
- * order in the returned list as in the input list.
- * Options are optional parameter.
- */
-%SetProperty(Intl.Collator, 'supportedLocalesOf', function(locales) {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    return supportedLocalesOf('collator', locales, arguments[1]);
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.Collator.supportedLocalesOf, 'supportedLocalesOf');
-%FunctionRemovePrototype(Intl.Collator.supportedLocalesOf);
-%SetNativeFlag(Intl.Collator.supportedLocalesOf);
-
-
-/**
- * When the compare method is called with two arguments x and y, it returns a
- * Number other than NaN that represents the result of a locale-sensitive
- * String comparison of x with y.
- * The result is intended to order String values in the sort order specified
- * by the effective locale and collation options computed during construction
- * of this Collator object, and will be negative, zero, or positive, depending
- * on whether x comes before y in the sort order, the Strings are equal under
- * the sort order, or x comes after y in the sort order, respectively.
- */
-function compare(collator, x, y) {
-  return %InternalCompare(collator.collator, $String(x), $String(y));
-};
-
-
-addBoundMethod(Intl.Collator, 'compare', compare, 2);
-
-/**
- * Verifies that the input is a well-formed ISO 4217 currency code.
- * Don't uppercase to test. It could convert invalid code into a valid one.
- * For example \u00DFP (Eszett+P) becomes SSP.
- */
-function isWellFormedCurrencyCode(currency) {
-  return typeof currency == "string" &&
-      currency.length == 3 &&
-      currency.match(/[^A-Za-z]/) == null;
-}
-
-
-/**
- * Returns the valid digit count for a property, or throws RangeError on
- * a value out of the range.
- */
-function getNumberOption(options, property, min, max, fallback) {
-  var value = options[property];
-  if (value !== undefined) {
-    value = $Number(value);
-    if ($isNaN(value) || value < min || value > max) {
-      throw new $RangeError(property + ' value is out of range.');
-    }
-    return $floor(value);
-  }
-
-  return fallback;
-}
-
-
-/**
- * Initializes the given object so it's a valid NumberFormat instance.
- * Useful for subclassing.
- */
-function initializeNumberFormat(numberFormat, locales, options) {
-  if (numberFormat.hasOwnProperty('__initializedIntlObject')) {
-    throw new $TypeError('Trying to re-initialize NumberFormat object.');
-  }
-
-  if (options === undefined) {
-    options = {};
-  }
-
-  var getOption = getGetOption(options, 'numberformat');
-
-  var locale = resolveLocale('numberformat', locales, options);
-
-  var internalOptions = {};
-  defineWEProperty(internalOptions, 'style', getOption(
-    'style', 'string', ['decimal', 'percent', 'currency'], 'decimal'));
-
-  var currency = getOption('currency', 'string');
-  if (currency !== undefined && !isWellFormedCurrencyCode(currency)) {
-    throw new $RangeError('Invalid currency code: ' + currency);
-  }
-
-  if (internalOptions.style === 'currency' && currency === undefined) {
-    throw new $TypeError('Currency code is required with currency style.');
-  }
-
-  var currencyDisplay = getOption(
-      'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol');
-  if (internalOptions.style === 'currency') {
-    defineWEProperty(internalOptions, 'currency', currency.toUpperCase());
-    defineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay);
-  }
-
-  // Digit ranges.
-  var mnid = getNumberOption(options, 'minimumIntegerDigits', 1, 21, 1);
-  defineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
-
-  var mnfd = getNumberOption(options, 'minimumFractionDigits', 0, 20, 0);
-  defineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
-
-  var mxfd = getNumberOption(options, 'maximumFractionDigits', mnfd, 20, 3);
-  defineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
-
-  var mnsd = options['minimumSignificantDigits'];
-  var mxsd = options['maximumSignificantDigits'];
-  if (mnsd !== undefined || mxsd !== undefined) {
-    mnsd = getNumberOption(options, 'minimumSignificantDigits', 1, 21, 0);
-    defineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
-
-    mxsd = getNumberOption(options, 'maximumSignificantDigits', mnsd, 21, 21);
-    defineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
-  }
-
-  // Grouping.
-  defineWEProperty(internalOptions, 'useGrouping', getOption(
-    'useGrouping', 'boolean', undefined, true));
-
-  // ICU prefers options to be passed using -u- extension key/values for
-  // number format, so we need to build that.
-  var extensionMap = parseExtension(locale.extension);
-  var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP,
-                             getOption, internalOptions);
-
-  var requestedLocale = locale.locale + extension;
-  var resolved = $Object.defineProperties({}, {
-    currency: {writable: true},
-    currencyDisplay: {writable: true},
-    locale: {writable: true},
-    maximumFractionDigits: {writable: true},
-    minimumFractionDigits: {writable: true},
-    minimumIntegerDigits: {writable: true},
-    numberingSystem: {writable: true},
-    requestedLocale: {value: requestedLocale, writable: true},
-    style: {value: internalOptions.style, writable: true},
-    useGrouping: {writable: true}
-  });
-  if (internalOptions.hasOwnProperty('minimumSignificantDigits')) {
-    defineWEProperty(resolved, 'minimumSignificantDigits', undefined);
-  }
-  if (internalOptions.hasOwnProperty('maximumSignificantDigits')) {
-    defineWEProperty(resolved, 'maximumSignificantDigits', undefined);
-  }
-  var formatter = %CreateNumberFormat(requestedLocale,
-                                      internalOptions,
-                                      resolved);
-
-  // We can't get information about number or currency style from ICU, so we
-  // assume user request was fulfilled.
-  if (internalOptions.style === 'currency') {
-    $Object.defineProperty(resolved, 'currencyDisplay', {value: currencyDisplay,
-                                                         writable: true});
-  }
-
-  $Object.defineProperty(numberFormat, 'formatter', {value: formatter});
-  $Object.defineProperty(numberFormat, 'resolved', {value: resolved});
-  $Object.defineProperty(numberFormat, '__initializedIntlObject',
-                         {value: 'numberformat'});
-
-  return numberFormat;
-}
-
-
-/**
- * Constructs Intl.NumberFormat object given optional locales and options
- * parameters.
- *
- * @constructor
- */
-%SetProperty(Intl, 'NumberFormat', function() {
-    var locales = arguments[0];
-    var options = arguments[1];
-
-    if (!this || this === Intl) {
-      // Constructor is called as a function.
-      return new Intl.NumberFormat(locales, options);
-    }
-
-    return initializeNumberFormat(toObject(this), locales, options);
-  },
-  DONT_ENUM
-);
-
-
-/**
- * NumberFormat resolvedOptions method.
- */
-%SetProperty(Intl.NumberFormat.prototype, 'resolvedOptions', function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    if (!this || typeof this !== 'object' ||
-        this.__initializedIntlObject !== 'numberformat') {
-      throw new $TypeError('resolvedOptions method called on a non-object' +
-          ' or on a object that is not Intl.NumberFormat.');
-    }
-
-    var format = this;
-    var locale = getOptimalLanguageTag(format.resolved.requestedLocale,
-                                       format.resolved.locale);
-
-    var result = {
-      locale: locale,
-      numberingSystem: format.resolved.numberingSystem,
-      style: format.resolved.style,
-      useGrouping: format.resolved.useGrouping,
-      minimumIntegerDigits: format.resolved.minimumIntegerDigits,
-      minimumFractionDigits: format.resolved.minimumFractionDigits,
-      maximumFractionDigits: format.resolved.maximumFractionDigits,
-    };
-
-    if (result.style === 'currency') {
-      defineWECProperty(result, 'currency', format.resolved.currency);
-      defineWECProperty(result, 'currencyDisplay',
-                        format.resolved.currencyDisplay);
-    }
-
-    if (format.resolved.hasOwnProperty('minimumSignificantDigits')) {
-      defineWECProperty(result, 'minimumSignificantDigits',
-                        format.resolved.minimumSignificantDigits);
-    }
-
-    if (format.resolved.hasOwnProperty('maximumSignificantDigits')) {
-      defineWECProperty(result, 'maximumSignificantDigits',
-                        format.resolved.maximumSignificantDigits);
-    }
-
-    return result;
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.NumberFormat.prototype.resolvedOptions,
-                 'resolvedOptions');
-%FunctionRemovePrototype(Intl.NumberFormat.prototype.resolvedOptions);
-%SetNativeFlag(Intl.NumberFormat.prototype.resolvedOptions);
-
-
-/**
- * Returns the subset of the given locale list for which this locale list
- * has a matching (possibly fallback) locale. Locales appear in the same
- * order in the returned list as in the input list.
- * Options are optional parameter.
- */
-%SetProperty(Intl.NumberFormat, 'supportedLocalesOf', function(locales) {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    return supportedLocalesOf('numberformat', locales, arguments[1]);
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.NumberFormat.supportedLocalesOf, 'supportedLocalesOf');
-%FunctionRemovePrototype(Intl.NumberFormat.supportedLocalesOf);
-%SetNativeFlag(Intl.NumberFormat.supportedLocalesOf);
-
-
-/**
- * Returns a String value representing the result of calling ToNumber(value)
- * according to the effective locale and the formatting options of this
- * NumberFormat.
- */
-function formatNumber(formatter, value) {
-  // Spec treats -0 and +0 as 0.
-  var number = $Number(value);
-  if (number === -0) {
-    number = 0;
-  }
-
-  return %InternalNumberFormat(formatter.formatter, number);
-}
-
-
-/**
- * Returns a Number that represents string value that was passed in.
- */
-function parseNumber(formatter, value) {
-  return %InternalNumberParse(formatter.formatter, $String(value));
-}
-
-
-addBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1);
-addBoundMethod(Intl.NumberFormat, 'v8Parse', parseNumber, 1);
-
-/**
- * Returns a string that matches LDML representation of the options object.
- */
-function toLDMLString(options) {
-  var getOption = getGetOption(options, 'dateformat');
-
-  var ldmlString = '';
-
-  var option = getOption('weekday', 'string', ['narrow', 'short', 'long']);
-  ldmlString += appendToLDMLString(
-      option, {narrow: 'EEEEE', short: 'EEE', long: 'EEEE'});
-
-  option = getOption('era', 'string', ['narrow', 'short', 'long']);
-  ldmlString += appendToLDMLString(
-      option, {narrow: 'GGGGG', short: 'GGG', long: 'GGGG'});
-
-  option = getOption('year', 'string', ['2-digit', 'numeric']);
-  ldmlString += appendToLDMLString(option, {'2-digit': 'yy', 'numeric': 'y'});
-
-  option = getOption('month', 'string',
-                     ['2-digit', 'numeric', 'narrow', 'short', 'long']);
-  ldmlString += appendToLDMLString(option, {'2-digit': 'MM', 'numeric': 'M',
-          'narrow': 'MMMMM', 'short': 'MMM', 'long': 'MMMM'});
-
-  option = getOption('day', 'string', ['2-digit', 'numeric']);
-  ldmlString += appendToLDMLString(
-      option, {'2-digit': 'dd', 'numeric': 'd'});
-
-  var hr12 = getOption('hour12', 'boolean');
-  option = getOption('hour', 'string', ['2-digit', 'numeric']);
-  if (hr12 === undefined) {
-    ldmlString += appendToLDMLString(option, {'2-digit': 'jj', 'numeric': 'j'});
-  } else if (hr12 === true) {
-    ldmlString += appendToLDMLString(option, {'2-digit': 'hh', 'numeric': 'h'});
-  } else {
-    ldmlString += appendToLDMLString(option, {'2-digit': 'HH', 'numeric': 'H'});
-  }
-
-  option = getOption('minute', 'string', ['2-digit', 'numeric']);
-  ldmlString += appendToLDMLString(option, {'2-digit': 'mm', 'numeric': 'm'});
-
-  option = getOption('second', 'string', ['2-digit', 'numeric']);
-  ldmlString += appendToLDMLString(option, {'2-digit': 'ss', 'numeric': 's'});
-
-  option = getOption('timeZoneName', 'string', ['short', 'long']);
-  ldmlString += appendToLDMLString(option, {short: 'v', long: 'vv'});
-
-  return ldmlString;
-}
-
-
-/**
- * Returns either LDML equivalent of the current option or empty string.
- */
-function appendToLDMLString(option, pairs) {
-  if (option !== undefined) {
-    return pairs[option];
-  } else {
-    return '';
-  }
-}
-
-
-/**
- * Returns object that matches LDML representation of the date.
- */
-function fromLDMLString(ldmlString) {
-  // First remove '' quoted text, so we lose 'Uhr' strings.
-  ldmlString = ldmlString.replace(GetQuotedStringRE(), '');
-
-  var options = {};
-  var match = ldmlString.match(/E{3,5}/g);
-  options = appendToDateTimeObject(
-      options, 'weekday', match, {EEEEE: 'narrow', EEE: 'short', EEEE: 'long'});
-
-  match = ldmlString.match(/G{3,5}/g);
-  options = appendToDateTimeObject(
-      options, 'era', match, {GGGGG: 'narrow', GGG: 'short', GGGG: 'long'});
-
-  match = ldmlString.match(/y{1,2}/g);
-  options = appendToDateTimeObject(
-      options, 'year', match, {y: 'numeric', yy: '2-digit'});
-
-  match = ldmlString.match(/M{1,5}/g);
-  options = appendToDateTimeObject(options, 'month', match, {MM: '2-digit',
-      M: 'numeric', MMMMM: 'narrow', MMM: 'short', MMMM: 'long'});
-
-  // Sometimes we get L instead of M for month - standalone name.
-  match = ldmlString.match(/L{1,5}/g);
-  options = appendToDateTimeObject(options, 'month', match, {LL: '2-digit',
-      L: 'numeric', LLLLL: 'narrow', LLL: 'short', LLLL: 'long'});
-
-  match = ldmlString.match(/d{1,2}/g);
-  options = appendToDateTimeObject(
-      options, 'day', match, {d: 'numeric', dd: '2-digit'});
-
-  match = ldmlString.match(/h{1,2}/g);
-  if (match !== null) {
-    options['hour12'] = true;
-  }
-  options = appendToDateTimeObject(
-      options, 'hour', match, {h: 'numeric', hh: '2-digit'});
-
-  match = ldmlString.match(/H{1,2}/g);
-  if (match !== null) {
-    options['hour12'] = false;
-  }
-  options = appendToDateTimeObject(
-      options, 'hour', match, {H: 'numeric', HH: '2-digit'});
-
-  match = ldmlString.match(/m{1,2}/g);
-  options = appendToDateTimeObject(
-      options, 'minute', match, {m: 'numeric', mm: '2-digit'});
-
-  match = ldmlString.match(/s{1,2}/g);
-  options = appendToDateTimeObject(
-      options, 'second', match, {s: 'numeric', ss: '2-digit'});
-
-  match = ldmlString.match(/v{1,2}/g);
-  options = appendToDateTimeObject(
-      options, 'timeZoneName', match, {v: 'short', vv: 'long'});
-
-  return options;
-}
-
-
-function appendToDateTimeObject(options, option, match, pairs) {
-  if (match === null) {
-    if (!options.hasOwnProperty(option)) {
-      defineWEProperty(options, option, undefined);
-    }
-    return options;
-  }
-
-  var property = match[0];
-  defineWEProperty(options, option, pairs[property]);
-
-  return options;
-}
-
-
-/**
- * Returns options with at least default values in it.
- */
-function toDateTimeOptions(options, required, defaults) {
-  if (options === undefined) {
-    options = null;
-  } else {
-    options = toObject(options);
-  }
-
-  options = $Object.apply(this, [options]);
-
-  var needsDefault = true;
-  if ((required === 'date' || required === 'any') &&
-      (options.weekday !== undefined || options.year !== undefined ||
-       options.month !== undefined || options.day !== undefined)) {
-    needsDefault = false;
-  }
-
-  if ((required === 'time' || required === 'any') &&
-      (options.hour !== undefined || options.minute !== undefined ||
-       options.second !== undefined)) {
-    needsDefault = false;
-  }
-
-  if (needsDefault && (defaults === 'date' || defaults === 'all')) {
-    $Object.defineProperty(options, 'year', {value: 'numeric',
-                                             writable: true,
-                                             enumerable: true,
-                                             configurable: true});
-    $Object.defineProperty(options, 'month', {value: 'numeric',
-                                              writable: true,
-                                              enumerable: true,
-                                              configurable: true});
-    $Object.defineProperty(options, 'day', {value: 'numeric',
-                                            writable: true,
-                                            enumerable: true,
-                                            configurable: true});
-  }
-
-  if (needsDefault && (defaults === 'time' || defaults === 'all')) {
-    $Object.defineProperty(options, 'hour', {value: 'numeric',
-                                             writable: true,
-                                             enumerable: true,
-                                             configurable: true});
-    $Object.defineProperty(options, 'minute', {value: 'numeric',
-                                               writable: true,
-                                               enumerable: true,
-                                               configurable: true});
-    $Object.defineProperty(options, 'second', {value: 'numeric',
-                                               writable: true,
-                                               enumerable: true,
-                                               configurable: true});
-  }
-
-  return options;
-}
-
-
-/**
- * Initializes the given object so it's a valid DateTimeFormat instance.
- * Useful for subclassing.
- */
-function initializeDateTimeFormat(dateFormat, locales, options) {
-
-  if (dateFormat.hasOwnProperty('__initializedIntlObject')) {
-    throw new $TypeError('Trying to re-initialize DateTimeFormat object.');
-  }
-
-  if (options === undefined) {
-    options = {};
-  }
-
-  var locale = resolveLocale('dateformat', locales, options);
-
-  options = toDateTimeOptions(options, 'any', 'date');
-
-  var getOption = getGetOption(options, 'dateformat');
-
-  // We implement only best fit algorithm, but still need to check
-  // if the formatMatcher values are in range.
-  var matcher = getOption('formatMatcher', 'string',
-                          ['basic', 'best fit'], 'best fit');
-
-  // Build LDML string for the skeleton that we pass to the formatter.
-  var ldmlString = toLDMLString(options);
-
-  // Filter out supported extension keys so we know what to put in resolved
-  // section later on.
-  // We need to pass calendar and number system to the method.
-  var tz = canonicalizeTimeZoneID(options.timeZone);
-
-  // ICU prefers options to be passed using -u- extension key/values, so
-  // we need to build that.
-  var internalOptions = {};
-  var extensionMap = parseExtension(locale.extension);
-  var extension = setOptions(options, extensionMap, DATETIME_FORMAT_KEY_MAP,
-                             getOption, internalOptions);
-
-  var requestedLocale = locale.locale + extension;
-  var resolved = $Object.defineProperties({}, {
-    calendar: {writable: true},
-    day: {writable: true},
-    era: {writable: true},
-    hour12: {writable: true},
-    hour: {writable: true},
-    locale: {writable: true},
-    minute: {writable: true},
-    month: {writable: true},
-    numberingSystem: {writable: true},
-    pattern: {writable: true},
-    requestedLocale: {value: requestedLocale, writable: true},
-    second: {writable: true},
-    timeZone: {writable: true},
-    timeZoneName: {writable: true},
-    tz: {value: tz, writable: true},
-    weekday: {writable: true},
-    year: {writable: true}
-  });
-
-  var formatter = %CreateDateTimeFormat(
-    requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved);
-
-  if (tz !== undefined && tz !== resolved.timeZone) {
-    throw new $RangeError('Unsupported time zone specified ' + tz);
-  }
-
-  $Object.defineProperty(dateFormat, 'formatter', {value: formatter});
-  $Object.defineProperty(dateFormat, 'resolved', {value: resolved});
-  $Object.defineProperty(dateFormat, '__initializedIntlObject',
-                         {value: 'dateformat'});
-
-  return dateFormat;
-}
-
-
-/**
- * Constructs Intl.DateTimeFormat object given optional locales and options
- * parameters.
- *
- * @constructor
- */
-%SetProperty(Intl, 'DateTimeFormat', function() {
-    var locales = arguments[0];
-    var options = arguments[1];
-
-    if (!this || this === Intl) {
-      // Constructor is called as a function.
-      return new Intl.DateTimeFormat(locales, options);
-    }
-
-    return initializeDateTimeFormat(toObject(this), locales, options);
-  },
-  DONT_ENUM
-);
-
-
-/**
- * DateTimeFormat resolvedOptions method.
- */
-%SetProperty(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    if (!this || typeof this !== 'object' ||
-        this.__initializedIntlObject !== 'dateformat') {
-      throw new $TypeError('resolvedOptions method called on a non-object or ' +
-          'on a object that is not Intl.DateTimeFormat.');
-    }
-
-    var format = this;
-    var fromPattern = fromLDMLString(format.resolved.pattern);
-    var userCalendar = ICU_CALENDAR_MAP[format.resolved.calendar];
-    if (userCalendar === undefined) {
-      // Use ICU name if we don't have a match. It shouldn't happen, but
-      // it would be too strict to throw for this.
-      userCalendar = format.resolved.calendar;
-    }
-
-    var locale = getOptimalLanguageTag(format.resolved.requestedLocale,
-                                       format.resolved.locale);
-
-    var result = {
-      locale: locale,
-      numberingSystem: format.resolved.numberingSystem,
-      calendar: userCalendar,
-      timeZone: format.resolved.timeZone
-    };
-
-    addWECPropertyIfDefined(result, 'timeZoneName', fromPattern.timeZoneName);
-    addWECPropertyIfDefined(result, 'era', fromPattern.era);
-    addWECPropertyIfDefined(result, 'year', fromPattern.year);
-    addWECPropertyIfDefined(result, 'month', fromPattern.month);
-    addWECPropertyIfDefined(result, 'day', fromPattern.day);
-    addWECPropertyIfDefined(result, 'weekday', fromPattern.weekday);
-    addWECPropertyIfDefined(result, 'hour12', fromPattern.hour12);
-    addWECPropertyIfDefined(result, 'hour', fromPattern.hour);
-    addWECPropertyIfDefined(result, 'minute', fromPattern.minute);
-    addWECPropertyIfDefined(result, 'second', fromPattern.second);
-
-    return result;
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.DateTimeFormat.prototype.resolvedOptions,
-                 'resolvedOptions');
-%FunctionRemovePrototype(Intl.DateTimeFormat.prototype.resolvedOptions);
-%SetNativeFlag(Intl.DateTimeFormat.prototype.resolvedOptions);
-
-
-/**
- * Returns the subset of the given locale list for which this locale list
- * has a matching (possibly fallback) locale. Locales appear in the same
- * order in the returned list as in the input list.
- * Options are optional parameter.
- */
-%SetProperty(Intl.DateTimeFormat, 'supportedLocalesOf', function(locales) {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    return supportedLocalesOf('dateformat', locales, arguments[1]);
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.DateTimeFormat.supportedLocalesOf, 'supportedLocalesOf');
-%FunctionRemovePrototype(Intl.DateTimeFormat.supportedLocalesOf);
-%SetNativeFlag(Intl.DateTimeFormat.supportedLocalesOf);
-
-
-/**
- * Returns a String value representing the result of calling ToNumber(date)
- * according to the effective locale and the formatting options of this
- * DateTimeFormat.
- */
-function formatDate(formatter, dateValue) {
-  var dateMs;
-  if (dateValue === undefined) {
-    dateMs = $Date.now();
-  } else {
-    dateMs = $Number(dateValue);
-  }
-
-  if (!$isFinite(dateMs)) {
-    throw new $RangeError('Provided date is not in valid range.');
-  }
-
-  return %InternalDateFormat(formatter.formatter, new $Date(dateMs));
-}
-
-
-/**
- * Returns a Date object representing the result of calling ToString(value)
- * according to the effective locale and the formatting options of this
- * DateTimeFormat.
- * Returns undefined if date string cannot be parsed.
- */
-function parseDate(formatter, value) {
-  return %InternalDateParse(formatter.formatter, $String(value));
-}
-
-
-// 0 because date is optional argument.
-addBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0);
-addBoundMethod(Intl.DateTimeFormat, 'v8Parse', parseDate, 1);
-
-
-/**
- * Returns canonical Area/Location name, or throws an exception if the zone
- * name is invalid IANA name.
- */
-function canonicalizeTimeZoneID(tzID) {
-  // Skip undefined zones.
-  if (tzID === undefined) {
-    return tzID;
-  }
-
-  // Special case handling (UTC, GMT).
-  var upperID = tzID.toUpperCase();
-  if (upperID === 'UTC' || upperID === 'GMT' ||
-      upperID === 'ETC/UTC' || upperID === 'ETC/GMT') {
-    return 'UTC';
-  }
-
-  // We expect only _ and / beside ASCII letters.
-  // All inputs should conform to Area/Location from now on.
-  var match = GetTimezoneNameCheckRE().exec(tzID);
-  if (match === null) {
-    throw new $RangeError('Expected Area/Location for time zone, got ' + tzID);
-  }
-
-  var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]);
-  var i = 3;
-  while (match[i] !== undefined && i < match.length) {
-    result = result + '_' + toTitleCaseWord(match[i]);
-    i++;
-  }
-
-  return result;
-}
-
-/**
- * Initializes the given object so it's a valid BreakIterator instance.
- * Useful for subclassing.
- */
-function initializeBreakIterator(iterator, locales, options) {
-  if (iterator.hasOwnProperty('__initializedIntlObject')) {
-    throw new $TypeError('Trying to re-initialize v8BreakIterator object.');
-  }
-
-  if (options === undefined) {
-    options = {};
-  }
-
-  var getOption = getGetOption(options, 'breakiterator');
-
-  var internalOptions = {};
-
-  defineWEProperty(internalOptions, 'type', getOption(
-    'type', 'string', ['character', 'word', 'sentence', 'line'], 'word'));
-
-  var locale = resolveLocale('breakiterator', locales, options);
-  var resolved = $Object.defineProperties({}, {
-    requestedLocale: {value: locale.locale, writable: true},
-    type: {value: internalOptions.type, writable: true},
-    locale: {writable: true}
-  });
-
-  var internalIterator = %CreateBreakIterator(locale.locale,
-                                              internalOptions,
-                                              resolved);
-
-  $Object.defineProperty(iterator, 'iterator', {value: internalIterator});
-  $Object.defineProperty(iterator, 'resolved', {value: resolved});
-  $Object.defineProperty(iterator, '__initializedIntlObject',
-                         {value: 'breakiterator'});
-
-  return iterator;
-}
-
-
-/**
- * Constructs Intl.v8BreakIterator object given optional locales and options
- * parameters.
- *
- * @constructor
- */
-%SetProperty(Intl, 'v8BreakIterator', function() {
-    var locales = arguments[0];
-    var options = arguments[1];
-
-    if (!this || this === Intl) {
-      // Constructor is called as a function.
-      return new Intl.v8BreakIterator(locales, options);
-    }
-
-    return initializeBreakIterator(toObject(this), locales, options);
-  },
-  DONT_ENUM
-);
-
-
-/**
- * BreakIterator resolvedOptions method.
- */
-%SetProperty(Intl.v8BreakIterator.prototype, 'resolvedOptions', function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    if (!this || typeof this !== 'object' ||
-        this.__initializedIntlObject !== 'breakiterator') {
-      throw new $TypeError('resolvedOptions method called on a non-object or ' +
-          'on a object that is not Intl.v8BreakIterator.');
-    }
-
-    var segmenter = this;
-    var locale = getOptimalLanguageTag(segmenter.resolved.requestedLocale,
-                                       segmenter.resolved.locale);
-
-    return {
-      locale: locale,
-      type: segmenter.resolved.type
-    };
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.v8BreakIterator.prototype.resolvedOptions,
-                 'resolvedOptions');
-%FunctionRemovePrototype(Intl.v8BreakIterator.prototype.resolvedOptions);
-%SetNativeFlag(Intl.v8BreakIterator.prototype.resolvedOptions);
-
-
-/**
- * Returns the subset of the given locale list for which this locale list
- * has a matching (possibly fallback) locale. Locales appear in the same
- * order in the returned list as in the input list.
- * Options are optional parameter.
- */
-%SetProperty(Intl.v8BreakIterator, 'supportedLocalesOf', function(locales) {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    return supportedLocalesOf('breakiterator', locales, arguments[1]);
-  },
-  DONT_ENUM
-);
-%FunctionSetName(Intl.v8BreakIterator.supportedLocalesOf, 'supportedLocalesOf');
-%FunctionRemovePrototype(Intl.v8BreakIterator.supportedLocalesOf);
-%SetNativeFlag(Intl.v8BreakIterator.supportedLocalesOf);
-
-
-/**
- * Adopts text to segment using the iterator. Old text, if present,
- * gets discarded.
- */
-function adoptText(iterator, text) {
-  %BreakIteratorAdoptText(iterator.iterator, $String(text));
-}
-
-
-/**
- * Returns index of the first break in the string and moves current pointer.
- */
-function first(iterator) {
-  return %BreakIteratorFirst(iterator.iterator);
-}
-
-
-/**
- * Returns the index of the next break and moves the pointer.
- */
-function next(iterator) {
-  return %BreakIteratorNext(iterator.iterator);
-}
-
-
-/**
- * Returns index of the current break.
- */
-function current(iterator) {
-  return %BreakIteratorCurrent(iterator.iterator);
-}
-
-
-/**
- * Returns type of the current break.
- */
-function breakType(iterator) {
-  return %BreakIteratorBreakType(iterator.iterator);
-}
-
-
-addBoundMethod(Intl.v8BreakIterator, 'adoptText', adoptText, 1);
-addBoundMethod(Intl.v8BreakIterator, 'first', first, 0);
-addBoundMethod(Intl.v8BreakIterator, 'next', next, 0);
-addBoundMethod(Intl.v8BreakIterator, 'current', current, 0);
-addBoundMethod(Intl.v8BreakIterator, 'breakType', breakType, 0);
-
-// Save references to Intl objects and methods we use, for added security.
-var savedObjects = {
-  'collator': Intl.Collator,
-  'numberformat': Intl.NumberFormat,
-  'dateformatall': Intl.DateTimeFormat,
-  'dateformatdate': Intl.DateTimeFormat,
-  'dateformattime': Intl.DateTimeFormat
-};
-
-
-// Default (created with undefined locales and options parameters) collator,
-// number and date format instances. They'll be created as needed.
-var defaultObjects = {
-  'collator': undefined,
-  'numberformat': undefined,
-  'dateformatall': undefined,
-  'dateformatdate': undefined,
-  'dateformattime': undefined,
-};
-
-
-/**
- * Returns cached or newly created instance of a given service.
- * We cache only default instances (where no locales or options are provided).
- */
-function cachedOrNewService(service, locales, options, defaults) {
-  var useOptions = (defaults === undefined) ? options : defaults;
-  if (locales === undefined && options === undefined) {
-    if (defaultObjects[service] === undefined) {
-      defaultObjects[service] = new savedObjects[service](locales, useOptions);
-    }
-    return defaultObjects[service];
-  }
-  return new savedObjects[service](locales, useOptions);
-}
-
-
-/**
- * Compares this and that, and returns less than 0, 0 or greater than 0 value.
- * Overrides the built-in method.
- */
-$Object.defineProperty($String.prototype, 'localeCompare', {
-  value: function(that) {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    if (this === undefined || this === null) {
-      throw new $TypeError('Method invoked on undefined or null value.');
-    }
-
-    var locales = arguments[1];
-    var options = arguments[2];
-    var collator = cachedOrNewService('collator', locales, options);
-    return compare(collator, this, that);
-  },
-  writable: true,
-  configurable: true,
-  enumerable: false
-});
-%FunctionSetName($String.prototype.localeCompare, 'localeCompare');
-%FunctionRemovePrototype($String.prototype.localeCompare);
-%SetNativeFlag($String.prototype.localeCompare);
-
-
-/**
- * Formats a Number object (this) using locale and options values.
- * If locale or options are omitted, defaults are used.
- */
-$Object.defineProperty($Number.prototype, 'toLocaleString', {
-  value: function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    if (!(this instanceof $Number) && typeof(this) !== 'number') {
-      throw new $TypeError('Method invoked on an object that is not Number.');
-    }
-
-    var locales = arguments[0];
-    var options = arguments[1];
-    var numberFormat = cachedOrNewService('numberformat', locales, options);
-    return formatNumber(numberFormat, this);
-  },
-  writable: true,
-  configurable: true,
-  enumerable: false
-});
-%FunctionSetName($Number.prototype.toLocaleString, 'toLocaleString');
-%FunctionRemovePrototype($Number.prototype.toLocaleString);
-%SetNativeFlag($Number.prototype.toLocaleString);
-
-
-/**
- * Returns actual formatted date or fails if date parameter is invalid.
- */
-function toLocaleDateTime(date, locales, options, required, defaults, service) {
-  if (!(date instanceof $Date)) {
-    throw new $TypeError('Method invoked on an object that is not Date.');
-  }
-
-  if ($isNaN(date)) {
-    return 'Invalid Date';
-  }
-
-  var internalOptions = toDateTimeOptions(options, required, defaults);
-
-  var dateFormat =
-      cachedOrNewService(service, locales, options, internalOptions);
-
-  return formatDate(dateFormat, date);
-}
-
-
-/**
- * Formats a Date object (this) using locale and options values.
- * If locale or options are omitted, defaults are used - both date and time are
- * present in the output.
- */
-$Object.defineProperty($Date.prototype, 'toLocaleString', {
-  value: function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    var locales = arguments[0];
-    var options = arguments[1];
-    return toLocaleDateTime(
-        this, locales, options, 'any', 'all', 'dateformatall');
-  },
-  writable: true,
-  configurable: true,
-  enumerable: false
-});
-%FunctionSetName($Date.prototype.toLocaleString, 'toLocaleString');
-%FunctionRemovePrototype($Date.prototype.toLocaleString);
-%SetNativeFlag($Date.prototype.toLocaleString);
-
-
-/**
- * Formats a Date object (this) using locale and options values.
- * If locale or options are omitted, defaults are used - only date is present
- * in the output.
- */
-$Object.defineProperty($Date.prototype, 'toLocaleDateString', {
-  value: function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    var locales = arguments[0];
-    var options = arguments[1];
-    return toLocaleDateTime(
-        this, locales, options, 'date', 'date', 'dateformatdate');
-  },
-  writable: true,
-  configurable: true,
-  enumerable: false
-});
-%FunctionSetName($Date.prototype.toLocaleDateString, 'toLocaleDateString');
-%FunctionRemovePrototype($Date.prototype.toLocaleDateString);
-%SetNativeFlag($Date.prototype.toLocaleDateString);
-
-
-/**
- * Formats a Date object (this) using locale and options values.
- * If locale or options are omitted, defaults are used - only time is present
- * in the output.
- */
-$Object.defineProperty($Date.prototype, 'toLocaleTimeString', {
-  value: function() {
-    if (%_IsConstructCall()) {
-      throw new $TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
-    }
-
-    var locales = arguments[0];
-    var options = arguments[1];
-    return toLocaleDateTime(
-        this, locales, options, 'time', 'time', 'dateformattime');
-  },
-  writable: true,
-  configurable: true,
-  enumerable: false
-});
-%FunctionSetName($Date.prototype.toLocaleTimeString, 'toLocaleTimeString');
-%FunctionRemovePrototype($Date.prototype.toLocaleTimeString);
-%SetNativeFlag($Date.prototype.toLocaleTimeString);
-
-return Intl;
-}())});
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index ab4e0a4..7ff6913 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -101,80 +101,28 @@
     return;  // No features if we might serialize.
   }
 
-  const int kBufferSize = 4 * KB;
-  VirtualMemory* memory = new VirtualMemory(kBufferSize);
-  if (!memory->IsReserved()) {
-    delete memory;
-    return;
+  uint64_t probed_features = 0;
+  CPU cpu;
+  if (cpu.has_sse41()) {
+    probed_features |= static_cast<uint64_t>(1) << SSE4_1;
   }
-  ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
-  if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
-    delete memory;
-    return;
+  if (cpu.has_sse3()) {
+    probed_features |= static_cast<uint64_t>(1) << SSE3;
+  }
+  if (cpu.has_sse2()) {
+    probed_features |= static_cast<uint64_t>(1) << SSE2;
+  }
+  if (cpu.has_cmov()) {
+    probed_features |= static_cast<uint64_t>(1) << CMOV;
   }
 
-  Assembler assm(NULL, memory->address(), kBufferSize);
-  Label cpuid, done;
-#define __ assm.
-  // Save old esp, since we are going to modify the stack.
-  __ push(ebp);
-  __ pushfd();
-  __ push(ecx);
-  __ push(ebx);
-  __ mov(ebp, esp);
+  // SAHF must be available in compat/legacy mode.
+  ASSERT(cpu.has_sahf());
+  probed_features |= static_cast<uint64_t>(1) << SAHF;
 
-  // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
-  __ pushfd();
-  __ pop(eax);
-  __ mov(edx, eax);
-  __ xor_(eax, 0x200000);  // Flip bit 21.
-  __ push(eax);
-  __ popfd();
-  __ pushfd();
-  __ pop(eax);
-  __ xor_(eax, edx);  // Different if CPUID is supported.
-  __ j(not_zero, &cpuid);
-
-  // CPUID not supported. Clear the supported features in edx:eax.
-  __ xor_(eax, eax);
-  __ xor_(edx, edx);
-  __ jmp(&done);
-
-  // Invoke CPUID with 1 in eax to get feature information in
-  // ecx:edx. Temporarily enable CPUID support because we know it's
-  // safe here.
-  __ bind(&cpuid);
-  __ mov(eax, 1);
-  supported_ = (1 << CPUID);
-  { CpuFeatureScope fscope(&assm, CPUID);
-    __ cpuid();
-  }
-  supported_ = 0;
-
-  // Move the result from ecx:edx to edx:eax and make sure to mark the
-  // CPUID feature as supported.
-  __ mov(eax, edx);
-  __ or_(eax, 1 << CPUID);
-  __ mov(edx, ecx);
-
-  // Done.
-  __ bind(&done);
-  __ mov(esp, ebp);
-  __ pop(ebx);
-  __ pop(ecx);
-  __ popfd();
-  __ pop(ebp);
-  __ ret(0);
-#undef __
-
-  typedef uint64_t (*F0)();
-  F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
-  uint64_t probed_features = probe();
   uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
   supported_ = probed_features | platform_features;
   found_by_runtime_probing_only_ = probed_features & ~platform_features;
-
-  delete memory;
 }
 
 
@@ -474,7 +422,6 @@
 
 
 void Assembler::cpuid() {
-  ASSERT(IsEnabled(CPUID));
   EnsureSpace ensure_space(this);
   EMIT(0x0F);
   EMIT(0xA2);
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 892b66e..293d428 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -606,7 +606,7 @@
     }
     ASSERT_NE(NULL, mnem);
     AppendToBuffer("%s %s,", mnem, NameOfCPURegister(rm));
-    if (imm8 > 0) {
+    if (imm8 >= 0) {
       AppendToBuffer("%d", imm8);
     } else {
       AppendToBuffer("cl");
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 10115b1..81c22e2 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -1787,8 +1787,8 @@
       case Token::ROR:
         __ ror_cl(ToRegister(left));
         if (instr->can_deopt()) {
-          __ test(ToRegister(left), Immediate(0x80000000));
-          DeoptimizeIf(not_zero, instr->environment());
+          __ test(ToRegister(left), ToRegister(left));
+          DeoptimizeIf(sign, instr->environment());
         }
         break;
       case Token::SAR:
@@ -1797,8 +1797,8 @@
       case Token::SHR:
         __ shr_cl(ToRegister(left));
         if (instr->can_deopt()) {
-          __ test(ToRegister(left), Immediate(0x80000000));
-          DeoptimizeIf(not_zero, instr->environment());
+          __ test(ToRegister(left), ToRegister(left));
+          DeoptimizeIf(sign, instr->environment());
         }
         break;
       case Token::SHL:
@@ -1814,8 +1814,8 @@
     switch (instr->op()) {
       case Token::ROR:
         if (shift_count == 0 && instr->can_deopt()) {
-          __ test(ToRegister(left), Immediate(0x80000000));
-          DeoptimizeIf(not_zero, instr->environment());
+          __ test(ToRegister(left), ToRegister(left));
+          DeoptimizeIf(sign, instr->environment());
         } else {
           __ ror(ToRegister(left), shift_count);
         }
@@ -1827,8 +1827,8 @@
         break;
       case Token::SHR:
         if (shift_count == 0 && instr->can_deopt()) {
-          __ test(ToRegister(left), Immediate(0x80000000));
-          DeoptimizeIf(not_zero, instr->environment());
+          __ test(ToRegister(left), ToRegister(left));
+          DeoptimizeIf(sign, instr->environment());
         } else {
           __ shr(ToRegister(left), shift_count);
         }
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 2c4799e..2fdbb98 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -2564,6 +2564,9 @@
 
 
 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
+  HEnvironment* env = current_block_->last_environment();
+  instr->ReplayEnvironment(env);
+
   // There are no real uses of a captured object.
   return NULL;
 }
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index f86820c..bf785df 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -2774,6 +2774,11 @@
     RecordComment("Abort message: ");
     RecordComment(msg);
   }
+
+  if (FLAG_trap_on_abort) {
+    int3();
+    return;
+  }
 #endif
 
   push(eax);
diff --git a/src/lazy-instance.h b/src/lazy-instance.h
index 9d68b8c..fc03f4d 100644
--- a/src/lazy-instance.h
+++ b/src/lazy-instance.h
@@ -91,12 +91,13 @@
 #ifndef V8_LAZY_INSTANCE_H_
 #define V8_LAZY_INSTANCE_H_
 
+#include "checks.h"
 #include "once.h"
 
 namespace v8 {
 namespace internal {
 
-#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, {} }
+#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, { {} } }
 #define LAZY_DYNAMIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, 0 }
 
 // Default to static mode.
@@ -111,17 +112,15 @@
 
 // Traits that define how an instance is allocated and accessed.
 
-// TODO(kalmard): __alignof__ is only defined for GCC > 4.2. Fix alignment issue
-// on MIPS with other compilers.
-#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2))
-#define LAZY_ALIGN(x) __attribute__((aligned(__alignof__(x))))
-#else
-#define LAZY_ALIGN(x)
-#endif
 
 template <typename T>
 struct StaticallyAllocatedInstanceTrait {
-  typedef char StorageType[sizeof(T)] LAZY_ALIGN(T);
+  // 16-byte alignment fallback to be on the safe side here.
+  struct V8_ALIGNAS(T, 16) StorageType {
+    char x[sizeof(T)];
+  };
+
+  STATIC_ASSERT(V8_ALIGNOF(StorageType) >= V8_ALIGNOF(T));
 
   static T* MutableInstance(StorageType* storage) {
     return reinterpret_cast<T*>(storage);
@@ -133,8 +132,6 @@
   }
 };
 
-#undef LAZY_ALIGN
-
 
 template <typename T>
 struct DynamicallyAllocatedInstanceTrait {
diff --git a/src/log.cc b/src/log.cc
index e93a760..ff67d10 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -560,6 +560,14 @@
     }
   }
 
+  virtual void Run();
+
+  // Pause and Resume TickSample data collection.
+  bool paused() const { return paused_; }
+  void pause() { paused_ = true; }
+  void resume() { paused_ = false; }
+
+ private:
   // Waits for a signal and removes profiling data.
   bool Remove(TickSample* sample) {
     buffer_semaphore_->Wait();  // Wait for an element.
@@ -570,14 +578,6 @@
     return result;
   }
 
-  void Run();
-
-  // Pause and Resume TickSample data collection.
-  bool paused() const { return paused_; }
-  void pause() { paused_ = true; }
-  void resume() { paused_ = false; }
-
- private:
   // Returns the next index in the cyclic buffer.
   int Succ(int index) { return (index + 1) % kBufferSize; }
 
@@ -589,7 +589,8 @@
   int head_;  // Index to the buffer head.
   int tail_;  // Index to the buffer tail.
   bool overflow_;  // Tell whether a buffer overflow has occurred.
-  Semaphore* buffer_semaphore_;  // Sempahore used for buffer synchronization.
+  // Sempahore used for buffer synchronization.
+  SmartPointer<Semaphore> buffer_semaphore_;
 
   // Tells whether profiler is engaged, that is, processing thread is stated.
   bool engaged_;
@@ -1233,7 +1234,7 @@
                              Code* code,
                              SharedFunctionInfo* shared,
                              CompilationInfo* info,
-                             Name* source, int line) {
+                             Name* source, int line, int column) {
   PROFILER_LOG(CodeCreateEvent(tag, code, shared, info, source, line));
 
   if (!is_logging_code_events()) return;
@@ -1252,7 +1253,7 @@
   } else {
     msg.AppendSymbolName(Symbol::cast(source));
   }
-  msg.Append(":%d\",", line);
+  msg.Append(":%d:%d\",", line, column);
   msg.AppendAddress(shared->address());
   msg.Append(",%s", ComputeMarker(code));
   msg.Append('\n');
@@ -1712,6 +1713,8 @@
   if (shared->script()->IsScript()) {
     Handle<Script> script(Script::cast(shared->script()));
     int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
+    int column_num =
+        GetScriptColumnNumber(script, shared->start_position()) + 1;
     if (script->name()->IsString()) {
       Handle<String> script_name(String::cast(script->name()));
       if (line_num > 0) {
@@ -1719,7 +1722,7 @@
                 CodeCreateEvent(
                     Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
                     *code, *shared, NULL,
-                    *script_name, line_num));
+                    *script_name, line_num, column_num));
       } else {
         // Can't distinguish eval and script here, so always use Script.
         PROFILE(isolate_,
@@ -1732,7 +1735,7 @@
               CodeCreateEvent(
                   Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
                   *code, *shared, NULL,
-                  isolate_->heap()->empty_string(), line_num));
+                  isolate_->heap()->empty_string(), line_num, column_num));
     }
   } else if (shared->IsApiFunction()) {
     // API function.
diff --git a/src/log.h b/src/log.h
index f046ad7..76e3cee 100644
--- a/src/log.h
+++ b/src/log.h
@@ -248,7 +248,7 @@
                        Code* code,
                        SharedFunctionInfo* shared,
                        CompilationInfo* info,
-                       Name* source, int line);
+                       Name* source, int line, int column);
   void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
   void CodeMovingGCEvent();
   // Emits a code create event for a RegExp.
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index 3e02f32..0bb00b4 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -126,7 +126,8 @@
   supported_ |= static_cast<uint64_t>(1) << FPU;
 #else
   // Probe for additional features not already known to be available.
-  if (OS::MipsCpuHasFeature(FPU)) {
+  CPU cpu;
+  if (cpu.has_fpu()) {
     // This implementation also sets the FPU flags if
     // runtime detection of FPU returns true.
     supported_ |= static_cast<uint64_t>(1) << FPU;
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 907c5b6..8025d8e 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -2361,6 +2361,9 @@
 
 
 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
+  HEnvironment* env = current_block_->last_environment();
+  instr->ReplayEnvironment(env);
+
   // There are no real uses of a captured object.
   return NULL;
 }
diff --git a/src/mksnapshot.cc b/src/mksnapshot.cc
index a4b5ae1..c1edcb1 100644
--- a/src/mksnapshot.cc
+++ b/src/mksnapshot.cc
@@ -314,6 +314,9 @@
   // By default, log code create information in the snapshot.
   i::FLAG_log_code = true;
 
+  // Disable the i18n extension, as it doesn't support being snapshotted yet.
+  i::FLAG_enable_i18n = false;
+
   // Print the usage if an error occurs when parsing the command line
   // flags or if the help flag is set.
   int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
diff --git a/src/natives.h b/src/natives.h
index 5f34420..e3f69d1 100644
--- a/src/natives.h
+++ b/src/natives.h
@@ -36,7 +36,7 @@
                                      int index);
 
 enum NativeType {
-  CORE, EXPERIMENTAL, D8, TEST
+  CORE, EXPERIMENTAL, D8, TEST, I18N
 };
 
 template <NativeType type>
@@ -61,6 +61,7 @@
 
 typedef NativesCollection<CORE> Natives;
 typedef NativesCollection<EXPERIMENTAL> ExperimentalNatives;
+typedef NativesCollection<I18N> I18NNatives;
 
 } }  // namespace v8::internal
 
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index e0cb8c9..a61eacf 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -856,6 +856,7 @@
   CHECK(IsAccessorPair());
   VerifyPointer(getter());
   VerifyPointer(setter());
+  VerifySmiField(kAccessFlagsOffset);
 }
 
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index ad5b0e3..22d1ac3 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1865,14 +1865,15 @@
 }
 
 
-bool JSObject::TooManyFastProperties(int properties,
-                                     JSObject::StoreFromKeyed store_mode) {
+bool JSObject::TooManyFastProperties(StoreFromKeyed store_mode) {
   // Allow extra fast properties if the object has more than
-  // kFastPropertiesSoftLimit in-object properties. When this is the case,
-  // it is very unlikely that the object is being used as a dictionary
-  // and there is a good chance that allowing more map transitions
-  // will be worth it.
-  int inobject = map()->inobject_properties();
+  // kFastPropertiesSoftLimit in-object properties. When this is the case, it is
+  // very unlikely that the object is being used as a dictionary and there is a
+  // good chance that allowing more map transitions will be worth it.
+  Map* map = this->map();
+  if (map->unused_property_fields() != 0) return false;
+
+  int inobject = map->inobject_properties();
 
   int limit;
   if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED) {
@@ -1880,7 +1881,7 @@
   } else {
     limit = Max(inobject, kFastPropertiesSoftLimit);
   }
-  return properties > limit;
+  return properties()->length() > limit;
 }
 
 
@@ -4454,6 +4455,7 @@
 
 ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
 ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
+ACCESSORS_TO_SMI(AccessorPair, access_flags, kAccessFlagsOffset)
 
 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
 ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
@@ -5850,6 +5852,36 @@
 }
 
 
+void AccessorPair::set_access_flags(v8::AccessControl access_control) {
+  int current = access_flags()->value();
+  current = BooleanBit::set(current,
+                            kProhibitsOverwritingBit,
+                            access_control & PROHIBITS_OVERWRITING);
+  current = BooleanBit::set(current,
+                            kAllCanReadBit,
+                            access_control & ALL_CAN_READ);
+  current = BooleanBit::set(current,
+                            kAllCanWriteBit,
+                            access_control & ALL_CAN_WRITE);
+  set_access_flags(Smi::FromInt(current));
+}
+
+
+bool AccessorPair::all_can_read() {
+  return BooleanBit::get(access_flags(), kAllCanReadBit);
+}
+
+
+bool AccessorPair::all_can_write() {
+  return BooleanBit::get(access_flags(), kAllCanWriteBit);
+}
+
+
+bool AccessorPair::prohibits_overwriting() {
+  return BooleanBit::get(access_flags(), kProhibitsOverwritingBit);
+}
+
+
 template<typename Shape, typename Key>
 void Dictionary<Shape, Key>::SetEntry(int entry,
                                       Object* key,
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 7b6f7a4..9ea060f 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -985,6 +985,8 @@
   getter()->ShortPrint(out);
   PrintF(out, "\n - setter: ");
   setter()->ShortPrint(out);
+  PrintF(out, "\n - flag: ");
+  access_flags()->ShortPrint(out);
 }
 
 
diff --git a/src/objects.cc b/src/objects.cc
index daa5a4a..d8a05eb 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -513,6 +513,12 @@
             return result->holder()->GetPropertyWithCallback(
                 receiver, result->GetCallbackObject(), name);
           }
+        } else if (obj->IsAccessorPair()) {
+          AccessorPair* pair = AccessorPair::cast(obj);
+          if (pair->all_can_read()) {
+            return result->holder()->GetPropertyWithCallback(
+                receiver, result->GetCallbackObject(), name);
+          }
         }
         break;
       }
@@ -573,6 +579,11 @@
           if (info->all_can_read()) {
             return result->GetAttributes();
           }
+        } else if (obj->IsAccessorPair()) {
+          AccessorPair* pair = AccessorPair::cast(obj);
+          if (pair->all_can_read()) {
+            return result->GetAttributes();
+          }
         }
         break;
       }
@@ -1916,7 +1927,8 @@
                                        Object* value,
                                        PropertyAttributes attributes,
                                        StoreFromKeyed store_mode,
-                                       ValueType value_type) {
+                                       ValueType value_type,
+                                       TransitionFlag flag) {
   ASSERT(!IsJSGlobalProxy());
   ASSERT(DescriptorArray::kNotFound ==
          map()->instance_descriptors()->Search(
@@ -1926,15 +1938,13 @@
   // hidden strings) and is not a real identifier.
   // Normalize the object if it will have too many fast properties.
   Isolate* isolate = GetHeap()->isolate();
-  if ((!name->IsSymbol() && !IsIdentifier(isolate->unicode_cache(), name)
-       && name != isolate->heap()->hidden_string()) ||
-      (map()->unused_property_fields() == 0 &&
-       TooManyFastProperties(properties()->length(), store_mode))) {
-    Object* obj;
-    MaybeObject* maybe_obj =
+  if ((!name->IsSymbol() &&
+       !IsIdentifier(isolate->unicode_cache(), name) &&
+       name != isolate->heap()->hidden_string()) ||
+      TooManyFastProperties(store_mode)) {
+    MaybeObject* maybe_failure =
         NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-
+    if (maybe_failure->IsFailure()) return maybe_failure;
     return AddSlowProperty(name, value, attributes);
   }
 
@@ -1961,8 +1971,6 @@
     if (!maybe_values->To(&values)) return maybe_values;
   }
 
-  TransitionFlag flag = INSERT_TRANSITION;
-
   Heap* heap = isolate->heap();
 
   Object* storage;
@@ -1995,7 +2003,8 @@
 MaybeObject* JSObject::AddConstantProperty(
     Name* name,
     Object* constant,
-    PropertyAttributes attributes) {
+    PropertyAttributes attributes,
+    TransitionFlag initial_flag) {
   // Allocate new instance descriptors with (name, constant) added
   ConstantDescriptor d(name, constant, attributes);
 
@@ -2006,7 +2015,7 @@
       // attributes.
        attributes != NONE)
       ? OMIT_TRANSITION
-      : INSERT_TRANSITION;
+      : initial_flag;
 
   Map* new_map;
   MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag);
@@ -2066,7 +2075,8 @@
                                    JSReceiver::StoreFromKeyed store_mode,
                                    ExtensibilityCheck extensibility_check,
                                    ValueType value_type,
-                                   StoreMode mode) {
+                                   StoreMode mode,
+                                   TransitionFlag transition_flag) {
   ASSERT(!IsJSGlobalProxy());
   Map* map_of_this = map();
   Heap* heap = GetHeap();
@@ -2093,10 +2103,10 @@
       //     !value->IsTheHole() &&
       //     !value->IsConsString()) {
       if (value->IsJSFunction()) {
-        result = AddConstantProperty(name, value, attributes);
+        result = AddConstantProperty(name, value, attributes, transition_flag);
       } else {
         result = AddFastProperty(
-            name, value, attributes, store_mode, value_type);
+            name, value, attributes, store_mode, value_type, transition_flag);
       }
     } else {
       // Normalize the object to prevent very large instance descriptors.
@@ -2200,56 +2210,6 @@
 }
 
 
-MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
-                                                Object* new_value,
-                                                PropertyAttributes attributes,
-                                                TransitionFlag flag) {
-  if (map()->unused_property_fields() == 0 &&
-      TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
-    Object* obj;
-    MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
-    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
-    return ReplaceSlowProperty(name, new_value, attributes);
-  }
-
-  Representation representation = IsJSContextExtensionObject()
-      ? Representation::Tagged() : new_value->OptimalRepresentation();
-  int index = map()->NextFreePropertyIndex();
-  FieldDescriptor new_field(name, index, attributes, representation);
-
-  // Make a new map for the object.
-  Map* new_map;
-  MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, flag);
-  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
-
-  // Make new properties array if necessary.
-  FixedArray* new_properties = NULL;
-  int new_unused_property_fields = map()->unused_property_fields() - 1;
-  if (map()->unused_property_fields() == 0) {
-    new_unused_property_fields = kFieldsAdded - 1;
-    MaybeObject* maybe_new_properties =
-        properties()->CopySize(properties()->length() + kFieldsAdded);
-    if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties;
-  }
-
-  Heap* heap = GetHeap();
-  Object* storage;
-  MaybeObject* maybe_storage =
-      new_value->AllocateNewStorageFor(heap, representation);
-  if (!maybe_storage->To(&storage)) return maybe_storage;
-
-  // Update pointers to commit changes.
-  // Object points to the new map.
-  new_map->set_unused_property_fields(new_unused_property_fields);
-  set_map(new_map);
-  if (new_properties != NULL) {
-    set_properties(new_properties);
-  }
-  FastPropertyAtPut(index, storage);
-  return new_value;
-}
-
-
 const char* Representation::Mnemonic() const {
   switch (kind_) {
     case kNone: return "v";
@@ -2396,6 +2356,10 @@
     PropertyDetails details = new_descriptors->GetDetails(i);
     if (details.type() != FIELD) continue;
     PropertyDetails old_details = old_descriptors->GetDetails(i);
+    if (old_details.type() == CALLBACKS) {
+      ASSERT(details.representation().IsTagged());
+      continue;
+    }
     ASSERT(old_details.type() == CONSTANT ||
            old_details.type() == FIELD);
     Object* value = old_details.type() == CONSTANT
@@ -2477,6 +2441,7 @@
 MaybeObject* Map::CopyGeneralizeAllRepresentations(
     int modify_index,
     StoreMode store_mode,
+    PropertyAttributes attributes,
     const char* reason) {
   Map* new_map;
   MaybeObject* maybe_map = this->Copy();
@@ -2490,7 +2455,7 @@
   if (store_mode == FORCE_FIELD && details.type() != FIELD) {
     FieldDescriptor d(descriptors->GetKey(modify_index),
                       new_map->NumberOfFields(),
-                      details.attributes(),
+                      attributes,
                       Representation::Tagged());
     d.SetSortedKeyIndex(details.pointer());
     descriptors->Set(modify_index, &d);
@@ -2655,8 +2620,8 @@
                                            StoreMode store_mode) {
   Map* old_map = this;
   DescriptorArray* old_descriptors = old_map->instance_descriptors();
-  Representation old_representation =
-      old_descriptors->GetDetails(modify_index).representation();
+  PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
+  Representation old_representation = old_details.representation();
 
   // It's fine to transition from None to anything but double without any
   // modification to the object, because the default uninitialized value for
@@ -2675,21 +2640,22 @@
   // Check the state of the root map.
   if (!old_map->EquivalentToForTransition(root_map)) {
     return CopyGeneralizeAllRepresentations(
-        modify_index, store_mode, "not equivalent");
+        modify_index, store_mode, old_details.attributes(), "not equivalent");
   }
 
   int verbatim = root_map->NumberOfOwnDescriptors();
 
   if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) {
     return CopyGeneralizeAllRepresentations(
-        modify_index, store_mode, "root modification");
+        modify_index, store_mode,
+        old_details.attributes(), "root modification");
   }
 
   Map* updated = root_map->FindUpdatedMap(
       verbatim, descriptors, old_descriptors);
   if (updated == NULL) {
     return CopyGeneralizeAllRepresentations(
-        modify_index, store_mode, "incompatible");
+        modify_index, store_mode, old_details.attributes(), "incompatible");
   }
 
   DescriptorArray* updated_descriptors = updated->instance_descriptors();
@@ -3395,6 +3361,15 @@
                                              result->holder(),
                                              strict_mode);
             }
+          } else if (obj->IsAccessorPair()) {
+            AccessorPair* pair = AccessorPair::cast(obj);
+            if (pair->all_can_read()) {
+              return SetPropertyWithCallback(result->GetCallbackObject(),
+                                             name,
+                                             value,
+                                             result->holder(),
+                                             strict_mode);
+            }
           }
           break;
         }
@@ -3796,8 +3771,14 @@
   PropertyDetails details = descriptors->GetDetails(descriptor);
 
   if (details.type() == CALLBACKS || attributes != details.attributes()) {
-    return lookup->holder()->ConvertDescriptorToField(
-        *name, *value, attributes);
+    // AddProperty will either normalize the object, or create a new fast copy
+    // of the map. If we get a fast copy of the map, all field representations
+    // will be tagged since the transition is omitted.
+    return lookup->holder()->AddProperty(
+        *name, *value, attributes, kNonStrictMode,
+        JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
+        JSReceiver::OMIT_EXTENSIBILITY_CHECK,
+        JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION);
   }
 
   // Keep the target CONSTANT if the same value is stored.
@@ -3862,6 +3843,56 @@
 }
 
 
+static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup,
+                                               Name* name,
+                                               Object* value,
+                                               PropertyAttributes attributes) {
+  JSObject* object = lookup->holder();
+  if (object->TooManyFastProperties()) {
+    MaybeObject* maybe_failure = object->NormalizeProperties(
+        CLEAR_INOBJECT_PROPERTIES, 0);
+    if (maybe_failure->IsFailure()) return maybe_failure;
+  }
+
+  if (!object->HasFastProperties()) {
+    return object->ReplaceSlowProperty(name, value, attributes);
+  }
+
+  int descriptor_index = lookup->GetDescriptorIndex();
+  if (lookup->GetAttributes() == attributes) {
+    MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation(
+        descriptor_index, Representation::Tagged(), FORCE_FIELD);
+    if (maybe_failure->IsFailure()) return maybe_failure;
+  } else {
+    Map* map;
+    MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations(
+        descriptor_index, FORCE_FIELD, attributes, "attributes mismatch");
+    if (!maybe_map->To(&map)) return maybe_map;
+    MaybeObject* maybe_failure = object->MigrateToMap(map);
+    if (maybe_failure->IsFailure()) return maybe_failure;
+  }
+
+  DescriptorArray* descriptors = object->map()->instance_descriptors();
+  int index = descriptors->GetDetails(descriptor_index).field_index();
+  object->FastPropertyAtPut(index, value);
+  return value;
+}
+
+
+static MaybeObject* SetPropertyToFieldWithAttributes(
+    LookupResult* lookup,
+    Handle<Name> name,
+    Handle<Object> value,
+    PropertyAttributes attributes) {
+  if (lookup->GetAttributes() == attributes) {
+    if (value->IsUninitialized()) return *value;
+    return SetPropertyToField(lookup, name, value);
+  } else {
+    return ConvertAndSetLocalProperty(lookup, *name, *value, attributes);
+  }
+}
+
+
 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
                                             Name* name_raw,
                                             Object* value_raw,
@@ -4085,25 +4116,41 @@
   // Check of IsReadOnly removed from here in clone.
   MaybeObject* result = *value;
   switch (lookup.type()) {
-    case NORMAL: {
-      PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
-      result = self->SetNormalizedProperty(*name, *value, details);
+    case NORMAL:
+      result = self->ReplaceSlowProperty(*name, *value, attributes);
       break;
-    }
     case FIELD:
-      if (value->IsUninitialized()) break;
-      result = SetPropertyToField(&lookup, name, value);
+      result = SetPropertyToFieldWithAttributes(
+          &lookup, name, value, attributes);
       break;
     case CONSTANT:
       // Only replace the constant if necessary.
-      if (*value == lookup.GetConstant()) return *value;
-      if (value->IsUninitialized()) break;
-      result = SetPropertyToField(&lookup, name, value);
+      if (lookup.GetAttributes() != attributes ||
+          *value != lookup.GetConstant()) {
+        result = SetPropertyToFieldWithAttributes(
+            &lookup, name, value, attributes);
+      }
       break;
     case CALLBACKS:
+      // Callbacks are not guaranteed to be installed on the receiver. Also
+      // perform a local lookup again. Fall through.
     case INTERCEPTOR:
-      // Override callback in clone
-      result = self->ConvertDescriptorToField(*name, *value, attributes);
+      self->LocalLookupRealNamedProperty(*name, &lookup);
+      if (lookup.IsFound()) {
+        if (lookup.IsPropertyCallbacks()) {
+          result = ConvertAndSetLocalProperty(
+              &lookup, *name, *value, attributes);
+        } else if (lookup.IsNormal()) {
+          result = self->ReplaceSlowProperty(*name, *value, attributes);
+        } else {
+          result = SetPropertyToFieldWithAttributes(
+              &lookup, name, value, attributes);
+        }
+      } else {
+        result = self->AddProperty(
+            *name, *value, attributes, kNonStrictMode, MAY_BE_STORE_FROM_KEYED,
+            extensibility_check, value_type, mode);
+      }
       break;
     case TRANSITION:
       result = SetPropertyUsingTransition(&lookup, name, value, attributes);
@@ -5892,7 +5939,8 @@
                                      uint32_t index,
                                      Handle<Object> getter,
                                      Handle<Object> setter,
-                                     PropertyAttributes attributes) {
+                                     PropertyAttributes attributes,
+                                     v8::AccessControl access_control) {
   switch (object->GetElementsKind()) {
     case FAST_SMI_ELEMENTS:
     case FAST_ELEMENTS:
@@ -5950,6 +5998,7 @@
   Isolate* isolate = object->GetIsolate();
   Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
   accessors->SetComponents(*getter, *setter);
+  accessors->set_access_flags(access_control);
 
   CALL_HEAP_FUNCTION_VOID(
       isolate, object->SetElementCallback(index, *accessors, attributes));
@@ -5981,11 +6030,13 @@
                                       Handle<Name> name,
                                       Handle<Object> getter,
                                       Handle<Object> setter,
-                                      PropertyAttributes attributes) {
+                                      PropertyAttributes attributes,
+                                      v8::AccessControl access_control) {
   // We could assert that the property is configurable here, but we would need
   // to do a lookup, which seems to be a bit of overkill.
   bool only_attribute_changes = getter->IsNull() && setter->IsNull();
   if (object->HasFastProperties() && !only_attribute_changes &&
+      access_control == v8::DEFAULT &&
       (object->map()->NumberOfOwnDescriptors() <
        DescriptorArray::kMaxNumberOfDescriptors)) {
     bool getterOk = getter->IsNull() ||
@@ -5997,6 +6048,7 @@
 
   Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
   accessors->SetComponents(*getter, *setter);
+  accessors->set_access_flags(access_control);
 
   CALL_HEAP_FUNCTION_VOID(
       object->GetIsolate(),
@@ -6018,12 +6070,13 @@
   LookupCallbackProperty(name, &callback_result);
   if (callback_result.IsFound()) {
     Object* obj = callback_result.GetCallbackObject();
-    if (obj->IsAccessorInfo() &&
-        AccessorInfo::cast(obj)->prohibits_overwriting()) {
-      return false;
+    if (obj->IsAccessorInfo()) {
+      return !AccessorInfo::cast(obj)->prohibits_overwriting();
+    }
+    if (obj->IsAccessorPair()) {
+      return !AccessorPair::cast(obj)->prohibits_overwriting();
     }
   }
-
   return true;
 }
 
@@ -6101,7 +6154,8 @@
                               Handle<Name> name,
                               Handle<Object> getter,
                               Handle<Object> setter,
-                              PropertyAttributes attributes) {
+                              PropertyAttributes attributes,
+                              v8::AccessControl access_control) {
   Isolate* isolate = object->GetIsolate();
   // Check access rights if needed.
   if (object->IsAccessCheckNeeded() &&
@@ -6114,8 +6168,12 @@
     Handle<Object> proto(object->GetPrototype(), isolate);
     if (proto->IsNull()) return;
     ASSERT(proto->IsJSGlobalObject());
-    DefineAccessor(
-        Handle<JSObject>::cast(proto), name, getter, setter, attributes);
+    DefineAccessor(Handle<JSObject>::cast(proto),
+                   name,
+                   getter,
+                   setter,
+                   attributes,
+                   access_control);
     return;
   }
 
@@ -6151,9 +6209,11 @@
   }
 
   if (is_element) {
-    DefineElementAccessor(object, index, getter, setter, attributes);
+    DefineElementAccessor(
+        object, index, getter, setter, attributes, access_control);
   } else {
-    DefinePropertyAccessor(object, name, getter, setter, attributes);
+    DefinePropertyAccessor(
+        object, name, getter, setter, attributes, access_control);
   }
 
   if (is_observed) {
@@ -9620,31 +9680,28 @@
 }
 
 
-bool JSFunction::PassesHydrogenFilter() {
+// The filter is a pattern that matches function names in this way:
+//   "*"      all; the default
+//   "-"      all but the top-level function
+//   "-name"  all but the function "name"
+//   ""       only the top-level function
+//   "name"   only the function "name"
+//   "name*"  only functions starting with "name"
+bool JSFunction::PassesFilter(const char* raw_filter) {
+  if (*raw_filter == '*') return true;
   String* name = shared()->DebugName();
-  // The filter string is a pattern that matches functions in this way:
-  //   "*"      all; the default
-  //   "-"      all but the top-level function
-  //   "-name"  all but the function "name"
-  //   ""       only the top-level function
-  //   "name"   only the function "name"
-  //   "name*"  only functions starting with "name"
-  if (*FLAG_hydrogen_filter != '*') {
-    Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
-    if (filter.length() == 0) return name->length() == 0;
-    if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true;
-    if (filter[0] == '-' &&
-        !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
-      return true;
-    }
-    if (filter[filter.length() - 1] == '*' &&
-        name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
-      return true;
-    }
-    return false;
+  Vector<const char> filter = CStrVector(raw_filter);
+  if (filter.length() == 0) return name->length() == 0;
+  if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true;
+  if (filter[0] == '-' &&
+      !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
+    return true;
   }
-
-  return true;
+  if (filter[filter.length() - 1] == '*' &&
+      name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
+    return true;
+  }
+  return false;
 }
 
 
diff --git a/src/objects.h b/src/objects.h
index c75a419..411908c 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2252,7 +2252,8 @@
                              Handle<Name> name,
                              Handle<Object> getter,
                              Handle<Object> setter,
-                             PropertyAttributes attributes);
+                             PropertyAttributes attributes,
+                             v8::AccessControl access_control = v8::DEFAULT);
 
   MaybeObject* LookupAccessor(Name* name, AccessorComponent component);
 
@@ -2499,7 +2500,8 @@
   MUST_USE_RESULT MaybeObject* AddConstantProperty(
       Name* name,
       Object* constant,
-      PropertyAttributes attributes);
+      PropertyAttributes attributes,
+      TransitionFlag flag);
 
   MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
       Name* name,
@@ -2522,14 +2524,6 @@
   MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
   MUST_USE_RESULT MaybeObject* UpdateAllocationSite(ElementsKind to_kind);
 
-  // Converts a descriptor of any other type to a real field, backed by the
-  // properties array.
-  MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
-      Name* name,
-      Object* new_value,
-      PropertyAttributes attributes,
-      TransitionFlag flag = OMIT_TRANSITION);
-
   MUST_USE_RESULT MaybeObject* MigrateToMap(Map* new_map);
   MUST_USE_RESULT MaybeObject* GeneralizeFieldRepresentation(
       int modify_index,
@@ -2542,7 +2536,8 @@
       Object* value,
       PropertyAttributes attributes,
       StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
-      ValueType value_type = OPTIMAL_REPRESENTATION);
+      ValueType value_type = OPTIMAL_REPRESENTATION,
+      TransitionFlag flag = INSERT_TRANSITION);
 
   // Add a property to a slow-case object.
   MUST_USE_RESULT MaybeObject* AddSlowProperty(Name* name,
@@ -2558,7 +2553,8 @@
       StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
       ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK,
       ValueType value_type = OPTIMAL_REPRESENTATION,
-      StoreMode mode = ALLOW_AS_CONSTANT);
+      StoreMode mode = ALLOW_AS_CONSTANT,
+      TransitionFlag flag = INSERT_TRANSITION);
 
   // Convert the object to use the canonical dictionary
   // representation. If the object is expected to have additional properties
@@ -2694,7 +2690,8 @@
   // Maximal number of fast properties for the JSObject. Used to
   // restrict the number of map transitions to avoid an explosion in
   // the number of maps for objects used as dictionaries.
-  inline bool TooManyFastProperties(int properties, StoreFromKeyed store_mode);
+  inline bool TooManyFastProperties(
+      StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
 
   // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
   // Also maximal value of JSArray's length property.
@@ -2715,7 +2712,11 @@
   // don't want to be wasteful with long lived objects.
   static const int kMaxUncheckedOldFastElementsLength = 500;
 
-  static const int kInitialMaxFastElementArray = 100000;
+  // TODO(2790): HAllocate currently always allocates fast backing stores
+  // in new space, where on x64 we can only fit ~98K elements. Keep this
+  // limit lower than that until HAllocate is made smarter.
+  static const int kInitialMaxFastElementArray = 95000;
+
   static const int kFastPropertiesSoftLimit = 12;
   static const int kMaxFastProperties = 64;
   static const int kMaxInstanceSize = 255 * kPointerSize;
@@ -2836,14 +2837,16 @@
                                     uint32_t index,
                                     Handle<Object> getter,
                                     Handle<Object> setter,
-                                    PropertyAttributes attributes);
+                                    PropertyAttributes attributes,
+                                    v8::AccessControl access_control);
   static Handle<AccessorPair> CreateAccessorPairFor(Handle<JSObject> object,
                                                     Handle<Name> name);
   static void DefinePropertyAccessor(Handle<JSObject> object,
                                      Handle<Name> name,
                                      Handle<Object> getter,
                                      Handle<Object> setter,
-                                     PropertyAttributes attributes);
+                                     PropertyAttributes attributes,
+                                     v8::AccessControl access_control);
 
   // Try to define a single accessor paying attention to map transitions.
   // Returns false if this was not possible and we have to use the slow case.
@@ -5624,6 +5627,7 @@
   MUST_USE_RESULT MaybeObject* CopyGeneralizeAllRepresentations(
       int modify_index,
       StoreMode store_mode,
+      PropertyAttributes attributes,
       const char* reason);
 
   void PrintGeneralization(FILE* file,
@@ -7081,7 +7085,8 @@
   // Retrieve the native context from a function's literal array.
   static Context* NativeContextFromLiterals(FixedArray* literals);
 
-  bool PassesHydrogenFilter();
+  // Used for flags such as --hydrogen-filter.
+  bool PassesFilter(const char* raw_filter);
 
   // Layout descriptors. The last property (from kNonWeakFieldsEndOffset to
   // kSize) is weak and has special handling during garbage collection.
@@ -9688,10 +9693,18 @@
 //   * undefined: considered an accessor by the spec, too, strangely enough
 //   * the hole: an accessor which has not been set
 //   * a pointer to a map: a transition used to ensure map sharing
+// access_flags provides the ability to override access checks on access check
+// failure.
 class AccessorPair: public Struct {
  public:
   DECL_ACCESSORS(getter, Object)
   DECL_ACCESSORS(setter, Object)
+  DECL_ACCESSORS(access_flags, Smi)
+
+  inline void set_access_flags(v8::AccessControl access_control);
+  inline bool all_can_read();
+  inline bool all_can_write();
+  inline bool prohibits_overwriting();
 
   static inline AccessorPair* cast(Object* obj);
 
@@ -9728,9 +9741,14 @@
 
   static const int kGetterOffset = HeapObject::kHeaderSize;
   static const int kSetterOffset = kGetterOffset + kPointerSize;
-  static const int kSize = kSetterOffset + kPointerSize;
+  static const int kAccessFlagsOffset = kSetterOffset + kPointerSize;
+  static const int kSize = kAccessFlagsOffset + kPointerSize;
 
  private:
+  static const int kAllCanReadBit = 0;
+  static const int kAllCanWriteBit = 1;
+  static const int kProhibitsOverwritingBit = 2;
+
   // Strangely enough, in addition to functions and harmony proxies, the spec
   // requires us to consider undefined as a kind of accessor, too:
   //    var obj = {};
diff --git a/src/parser.cc b/src/parser.cc
index 4947790..ccab7ec 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -542,6 +542,7 @@
       scanner_(isolate_->unicode_cache()),
       reusable_preparser_(NULL),
       top_scope_(NULL),
+      original_scope_(NULL),
       current_function_state_(NULL),
       target_stack_(NULL),
       extension_(info->extension()),
@@ -622,6 +623,7 @@
     if (!info->context().is_null()) {
       scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
     }
+    original_scope_ = scope;
     if (info->is_eval()) {
       if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
         scope = NewScope(scope, EVAL_SCOPE);
@@ -749,6 +751,7 @@
       scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
                                            zone());
     }
+    original_scope_ = scope;
     FunctionState function_state(this, scope, isolate());
     ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
     ASSERT(scope->language_mode() != EXTENDED_MODE ||
@@ -4279,10 +4282,38 @@
   // Function declarations are function scoped in normal mode, so they are
   // hoisted. In harmony block scoping mode they are block scoped, so they
   // are not hoisted.
+  //
+  // One tricky case are function declarations in a local sloppy-mode eval:
+  // their declaration is hoisted, but they still see the local scope. E.g.,
+  //
+  // function() {
+  //   var x = 0
+  //   try { throw 1 } catch (x) { eval("function g() { return x }") }
+  //   return g()
+  // }
+  //
+  // needs to return 1. To distinguish such cases, we need to detect
+  // (1) whether a function stems from a sloppy eval, and
+  // (2) whether it actually hoists across the eval.
+  // Unfortunately, we do not represent sloppy eval scopes, so we do not have
+  // either information available directly, especially not when lazily compiling
+  // a function like 'g'. We hence rely on the following invariants:
+  // - (1) is the case iff the innermost scope of the deserialized scope chain
+  //   under which we compile is _not_ a declaration scope. This holds because
+  //   in all normal cases, function declarations are fully hoisted to a
+  //   declaration scope and compiled relative to that.
+  // - (2) is the case iff the current declaration scope is still the original
+  //   one relative to the deserialized scope chain. Otherwise we must be
+  //   compiling a function in an inner declaration scope in the eval, e.g. a
+  //   nested function, and hoisting works normally relative to that.
+  Scope* declaration_scope = top_scope_->DeclarationScope();
+  Scope* original_declaration_scope = original_scope_->DeclarationScope();
   Scope* scope =
-      (function_type == FunctionLiteral::DECLARATION && !is_extended_mode())
-      ? NewScope(top_scope_->DeclarationScope(), FUNCTION_SCOPE)
-      : NewScope(top_scope_, FUNCTION_SCOPE);
+      function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
+      (original_scope_ == original_declaration_scope ||
+       declaration_scope != original_declaration_scope)
+          ? NewScope(declaration_scope, FUNCTION_SCOPE)
+          : NewScope(top_scope_, FUNCTION_SCOPE);
   ZoneList<Statement*>* body = NULL;
   int materialized_literal_count = -1;
   int expected_property_count = -1;
diff --git a/src/parser.h b/src/parser.h
index 68a74b7..2f26b84 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -855,6 +855,7 @@
   Scanner scanner_;
   preparser::PreParser* reusable_preparser_;
   Scope* top_scope_;
+  Scope* original_scope_;  // for ES5 function declarations in sloppy eval
   FunctionState* current_function_state_;
   Target* target_stack_;  // for break, continue statements
   v8::Extension* extension_;
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 8856833..ef97449 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -80,139 +80,6 @@
 
 
 #ifdef __arm__
-static bool CPUInfoContainsString(const char * search_string) {
-  const char* file_name = "/proc/cpuinfo";
-  // This is written as a straight shot one pass parser
-  // and not using STL string and ifstream because,
-  // on Linux, it's reading from a (non-mmap-able)
-  // character special device.
-  FILE* f = NULL;
-  const char* what = search_string;
-
-  if (NULL == (f = fopen(file_name, "r"))) {
-    OS::PrintError("Failed to open /proc/cpuinfo\n");
-    return false;
-  }
-
-  int k;
-  while (EOF != (k = fgetc(f))) {
-    if (k == *what) {
-      ++what;
-      while ((*what != '\0') && (*what == fgetc(f))) {
-        ++what;
-      }
-      if (*what == '\0') {
-        fclose(f);
-        return true;
-      } else {
-        what = search_string;
-      }
-    }
-  }
-  fclose(f);
-
-  // Did not find string in the proc file.
-  return false;
-}
-
-
-bool OS::ArmCpuHasFeature(CpuFeature feature) {
-  const char* search_string = NULL;
-  // Simple detection of VFP at runtime for Linux.
-  // It is based on /proc/cpuinfo, which reveals hardware configuration
-  // to user-space applications.  According to ARM (mid 2009), no similar
-  // facility is universally available on the ARM architectures,
-  // so it's up to individual OSes to provide such.
-  switch (feature) {
-    case VFP3:
-      search_string = "vfpv3";
-      break;
-    case NEON:
-      search_string = "neon";
-      break;
-    case ARMv7:
-      search_string = "ARMv7";
-      break;
-    case SUDIV:
-      search_string = "idiva";
-      break;
-    case VFP32DREGS:
-      // This case is handled specially below.
-      break;
-    default:
-      UNREACHABLE();
-  }
-
-  if (feature == VFP32DREGS) {
-    return ArmCpuHasFeature(VFP3) && !CPUInfoContainsString("d16");
-  }
-
-  if (CPUInfoContainsString(search_string)) {
-    return true;
-  }
-
-  if (feature == VFP3) {
-    // Some old kernels will report vfp not vfpv3. Here we make a last attempt
-    // to detect vfpv3 by checking for vfp *and* neon, since neon is only
-    // available on architectures with vfpv3.
-    // Checking neon on its own is not enough as it is possible to have neon
-    // without vfp.
-    if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-
-CpuImplementer OS::GetCpuImplementer() {
-  static bool use_cached_value = false;
-  static CpuImplementer cached_value = UNKNOWN_IMPLEMENTER;
-  if (use_cached_value) {
-    return cached_value;
-  }
-  if (CPUInfoContainsString("CPU implementer\t: 0x41")) {
-    cached_value = ARM_IMPLEMENTER;
-  } else if (CPUInfoContainsString("CPU implementer\t: 0x51")) {
-    cached_value = QUALCOMM_IMPLEMENTER;
-  } else {
-    cached_value = UNKNOWN_IMPLEMENTER;
-  }
-  use_cached_value = true;
-  return cached_value;
-}
-
-
-CpuPart OS::GetCpuPart(CpuImplementer implementer) {
-  static bool use_cached_value = false;
-  static CpuPart cached_value = CPU_UNKNOWN;
-  if (use_cached_value) {
-    return cached_value;
-  }
-  if (implementer == ARM_IMPLEMENTER) {
-    if (CPUInfoContainsString("CPU part\t: 0xc0f")) {
-      cached_value = CORTEX_A15;
-    } else if (CPUInfoContainsString("CPU part\t: 0xc0c")) {
-      cached_value = CORTEX_A12;
-    } else if (CPUInfoContainsString("CPU part\t: 0xc09")) {
-      cached_value = CORTEX_A9;
-    } else if (CPUInfoContainsString("CPU part\t: 0xc08")) {
-      cached_value = CORTEX_A8;
-    } else if (CPUInfoContainsString("CPU part\t: 0xc07")) {
-      cached_value = CORTEX_A7;
-    } else if (CPUInfoContainsString("CPU part\t: 0xc05")) {
-      cached_value = CORTEX_A5;
-    } else {
-      cached_value = CPU_UNKNOWN;
-    }
-  } else {
-    cached_value = CPU_UNKNOWN;
-  }
-  use_cached_value = true;
-  return cached_value;
-}
-
 
 bool OS::ArmUsingHardFloat() {
   // GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify
@@ -255,60 +122,6 @@
 #endif  // def __arm__
 
 
-#ifdef __mips__
-bool OS::MipsCpuHasFeature(CpuFeature feature) {
-  const char* search_string = NULL;
-  const char* file_name = "/proc/cpuinfo";
-  // Simple detection of FPU at runtime for Linux.
-  // It is based on /proc/cpuinfo, which reveals hardware configuration
-  // to user-space applications.  According to MIPS (early 2010), no similar
-  // facility is universally available on the MIPS architectures,
-  // so it's up to individual OSes to provide such.
-  //
-  // This is written as a straight shot one pass parser
-  // and not using STL string and ifstream because,
-  // on Linux, it's reading from a (non-mmap-able)
-  // character special device.
-
-  switch (feature) {
-    case FPU:
-      search_string = "FPU";
-      break;
-    default:
-      UNREACHABLE();
-  }
-
-  FILE* f = NULL;
-  const char* what = search_string;
-
-  if (NULL == (f = fopen(file_name, "r"))) {
-    OS::PrintError("Failed to open /proc/cpuinfo\n");
-    return false;
-  }
-
-  int k;
-  while (EOF != (k = fgetc(f))) {
-    if (k == *what) {
-      ++what;
-      while ((*what != '\0') && (*what == fgetc(f))) {
-        ++what;
-      }
-      if (*what == '\0') {
-        fclose(f);
-        return true;
-      } else {
-        what = search_string;
-      }
-    }
-  }
-  fclose(f);
-
-  // Did not find string in the proc file.
-  return false;
-}
-#endif  // def __mips__
-
-
 const char* OS::LocalTimezone(double time) {
   if (std::isnan(time)) return "";
   time_t tv = static_cast<time_t>(floor(time/msPerSecond));
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
index dd5a3dd..dc7adb6 100644
--- a/src/platform-nullos.cc
+++ b/src/platform-nullos.cc
@@ -215,21 +215,6 @@
 }
 
 
-CpuImplementer OS::GetCpuImplementer() {
-  UNIMPLEMENTED();
-}
-
-
-CpuPart OS::GetCpuPart(CpuImplementer implementer) {
-  UNIMPLEMENTED();
-}
-
-
-bool OS::ArmCpuHasFeature(CpuFeature feature) {
-  UNIMPLEMENTED();
-}
-
-
 bool OS::ArmUsingHardFloat() {
   UNIMPLEMENTED();
 }
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index f7ab8a1..1244493 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -79,11 +79,11 @@
 
 
 uint64_t OS::CpuFeaturesImpliedByPlatform() {
-#if defined(__APPLE__)
+#if V8_OS_MACOSX
   // Mac OS X requires all these to install so we can assume they are present.
   // These constants are defined by the CPUid instructions.
   const uint64_t one = 1;
-  return (one << SSE2) | (one << CMOV) | (one << CPUID);
+  return (one << SSE2) | (one << CMOV);
 #else
   return 0;  // Nothing special about the other systems.
 #endif
diff --git a/src/platform.h b/src/platform.h
index 8b27c19..384ae15 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -365,22 +365,10 @@
   // Returns the double constant NAN
   static double nan_value();
 
-  // Support runtime detection of Cpu implementer
-  static CpuImplementer GetCpuImplementer();
-
-  // Support runtime detection of Cpu implementer
-  static CpuPart GetCpuPart(CpuImplementer implementer);
-
-  // Support runtime detection of VFP3 on ARM CPUs.
-  static bool ArmCpuHasFeature(CpuFeature feature);
-
   // Support runtime detection of whether the hard float option of the
   // EABI is used.
   static bool ArmUsingHardFloat();
 
-  // Support runtime detection of FPU on MIPS CPUs.
-  static bool MipsCpuHasFeature(CpuFeature feature);
-
   // Returns the activation frame alignment constraint or zero if
   // the platform doesn't care. Guaranteed to be a power of two.
   static int ActivationFrameAlignment();
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index bea7bca..3752b27 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -127,7 +127,7 @@
 void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
   ASSERT(function->IsOptimizable());
 
-  if (FLAG_trace_opt && function->PassesHydrogenFilter()) {
+  if (FLAG_trace_opt && function->PassesFilter(FLAG_hydrogen_filter)) {
     PrintF("[marking ");
     function->ShortPrint();
     PrintF(" for recompilation, reason: %s", reason);
diff --git a/src/runtime.cc b/src/runtime.cc
index ad18cfc..65b1d35 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1662,6 +1662,14 @@
         (access_type == v8::ACCESS_GET && info->all_can_read()) ||
         (access_type == v8::ACCESS_SET && info->all_can_write());
   }
+  if (callback->IsAccessorPair()) {
+    AccessorPair* info = AccessorPair::cast(callback);
+    return
+        (access_type == v8::ACCESS_HAS &&
+           (info->all_can_read() || info->all_can_write())) ||
+        (access_type == v8::ACCESS_GET && info->all_can_read()) ||
+        (access_type == v8::ACCESS_SET && info->all_can_write());
+  }
   return false;
 }
 
@@ -1943,6 +1951,35 @@
 }
 
 
+// Transform getter or setter into something DefineAccessor can handle.
+static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
+                                                   Handle<Object> component) {
+  if (component->IsUndefined()) return isolate->factory()->null_value();
+  Handle<FunctionTemplateInfo> info =
+      Handle<FunctionTemplateInfo>::cast(component);
+  return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 6);
+  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
+  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
+  CONVERT_SMI_ARG_CHECKED(attribute, 4);
+  CONVERT_SMI_ARG_CHECKED(access_control, 5);
+  JSObject::DefineAccessor(object,
+                           name,
+                           InstantiateAccessorComponent(isolate, getter),
+                           InstantiateAccessorComponent(isolate, setter),
+                           static_cast<PropertyAttributes>(attribute),
+                           static_cast<v8::AccessControl>(access_control));
+  return isolate->heap()->undefined_value();
+}
+
+
 static Failure* ThrowRedeclarationError(Isolate* isolate,
                                         const char* type,
                                         Handle<String> name) {
diff --git a/src/runtime.h b/src/runtime.h
index 10b3043..e0e0b48 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -258,6 +258,7 @@
   F(GetTemplateField, 2, 1) \
   F(DisableAccessChecks, 1, 1) \
   F(EnableAccessChecks, 1, 1) \
+  F(SetAccessorProperty, 6, 1) \
   \
   /* Dates */ \
   F(DateCurrentTime, 0, 1) \
diff --git a/src/sampler.cc b/src/sampler.cc
index 4a13b1d..fa8c2e8 100644
--- a/src/sampler.cc
+++ b/src/sampler.cc
@@ -29,7 +29,7 @@
 
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
     || defined(__NetBSD__) || defined(__sun) || defined(__ANDROID__) \
-    || defined(__native_client__)
+    || defined(__native_client__) || defined(__MACH__)
 
 #define USE_SIGNALS
 
@@ -38,9 +38,12 @@
 #include <signal.h>
 #include <sys/time.h>
 #include <sys/syscall.h>
+
+#if defined(__MACH__)
+#include <mach/mach.h>
 // OpenBSD doesn't have <ucontext.h>. ucontext_t lives in <signal.h>
 // and is a typedef for struct sigcontext. There is no uc_mcontext.
-#if (!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \
+#elif(!defined(__ANDROID__) || defined(__BIONIC_HAVE_UCONTEXT_T)) \
     && !defined(__OpenBSD__)
 #include <ucontext.h>
 #endif
@@ -53,10 +56,6 @@
 #include <asm/sigcontext.h>
 #endif
 
-#elif defined(__MACH__)
-
-#include <mach/mach.h>
-
 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
 
 #include "win32-headers.h"
@@ -180,26 +179,6 @@
   pthread_t vm_tid_;
 };
 
-#elif defined(__MACH__)
-
-class Sampler::PlatformData : public PlatformDataCommon {
- public:
-  PlatformData() : profiled_thread_(mach_thread_self()) {}
-
-  ~PlatformData() {
-    // Deallocate Mach port for thread.
-    mach_port_deallocate(mach_task_self(), profiled_thread_);
-  }
-
-  thread_act_t profiled_thread() { return profiled_thread_; }
-
- private:
-  // Note: for profiled_thread_ Mach primitives are used instead of PThread's
-  // because the latter doesn't provide thread manipulation primitives required.
-  // For details, consult "Mac OS X Internals" book, Section 7.3.
-  thread_act_t profiled_thread_;
-};
-
 #elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
 
 // ----------------------------------------------------------------------------
@@ -364,6 +343,28 @@
   state.sp = reinterpret_cast<Address>(mcontext.gregs[29]);
   state.fp = reinterpret_cast<Address>(mcontext.gregs[30]);
 #endif  // V8_HOST_ARCH_*
+#elif defined(__MACH__)
+#if V8_HOST_ARCH_X64
+#if __DARWIN_UNIX03
+  state.pc = reinterpret_cast<Address>(mcontext->__ss.__rip);
+  state.sp = reinterpret_cast<Address>(mcontext->__ss.__rsp);
+  state.fp = reinterpret_cast<Address>(mcontext->__ss.__rbp);
+#else  // !__DARWIN_UNIX03
+  state.pc = reinterpret_cast<Address>(mcontext->ss.rip);
+  state.sp = reinterpret_cast<Address>(mcontext->ss.rsp);
+  state.fp = reinterpret_cast<Address>(mcontext->ss.rbp);
+#endif  // __DARWIN_UNIX03
+#elif V8_HOST_ARCH_IA32
+#if __DARWIN_UNIX03
+  state.pc = reinterpret_cast<Address>(mcontext->__ss.__eip);
+  state.sp = reinterpret_cast<Address>(mcontext->__ss.__esp);
+  state.fp = reinterpret_cast<Address>(mcontext->__ss.__ebp);
+#else  // !__DARWIN_UNIX03
+  state.pc = reinterpret_cast<Address>(mcontext->ss.eip);
+  state.sp = reinterpret_cast<Address>(mcontext->ss.esp);
+  state.fp = reinterpret_cast<Address>(mcontext->ss.ebp);
+#endif  // __DARWIN_UNIX03
+#endif  // V8_HOST_ARCH_IA32
 #elif defined(__FreeBSD__)
 #if V8_HOST_ARCH_IA32
   state.pc = reinterpret_cast<Address>(mcontext.mc_eip);
@@ -481,7 +482,7 @@
           Sampler* sampler = active_samplers_.at(i);
           if (!sampler->isolate()->IsInitialized()) continue;
           if (!sampler->IsProfiling()) continue;
-          SampleContext(sampler);
+          sampler->DoSample();
         }
       }
       OS::Sleep(interval_);
@@ -489,109 +490,6 @@
   }
 
  private:
-#if defined(USE_SIGNALS)
-
-  void SampleContext(Sampler* sampler) {
-    if (!SignalHandler::Installed()) return;
-    pthread_t tid = sampler->platform_data()->vm_tid();
-    pthread_kill(tid, SIGPROF);
-  }
-
-#elif defined(__MACH__)
-
-  void SampleContext(Sampler* sampler) {
-    thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
-
-#if defined(USE_SIMULATOR)
-    SimulatorHelper helper;
-    Isolate* isolate = sampler->isolate();
-    if (!helper.Init(sampler, isolate)) return;
-#endif
-
-    if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
-
-#if V8_HOST_ARCH_X64
-    thread_state_flavor_t flavor = x86_THREAD_STATE64;
-    x86_thread_state64_t thread_state;
-    mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
-#if __DARWIN_UNIX03
-#define REGISTER_FIELD(name) __r ## name
-#else
-#define REGISTER_FIELD(name) r ## name
-#endif  // __DARWIN_UNIX03
-#elif V8_HOST_ARCH_IA32
-    thread_state_flavor_t flavor = i386_THREAD_STATE;
-    i386_thread_state_t thread_state;
-    mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
-#if __DARWIN_UNIX03
-#define REGISTER_FIELD(name) __e ## name
-#else
-#define REGISTER_FIELD(name) e ## name
-#endif  // __DARWIN_UNIX03
-#else
-#error Unsupported Mac OS X host architecture.
-#endif  // V8_HOST_ARCH
-
-    if (thread_get_state(profiled_thread,
-                         flavor,
-                         reinterpret_cast<natural_t*>(&thread_state),
-                         &count) == KERN_SUCCESS) {
-      RegisterState state;
-#if defined(USE_SIMULATOR)
-      helper.FillRegisters(&state);
-#else
-      state.pc = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(ip));
-      state.sp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(sp));
-      state.fp = reinterpret_cast<Address>(thread_state.REGISTER_FIELD(bp));
-#endif  // USE_SIMULATOR
-#undef REGISTER_FIELD
-      sampler->SampleStack(state);
-    }
-    thread_resume(profiled_thread);
-  }
-
-#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
-
-  void SampleContext(Sampler* sampler) {
-    HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
-    if (profiled_thread == NULL) return;
-
-    Isolate* isolate = sampler->isolate();
-#if defined(USE_SIMULATOR)
-    SimulatorHelper helper;
-    if (!helper.Init(sampler, isolate)) return;
-#endif
-
-    const DWORD kSuspendFailed = static_cast<DWORD>(-1);
-    if (SuspendThread(profiled_thread) == kSuspendFailed) return;
-
-    // Context used for sampling the register state of the profiled thread.
-    CONTEXT context;
-    memset(&context, 0, sizeof(context));
-    context.ContextFlags = CONTEXT_FULL;
-    if (GetThreadContext(profiled_thread, &context) != 0) {
-      RegisterState state;
-#if defined(USE_SIMULATOR)
-      helper.FillRegisters(&state);
-#else
-#if V8_HOST_ARCH_X64
-      state.pc = reinterpret_cast<Address>(context.Rip);
-      state.sp = reinterpret_cast<Address>(context.Rsp);
-      state.fp = reinterpret_cast<Address>(context.Rbp);
-#else
-      state.pc = reinterpret_cast<Address>(context.Eip);
-      state.sp = reinterpret_cast<Address>(context.Esp);
-      state.fp = reinterpret_cast<Address>(context.Ebp);
-#endif
-#endif  // USE_SIMULATOR
-      sampler->SampleStack(state);
-    }
-    ResumeThread(profiled_thread);
-  }
-
-#endif  // USE_SIGNALS
-
-
   // Protects the process wide state below.
   static Mutex* mutex_;
   static SamplerThread* instance_;
@@ -665,6 +563,7 @@
     : isolate_(isolate),
       interval_(interval),
       profiling_(false),
+      has_processing_thread_(false),
       active_(false),
       is_counting_samples_(false),
       js_and_external_sample_count_(0) {
@@ -708,4 +607,62 @@
   }
 }
 
+
+bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
+#if defined(USE_SIGNALS)
+  return true;
+#else
+  return false;
+#endif
+}
+
+
+#if defined(USE_SIGNALS)
+
+void Sampler::DoSample() {
+  if (!SignalHandler::Installed()) return;
+  pthread_kill(platform_data()->vm_tid(), SIGPROF);
+}
+
+#elif defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
+
+void Sampler::DoSample() {
+  HANDLE profiled_thread = platform_data()->profiled_thread();
+  if (profiled_thread == NULL) return;
+
+#if defined(USE_SIMULATOR)
+  SimulatorHelper helper;
+  if (!helper.Init(this, isolate())) return;
+#endif
+
+  const DWORD kSuspendFailed = static_cast<DWORD>(-1);
+  if (SuspendThread(profiled_thread) == kSuspendFailed) return;
+
+  // Context used for sampling the register state of the profiled thread.
+  CONTEXT context;
+  memset(&context, 0, sizeof(context));
+  context.ContextFlags = CONTEXT_FULL;
+  if (GetThreadContext(profiled_thread, &context) != 0) {
+    RegisterState state;
+#if defined(USE_SIMULATOR)
+    helper.FillRegisters(&state);
+#else
+#if V8_HOST_ARCH_X64
+    state.pc = reinterpret_cast<Address>(context.Rip);
+    state.sp = reinterpret_cast<Address>(context.Rsp);
+    state.fp = reinterpret_cast<Address>(context.Rbp);
+#else
+    state.pc = reinterpret_cast<Address>(context.Eip);
+    state.sp = reinterpret_cast<Address>(context.Esp);
+    state.fp = reinterpret_cast<Address>(context.Ebp);
+#endif
+#endif  // USE_SIMULATOR
+    SampleStack(state);
+  }
+  ResumeThread(profiled_thread);
+}
+
+#endif  // USE_SIGNALS
+
+
 } }  // namespace v8::internal
diff --git a/src/sampler.h b/src/sampler.h
index 80ccc08..cd65b12 100644
--- a/src/sampler.h
+++ b/src/sampler.h
@@ -94,14 +94,25 @@
   void Start();
   void Stop();
 
-  // Is the sampler used for profiling?
-  bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
+  // Whether the sampling thread should use this Sampler for CPU profiling?
+  bool IsProfiling() const {
+    return NoBarrier_Load(&profiling_) > 0 &&
+        !NoBarrier_Load(&has_processing_thread_);
+  }
   void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
   void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
 
   // Whether the sampler is running (that is, consumes resources).
   bool IsActive() const { return NoBarrier_Load(&active_); }
 
+  // If true next sample must be initiated on the profiler event processor
+  // thread right after latest sample is processed.
+  static bool CanSampleOnProfilerEventsProcessorThread();
+  void DoSample();
+  void SetHasProcessingThread(bool value) {
+    NoBarrier_Store(&has_processing_thread_, value);
+  }
+
   // Used in tests to make sure that stack sampling is performed.
   unsigned js_and_external_sample_count() const {
     return js_and_external_sample_count_;
@@ -125,6 +136,7 @@
   Isolate* isolate_;
   const int interval_;
   Atomic32 profiling_;
+  Atomic32 has_processing_thread_;
   Atomic32 active_;
   PlatformData* data_;  // Platform specific data.
   bool is_counting_samples_;
diff --git a/src/scopes.cc b/src/scopes.cc
index e631332..e38e903 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -907,26 +907,32 @@
   PrintF("%d heap slots\n", num_heap_slots_); }
 
   // Print locals.
-  Indent(n1, "// function var\n");
   if (function_ != NULL) {
+    Indent(n1, "// function var:\n");
     PrintVar(n1, function_->proxy()->var());
   }
 
-  Indent(n1, "// temporary vars\n");
-  for (int i = 0; i < temps_.length(); i++) {
-    PrintVar(n1, temps_[i]);
+  if (temps_.length() > 0) {
+    Indent(n1, "// temporary vars:\n");
+    for (int i = 0; i < temps_.length(); i++) {
+      PrintVar(n1, temps_[i]);
+    }
   }
 
-  Indent(n1, "// internal vars\n");
-  for (int i = 0; i < internals_.length(); i++) {
-    PrintVar(n1, internals_[i]);
+  if (internals_.length() > 0) {
+    Indent(n1, "// internal vars:\n");
+    for (int i = 0; i < internals_.length(); i++) {
+      PrintVar(n1, internals_[i]);
+    }
   }
 
-  Indent(n1, "// local vars\n");
-  PrintMap(n1, &variables_);
+  if (variables_.Start() != NULL) {
+    Indent(n1, "// local vars:\n");
+    PrintMap(n1, &variables_);
+  }
 
-  Indent(n1, "// dynamic vars\n");
   if (dynamics_ != NULL) {
+    Indent(n1, "// dynamic vars:\n");
     PrintMap(n1, dynamics_->GetMap(DYNAMIC));
     PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
     PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
diff --git a/src/v8globals.h b/src/v8globals.h
index f76dcc2..8a1cc17 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -412,33 +412,12 @@
 #endif
 
 
-enum CpuImplementer {
-  UNKNOWN_IMPLEMENTER,
-  ARM_IMPLEMENTER,
-  QUALCOMM_IMPLEMENTER
-};
-
-
-enum CpuPart {
-  CPU_UNKNOWN,
-  CORTEX_A15,
-  CORTEX_A12,
-  CORTEX_A9,
-  CORTEX_A8,
-  CORTEX_A7,
-  CORTEX_A5
-};
-
-
 // Feature flags bit positions. They are mostly based on the CPUID spec.
-// (We assign CPUID itself to one of the currently reserved bits --
-// feel free to change this if needed.)
 // On X86/X64, values below 32 are bits in EDX, values above 32 are bits in ECX.
 enum CpuFeature { SSE4_1 = 32 + 19,  // x86
                   SSE3 = 32 + 0,     // x86
                   SSE2 = 26,   // x86
                   CMOV = 15,   // x86
-                  CPUID = 10,  // x86
                   VFP3 = 1,    // ARM
                   ARMv7 = 2,   // ARM
                   SUDIV = 3,   // ARM
diff --git a/src/version.cc b/src/version.cc
index 0f682f6..0d6cb5b 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     21
-#define BUILD_NUMBER      3
-#define PATCH_LEVEL       2
+#define BUILD_NUMBER      4
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 68d2c05..8910b07 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -63,98 +63,32 @@
     return;  // No features if we might serialize.
   }
 
-  const int kBufferSize = 4 * KB;
-  VirtualMemory* memory = new VirtualMemory(kBufferSize);
-  if (!memory->IsReserved()) {
-    delete memory;
-    return;
+  uint64_t probed_features = 0;
+  CPU cpu;
+  if (cpu.has_sse41()) {
+    probed_features |= static_cast<uint64_t>(1) << SSE4_1;
   }
-  ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
-  if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
-    delete memory;
-    return;
+  if (cpu.has_sse3()) {
+    probed_features |= static_cast<uint64_t>(1) << SSE3;
   }
 
-  Assembler assm(NULL, memory->address(), kBufferSize);
-  Label cpuid, done;
-#define __ assm.
-  // Save old rsp, since we are going to modify the stack.
-  __ push(rbp);
-  __ pushfq();
-  __ push(rdi);
-  __ push(rcx);
-  __ push(rbx);
-  __ movq(rbp, rsp);
+  // SSE2 must be available on every x64 CPU.
+  ASSERT(cpu.has_sse2());
+  probed_features |= static_cast<uint64_t>(1) << SSE2;
 
-  // If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
-  __ pushfq();
-  __ pop(rax);
-  __ movq(rdx, rax);
-  __ xor_(rax, Immediate(0x200000));  // Flip bit 21.
-  __ push(rax);
-  __ popfq();
-  __ pushfq();
-  __ pop(rax);
-  __ xor_(rax, rdx);  // Different if CPUID is supported.
-  __ j(not_zero, &cpuid);
+  // CMOD must be available on every x64 CPU.
+  ASSERT(cpu.has_cmov());
+  probed_features |= static_cast<uint64_t>(1) << CMOV;
 
-  // CPUID not supported. Clear the supported features in rax.
-  __ xor_(rax, rax);
-  __ jmp(&done);
-
-  // Invoke CPUID with 1 in eax to get feature information in
-  // ecx:edx. Temporarily enable CPUID support because we know it's
-  // safe here.
-  __ bind(&cpuid);
-  __ movl(rax, Immediate(1));
-  supported_ = kDefaultCpuFeatures | (1 << CPUID);
-  { CpuFeatureScope fscope(&assm, CPUID);
-    __ cpuid();
-    // Move the result from ecx:edx to rdi.
-    __ movl(rdi, rdx);  // Zero-extended to 64 bits.
-    __ shl(rcx, Immediate(32));
-    __ or_(rdi, rcx);
-
-    // Get the sahf supported flag, from CPUID(0x80000001)
-    __ movq(rax, 0x80000001, RelocInfo::NONE64);
-    __ cpuid();
+  // SAHF is not generally available in long mode.
+  if (cpu.has_sahf()) {
+    probed_features |= static_cast<uint64_t>(1) << SAHF;
   }
-  supported_ = kDefaultCpuFeatures;
 
-  // Put the CPU flags in rax.
-  // rax = (rcx & 1) | (rdi & ~1) | (1 << CPUID).
-  __ movl(rax, Immediate(1));
-  __ and_(rcx, rax);  // Bit 0 is set if SAHF instruction supported.
-  __ not_(rax);
-  __ and_(rax, rdi);
-  __ or_(rax, rcx);
-  __ or_(rax, Immediate(1 << CPUID));
-
-  // Done.
-  __ bind(&done);
-  __ movq(rsp, rbp);
-  __ pop(rbx);
-  __ pop(rcx);
-  __ pop(rdi);
-  __ popfq();
-  __ pop(rbp);
-  __ ret(0);
-#undef __
-
-  typedef uint64_t (*F0)();
-  F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
-
-  uint64_t probed_features = probe();
   uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
   supported_ = probed_features | platform_features;
   found_by_runtime_probing_only_
       = probed_features & ~kDefaultCpuFeatures & ~platform_features;
-
-  // CMOV must be available on an X64 CPU.
-  ASSERT(IsSupported(CPUID));
-  ASSERT(IsSupported(CMOV));
-
-  delete memory;
 }
 
 
@@ -987,7 +921,6 @@
 
 
 void Assembler::cpuid() {
-  ASSERT(IsEnabled(CPUID));
   EnsureSpace ensure_space(this);
   emit(0x0F);
   emit(0xA2);
@@ -2985,6 +2918,17 @@
 }
 
 
+void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit(0xF2);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0xC2);
+  emit_sse_operand(dst, src);
+  emit(0x01);  // LT == 1
+}
+
+
 void Assembler::roundsd(XMMRegister dst, XMMRegister src,
                         Assembler::RoundingMode mode) {
   ASSERT(IsEnabled(SSE4_1));
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index d92849a..f2e37fe 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -1384,6 +1384,8 @@
   void movmskpd(Register dst, XMMRegister src);
   void movmskps(Register dst, XMMRegister src);
 
+  void cmpltsd(XMMRegister dst, XMMRegister src);
+
   // The first argument is the reg field, the second argument is the r/m field.
   void emit_sse_operand(XMMRegister dst, XMMRegister src);
   void emit_sse_operand(XMMRegister reg, const Operand& adr);
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index e9ace15..3509794 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -1153,6 +1153,25 @@
       get_modrm(*current, &mod, &regop, &rm);
       AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
       current += PrintRightXMMOperand(current);
+    } else if (opcode == 0xC2) {
+      // Intel manual 2A, Table 3-18.
+      int mod, regop, rm;
+      get_modrm(*current, &mod, &regop, &rm);
+      const char* const pseudo_op[] = {
+        "cmpeqsd",
+        "cmpltsd",
+        "cmplesd",
+        "cmpunordsd",
+        "cmpneqsd",
+        "cmpnltsd",
+        "cmpnlesd",
+        "cmpordsd"
+      };
+      AppendToBuffer("%s %s,%s",
+                     pseudo_op[current[1]],
+                     NameOfXMMRegister(regop),
+                     NameOfXMMRegister(rm));
+      current += 2;
     } else {
       UnimplementedInstruction();
     }
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index a449d8e..96fa719 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -2374,6 +2374,9 @@
 
 
 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
+  HEnvironment* env = current_block_->last_environment();
+  instr->ReplayEnvironment(env);
+
   // There are no real uses of a captured object.
   return NULL;
 }
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 74e3fcc..5180e6b 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -524,7 +524,13 @@
     RecordComment("Abort message: ");
     RecordComment(msg);
   }
+
+  if (FLAG_trap_on_abort) {
+    int3();
+    return;
+  }
 #endif
+
   push(rax);
   movq(kScratchRegister, p0, RelocInfo::NONE64);
   push(kScratchRegister);
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 58c76d6..6883d38 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -2200,8 +2200,130 @@
     Handle<JSFunction> function,
     Handle<String> name,
     Code::StubType type) {
-  // TODO(872): implement this.
-  return Handle<Code>::null();
+  // ----------- S t a t e -------------
+  //  -- rcx                 : name
+  //  -- rsp[0]              : return address
+  //  -- rsp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- rsp[(argc + 1) * 4] : receiver
+  // -----------------------------------
+
+  if (!CpuFeatures::IsSupported(SSE2)) {
+    return Handle<Code>::null();
+  }
+
+  CpuFeatureScope use_sse2(masm(), SSE2);
+
+  const int argc = arguments().immediate();
+
+  // If the object is not a JSObject or we got an unexpected number of
+  // arguments, bail out to the regular call.
+  if (!object->IsJSObject() || argc != 1) {
+    return Handle<Code>::null();
+  }
+
+  Label miss;
+  GenerateNameCheck(name, &miss);
+
+  if (cell.is_null()) {
+    __ movq(rdx, Operand(rsp, 2 * kPointerSize));
+
+    STATIC_ASSERT(kSmiTag == 0);
+    __ JumpIfSmi(rdx, &miss);
+
+    CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
+                    name, &miss);
+  } else {
+    ASSERT(cell->value() == *function);
+    GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+                                &miss);
+    GenerateLoadFunctionFromCell(cell, function, &miss);
+  }
+
+  // Load the (only) argument into rax.
+  __ movq(rax, Operand(rsp, 1 * kPointerSize));
+
+  // Check if the argument is a smi.
+  Label smi;
+  STATIC_ASSERT(kSmiTag == 0);
+  __ JumpIfSmi(rax, &smi);
+
+  // Check if the argument is a heap number and load its value into xmm0.
+  Label slow;
+  __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
+  __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
+
+  // Check if the argument is strictly positive. Note this also discards NaN.
+  __ xorpd(xmm1, xmm1);
+  __ ucomisd(xmm0, xmm1);
+  __ j(below_equal, &slow);
+
+  // Do a truncating conversion.
+  __ cvttsd2si(rax, xmm0);
+
+  // Checks for 0x80000000 which signals a failed conversion.
+  Label conversion_failure;
+  __ cmpl(rax, Immediate(0x80000000));
+  __ j(equal, &conversion_failure);
+
+  // Smi tag and return.
+  __ Integer32ToSmi(rax, rax);
+  __ bind(&smi);
+  __ ret(2 * kPointerSize);
+
+  // Check if the argument is < 2^kMantissaBits.
+  Label already_round;
+  __ bind(&conversion_failure);
+  int64_t kTwoMantissaBits= V8_INT64_C(0x4330000000000000);
+  __ movq(rbx, kTwoMantissaBits, RelocInfo::NONE64);
+  __ movq(xmm1, rbx);
+  __ ucomisd(xmm0, xmm1);
+  __ j(above_equal, &already_round);
+
+  // Save a copy of the argument.
+  __ movaps(xmm2, xmm0);
+
+  // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
+  __ addsd(xmm0, xmm1);
+  __ subsd(xmm0, xmm1);
+
+  // Compare the argument and the tentative result to get the right mask:
+  //   if xmm2 < xmm0:
+  //     xmm2 = 1...1
+  //   else:
+  //     xmm2 = 0...0
+  __ cmpltsd(xmm2, xmm0);
+
+  // Subtract 1 if the argument was less than the tentative result.
+  int64_t kOne = V8_INT64_C(0x3ff0000000000000);
+  __ movq(rbx, kOne, RelocInfo::NONE64);
+  __ movq(xmm1, rbx);
+  __ andpd(xmm1, xmm2);
+  __ subsd(xmm0, xmm1);
+
+  // Return a new heap number.
+  __ AllocateHeapNumber(rax, rbx, &slow);
+  __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
+  __ ret(2 * kPointerSize);
+
+  // Return the argument (when it's an already round heap number).
+  __ bind(&already_round);
+  __ movq(rax, Operand(rsp, 1 * kPointerSize));
+  __ ret(2 * kPointerSize);
+
+  // Tail call the full function. We do not have to patch the receiver
+  // because the function makes no use of it.
+  __ bind(&slow);
+  ParameterCount expected(function);
+  __ InvokeFunction(function, expected, arguments(),
+                    JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
+
+  __ bind(&miss);
+  // rcx: function name.
+  GenerateMissBranch();
+
+  // Return the generated code.
+  return GetCode(type, name);
 }
 
 
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 9df5c7b..b7e0771 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -56,6 +56,7 @@
         'test-circular-queue.cc',
         'test-compiler.cc',
         'test-conversions.cc',
+        'test-cpu.cc',
         'test-cpu-profiler.cc',
         'test-dataflow.cc',
         'test-date.cc',
@@ -113,6 +114,7 @@
             'test-assembler-ia32.cc',
             'test-code-stubs.cc',
             'test-code-stubs-ia32.cc',
+            'test-cpu-ia32.cc',
             'test-disasm-ia32.cc',
             'test-log-stack-tracer.cc'
           ],
@@ -122,6 +124,7 @@
             'test-assembler-x64.cc',
             'test-code-stubs.cc',
             'test-code-stubs-x64.cc',
+            'test-cpu-x64.cc',
             'test-macro-assembler-x64.cc',
             'test-log-stack-tracer.cc'
           ],
@@ -129,6 +132,8 @@
         ['v8_target_arch=="arm"', {
           'sources': [
             'test-assembler-arm.cc',
+            'test-code-stubs.cc',
+            'test-code-stubs-arm.cc',
             'test-disasm-arm.cc'
           ],
         }],
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 71d7717..0d3ff15 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -42,8 +42,8 @@
 # This test always fails.  It tests that LiveEdit causes abort when turned off.
 test-debug/LiveEditDisabled: FAIL
 
-# Bug(2857)
-test-log/EquivalenceOfLoggingAndTraversal: SKIP
+# TODO(gc): Temporarily disabled in the GC branch.
+test-log/EquivalenceOfLoggingAndTraversal: PASS || FAIL
 
 # We do not yet shrink weak maps after they have been emptied by the GC
 test-weakmaps/Shrinking: FAIL
diff --git a/test/cctest/log-eq-of-logging-and-traversal.js b/test/cctest/log-eq-of-logging-and-traversal.js
index 05643bf..522a372 100644
--- a/test/cctest/log-eq-of-logging-and-traversal.js
+++ b/test/cctest/log-eq-of-logging-and-traversal.js
@@ -39,7 +39,7 @@
 function LogProcessor() {
   LogReader.call(this, {
       'code-creation': {
-          parsers: [null, parseInt, parseInt, null, 'var-args'],
+          parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
           processor: this.processCodeCreation },
       'code-move': { parsers: [parseInt, parseInt],
           processor: this.processCodeMove },
@@ -55,8 +55,12 @@
 LogProcessor.prototype.__proto__ = LogReader.prototype;
 
 LogProcessor.prototype.processCodeCreation = function(
-    type, start, size, name, maybe_func) {
+    type, kind, start, size, name, maybe_func) {
   if (type != "LazyCompile" && type != "Script" && type != "Function") return;
+  // Scripts will compile into anonymous functions starting at 1:1. Adjust the
+  // name here so that it matches corrsponding function's name during the heap
+  // traversal.
+  if (type == "Script") name = " :1:1";
   // Discard types to avoid discrepancies in "LazyCompile" vs. "Function".
   type = "";
   if (maybe_func.length) {
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
index 7d96ea6..7e0ee70 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -51,17 +51,33 @@
 }
 
 
+static void handle_property(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  ApiTestFuzzer::Fuzz();
+  CHECK_EQ(0, info.Length());
+  info.GetReturnValue().Set(v8_num(907));
+}
+
+
 THREADED_TEST(PropertyHandler) {
   LocalContext env;
   v8::HandleScope scope(env->GetIsolate());
   Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
   fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
+  Local<v8::FunctionTemplate> getter_templ =
+      v8::FunctionTemplate::New(handle_property);
+  getter_templ->SetLength(0);
+  fun_templ->
+      InstanceTemplate()->SetAccessorProperty(v8_str("bar"), getter_templ);
   Local<Function> fun = fun_templ->GetFunction();
   env->Global()->Set(v8_str("Fun"), fun);
   Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
   CHECK_EQ(900, getter->Run()->Int32Value());
   Local<Script> setter = v8_compile("obj.foo = 901;");
   CHECK_EQ(901, setter->Run()->Int32Value());
+  getter = v8_compile("obj.bar;");
+  CHECK_EQ(907, getter->Run()->Int32Value());
+  setter = v8_compile("obj.bar = 908;");
+  CHECK_EQ(908, setter->Run()->Int32Value());
 }
 
 
@@ -109,30 +125,52 @@
 }
 
 
-static int x_register = 0;
+static int x_register[2] = {0, 0};
 static v8::Handle<v8::Object> x_receiver;
 static v8::Handle<v8::Object> x_holder;
 
-
-static void XGetter(Local<String> name,
-                    const v8::PropertyCallbackInfo<v8::Value>& info) {
+template<class Info>
+static void XGetter(const Info& info, int offset) {
   ApiTestFuzzer::Fuzz();
   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   CHECK_EQ(isolate, info.GetIsolate());
   CHECK_EQ(x_receiver, info.This());
+  info.GetReturnValue().Set(v8_num(x_register[offset]));
+}
+
+
+static void XGetter(Local<String> name,
+                    const v8::PropertyCallbackInfo<v8::Value>& info) {
   CHECK_EQ(x_holder, info.Holder());
-  info.GetReturnValue().Set(v8_num(x_register));
+  XGetter(info, 0);
+}
+
+
+static void XGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  XGetter(info, 1);
+}
+
+
+template<class Info>
+static void XSetter(Local<Value> value, const Info& info, int offset) {
+  v8::Isolate* isolate = v8::Isolate::GetCurrent();
+  CHECK_EQ(isolate, info.GetIsolate());
+  CHECK_EQ(x_holder, info.This());
+  x_register[offset] = value->Int32Value();
 }
 
 
 static void XSetter(Local<String> name,
                     Local<Value> value,
                     const v8::PropertyCallbackInfo<void>& info) {
-  v8::Isolate* isolate = v8::Isolate::GetCurrent();
-  CHECK_EQ(isolate, info.GetIsolate());
-  CHECK_EQ(x_holder, info.This());
   CHECK_EQ(x_holder, info.Holder());
-  x_register = value->Int32Value();
+  XSetter(value, info, 0);
+}
+
+
+static void XSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  CHECK_EQ(1, info.Length());
+  XSetter(info[0], info, 1);
 }
 
 
@@ -140,7 +178,10 @@
   LocalContext context;
   v8::HandleScope scope(context->GetIsolate());
   v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
-  obj->SetAccessor(v8_str("x"), XGetter, XSetter);
+  obj->SetAccessor(v8_str("x0"), XGetter, XSetter);
+  obj->SetAccessorProperty(v8_str("x1"),
+                           v8::FunctionTemplate::New(XGetter),
+                           v8::FunctionTemplate::New(XSetter));
   x_holder = obj->NewInstance();
   context->Global()->Set(v8_str("holder"), x_holder);
   x_receiver = v8::Object::New();
@@ -149,14 +190,16 @@
     "obj.__proto__ = holder;"
     "var result = [];"
     "for (var i = 0; i < 10; i++) {"
-    "  holder.x = i;"
-    "  result.push(obj.x);"
+    "  holder.x0 = i;"
+    "  holder.x1 = i;"
+    "  result.push(obj.x0);"
+    "  result.push(obj.x1);"
     "}"
     "result"));
-  CHECK_EQ(10, array->Length());
-  for (int i = 0; i < 10; i++) {
+  CHECK_EQ(20, array->Length());
+  for (int i = 0; i < 20; i++) {
     v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
-    CHECK_EQ(v8::Integer::New(i), entry);
+    CHECK_EQ(v8::Integer::New(i/2), entry);
   }
 }
 
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index b1e82aa..192f114 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -8257,11 +8257,19 @@
 }
 
 
-static int g_echo_value = -1;
+static int g_echo_value_1 = -1;
+static int g_echo_value_2 = -1;
+
+
 static void EchoGetter(
     Local<String> name,
     const v8::PropertyCallbackInfo<v8::Value>& info) {
-  info.GetReturnValue().Set(v8_num(g_echo_value));
+  info.GetReturnValue().Set(v8_num(g_echo_value_1));
+}
+
+
+static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  info.GetReturnValue().Set(v8_num(g_echo_value_2));
 }
 
 
@@ -8269,7 +8277,14 @@
                        Local<Value> value,
                        const v8::PropertyCallbackInfo<void>&) {
   if (value->IsNumber())
-    g_echo_value = value->Int32Value();
+    g_echo_value_1 = value->Int32Value();
+}
+
+
+static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
+  v8::Handle<v8::Value> value = info[0];
+  if (value->IsNumber())
+    g_echo_value_2 = value->Int32Value();
 }
 
 
@@ -8287,6 +8302,12 @@
 }
 
 
+static void UnreachableFunction(
+    const v8::FunctionCallbackInfo<v8::Value>& info) {
+  CHECK(false);  // This function should not be called..
+}
+
+
 TEST(AccessControl) {
   v8::Isolate* isolate = v8::Isolate::GetCurrent();
   v8::HandleScope handle_scope(isolate);
@@ -8302,12 +8323,27 @@
       v8::Handle<Value>(),
       v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
 
+
+  global_template->SetAccessorProperty(
+      v8_str("accessible_js_prop"),
+      v8::FunctionTemplate::New(EchoGetter),
+      v8::FunctionTemplate::New(EchoSetter),
+      v8::None,
+      v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
+
   // Add an accessor that is not accessible by cross-domain JS code.
   global_template->SetAccessor(v8_str("blocked_prop"),
                                UnreachableGetter, UnreachableSetter,
                                v8::Handle<Value>(),
                                v8::DEFAULT);
 
+  global_template->SetAccessorProperty(
+      v8_str("blocked_js_prop"),
+      v8::FunctionTemplate::New(UnreachableFunction),
+      v8::FunctionTemplate::New(UnreachableFunction),
+      v8::None,
+      v8::DEFAULT);
+
   // Create an environment
   v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
   context0->Enter();
@@ -8500,26 +8536,47 @@
   value = CompileRun("other.accessible_prop = 3");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());
-  CHECK_EQ(3, g_echo_value);
+  CHECK_EQ(3, g_echo_value_1);
+
+  // Access accessible js property
+  value = CompileRun("other.accessible_js_prop = 3");
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+  CHECK_EQ(3, g_echo_value_2);
 
   value = CompileRun("other.accessible_prop");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());
 
+  value = CompileRun("other.accessible_js_prop");
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
   value = CompileRun(
       "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
   CHECK(value->IsNumber());
   CHECK_EQ(3, value->Int32Value());
 
+  value = CompileRun(
+      "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
+  CHECK(value->IsNumber());
+  CHECK_EQ(3, value->Int32Value());
+
   value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
   CHECK(value->IsTrue());
 
+  value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
+  CHECK(value->IsTrue());
+
   // Enumeration doesn't enumerate accessors from inaccessible objects in
   // the prototype chain even if the accessors are in themselves accessible.
   value =
       CompileRun("(function(){var obj = {'__proto__':other};"
                  "for (var p in obj)"
-                 "   if (p == 'accessible_prop' || p == 'blocked_prop') {"
+                 "   if (p == 'accessible_prop' ||"
+                 "       p == 'accessible_js_prop' ||"
+                 "       p == 'blocked_js_prop' ||"
+                 "       p == 'blocked_js_prop') {"
                  "     return false;"
                  "   }"
                  "return true;})()");
@@ -8591,7 +8648,7 @@
   // Make sure that we can set the accessible accessors value using normal
   // assignment.
   CompileRun("other.accessible_prop = 42");
-  CHECK_EQ(42, g_echo_value);
+  CHECK_EQ(42, g_echo_value_1);
 
   v8::Handle<Value> value;
   // We follow Safari in ignoring assignments to host object accessors.
diff --git a/test/cctest/test-code-stubs-arm.cc b/test/cctest/test-code-stubs-arm.cc
new file mode 100644
index 0000000..cc51e83
--- /dev/null
+++ b/test/cctest/test-code-stubs-arm.cc
@@ -0,0 +1,181 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Rrdistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Rrdistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Rrdistributions 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 <stdlib.h>
+
+#include "v8.h"
+
+#include "cctest.h"
+#include "code-stubs.h"
+#include "test-code-stubs.h"
+#include "factory.h"
+#include "macro-assembler.h"
+#include "platform.h"
+#include "simulator.h"
+
+using namespace v8::internal;
+
+#define __ masm.
+
+ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
+                                              Register source_reg,
+                                              Register destination_reg,
+                                              bool inline_fastpath) {
+  // Allocate an executable page of memory.
+  size_t actual_size;
+  byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
+                                                 &actual_size,
+                                                 true));
+  CHECK(buffer);
+  HandleScope handles(isolate);
+  MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size));
+  masm.set_allow_stub_calls(false);
+  DoubleToIStub stub(source_reg, destination_reg, 0, true, inline_fastpath);
+
+  byte* start = stub.GetCode(isolate)->instruction_start();
+  Label done;
+
+  // Save callee save registers.
+  __ Push(r7, r6, r5, r4);
+  __ Push(lr);
+
+  // Push the double argument.
+  __ vmov(d0, r0, r1);
+  __ sub(sp, sp, Operand(kDoubleSize));
+  __ vstr(d0, sp, 0);
+  if (!source_reg.is(sp)) {
+    __ mov(source_reg, sp);
+  }
+
+  // Save registers make sure they don't get clobbered.
+  int source_reg_offset = kDoubleSize;
+  int reg_num = 0;
+  for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
+    Register reg = Register::from_code(reg_num);
+    if (!reg.is(destination_reg)) {
+      __ push(reg);
+      source_reg_offset += kPointerSize;
+    }
+  }
+
+  // Re-push the double argument.
+  __ sub(sp, sp, Operand(kDoubleSize));
+  __ vstr(d0, sp, 0);
+
+  // Call through to the actual stub
+  if (inline_fastpath) {
+    __ vldr(d0, MemOperand(source_reg));
+    __ TryInlineTruncateDoubleToI(destination_reg, d0, &done);
+    if (destination_reg.is(source_reg) && !source_reg.is(sp)) {
+      // Restore clobbered source_reg.
+      __ add(source_reg, sp, Operand(source_reg_offset));
+    }
+  }
+  __ Call(start, RelocInfo::EXTERNAL_REFERENCE);
+  __ bind(&done);
+
+  __ add(sp, sp, Operand(kDoubleSize));
+
+  // Make sure no registers have been unexpectedly clobbered
+  for (--reg_num; reg_num >= 0; --reg_num) {
+    Register reg = Register::from_code(reg_num);
+    if (!reg.is(destination_reg)) {
+      __ ldr(ip, MemOperand(sp, 0));
+      __ cmp(reg, ip);
+      __ Assert(eq, kRegisterWasClobbered);
+      __ add(sp, sp, Operand(kPointerSize));
+    }
+  }
+
+  __ add(sp, sp, Operand(kDoubleSize));
+
+  if (!destination_reg.is(r0))
+    __ mov(r0, destination_reg);
+
+  // Restore callee save registers.
+  __ Pop(lr);
+  __ Pop(r7, r6, r5, r4);
+
+  __ Ret(0);
+
+  CodeDesc desc;
+  masm.GetCode(&desc);
+  return (reinterpret_cast<ConvertDToIFunc>(
+      reinterpret_cast<intptr_t>(buffer)));
+}
+
+#undef __
+
+
+static Isolate* GetIsolateFrom(LocalContext* context) {
+  return reinterpret_cast<Isolate*>((*context)->GetIsolate());
+}
+
+
+int32_t RunGeneratedCodeCallWrapper(ConvertDToIFunc func,
+                                    double from) {
+#ifdef USE_SIMULATOR
+  return reinterpret_cast<int32_t>(CALL_GENERATED_CODE(func, from, 0, 0, 0, 0));
+#else
+  return (*func)(from);
+#endif
+}
+
+
+TEST(ConvertDToI) {
+  CcTest::InitializeVM();
+  LocalContext context;
+  Isolate* isolate = GetIsolateFrom(&context);
+  HandleScope scope(isolate);
+
+#if DEBUG
+  // Verify that the tests actually work with the C version. In the release
+  // code, the compiler optimizes it away because it's all constant, but does it
+  // wrong, triggering an assert on gcc.
+  RunAllTruncationTests(&ConvertDToICVersion);
+#endif
+
+  Register source_registers[] = {sp, r0, r1, r2, r3, r4, r5, r6, r7};
+  Register dest_registers[] = {r0, r1, r2, r3, r4, r5, r6, r7};
+
+  for (size_t s = 0; s < sizeof(source_registers) / sizeof(Register); s++) {
+    for (size_t d = 0; d < sizeof(dest_registers) / sizeof(Register); d++) {
+      RunAllTruncationTests(
+          RunGeneratedCodeCallWrapper,
+          MakeConvertDToIFuncTrampoline(isolate,
+                                        source_registers[s],
+                                        dest_registers[d],
+                                        false));
+      RunAllTruncationTests(
+          RunGeneratedCodeCallWrapper,
+          MakeConvertDToIFuncTrampoline(isolate,
+                                        source_registers[s],
+                                        dest_registers[d],
+                                        true));
+    }
+  }
+}
diff --git a/test/cctest/test-code-stubs.cc b/test/cctest/test-code-stubs.cc
index 4050696..db00e9a 100644
--- a/test/cctest/test-code-stubs.cc
+++ b/test/cctest/test-code-stubs.cc
@@ -42,8 +42,9 @@
 
 
 int STDCALL ConvertDToICVersion(double d) {
-  Address double_ptr = reinterpret_cast<Address>(&d);
-  uint32_t exponent_bits = Memory::uint32_at(double_ptr + kDoubleSize / 2);
+  union { double d; uint32_t u[2]; } dbl;
+  dbl.d = d;
+  uint32_t exponent_bits = dbl.u[1];
   int32_t shifted_mask = static_cast<int32_t>(Double::kExponentMask >> 32);
   int32_t exponent = (((exponent_bits & shifted_mask) >>
                        (Double::kPhysicalSignificandSize - 32)) -
@@ -54,8 +55,7 @@
     static_cast<uint32_t>(Double::kPhysicalSignificandSize);
   if (unsigned_exponent >= max_exponent) {
     if ((exponent - Double::kPhysicalSignificandSize) < 32) {
-      result = Memory::uint32_at(double_ptr) <<
-        (exponent - Double::kPhysicalSignificandSize);
+      result = dbl.u[0] << (exponent - Double::kPhysicalSignificandSize);
     }
   } else {
     uint64_t big_result =
@@ -71,22 +71,37 @@
 }
 
 
-void RunOneTruncationTestWithTest(ConvertDToIFunc func,
+void RunOneTruncationTestWithTest(ConvertDToICallWrapper callWrapper,
+                                  ConvertDToIFunc func,
                                   double from,
                                   double raw) {
   uint64_t to = static_cast<int64_t>(raw);
-  int result = (*func)(from);
+  int result = (*callWrapper)(func, from);
   CHECK_EQ(static_cast<int>(to), result);
 }
 
 
+int32_t DefaultCallWrapper(ConvertDToIFunc func,
+                           double from) {
+  return (*func)(from);
+}
+
+
 // #define NaN and Infinity so that it's possible to cut-and-paste these tests
 // directly to a .js file and run them.
 #define NaN (OS::nan_value())
 #define Infinity (std::numeric_limits<double>::infinity())
-#define RunOneTruncationTest(p1, p2) RunOneTruncationTestWithTest(func, p1, p2)
+#define RunOneTruncationTest(p1, p2) \
+    RunOneTruncationTestWithTest(callWrapper, func, p1, p2)
+
 
 void RunAllTruncationTests(ConvertDToIFunc func) {
+  RunAllTruncationTests(DefaultCallWrapper, func);
+}
+
+
+void RunAllTruncationTests(ConvertDToICallWrapper callWrapper,
+                           ConvertDToIFunc func) {
   RunOneTruncationTest(0, 0);
   RunOneTruncationTest(0.5, 0);
   RunOneTruncationTest(-0.5, 0);
diff --git a/test/cctest/test-code-stubs.h b/test/cctest/test-code-stubs.h
index eab8e63..910e0d1 100644
--- a/test/cctest/test-code-stubs.h
+++ b/test/cctest/test-code-stubs.h
@@ -41,8 +41,13 @@
 typedef int32_t STDCALL ConvertDToIFuncType(double input);
 typedef ConvertDToIFuncType* ConvertDToIFunc;
 
+typedef int32_t ConvertDToICallWrapperType(ConvertDToIFunc func, double from);
+typedef ConvertDToICallWrapperType* ConvertDToICallWrapper;
+
 int STDCALL ConvertDToICVersion(double d);
 
 void RunAllTruncationTests(ConvertDToIFunc func);
+void RunAllTruncationTests(ConvertDToICallWrapper callWrapper,
+                           ConvertDToIFunc func);
 
 #endif
diff --git a/test/cctest/test-cpu-ia32.cc b/test/cctest/test-cpu-ia32.cc
new file mode 100644
index 0000000..245450b
--- /dev/null
+++ b/test/cctest/test-cpu-ia32.cc
@@ -0,0 +1,40 @@
+// 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 "cctest.h"
+#include "cpu.h"
+
+using namespace v8::internal;
+
+
+TEST(RequiredFeaturesX64) {
+  // Test for the features required by every x86 CPU in compat/legacy mode.
+  CPU cpu;
+  CHECK(cpu.has_sahf());
+}
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 3b267c4..6d3c2ee 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -51,7 +51,7 @@
   CpuProfilesCollection profiles;
   ProfileGenerator generator(&profiles);
   SmartPointer<ProfilerEventsProcessor> processor(
-      new ProfilerEventsProcessor(&generator));
+      new ProfilerEventsProcessor(&generator, NULL, 100));
   processor->Start();
   processor->StopSynchronously();
 }
@@ -143,7 +143,7 @@
   profiles->StartProfiling("", 1, false);
   ProfileGenerator generator(profiles);
   SmartPointer<ProfilerEventsProcessor> processor(
-      new ProfilerEventsProcessor(&generator));
+      new ProfilerEventsProcessor(&generator, NULL, 100));
   processor->Start();
   CpuProfiler profiler(isolate, profiles, &generator, *processor);
 
@@ -205,7 +205,7 @@
   profiles->StartProfiling("", 1, false);
   ProfileGenerator generator(profiles);
   SmartPointer<ProfilerEventsProcessor> processor(
-      new ProfilerEventsProcessor(&generator));
+      new ProfilerEventsProcessor(&generator, NULL, 100));
   processor->Start();
   CpuProfiler profiler(isolate, profiles, &generator, *processor);
 
@@ -274,7 +274,7 @@
   profiles->StartProfiling("", 1, false);
   ProfileGenerator generator(profiles);
   SmartPointer<ProfilerEventsProcessor> processor(
-      new ProfilerEventsProcessor(&generator));
+      new ProfilerEventsProcessor(&generator, NULL, 100));
   processor->Start();
   CpuProfiler profiler(isolate, profiles, &generator, *processor);
 
@@ -1372,13 +1372,11 @@
   const v8::CpuProfileNode* programNode =
       GetChild(root, ProfileGenerator::kProgramEntryName);
   CHECK_EQ(0, programNode->GetChildrenCount());
-  CHECK_GE(programNode->GetSelfSamplesCount(), 3);
   CHECK_GE(programNode->GetHitCount(), 3);
 
   const v8::CpuProfileNode* idleNode =
       GetChild(root, ProfileGenerator::kIdleEntryName);
   CHECK_EQ(0, idleNode->GetChildrenCount());
-  CHECK_GE(idleNode->GetSelfSamplesCount(), 3);
   CHECK_GE(idleNode->GetHitCount(), 3);
 
   cpu_profiler->DeleteAllCpuProfiles();
diff --git a/test/cctest/test-cpu-x64.cc b/test/cctest/test-cpu-x64.cc
new file mode 100644
index 0000000..a2c45cf
--- /dev/null
+++ b/test/cctest/test-cpu-x64.cc
@@ -0,0 +1,44 @@
+// 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 "cctest.h"
+#include "cpu.h"
+
+using namespace v8::internal;
+
+
+TEST(RequiredFeaturesX64) {
+  // Test for the features required by every x64 CPU.
+  CPU cpu;
+  CHECK(cpu.has_fpu());
+  CHECK(cpu.has_cmov());
+  CHECK(cpu.has_mmx());
+  CHECK(cpu.has_sse());
+  CHECK(cpu.has_sse2());
+}
diff --git a/test/cctest/test-cpu.cc b/test/cctest/test-cpu.cc
new file mode 100644
index 0000000..1c61ab1
--- /dev/null
+++ b/test/cctest/test-cpu.cc
@@ -0,0 +1,50 @@
+// 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 "cctest.h"
+#include "cpu.h"
+
+using namespace v8::internal;
+
+
+TEST(FeatureImplications) {
+  // Test for features implied by other features.
+  CPU cpu;
+
+  // ia32 and x64 features
+  CHECK(!cpu.has_sse() || cpu.has_mmx());
+  CHECK(!cpu.has_sse2() || cpu.has_sse());
+  CHECK(!cpu.has_sse3() || cpu.has_sse2());
+  CHECK(!cpu.has_ssse3() || cpu.has_sse3());
+  CHECK(!cpu.has_sse41() || cpu.has_sse3());
+  CHECK(!cpu.has_sse42() || cpu.has_sse41());
+
+  // arm features
+  CHECK(!cpu.has_vfp3_d32() || cpu.has_vfp3());
+}
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 90469e5..1b6af47 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -99,11 +99,7 @@
   __ or_(edx, 3);
   __ xor_(edx, 3);
   __ nop();
-  {
-    CHECK(CpuFeatures::IsSupported(CPUID));
-    CpuFeatureScope fscope(&assm, CPUID);
-    __ cpuid();
-  }
+  __ cpuid();
   __ movsx_b(edx, ecx);
   __ movsx_w(edx, ecx);
   __ movzx_b(edx, ecx);
diff --git a/test/cctest/test-global-handles.cc b/test/cctest/test-global-handles.cc
index 0b652db..d3fc25c 100644
--- a/test/cctest/test-global-handles.cc
+++ b/test/cctest/test-global-handles.cc
@@ -321,24 +321,26 @@
   CcTest::InitializeVM();
   Isolate* isolate = Isolate::Current();
   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
-  EternalHandles* eternals = isolate->eternal_handles();
+  EternalHandles* eternal_handles = isolate->eternal_handles();
 
   // Create a number of handles that will not be on a block boundary
   const int kArrayLength = 2048-1;
   int indices[kArrayLength];
+  v8::Eternal<v8::Value> eternals[kArrayLength];
 
-  CHECK_EQ(0, eternals->NumberOfHandles());
+  CHECK_EQ(0, eternal_handles->NumberOfHandles());
   for (int i = 0; i < kArrayLength; i++) {
+    indices[i] = -1;
     HandleScope scope(isolate);
     v8::Local<v8::Object> object = v8::Object::New();
     object->Set(i, v8::Integer::New(i, v8_isolate));
-    if (i % 2 == 0) {
-      // Create with internal api
-      indices[i] = eternals->Create(isolate, *v8::Utils::OpenHandle(*object));
-    } else {
-      // Create with external api
-      indices[i] = object.Eternalize(v8_isolate);
-    }
+    // Create with internal api
+    eternal_handles->Create(
+        isolate, *v8::Utils::OpenHandle(*object), &indices[i]);
+    // Create with external api
+    CHECK(!eternals[i].IsEmpty());
+    eternals[i].Set(v8_isolate, object);
+    CHECK(eternals[i].IsEmpty());
   }
 
   isolate->heap()->CollectAllAvailableGarbage();
@@ -346,21 +348,31 @@
   for (int i = 0; i < kArrayLength; i++) {
     for (int j = 0; j < 2; j++) {
       HandleScope scope(isolate);
-      v8::Local<v8::Object> object;
+      v8::Local<v8::Value> local;
       if (j == 0) {
         // Test internal api
-        v8::Local<v8::Value> local =
-            v8::Utils::ToLocal(eternals->Get(indices[i]));
-        object = v8::Handle<v8::Object>::Cast(local);
+        local = v8::Utils::ToLocal(eternal_handles->Get(indices[i]));
       } else {
         // Test external api
-        object = v8::Local<v8::Object>::GetEternal(v8_isolate, indices[i]);
+        local = eternals[i].Get(v8_isolate);
       }
+      v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(local);
       v8::Local<v8::Value> value = object->Get(i);
       CHECK(value->IsInt32());
       CHECK_EQ(i, value->Int32Value());
     }
   }
 
-  CHECK_EQ(kArrayLength, eternals->NumberOfHandles());
+  CHECK_EQ(2*kArrayLength, eternal_handles->NumberOfHandles());
+
+  // Create an eternal via the constructor
+  {
+    HandleScope scope(isolate);
+    v8::Local<v8::Object> object = v8::Object::New();
+    v8::Eternal<v8::Object> eternal(v8_isolate, object);
+    CHECK(eternal.IsEmpty());
+    CHECK(object == eternal.Get(v8_isolate));
+  }
+
+  CHECK_EQ(2*kArrayLength + 1, eternal_handles->NumberOfHandles());
 }
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 0744322..83b45ab 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -3068,6 +3068,10 @@
   i::FLAG_allow_natives_syntax = true;
   i::FLAG_flush_code_incrementally = true;
 
+  // Disable loading the i18n extension which breaks the assumptions of this
+  // test about the heap layout.
+  i::FLAG_enable_i18n = false;
+
   CcTest::InitializeVM();
   Isolate* isolate = Isolate::Current();
   Heap* heap = isolate->heap();
diff --git a/test/mjsunit/array-store-and-grow.js b/test/mjsunit/array-store-and-grow.js
index a03a753..5ac95e9 100644
--- a/test/mjsunit/array-store-and-grow.js
+++ b/test/mjsunit/array-store-and-grow.js
@@ -187,6 +187,7 @@
 assertEquals(0.5, a[0]);
 assertEquals(0.5, array_store_1([], 0, 0.5));
 
+
 // Verify that a grow store will deoptimize if the max gap (difference between
 // the end of an array capacity and a new index) is passed. The wrapper is to
 // make sure array_store_10 isn't inlined.
@@ -207,3 +208,49 @@
   %ClearFunctionTypeFeedback(grow_store);
 })();
 
+
+// Verify that a polymorphic store and grow IC when crankshafted is still
+// a grow IC (earlier it would revert to a standard store in the polymorphic
+// case).
+(function() {
+  function f(o, k, v) {
+    o[k] = v;
+  }
+
+  a = [3.5];
+  f(a, 1, "hi");  // DOUBLE packed array -> tagged packed grow
+  a = {};
+  a.p = "property";
+  a[0] = 1;
+  f(a, 0, 5.4);
+
+  %OptimizeFunctionOnNextCall(f);
+  // Should be a polymorphic grow stub. If not a grow stub it will deopt.
+  f(new Array("hi"), 1, 3);
+  assertOptimized(f);
+  %ClearFunctionTypeFeedback(f);
+})();
+
+
+// Now verify that a polymorphic store (non-growing) IC when crankshafted WILL
+// deopt if you pass an element out of bounds.
+(function() {
+  function f(o, k, v) {
+    o[k] = v;
+  }
+
+  a = [3.5];
+  f(a, 0, "hi");  // DOUBLE packed array -> tagged packed grow
+  a = {};
+  a.p = "property";
+  a[0] = 1;
+  f(a, 0, 5.4);
+
+  %OptimizeFunctionOnNextCall(f);
+  f(new Array("hi"), 0, 3);
+  assertOptimized(f);
+  // An attempt to grow should cause deopt
+  f(new Array("hi"), 1, 3);
+  assertUnoptimized(f);
+  %ClearFunctionTypeFeedback(f);
+})();
diff --git a/test/mjsunit/compiler/escape-analysis.js b/test/mjsunit/compiler/escape-analysis.js
index 9776f67..9b9341b 100644
--- a/test/mjsunit/compiler/escape-analysis.js
+++ b/test/mjsunit/compiler/escape-analysis.js
@@ -132,3 +132,44 @@
   delete deopt.deopt;
   func(); func();
 })();
+
+
+// Test deoptimization with captured objects on operand stack.
+(function testDeoptOperand() {
+  var deopt = { deopt:false };
+  function constructor1() {
+    this.a = 1.0;
+    this.b = 2.3;
+    deopt.deopt;
+    assertEquals(1.0, this.a);
+    assertEquals(2.3, this.b);
+    this.b = 2.7;
+    this.c = 3.0;
+    this.d = 4.5;
+  }
+  function constructor2() {
+    this.e = 5.0;
+    this.f = new constructor1();
+    assertEquals(1.0, this.f.a);
+    assertEquals(2.7, this.f.b);
+    assertEquals(3.0, this.f.c);
+    assertEquals(4.5, this.f.d);
+    assertEquals(5.0, this.e);
+    this.e = 5.9;
+    this.g = 6.7;
+  }
+  function func() {
+    var o = new constructor2();
+    assertEquals(1.0, o.f.a);
+    assertEquals(2.7, o.f.b);
+    assertEquals(3.0, o.f.c);
+    assertEquals(4.5, o.f.d);
+    assertEquals(5.9, o.e);
+    assertEquals(6.7, o.g);
+  }
+  func(); func();
+  %OptimizeFunctionOnNextCall(func);
+  func(); func();
+  delete deopt.deopt;
+  func(); func();
+})();
diff --git a/test/mjsunit/debug-script.js b/test/mjsunit/debug-script.js
index 1cbdb37..6e673f7 100644
--- a/test/mjsunit/debug-script.js
+++ b/test/mjsunit/debug-script.js
@@ -59,9 +59,9 @@
 }
 
 // This has to be updated if the number of native scripts change.
-assertTrue(named_native_count == 16 || named_native_count == 17);
-// Only the 'gc' extension is loaded.
-assertEquals(1, extension_count);
+assertEquals(16, named_native_count);
+// Only the 'gc' and (depending on flags) the 'i18n' extensions are loaded.
+assertTrue(extension_count == 1 || extension_count == 2);
 // This script and mjsunit.js has been loaded.  If using d8, d8 loads
 // a normal script during startup too.
 assertTrue(normal_count == 2 || normal_count == 3);
diff --git a/test/mjsunit/fuzz-natives-part2.js b/test/mjsunit/fuzz-natives-part2.js
index 420064c..1cebf41 100644
--- a/test/mjsunit/fuzz-natives-part2.js
+++ b/test/mjsunit/fuzz-natives-part2.js
@@ -165,6 +165,7 @@
   "DeclareGlobals": true,
   "ArrayConstructor": true,
   "InternalArrayConstructor": true,
+  "SetAccessorProperty": true,
 
   "PromoteScheduledException": true,
   "DeleteHandleScopeExtensions": true,
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 829efaf..ee35af5 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -251,8 +251,5 @@
 readonly: SKIP
 array-feedback: SKIP
 
-# TODO(mstarzinger): Enable once escape analysis is stabilized.
-compiler/escape-analysis: SKIP
-
 # Deopt every n garbage collections collides with the deopt every n times flag.
 regress/regress-2653: SKIP
diff --git a/test/mjsunit/regress/regress-2594.js b/test/mjsunit/regress/regress-2594.js
new file mode 100644
index 0000000..60720cb
--- /dev/null
+++ b/test/mjsunit/regress/regress-2594.js
@@ -0,0 +1,104 @@
+// 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.
+
+// In the assertions but the first, the ES5 spec actually requires 0, but
+// that is arguably a spec bug, and other browsers return 1 like us.
+// In ES6, all of those will presumably result in a ReferenceError.
+// Our main concern with this test is that we do not crash, though.
+
+function f1() {
+  var XXX = 0
+  try { throw 1 } catch (XXX) {
+    eval("var h = function() { return XXX }")
+  }
+  return h()
+}
+assertEquals(1, f1())
+
+function f2() {
+  var XXX = 0
+  try { throw 1 } catch (XXX) {
+    eval("function h(){ return XXX }")
+  }
+  return h()
+}
+assertEquals(1, f2())
+
+function f3() {
+  var XXX = 0
+  try { throw 1 } catch (XXX) {
+    try { throw 2 } catch (y) {
+      eval("function h(){ return XXX }")
+    }
+  }
+  return h()
+}
+assertEquals(1, f3())
+
+function f4() {
+  var XXX = 0
+  try { throw 1 } catch (XXX) {
+    with ({}) {
+      eval("function h(){ return XXX }")
+    }
+  }
+  return h()
+}
+assertEquals(1, f4())
+
+function f5() {
+  var XXX = 0
+  try { throw 1 } catch (XXX) {
+    eval('eval("function h(){ return XXX }")')
+  }
+  return h()
+}
+assertEquals(1, f5())
+
+function f6() {
+  var XXX = 0
+  try { throw 1 } catch (XXX) {
+    eval("var h = (function() { function g(){ return XXX } return g })()")
+  }
+  return h()
+}
+assertEquals(1, f6())
+
+function f7() {
+  var XXX = 0
+  try { throw 1 } catch (XXX) {
+    eval("function h() { var XXX=2; function g(){ return XXX } return g }")
+  }
+  return h()()
+}
+assertEquals(2, f7())  // !
+
+var XXX = 0
+try { throw 1 } catch (XXX) {
+  eval("function h(){ return XXX }")
+}
+assertEquals(1, h())
diff --git a/test/mjsunit/regress/regress-2790.js b/test/mjsunit/regress/regress-2790.js
new file mode 100644
index 0000000..86305b8
--- /dev/null
+++ b/test/mjsunit/regress/regress-2790.js
@@ -0,0 +1,31 @@
+// 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.
+
+// Test that we can create arrays of any size.
+for (var i = 1000; i < 1000000; i += 97) {
+  new Array(i);
+}
diff --git a/tools/SourceMap.js b/tools/SourceMap.js
new file mode 100644
index 0000000..9cbd37a
--- /dev/null
+++ b/tools/SourceMap.js
@@ -0,0 +1,371 @@
+// 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.
+
+// This is a copy from blink dev tools, see:
+// http://src.chromium.org/viewvc/blink/trunk/Source/devtools/front_end/SourceMap.js
+// revision: 153407
+
+// Added to make the file work without dev tools
+WebInspector = {};
+WebInspector.ParsedURL = {};
+WebInspector.ParsedURL.completeURL = function(){};
+// start of original file content
+
+/*
+ * Copyright (C) 2012 Google Inc. 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.
+ */
+
+/**
+ * Implements Source Map V3 model. See http://code.google.com/p/closure-compiler/wiki/SourceMaps
+ * for format description.
+ * @constructor
+ * @param {string} sourceMappingURL
+ * @param {SourceMapV3} payload
+ */
+WebInspector.SourceMap = function(sourceMappingURL, payload)
+{
+    if (!WebInspector.SourceMap.prototype._base64Map) {
+        const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+        WebInspector.SourceMap.prototype._base64Map = {};
+        for (var i = 0; i < base64Digits.length; ++i)
+            WebInspector.SourceMap.prototype._base64Map[base64Digits.charAt(i)] = i;
+    }
+
+    this._sourceMappingURL = sourceMappingURL;
+    this._reverseMappingsBySourceURL = {};
+    this._mappings = [];
+    this._sources = {};
+    this._sourceContentByURL = {};
+    this._parseMappingPayload(payload);
+}
+
+/**
+ * @param {string} sourceMapURL
+ * @param {string} compiledURL
+ * @param {function(WebInspector.SourceMap)} callback
+ */
+WebInspector.SourceMap.load = function(sourceMapURL, compiledURL, callback)
+{
+    NetworkAgent.loadResourceForFrontend(WebInspector.resourceTreeModel.mainFrame.id, sourceMapURL, undefined, contentLoaded.bind(this));
+
+    /**
+     * @param {?Protocol.Error} error
+     * @param {number} statusCode
+     * @param {NetworkAgent.Headers} headers
+     * @param {string} content
+     */
+    function contentLoaded(error, statusCode, headers, content)
+    {
+        if (error || !content || statusCode >= 400) {
+            console.error("Could not load content for " + sourceMapURL + " : " + (error || ("HTTP status code: " + statusCode)));
+            callback(null);
+            return;
+        }
+
+        if (content.slice(0, 3) === ")]}")
+            content = content.substring(content.indexOf('\n'));
+        try {
+            var payload = /** @type {SourceMapV3} */ (JSON.parse(content));
+            var baseURL = sourceMapURL.startsWith("data:") ? compiledURL : sourceMapURL;
+            callback(new WebInspector.SourceMap(baseURL, payload));
+        } catch(e) {
+            console.error(e.message);
+            callback(null);
+        }
+    }
+}
+
+WebInspector.SourceMap.prototype = {
+    /**
+     * @return {Array.<string>}
+     */
+    sources: function()
+    {
+        return Object.keys(this._sources);
+    },
+
+    /**
+     * @param {string} sourceURL
+     * @return {string|undefined}
+     */
+    sourceContent: function(sourceURL)
+    {
+        return this._sourceContentByURL[sourceURL];
+    },
+
+    /**
+     * @param {string} sourceURL
+     * @param {WebInspector.ResourceType} contentType
+     * @return {WebInspector.ContentProvider}
+     */
+    sourceContentProvider: function(sourceURL, contentType)
+    {
+        var lastIndexOfDot = sourceURL.lastIndexOf(".");
+        var extension = lastIndexOfDot !== -1 ? sourceURL.substr(lastIndexOfDot + 1) : "";
+        var mimeType = WebInspector.ResourceType.mimeTypesForExtensions[extension.toLowerCase()];
+        var sourceContent = this.sourceContent(sourceURL);
+        if (sourceContent)
+            return new WebInspector.StaticContentProvider(contentType, sourceContent, mimeType);
+        return new WebInspector.CompilerSourceMappingContentProvider(sourceURL, contentType, mimeType);
+    },
+
+    /**
+     * @param {SourceMapV3} mappingPayload
+     */
+    _parseMappingPayload: function(mappingPayload)
+    {
+        if (mappingPayload.sections)
+            this._parseSections(mappingPayload.sections);
+        else
+            this._parseMap(mappingPayload, 0, 0);
+    },
+
+    /**
+     * @param {Array.<SourceMapV3.Section>} sections
+     */
+    _parseSections: function(sections)
+    {
+        for (var i = 0; i < sections.length; ++i) {
+            var section = sections[i];
+            this._parseMap(section.map, section.offset.line, section.offset.column);
+        }
+    },
+
+    /**
+     * @param {number} lineNumber in compiled resource
+     * @param {number} columnNumber in compiled resource
+     * @return {?Array}
+     */
+    findEntry: function(lineNumber, columnNumber)
+    {
+        var first = 0;
+        var count = this._mappings.length;
+        while (count > 1) {
+          var step = count >> 1;
+          var middle = first + step;
+          var mapping = this._mappings[middle];
+          if (lineNumber < mapping[0] || (lineNumber === mapping[0] && columnNumber < mapping[1]))
+              count = step;
+          else {
+              first = middle;
+              count -= step;
+          }
+        }
+        var entry = this._mappings[first];
+        if (!first && entry && (lineNumber < entry[0] || (lineNumber === entry[0] && columnNumber < entry[1])))
+            return null;
+        return entry;
+    },
+
+    /**
+     * @param {string} sourceURL of the originating resource
+     * @param {number} lineNumber in the originating resource
+     * @return {Array}
+     */
+    findEntryReversed: function(sourceURL, lineNumber)
+    {
+        var mappings = this._reverseMappingsBySourceURL[sourceURL];
+        for ( ; lineNumber < mappings.length; ++lineNumber) {
+            var mapping = mappings[lineNumber];
+            if (mapping)
+                return mapping;
+        }
+        return this._mappings[0];
+    },
+
+    /**
+     * @override
+     */
+    _parseMap: function(map, lineNumber, columnNumber)
+    {
+        var sourceIndex = 0;
+        var sourceLineNumber = 0;
+        var sourceColumnNumber = 0;
+        var nameIndex = 0;
+
+        var sources = [];
+        var originalToCanonicalURLMap = {};
+        for (var i = 0; i < map.sources.length; ++i) {
+            var originalSourceURL = map.sources[i];
+            var sourceRoot = map.sourceRoot || "";
+            if (sourceRoot && !sourceRoot.endsWith("/"))
+                sourceRoot += "/";
+            var href = sourceRoot + originalSourceURL;
+            var url = WebInspector.ParsedURL.completeURL(this._sourceMappingURL, href) || href;
+            originalToCanonicalURLMap[originalSourceURL] = url;
+            sources.push(url);
+            this._sources[url] = true;
+
+            if (map.sourcesContent && map.sourcesContent[i])
+                this._sourceContentByURL[url] = map.sourcesContent[i];
+        }
+
+        var stringCharIterator = new WebInspector.SourceMap.StringCharIterator(map.mappings);
+        var sourceURL = sources[sourceIndex];
+
+        while (true) {
+            if (stringCharIterator.peek() === ",")
+                stringCharIterator.next();
+            else {
+                while (stringCharIterator.peek() === ";") {
+                    lineNumber += 1;
+                    columnNumber = 0;
+                    stringCharIterator.next();
+                }
+                if (!stringCharIterator.hasNext())
+                    break;
+            }
+
+            columnNumber += this._decodeVLQ(stringCharIterator);
+            if (this._isSeparator(stringCharIterator.peek())) {
+                this._mappings.push([lineNumber, columnNumber]);
+                continue;
+            }
+
+            var sourceIndexDelta = this._decodeVLQ(stringCharIterator);
+            if (sourceIndexDelta) {
+                sourceIndex += sourceIndexDelta;
+                sourceURL = sources[sourceIndex];
+            }
+            sourceLineNumber += this._decodeVLQ(stringCharIterator);
+            sourceColumnNumber += this._decodeVLQ(stringCharIterator);
+            if (!this._isSeparator(stringCharIterator.peek()))
+                nameIndex += this._decodeVLQ(stringCharIterator);
+
+            this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]);
+        }
+
+        for (var i = 0; i < this._mappings.length; ++i) {
+            var mapping = this._mappings[i];
+            var url = mapping[2];
+            if (!url)
+                continue;
+            if (!this._reverseMappingsBySourceURL[url])
+                this._reverseMappingsBySourceURL[url] = [];
+            var reverseMappings = this._reverseMappingsBySourceURL[url];
+            var sourceLine = mapping[3];
+            if (!reverseMappings[sourceLine])
+                reverseMappings[sourceLine] = [mapping[0], mapping[1]];
+        }
+    },
+
+    /**
+     * @param {string} char
+     * @return {boolean}
+     */
+    _isSeparator: function(char)
+    {
+        return char === "," || char === ";";
+    },
+
+    /**
+     * @param {WebInspector.SourceMap.StringCharIterator} stringCharIterator
+     * @return {number}
+     */
+    _decodeVLQ: function(stringCharIterator)
+    {
+        // Read unsigned value.
+        var result = 0;
+        var shift = 0;
+        do {
+            var digit = this._base64Map[stringCharIterator.next()];
+            result += (digit & this._VLQ_BASE_MASK) << shift;
+            shift += this._VLQ_BASE_SHIFT;
+        } while (digit & this._VLQ_CONTINUATION_MASK);
+
+        // Fix the sign.
+        var negative = result & 1;
+        result >>= 1;
+        return negative ? -result : result;
+    },
+
+    _VLQ_BASE_SHIFT: 5,
+    _VLQ_BASE_MASK: (1 << 5) - 1,
+    _VLQ_CONTINUATION_MASK: 1 << 5
+}
+
+/**
+ * @constructor
+ * @param {string} string
+ */
+WebInspector.SourceMap.StringCharIterator = function(string)
+{
+    this._string = string;
+    this._position = 0;
+}
+
+WebInspector.SourceMap.StringCharIterator.prototype = {
+    /**
+     * @return {string}
+     */
+    next: function()
+    {
+        return this._string.charAt(this._position++);
+    },
+
+    /**
+     * @return {string}
+     */
+    peek: function()
+    {
+        return this._string.charAt(this._position);
+    },
+
+    /**
+     * @return {boolean}
+     */
+    hasNext: function()
+    {
+        return this._position < this._string.length;
+    }
+}
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 6b6b115..eefd142 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -129,6 +129,11 @@
             ],
           },
         }],
+        ['v8_enable_i18n_support==1', {
+          'sources': [
+            '<(SHARED_INTERMEDIATE_DIR)/i18n-libraries.cc',
+          ],
+        }],
       ],
       'dependencies': [
         'v8_base.<(v8_target_arch)',
@@ -192,6 +197,11 @@
             'V8_SHARED',
           ],
         }],
+        ['v8_enable_i18n_support==1', {
+          'sources': [
+            '<(SHARED_INTERMEDIATE_DIR)/i18n-libraries.cc',
+          ],
+        }],
       ]
     },
     {
@@ -257,6 +267,7 @@
         '../../src/cpu-profiler-inl.h',
         '../../src/cpu-profiler.cc',
         '../../src/cpu-profiler.h',
+        '../../src/cpu.cc',
         '../../src/cpu.h',
         '../../src/data-flow.cc',
         '../../src/data-flow.h',
@@ -813,6 +824,10 @@
           ]
         }],
         ['v8_enable_i18n_support==1', {
+          'sources': [
+            '../../src/extensions/i18n/i18n-extension.cc',
+            '../../src/extensions/i18n/i18n-extension.h',
+          ],
           'dependencies': [
             '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
             '<(DEPTH)/third_party/icu/icu.gyp:icuuc',
@@ -840,15 +855,24 @@
           'toolsets': ['target'],
         }],
         ['v8_enable_i18n_support==1', {
-          'variables': {
-            'i18n_library_files': [
-              '../../src/i18n.js',
+          'actions': [{
+            'action_name': 'js2c_i18n',
+            'inputs': [
+              '../../tools/js2c.py',
+              '<@(i18n_library_files)',
             ],
-          },
-        }, {
-          'variables': {
-            'i18n_library_files': [],
-          },
+            'outputs': [
+              '<(SHARED_INTERMEDIATE_DIR)/i18n-libraries.cc',
+            ],
+            'action': [
+              'python',
+              '../../tools/js2c.py',
+              '<@(_outputs)',
+              'I18N',
+              '<(v8_compress_startup_data)',
+              '<@(i18n_library_files)'
+            ],
+          }],
         }],
       ],
       'variables': {
@@ -882,6 +906,18 @@
           '../../src/harmony-string.js',
           '../../src/harmony-array.js',
         ],
+        'i18n_library_files': [
+          '../../src/extensions/i18n/header.js',
+          '../../src/extensions/i18n/globals.js',
+          '../../src/extensions/i18n/locale.js',
+          '../../src/extensions/i18n/collator.js',
+          '../../src/extensions/i18n/number-format.js',
+          '../../src/extensions/i18n/date-format.js',
+          '../../src/extensions/i18n/break-iterator.js',
+          '../../src/extensions/i18n/i18n-utils.js',
+          '../../src/extensions/i18n/overrides.js',
+          '../../src/extensions/i18n/footer.js',
+        ],
       },
       'actions': [
         {
@@ -889,7 +925,6 @@
           'inputs': [
             '../../tools/js2c.py',
             '<@(library_files)',
-            '<@(i18n_library_files)',
           ],
           'outputs': [
             '<(SHARED_INTERMEDIATE_DIR)/libraries.cc',
@@ -900,8 +935,7 @@
             '<@(_outputs)',
             'CORE',
             '<(v8_compress_startup_data)',
-            '<@(library_files)',
-            '<@(i18n_library_files)',
+            '<@(library_files)'
           ],
         },
         {
diff --git a/tools/linux-tick-processor b/tools/linux-tick-processor
index 93f143f..7864fb4 100755
--- a/tools/linux-tick-processor
+++ b/tools/linux-tick-processor
@@ -37,4 +37,5 @@
   $tools_path/csvparser.js $tools_path/consarray.js \
   $tools_path/profile.js $tools_path/profile_view.js \
   $tools_path/logreader.js $tools_path/tickprocessor.js \
+  $tools_path/SourceMap.js \
   $tools_path/tickprocessor-driver.js -- $@ 2>/dev/null
diff --git a/tools/tickprocessor-driver.js b/tools/tickprocessor-driver.js
index 02cb81a..8ba3326 100644
--- a/tools/tickprocessor-driver.js
+++ b/tools/tickprocessor-driver.js
@@ -37,6 +37,18 @@
   }
 }
 
+function initSourceMapSupport() {
+  // Pull dev tools source maps  into our name space.
+  SourceMap = WebInspector.SourceMap;
+
+  // Overwrite the load function to load scripts synchronously.
+  SourceMap.load = function(sourceMapURL) {
+    var content = readFile(sourceMapURL);
+    var sourceMapObject = (JSON.parse(content));
+    return new SourceMap(sourceMapURL, sourceMapObject);
+  };
+}
+
 var entriesProviders = {
   'unix': UnixCppEntriesProvider,
   'windows': WindowsCppEntriesProvider,
@@ -44,6 +56,11 @@
 };
 
 var params = processArguments(arguments);
+var sourceMap = null;
+if (params.sourceMap) {
+  initSourceMapSupport();
+  sourceMap = SourceMap.load(params.sourceMap);
+}
 var snapshotLogProcessor;
 if (params.snapshotLogFileName) {
   snapshotLogProcessor = new SnapshotLogProcessor();
@@ -57,6 +74,7 @@
   params.stateFilter,
   snapshotLogProcessor,
   params.distortion,
-  params.range);
+  params.range,
+  sourceMap);
 tickProcessor.processLogFile(params.logFileName);
 tickProcessor.printStatistics();
diff --git a/tools/tickprocessor.js b/tools/tickprocessor.js
index f1a11cc..ff52541 100644
--- a/tools/tickprocessor.js
+++ b/tools/tickprocessor.js
@@ -153,7 +153,8 @@
     stateFilter,
     snapshotLogProcessor,
     distortion,
-    range) {
+    range,
+    sourceMap) {
   LogReader.call(this, {
       'shared-library': { parsers: [null, parseInt, parseInt],
           processor: this.processSharedLibrary },
@@ -196,6 +197,7 @@
   this.ignoreUnknown_ = ignoreUnknown;
   this.stateFilter_ = stateFilter;
   this.snapshotLogProcessor_ = snapshotLogProcessor;
+  this.sourceMap = sourceMap;
   this.deserializedEntriesNames_ = [];
   var ticks = this.ticks_ =
     { total: 0, unaccounted: 0, excluded: 0, gc: 0 };
@@ -544,17 +546,52 @@
   }
 };
 
+TickProcessor.prototype.getLineAndColumn = function(name) {
+  var re = /:([0-9]+):([0-9]+)$/;
+  var array = re.exec(name);
+  if (!array) {
+    return null;
+  }
+  return {line: array[1], column: array[2]};
+}
+
+TickProcessor.prototype.hasSourceMap = function() {
+  return this.sourceMap != null;
+};
+
+
+TickProcessor.prototype.formatFunctionName = function(funcName) {
+  if (!this.hasSourceMap()) {
+    return funcName;
+  }
+  var lc = this.getLineAndColumn(funcName);
+  if (lc == null) {
+    return funcName;
+  }
+  // in source maps lines and columns are zero based
+  var lineNumber = lc.line - 1;
+  var column = lc.column - 1;
+  var entry = this.sourceMap.findEntry(lineNumber, column);
+  var sourceFile = entry[2];
+  var sourceLine = entry[3] + 1;
+  var sourceColumn = entry[4] + 1;
+
+  return sourceFile + ':' + sourceLine + ':' + sourceColumn + ' -> ' + funcName;
+};
 
 TickProcessor.prototype.printEntries = function(
     profile, nonLibTicks, filterP) {
+  var that = this;
   this.processProfile(profile, filterP, function (rec) {
     if (rec.selfTime == 0) return;
     var nonLibPct = nonLibTicks != null ?
         rec.selfTime * 100.0 / nonLibTicks : 0.0;
+    var funcName = that.formatFunctionName(rec.internalFuncName);
+
     print('  ' + padLeft(rec.selfTime, 5) + '  ' +
           padLeft(rec.selfPercent.toFixed(1), 5) + '%  ' +
           padLeft(nonLibPct.toFixed(1), 5) + '%  ' +
-          rec.internalFuncName);
+          funcName);
   });
 };
 
@@ -566,9 +603,10 @@
   this.processProfile(profile, function() { return true; }, function (rec) {
     // Cut off too infrequent callers.
     if (rec.parentTotalPercent < TickProcessor.CALL_PROFILE_CUTOFF_PCT) return;
+    var funcName = self.formatFunctionName(rec.internalFuncName);
     print('  ' + padLeft(rec.totalTime, 5) + '  ' +
           padLeft(rec.parentTotalPercent.toFixed(1), 5) + '%  ' +
-          indentStr + rec.internalFuncName);
+          indentStr + funcName);
     // Limit backtrace depth.
     if (indent < 2 * self.callGraphSize_) {
       self.printHeavyProfile(rec.children, indent + 2);
@@ -823,9 +861,11 @@
     '--snapshot-log': ['snapshotLogFileName', 'snapshot.log',
         'Specify snapshot log file to use (e.g. --snapshot-log=snapshot.log)'],
     '--range': ['range', 'auto,auto',
-                'Specify the range limit as [start],[end]'],
+        'Specify the range limit as [start],[end]'],
     '--distortion': ['distortion', 0,
-                     'Specify the logging overhead in picoseconds']
+        'Specify the logging overhead in picoseconds'],
+    '--source-map': ['sourceMap', null,
+        'Specify the source map that should be used for output']
   };
   this.argsDispatch_['--js'] = this.argsDispatch_['-j'];
   this.argsDispatch_['--gc'] = this.argsDispatch_['-g'];
diff --git a/tools/v8heapconst.py b/tools/v8heapconst.py
index 57a1f59..18bd3fb 100644
--- a/tools/v8heapconst.py
+++ b/tools/v8heapconst.py
@@ -227,14 +227,14 @@
   ("OLD_POINTER_SPACE", 0x0a9d9): "NonMonomorphicCache",
   ("OLD_POINTER_SPACE", 0x0afed): "PolymorphicCodeCache",
   ("OLD_POINTER_SPACE", 0x0aff5): "NativesSourceCache",
-  ("OLD_POINTER_SPACE", 0x0b035): "EmptyScript",
-  ("OLD_POINTER_SPACE", 0x0b06d): "IntrinsicFunctionNames",
-  ("OLD_POINTER_SPACE", 0x0e089): "ObservationState",
-  ("OLD_POINTER_SPACE", 0x0e095): "FrozenSymbol",
-  ("OLD_POINTER_SPACE", 0x0e0a1): "ElementsTransitionSymbol",
-  ("OLD_POINTER_SPACE", 0x0e0ad): "EmptySlowElementDictionary",
-  ("OLD_POINTER_SPACE", 0x0e249): "ObservedSymbol",
-  ("OLD_POINTER_SPACE", 0x274e9): "StringTable",
+  ("OLD_POINTER_SPACE", 0x0b03d): "EmptyScript",
+  ("OLD_POINTER_SPACE", 0x0b075): "IntrinsicFunctionNames",
+  ("OLD_POINTER_SPACE", 0x0e091): "ObservationState",
+  ("OLD_POINTER_SPACE", 0x0e09d): "FrozenSymbol",
+  ("OLD_POINTER_SPACE", 0x0e0a9): "ElementsTransitionSymbol",
+  ("OLD_POINTER_SPACE", 0x0e0b5): "EmptySlowElementDictionary",
+  ("OLD_POINTER_SPACE", 0x0e251): "ObservedSymbol",
+  ("OLD_POINTER_SPACE", 0x29861): "StringTable",
   ("OLD_DATA_SPACE", 0x08099): "EmptyDescriptorArray",
   ("OLD_DATA_SPACE", 0x080a1): "EmptyFixedArray",
   ("OLD_DATA_SPACE", 0x080a9): "NanValue",
@@ -250,6 +250,6 @@
   ("OLD_DATA_SPACE", 0x082c9): "EmptyExternalPixelArray",
   ("OLD_DATA_SPACE", 0x082d5): "InfinityValue",
   ("OLD_DATA_SPACE", 0x082e1): "MinusZeroValue",
-  ("CODE_SPACE", 0x10d01): "JsConstructEntryCode",
-  ("CODE_SPACE", 0x183c1): "JsEntryCode",
+  ("CODE_SPACE", 0x114e1): "JsConstructEntryCode",
+  ("CODE_SPACE", 0x18ca1): "JsEntryCode",
 }
diff --git a/tools/windows-tick-processor.bat b/tools/windows-tick-processor.bat
index d67f047..79b440f 100755
--- a/tools/windows-tick-processor.bat
+++ b/tools/windows-tick-processor.bat
@@ -27,4 +27,4 @@
 SET arg9=9%9
 IF NOT %arg9:~0,2% == 9 (IF NOT %arg9:~0,2% == 9- SET log_file=%9)
 
-type %log_file% | %D8_PATH%\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%logreader.js %tools_dir%tickprocessor.js %tools_dir%tickprocessor-driver.js -- --windows %*
+type %log_file% | %D8_PATH%\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%logreader.js %tools_dir%SourceMap.js %tools_dir%tickprocessor.js %tools_dir%tickprocessor-driver.js -- --windows %*