Version 3.17.8

Added missing license headers. (Chromium issue 98597)

Inserted missing type cast in JSON.stringify. (issue 2570)

Reverted "Send SIGPROF signals on the profiler event processor thread" (issue 2571)

Fixed Array.length, String.length and Function.prototype LoadICs on x64. (issue 2568)

ES6 symbols: filter symbols form for-in loops and Object.keys. (issue 2158)

Properly handle misses for StoreArrayLengthStub on ia32 and x64 (issue 2566)

Fixed x32 handling of Atomic64. (Chromium issue chromium-os:36866)

Removed "library" variable from standalone.gypi. (Chromium issue 111541)

Fixed HCheckSmiOrInt <-> HBoundsCheck interaction wrt. representations. (issue 2556)

Enabled zapping of disposed global handles in release mode. (Chromium issue 176056)

Added workaround for redefinition of __proto__ property. (issue 2565)

ES6 symbols: Allow symbols as property names. (issue 2158)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@13864 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 4bcf89e..d401a26 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2013-03-07: Version 3.17.8
+
+        Added missing license headers. (Chromium issue 98597)
+
+        Inserted missing type cast in JSON.stringify. (issue 2570)
+
+        Reverted "Send SIGPROF signals on the profiler event processor thread"
+        (issue 2571)
+
+        Fixed Array.length, String.length and Function.prototype LoadICs on x64.
+        (issue 2568)
+
+        ES6 symbols: filter symbols form for-in loops and Object.keys.
+        (issue 2158)
+
+        Properly handle misses for StoreArrayLengthStub on ia32 and x64
+        (issue 2566)
+
+        Fixed x32 handling of Atomic64. (Chromium issue chromium-os:36866)
+
+        Removed "library" variable from standalone.gypi. (Chromium issue 111541)
+
+        Fixed HCheckSmiOrInt <-> HBoundsCheck interaction wrt. representations.
+        (issue 2556)
+
+        Enabled zapping of disposed global handles in release mode.
+        (Chromium issue 176056)
+
+        Added workaround for redefinition of __proto__ property. (issue 2565)
+
+        ES6 symbols: Allow symbols as property names. (issue 2158)
+
+        Performance and stability improvements on all platforms.
+
+
 2013-03-04: Version 3.17.7
 
         Limited recursion in regexp compilation by a budget.
diff --git a/build/standalone.gypi b/build/standalone.gypi
index 125c5bf..749755c 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -29,7 +29,6 @@
 
 {
   'variables': {
-    'library%': 'static_library',
     'component%': 'static_library',
     'visibility%': 'hidden',
     'v8_enable_backtrace%': 0,
diff --git a/include/v8.h b/include/v8.h
index 1426f57..0e5ab40 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -133,6 +133,9 @@
 class StackTrace;
 class StackFrame;
 class Isolate;
+class DeclaredAccessorDescriptor;
+class ObjectOperationDescriptor;
+class RawOperationDescriptor;
 
 namespace internal {
 
@@ -1608,6 +1611,12 @@
                    AccessControl settings = DEFAULT,
                    PropertyAttribute attribute = None);
 
+  // This function is not yet stable and should not be used at this time.
+  bool SetAccessor(Handle<String> name,
+                   Handle<DeclaredAccessorDescriptor> descriptor,
+                   AccessControl settings = DEFAULT,
+                   PropertyAttribute attribute = None);
+
   /**
    * Returns an array containing the names of the enumerable properties
    * of this object, including properties from prototype objects.  The
@@ -2379,13 +2388,6 @@
 
  private:
   FunctionTemplate();
-  void AddInstancePropertyAccessor(Handle<String> name,
-                                   AccessorGetter getter,
-                                   AccessorSetter setter,
-                                   Handle<Value> data,
-                                   AccessControl settings,
-                                   PropertyAttribute attributes,
-                                   Handle<AccessorSignature> signature);
   void SetNamedInstancePropertyHandler(NamedPropertyGetter getter,
                                        NamedPropertySetter setter,
                                        NamedPropertyQuery query,
@@ -2458,6 +2460,14 @@
                    Handle<AccessorSignature> signature =
                        Handle<AccessorSignature>());
 
+  // This function is not yet stable and should not be used at this time.
+  bool SetAccessor(Handle<String> name,
+                   Handle<DeclaredAccessorDescriptor> descriptor,
+                   AccessControl settings = DEFAULT,
+                   PropertyAttribute attribute = None,
+                   Handle<AccessorSignature> signature =
+                       Handle<AccessorSignature>());
+
   /**
    * Sets a named property handler on the object template.
    *
@@ -2587,6 +2597,61 @@
 };
 
 
+class V8EXPORT DeclaredAccessorDescriptor : public Data {
+ private:
+  DeclaredAccessorDescriptor();
+};
+
+
+class V8EXPORT ObjectOperationDescriptor : public Data {
+ public:
+  // This function is not yet stable and should not be used at this time.
+  static Local<RawOperationDescriptor> NewInternalFieldDereference(
+      Isolate* isolate,
+      int internal_field);
+ private:
+  ObjectOperationDescriptor();
+};
+
+
+enum DeclaredAccessorDescriptorDataType {
+    kDescriptorBoolType,
+    kDescriptorInt8Type, kDescriptorUint8Type,
+    kDescriptorInt16Type, kDescriptorUint16Type,
+    kDescriptorInt32Type, kDescriptorUint32Type,
+    kDescriptorFloatType, kDescriptorDoubleType
+};
+
+
+class V8EXPORT RawOperationDescriptor : public Data {
+ public:
+  Local<DeclaredAccessorDescriptor> NewHandleDereference(Isolate* isolate);
+  Local<RawOperationDescriptor> NewRawDereference(Isolate* isolate);
+  Local<RawOperationDescriptor> NewRawShift(Isolate* isolate,
+                                            int16_t byte_offset);
+  Local<DeclaredAccessorDescriptor> NewPointerCompare(Isolate* isolate,
+                                                      void* compare_value);
+  Local<DeclaredAccessorDescriptor> NewPrimitiveValue(
+      Isolate* isolate,
+      DeclaredAccessorDescriptorDataType data_type,
+      uint8_t bool_offset = 0);
+  Local<DeclaredAccessorDescriptor> NewBitmaskCompare8(Isolate* isolate,
+                                                       uint8_t bitmask,
+                                                       uint8_t compare_value);
+  Local<DeclaredAccessorDescriptor> NewBitmaskCompare16(
+      Isolate* isolate,
+      uint16_t bitmask,
+      uint16_t compare_value);
+  Local<DeclaredAccessorDescriptor> NewBitmaskCompare32(
+      Isolate* isolate,
+      uint32_t bitmask,
+      uint32_t compare_value);
+
+ private:
+  RawOperationDescriptor();
+};
+
+
 /**
  * A utility for determining the type of objects based on the template
  * they were constructed from.
diff --git a/src/api.cc b/src/api.cc
index e5135a2..4d91e8f 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1041,6 +1041,124 @@
 }
 
 
+template<typename Operation>
+static Local<Operation> NewDescriptor(
+    Isolate* isolate,
+    const i::DeclaredAccessorDescriptorData& data,
+    Data* previous_descriptor
+    ) {
+  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+  i::Handle<i::DeclaredAccessorDescriptor> previous =
+      i::Handle<i::DeclaredAccessorDescriptor>();
+  if (previous_descriptor != NULL) {
+    previous = Utils::OpenHandle(
+      static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
+  }
+  i::Handle<i::DeclaredAccessorDescriptor> descriptor =
+      i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
+  return Local<Operation>(
+      reinterpret_cast<Operation*>(*Utils::ToLocal(descriptor)));
+}
+
+
+Local<RawOperationDescriptor>
+  ObjectOperationDescriptor::NewInternalFieldDereference(
+    Isolate* isolate,
+    int internal_field) {
+  i::DeclaredAccessorDescriptorData data;
+  data.type = i::kDescriptorObjectDereference;
+  data.object_dereference_descriptor.internal_field = internal_field;
+  return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL);
+}
+
+
+Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift(
+    Isolate* isolate,
+    int16_t byte_offset) {
+  i::DeclaredAccessorDescriptorData data;
+  data.type = i::kDescriptorPointerShift;
+  data.pointer_shift_descriptor.byte_offset = byte_offset;
+  return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
+}
+
+
+Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference(
+    Isolate* isolate) {
+  i::DeclaredAccessorDescriptorData data;
+  data.type = i::kDescriptorReturnObject;
+  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
+}
+
+
+Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference(
+    Isolate* isolate) {
+  i::DeclaredAccessorDescriptorData data;
+  data.type = i::kDescriptorPointerDereference;
+  return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
+}
+
+
+Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare(
+    Isolate* isolate,
+    void* compare_value) {
+  i::DeclaredAccessorDescriptorData data;
+  data.type = i::kDescriptorPointerCompare;
+  data.pointer_compare_descriptor.compare_value = compare_value;
+  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
+}
+
+
+Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue(
+    Isolate* isolate,
+    DeclaredAccessorDescriptorDataType data_type,
+    uint8_t bool_offset) {
+  i::DeclaredAccessorDescriptorData data;
+  data.type = i::kDescriptorPrimitiveValue;
+  data.primitive_value_descriptor.data_type = data_type;
+  data.primitive_value_descriptor.bool_offset = bool_offset;
+  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
+}
+
+
+template<typename T>
+static Local<DeclaredAccessorDescriptor> NewBitmaskCompare(
+    Isolate* isolate,
+    T bitmask,
+    T compare_value,
+    RawOperationDescriptor* operation) {
+  i::DeclaredAccessorDescriptorData data;
+  data.type = i::kDescriptorBitmaskCompare;
+  data.bitmask_compare_descriptor.bitmask = bitmask;
+  data.bitmask_compare_descriptor.compare_value = compare_value;
+  data.bitmask_compare_descriptor.size = sizeof(T);
+  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation);
+}
+
+
+Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8(
+    Isolate* isolate,
+    uint8_t bitmask,
+    uint8_t compare_value) {
+  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
+}
+
+
+Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16(
+    Isolate* isolate,
+    uint16_t bitmask,
+    uint16_t compare_value) {
+  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
+}
+
+
+Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32(
+    Isolate* isolate,
+    uint32_t bitmask,
+    uint32_t compare_value) {
+  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
+}
+
+
 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
   Handle<FunctionTemplate> types[1] = { type };
   return TypeSwitch::New(1, types);
@@ -1102,20 +1220,12 @@
 }
 
 
-static i::Handle<i::AccessorInfo> MakeAccessorInfo(
-      v8::Handle<String> name,
-      AccessorGetter getter,
-      AccessorSetter setter,
-      v8::Handle<Value> data,
-      v8::AccessControl settings,
-      v8::PropertyAttribute attributes,
-      v8::Handle<AccessorSignature> signature) {
-  i::Handle<i::ExecutableAccessorInfo> obj =
-      FACTORY->NewExecutableAccessorInfo();
-  SET_FIELD_WRAPPED(obj, set_getter, getter);
-  SET_FIELD_WRAPPED(obj, set_setter, setter);
-  if (data.IsEmpty()) data = v8::Undefined();
-  obj->set_data(*Utils::OpenHandle(*data));
+static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
+    i::Handle<i::AccessorInfo> obj,
+    v8::Handle<String> name,
+    v8::AccessControl settings,
+    v8::PropertyAttribute attributes,
+    v8::Handle<AccessorSignature> signature) {
   obj->set_name(*Utils::OpenHandle(*name));
   if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
   if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
@@ -1128,7 +1238,7 @@
 }
 
 
-void FunctionTemplate::AddInstancePropertyAccessor(
+static i::Handle<i::AccessorInfo> MakeAccessorInfo(
       v8::Handle<String> name,
       AccessorGetter getter,
       AccessorSetter setter,
@@ -1136,25 +1246,29 @@
       v8::AccessControl settings,
       v8::PropertyAttribute attributes,
       v8::Handle<AccessorSignature> signature) {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  if (IsDeadCheck(isolate,
-                  "v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
-    return;
-  }
-  ENTER_V8(isolate);
-  i::HandleScope scope(isolate);
+  i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
+  i::Handle<i::ExecutableAccessorInfo> obj =
+      isolate->factory()->NewExecutableAccessorInfo();
+  SET_FIELD_WRAPPED(obj, set_getter, getter);
+  SET_FIELD_WRAPPED(obj, set_setter, setter);
+  if (data.IsEmpty()) data = v8::Undefined();
+  obj->set_data(*Utils::OpenHandle(*data));
+  return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
+}
 
-  i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name, getter, setter, data,
-                                                    settings, attributes,
-                                                    signature);
-  i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors(),
-                            isolate);
-  if (list->IsUndefined()) {
-    list = NeanderArray().value();
-    Utils::OpenHandle(this)->set_property_accessors(*list);
-  }
-  NeanderArray array(list);
-  array.add(obj);
+
+static i::Handle<i::AccessorInfo> MakeAccessorInfo(
+      v8::Handle<String> name,
+      v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
+      v8::AccessControl settings,
+      v8::PropertyAttribute attributes,
+      v8::Handle<AccessorSignature> signature) {
+  i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
+  if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
+  i::Handle<i::DeclaredAccessorInfo> obj =
+      isolate->factory()->NewDeclaredAccessorInfo();
+  obj->set_descriptor(*Utils::OpenHandle(*descriptor));
+  return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
 }
 
 
@@ -1335,6 +1449,19 @@
 }
 
 
+static inline void AddPropertyToFunctionTemplate(
+    i::Handle<i::FunctionTemplateInfo> cons,
+    i::Handle<i::AccessorInfo> obj) {
+  i::Handle<i::Object> list(cons->property_accessors(), cons->GetIsolate());
+  if (list->IsUndefined()) {
+    list = NeanderArray().value();
+    cons->set_property_accessors(*list);
+  }
+  NeanderArray array(list);
+  array.add(obj);
+}
+
+
 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
                                  AccessorGetter getter,
                                  AccessorSetter setter,
@@ -1350,13 +1477,31 @@
   i::FunctionTemplateInfo* constructor =
       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
   i::Handle<i::FunctionTemplateInfo> cons(constructor);
-  Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
-                                                    getter,
-                                                    setter,
-                                                    data,
-                                                    settings,
-                                                    attribute,
-                                                    signature);
+  i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name, getter, setter, data,
+                                                      settings, attribute,
+                                                      signature);
+  AddPropertyToFunctionTemplate(cons, obj);
+}
+
+
+bool ObjectTemplate::SetAccessor(Handle<String> name,
+                                 Handle<DeclaredAccessorDescriptor> descriptor,
+                                 AccessControl settings,
+                                 PropertyAttribute attribute,
+                                 Handle<AccessorSignature> signature) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessor()")) return false;
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  EnsureConstructor(this);
+  i::FunctionTemplateInfo* constructor =
+      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+  i::Handle<i::FunctionTemplateInfo> cons(constructor);
+  i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
+      name, descriptor, settings, attribute, signature);
+  if (obj.is_null()) return false;
+  AddPropertyToFunctionTemplate(cons, obj);
+  return true;
 }
 
 
@@ -3158,6 +3303,16 @@
 }
 
 
+static inline bool SetAccessor(Object* obj, i::Handle<i::AccessorInfo> info) {
+  if (info.is_null()) return false;
+  bool fast = Utils::OpenHandle(obj)->HasFastProperties();
+  i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(obj), info);
+  if (result.is_null() || result->IsUndefined()) return false;
+  if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0);
+  return true;
+}
+
+
 bool Object::SetAccessor(Handle<String> name,
                          AccessorGetter getter,
                          AccessorSetter setter,
@@ -3172,11 +3327,22 @@
   i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name, getter, setter, data,
                                                      settings, attributes,
                                                      signature);
-  bool fast = Utils::OpenHandle(this)->HasFastProperties();
-  i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
-  if (result.is_null() || result->IsUndefined()) return false;
-  if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(this), 0);
-  return true;
+  return v8::SetAccessor(this, info);
+}
+
+
+bool Object::SetAccessor(Handle<String> name,
+                         Handle<DeclaredAccessorDescriptor> descriptor,
+                         AccessControl settings,
+                         PropertyAttribute attributes) {
+  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+  ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
+  ENTER_V8(isolate);
+  i::HandleScope scope(isolate);
+  v8::Handle<AccessorSignature> signature;
+  i::Handle<i::AccessorInfo> info = MakeAccessorInfo(
+      name, descriptor, settings, attributes, signature);
+  return v8::SetAccessor(this, info);
 }
 
 
@@ -3831,68 +3997,200 @@
 }
 
 
-class Utf8LengthVisitor {
+class Utf8LengthHelper : public i::AllStatic {
  public:
-  explicit Utf8LengthVisitor()
-    : utf8_length_(0),
-      last_character_(unibrow::Utf16::kNoPreviousCharacter) {}
+  enum State {
+    kEndsWithLeadingSurrogate = 1 << 0,
+    kStartsWithTrailingSurrogate = 1 << 1,
+    kLeftmostEdgeIsCalculated = 1 << 2,
+    kRightmostEdgeIsCalculated = 1 << 3,
+    kLeftmostEdgeIsSurrogate = 1 << 4,
+    kRightmostEdgeIsSurrogate = 1 << 5
+  };
 
-  inline int GetLength() {
-    return utf8_length_;
+  static const uint8_t kInitialState = 0;
+
+  static inline bool EndsWithSurrogate(uint8_t state) {
+    return state & kEndsWithLeadingSurrogate;
   }
 
-  template<typename Char>
-  inline void Visit(const Char* chars, unsigned length) {
-    ASSERT(length > 0);
-    // TODO(dcarney) Add back ascii fast path.
-    int utf8_length = 0;
-    int last_character = last_character_;
-    for (unsigned i = 0; i < length; i++) {
-      uint16_t c = chars[i];
-      utf8_length += unibrow::Utf8::Length(c, last_character);
-      last_character = c;
+  static inline bool StartsWithSurrogate(uint8_t state) {
+    return state & kStartsWithTrailingSurrogate;
+  }
+
+  class Visitor {
+   public:
+    explicit Visitor()
+      : utf8_length_(0),
+        state_(kInitialState) {}
+
+    template<typename Char>
+    inline void Visit(const Char* chars, int length) {
+      int utf8_length = 0;
+      int last_character = unibrow::Utf16::kNoPreviousCharacter;
+      for (int i = 0; i < length; i++) {
+        uint16_t c = chars[i];
+        utf8_length += unibrow::Utf8::Length(c, last_character);
+        if (sizeof(Char) > 1) {
+          last_character = c;
+        }
+      }
+      utf8_length_ = utf8_length;
     }
-    last_character_ = last_character;
-    utf8_length_ += utf8_length;
+
+    void VisitOneByteString(const uint8_t* chars, int length) {
+      Visit(chars, length);
+      state_ = kInitialState;
+    }
+
+    void VisitTwoByteString(const uint16_t* chars, int length) {
+      Visit(chars, length);
+      uint8_t state = 0;
+      if (unibrow::Utf16::IsTrailSurrogate(chars[0])) {
+        state |= kStartsWithTrailingSurrogate;
+      }
+      if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) {
+        state |= kEndsWithLeadingSurrogate;
+      }
+      state_ = state;
+    }
+
+    static i::ConsString* VisitFlat(i::String* string,
+                                    int* length,
+                                    uint8_t* state) {
+      Visitor visitor;
+      i::ConsString* cons_string = i::String::VisitFlat(&visitor, string);
+      *length = visitor.utf8_length_;
+      *state = visitor.state_;
+      return cons_string;
+    }
+
+   private:
+    int utf8_length_;
+    uint8_t state_;
+    DISALLOW_COPY_AND_ASSIGN(Visitor);
+  };
+
+  static inline void MergeLeafLeft(int* length,
+                                   uint8_t* state,
+                                   uint8_t leaf_state) {
+    bool edge_surrogate = StartsWithSurrogate(leaf_state);
+    if (!(*state & kLeftmostEdgeIsCalculated)) {
+      ASSERT(!(*state & kLeftmostEdgeIsSurrogate));
+      *state |= kLeftmostEdgeIsCalculated
+          | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0);
+    } else if (EndsWithSurrogate(*state) && edge_surrogate) {
+      *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
+    }
+    if (EndsWithSurrogate(leaf_state)) {
+      *state |= kEndsWithLeadingSurrogate;
+    } else {
+      *state &= ~kEndsWithLeadingSurrogate;
+    }
   }
 
-  inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
-    Visit(chars, length);
+  static inline void MergeLeafRight(int* length,
+                                    uint8_t* state,
+                                    uint8_t leaf_state) {
+    bool edge_surrogate = EndsWithSurrogate(leaf_state);
+    if (!(*state & kRightmostEdgeIsCalculated)) {
+      ASSERT(!(*state & kRightmostEdgeIsSurrogate));
+      *state |= (kRightmostEdgeIsCalculated
+          | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
+    } else if (edge_surrogate && StartsWithSurrogate(*state)) {
+      *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
+    }
+    if (StartsWithSurrogate(leaf_state)) {
+      *state |= kStartsWithTrailingSurrogate;
+    } else {
+      *state &= ~kStartsWithTrailingSurrogate;
+    }
   }
 
-  inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
-    Visit(chars, length);
+  static inline void MergeTerminal(int* length,
+                                   uint8_t state,
+                                   uint8_t* state_out) {
+    ASSERT((state & kLeftmostEdgeIsCalculated) &&
+           (state & kRightmostEdgeIsCalculated));
+    if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) {
+      *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
+    }
+    *state_out = kInitialState |
+        (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) |
+        (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0);
+  }
+
+  static int Calculate(i::ConsString* current, uint8_t* state_out) {
+    using namespace internal;
+    int total_length = 0;
+    uint8_t state = kInitialState;
+    while (true) {
+      i::String* left = current->first();
+      i::String* right = current->second();
+      uint8_t right_leaf_state;
+      uint8_t left_leaf_state;
+      int leaf_length;
+      ConsString* left_as_cons =
+          Visitor::VisitFlat(left, &leaf_length, &left_leaf_state);
+      if (left_as_cons == NULL) {
+        total_length += leaf_length;
+        MergeLeafLeft(&total_length, &state, left_leaf_state);
+      }
+      ConsString* right_as_cons =
+          Visitor::VisitFlat(right, &leaf_length, &right_leaf_state);
+      if (right_as_cons == NULL) {
+        total_length += leaf_length;
+        MergeLeafRight(&total_length, &state, right_leaf_state);
+        // Terminal node.
+        if (left_as_cons == NULL) {
+          MergeTerminal(&total_length, state, state_out);
+          return total_length;
+        }
+      } else if (left_as_cons != NULL) {
+        // Both strings are ConsStrings.
+        // Recurse on smallest.
+        if (left->length() < right->length()) {
+          total_length += Calculate(left_as_cons, &left_leaf_state);
+          MergeLeafLeft(&total_length, &state, left_leaf_state);
+          current = right_as_cons;
+          continue;
+        } else {
+          total_length += Calculate(right_as_cons, &right_leaf_state);
+          MergeLeafRight(&total_length, &state, right_leaf_state);
+          current = left_as_cons;
+          continue;
+        }
+      }
+      // 1 leaf node. Do in place descent.
+      if (left_as_cons != NULL) {
+        current = left_as_cons;
+      } else {
+        ASSERT(right_as_cons != NULL);
+        current = right_as_cons;
+      }
+    }
+    UNREACHABLE();
+    return 0;
+  }
+
+  static inline int Calculate(i::ConsString* current) {
+    uint8_t state = kInitialState;
+    return Calculate(current, &state);
   }
 
  private:
-  int utf8_length_;
-  int last_character_;
-  DISALLOW_COPY_AND_ASSIGN(Utf8LengthVisitor);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper);
 };
 
 
 static int Utf8Length(i::String* str, i::Isolate* isolate) {
-  unsigned length = static_cast<unsigned>(str->length());
+  int length = str->length();
   if (length == 0) return 0;
-  int32_t type = str->map()->instance_type();
-  Utf8LengthVisitor visitor;
-  // Non ConsString branch.
-  if ((type & i::kStringRepresentationMask) != i::kConsStringTag) {
-    i::ConsStringNullOp null_op;
-    i::String::Visit(str, 0, visitor, null_op, type, length);
-    return visitor.GetLength();
-  }
-  i::ConsStringIteratorOp* op = isolate->write_iterator();
-  unsigned offset = 0;
-  i::String* leaf = op->Operate(str, &offset, &type, &length);
-  ASSERT(leaf != NULL);
-  while (leaf != NULL) {
-    i::ConsStringNullOp null_op;
-    ASSERT(offset == 0);
-    i::String::Visit(leaf, 0, visitor, null_op, type, length);
-    leaf = op->ContinueOperation(&type, &length);
-  }
-  return visitor.GetLength();
+  uint8_t state;
+  i::ConsString* cons_string =
+      Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state);
+  if (cons_string == NULL) return length;
+  return Utf8LengthHelper::Calculate(cons_string);
 }
 
 
@@ -3906,12 +4204,14 @@
 
 class Utf8WriterVisitor {
  public:
-  Utf8WriterVisitor(char* buffer, int capacity)
+  Utf8WriterVisitor(
+      char* buffer, int capacity, bool skip_capacity_check)
     : early_termination_(false),
       last_character_(unibrow::Utf16::kNoPreviousCharacter),
       buffer_(buffer),
       start_(buffer),
       capacity_(capacity),
+      skip_capacity_check_(capacity == -1 || skip_capacity_check),
       utf16_chars_read_(0) {
   }
 
@@ -3935,7 +4235,7 @@
     // Can't encode using last_character as gcc has array bounds issues.
     int written = Utf8::Encode(temp_buffer,
                                character,
-                               unibrow::Utf16::kNoPreviousCharacter);
+                               Utf16::kNoPreviousCharacter);
     // Won't fit.
     if (written > remaining) return 0;
     // Copy over the character from temp_buffer.
@@ -3948,45 +4248,55 @@
   template<typename Char>
   void Visit(const Char* chars, const int length) {
     using namespace unibrow;
-    // TODO(dcarney): Add back ascii fast path.
     ASSERT(!early_termination_);
-    ASSERT(length > 0);
+    if (length == 0) return;
     // Copy state to stack.
     char* buffer = buffer_;
-    int last_character = last_character_;
+    int last_character =
+        sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_;
     int i = 0;
     // Do a fast loop where there is no exit capacity check.
     while (true) {
       int fast_length;
-      if (capacity_ == -1) {
+      if (skip_capacity_check_) {
         fast_length = length;
       } else {
         int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
         // Need enough space to write everything but one character.
         STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
-        int writable_length = (remaining_capacity - 3)/3;
+        int max_size_per_char =  sizeof(Char) == 1 ? 2 : 3;
+        int writable_length =
+            (remaining_capacity - max_size_per_char)/max_size_per_char;
         // Need to drop into slow loop.
         if (writable_length <= 0) break;
         fast_length = i + writable_length;
         if (fast_length > length) fast_length = length;
       }
       // Write the characters to the stream.
-      for (; i < fast_length; i++) {
-        uint16_t character = *chars++;
-        buffer += Utf8::Encode(buffer, character, last_character);
-        last_character = character;
-        ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
+      if (sizeof(Char) == 1) {
+        for (; i < fast_length; i++) {
+          buffer +=
+              Utf8::Encode(buffer, *chars++, Utf16::kNoPreviousCharacter);
+          ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
+        }
+      } else {
+        for (; i < fast_length; i++) {
+          uint16_t character = *chars++;
+          buffer += Utf8::Encode(buffer, character, last_character);
+          last_character = character;
+          ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
+        }
       }
       // Array is fully written. Exit.
       if (fast_length == length) {
         // Write state back out to object.
         last_character_ = last_character;
         buffer_ = buffer;
-        utf16_chars_read_ += i;
+        utf16_chars_read_ += length;
         return;
       }
     }
-    ASSERT(capacity_ != -1);
+    ASSERT(!skip_capacity_check_);
     // Slow loop. Must check capacity on each iteration.
     int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
     ASSERT(remaining_capacity >= 0);
@@ -4014,15 +4324,15 @@
     return early_termination_;
   }
 
-  inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
-    Visit(chars, static_cast<int>(length));
+  inline void VisitOneByteString(const uint8_t* chars, int length) {
+    Visit(chars, length);
   }
 
-  inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
-    Visit(chars, static_cast<int>(length));
+  inline void VisitTwoByteString(const uint16_t* chars, int length) {
+    Visit(chars, length);
   }
 
-  inline int CompleteWrite(bool write_null, int* utf16_chars_read_out) {
+  int CompleteWrite(bool write_null, int* utf16_chars_read_out) {
     // Write out number of utf16 characters written to the stream.
     if (utf16_chars_read_out != NULL) {
       *utf16_chars_read_out = utf16_chars_read_;
@@ -4042,11 +4352,32 @@
   char* buffer_;
   char* const start_;
   int capacity_;
+  bool const skip_capacity_check_;
   int utf16_chars_read_;
   DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor);
 };
 
 
+static bool RecursivelySerializeToUtf8(i::String* current,
+                                      Utf8WriterVisitor* writer,
+                                      int recursion_budget) {
+  while (!writer->IsDone()) {
+    i::ConsString* cons_string = i::String::VisitFlat(writer, current);
+    if (cons_string == NULL) return true;  // Leaf node.
+    if (recursion_budget <= 0) return false;
+    // Must write the left branch first.
+    i::String* first = cons_string->first();
+    bool success = RecursivelySerializeToUtf8(first,
+                                              writer,
+                                              recursion_budget - 1);
+    if (!success) return false;
+    // Inline tail recurse for right branch.
+    current = cons_string->second();
+  }
+  return true;
+}
+
+
 int String::WriteUtf8(char* buffer,
                       int capacity,
                       int* nchars_ref,
@@ -4059,23 +4390,41 @@
   if (options & HINT_MANY_WRITES_EXPECTED) {
     FlattenString(str);  // Flatten the string for efficiency.
   }
-  Utf8WriterVisitor writer(buffer, capacity);
-  i::ConsStringIteratorOp* op = isolate->write_iterator();
-  op->Reset();
-  int32_t type = str->map()->instance_type();
-  unsigned str_length = static_cast<unsigned>(str->length());
-  if (str_length != 0) {
-    i::String::Visit(*str, 0, writer, *op, type, str_length);
-    while (!writer.IsDone()) {
-      unsigned length_out;
-      i::String* next = op->ContinueOperation(&type, &length_out);
-      if (next == NULL) break;
-      // TODO(dcarney): need an asserting null op.
-      i::ConsStringNullOp null_op;
-      i::String::Visit(next, 0, writer, null_op, type, length_out);
+  const int string_length = str->length();
+  bool write_null = !(options & NO_NULL_TERMINATION);
+  // First check if we can just write the string without checking capacity.
+  if (capacity == -1 || capacity / 3 >= string_length) {
+    Utf8WriterVisitor writer(buffer, capacity, true);
+    const int kMaxRecursion = 100;
+    bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion);
+    if (success) return writer.CompleteWrite(write_null, nchars_ref);
+  } else if (capacity >= string_length) {
+    // First check that the buffer is large enough.
+    int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate());
+    if (utf8_bytes <= capacity) {
+      // ASCII fast path.
+      if (utf8_bytes == string_length) {
+        WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options);
+        if (nchars_ref != NULL) *nchars_ref = string_length;
+        if (write_null && (utf8_bytes+1 <= capacity)) {
+          return string_length + 1;
+        }
+        return string_length;
+      }
+      if (write_null && (utf8_bytes+1 > capacity)) {
+        options |= NO_NULL_TERMINATION;
+      }
+      // Recurse once without a capacity limit.
+      // This will get into the first branch above.
+      // TODO(dcarney) Check max left rec. in Utf8Length and fall through.
+      return WriteUtf8(buffer, -1, nchars_ref, options);
     }
   }
-  return writer.CompleteWrite(!(options & NO_NULL_TERMINATION), nchars_ref);
+  // Recursive slow path can potentially be unreasonable slow. Flatten.
+  str = FlattenGetString(str);
+  Utf8WriterVisitor writer(buffer, capacity, false);
+  i::String::VisitFlat(&writer, *str);
+  return writer.CompleteWrite(write_null, nchars_ref);
 }
 
 
diff --git a/src/api.h b/src/api.h
index ca2240b..ac6b834 100644
--- a/src/api.h
+++ b/src/api.h
@@ -177,7 +177,8 @@
   V(Context, Context)                          \
   V(External, Foreign)                         \
   V(StackTrace, JSArray)                       \
-  V(StackFrame, JSObject)
+  V(StackFrame, JSObject)                      \
+  V(DeclaredAccessorDescriptor, DeclaredAccessorDescriptor)
 
 
 class Utils {
@@ -225,6 +226,8 @@
       v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);
   static inline Local<External> ExternalToLocal(
       v8::internal::Handle<v8::internal::JSObject> obj);
+  static inline Local<DeclaredAccessorDescriptor> ToLocal(
+      v8::internal::Handle<v8::internal::DeclaredAccessorDescriptor> obj);
 
 #define DECLARE_OPEN_HANDLE(From, To) \
   static inline v8::internal::Handle<v8::internal::To> \
@@ -280,6 +283,7 @@
 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
+MAKE_TO_LOCAL(ToLocal, DeclaredAccessorDescriptor, DeclaredAccessorDescriptor)
 
 #undef MAKE_TO_LOCAL
 
diff --git a/src/apinatives.js b/src/apinatives.js
index 79b41dd..ad1d869 100644
--- a/src/apinatives.js
+++ b/src/apinatives.js
@@ -90,7 +90,7 @@
       // internal ToBoolean doesn't handle that!
       if (!(typeof parent === 'undefined')) {
         var parent_fun = Instantiate(parent);
-        fun.prototype.__proto__ = parent_fun.prototype;
+        %SetPrototype(fun.prototype, parent_fun.prototype);
       }
       ConfigureTemplateInstance(fun, data);
     } catch (e) {
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index a8c32d9..1574d51 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -48,7 +48,7 @@
 bool CpuFeatures::initialized_ = false;
 #endif
 unsigned CpuFeatures::supported_ = 0;
-unsigned CpuFeatures::found_by_runtime_probing_ = 0;
+unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
 
 
 ExternalReference ExternalReference::cpu_features() {
@@ -110,7 +110,7 @@
 
 
 void CpuFeatures::Probe() {
-  unsigned standard_features = static_cast<unsigned>(
+  uint64_t standard_features = static_cast<unsigned>(
       OS::CpuFeaturesImpliedByPlatform()) | CpuFeaturesImpliedByCompiler();
   ASSERT(supported_ == 0 || supported_ == standard_features);
 #ifdef DEBUG
@@ -131,23 +131,26 @@
   // For the simulator=arm build, use VFP when FLAG_enable_vfp3 is
   // enabled. VFPv3 implies ARMv7, see ARM DDI 0406B, page A1-6.
   if (FLAG_enable_vfp3) {
-    supported_ |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2;
+    supported_ |=
+        static_cast<uint64_t>(1) << VFP3 |
+        static_cast<uint64_t>(1) << ARMv7 |
+        static_cast<uint64_t>(1) << VFP2;
   }
   // For the simulator=arm build, use ARMv7 when FLAG_enable_armv7 is enabled
   if (FLAG_enable_armv7) {
-    supported_ |= 1u << ARMv7;
+    supported_ |= static_cast<uint64_t>(1) << ARMv7;
   }
 
   if (FLAG_enable_sudiv) {
-    supported_ |= 1u << SUDIV;
+    supported_ |= static_cast<uint64_t>(1) << SUDIV;
   }
 
   if (FLAG_enable_movw_movt) {
-    supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
+    supported_ |= static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS;
   }
 
   if (FLAG_enable_32dregs) {
-    supported_ |= 1u << VFP32DREGS;
+    supported_ |= static_cast<uint64_t>(1) << VFP32DREGS;
   }
 
 #else  // __arm__
@@ -156,33 +159,38 @@
     // This implementation also sets the VFP flags if runtime
     // detection of VFP returns true. VFPv3 implies ARMv7 and VFP2, see ARM DDI
     // 0406B, page A1-6.
-    found_by_runtime_probing_ |= 1u << VFP3 | 1u << ARMv7 | 1u << VFP2;
+    found_by_runtime_probing_only_ |=
+        static_cast<uint64_t>(1) << VFP3 |
+        static_cast<uint64_t>(1) << ARMv7 |
+        static_cast<uint64_t>(1) << VFP2;
   } else if (!IsSupported(VFP2) && OS::ArmCpuHasFeature(VFP2)) {
-    found_by_runtime_probing_ |= 1u << VFP2;
+    found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP2;
   }
 
   if (!IsSupported(ARMv7) && OS::ArmCpuHasFeature(ARMv7)) {
-    found_by_runtime_probing_ |= 1u << ARMv7;
+    found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << ARMv7;
   }
 
   if (!IsSupported(SUDIV) && OS::ArmCpuHasFeature(SUDIV)) {
-    found_by_runtime_probing_ |= 1u << SUDIV;
+    found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << SUDIV;
   }
 
   if (!IsSupported(UNALIGNED_ACCESSES) && OS::ArmCpuHasFeature(ARMv7)) {
-    found_by_runtime_probing_ |= 1u << UNALIGNED_ACCESSES;
+    found_by_runtime_probing_only_ |=
+        static_cast<uint64_t>(1) << UNALIGNED_ACCESSES;
   }
 
   if (OS::GetCpuImplementer() == QUALCOMM_IMPLEMENTER &&
       OS::ArmCpuHasFeature(ARMv7)) {
-    found_by_runtime_probing_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS;
+    found_by_runtime_probing_only_ |=
+        static_cast<uint64_t>(1) << MOVW_MOVT_IMMEDIATE_LOADS;
   }
 
   if (!IsSupported(VFP32DREGS) && OS::ArmCpuHasFeature(VFP32DREGS)) {
-    found_by_runtime_probing_ |= 1u << VFP32DREGS;
+    found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << VFP32DREGS;
   }
 
-  supported_ |= found_by_runtime_probing_;
+  supported_ |= found_by_runtime_probing_only_;
 #endif
 
   // Assert that VFP3 implies VFP2 and ARMv7.
@@ -1541,7 +1549,7 @@
 
 void Assembler::ldrd(Register dst1, Register dst2,
                      const MemOperand& src, Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(ARMv7));
+  ASSERT(IsEnabled(ARMv7));
   ASSERT(src.rm().is(no_reg));
   ASSERT(!dst1.is(lr));  // r14.
   ASSERT_EQ(0, dst1.code() % 2);
@@ -1556,7 +1564,7 @@
   ASSERT(!src1.is(lr));  // r14.
   ASSERT_EQ(0, src1.code() % 2);
   ASSERT_EQ(src1.code() + 1, src2.code());
-  ASSERT(CpuFeatures::IsEnabled(ARMv7));
+  ASSERT(IsEnabled(ARMv7));
   addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
 }
 
@@ -1755,7 +1763,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-924.
   // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) |
   // Vd(15-12) | 1011(11-8) | offset
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -1799,7 +1807,7 @@
   // Instruction details available in ARM DDI 0406A, A8-628.
   // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) |
   // Vdst(15-12) | 1010(11-8) | offset
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -1843,7 +1851,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-1082.
   // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) |
   // Vd(15-12) | 1011(11-8) | (offset/4)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -1887,7 +1895,7 @@
   // Instruction details available in ARM DDI 0406A, A8-786.
   // cond(31-28) | 1101(27-24)| U000(23-20) | Rbase(19-16) |
   // Vdst(15-12) | 1010(11-8) | (offset/4)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int u = 1;
   if (offset < 0) {
     offset = -offset;
@@ -1930,7 +1938,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-922.
   // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
   // first(15-12) | 1011(11-8) | (count * 2)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT_LE(first.code(), last.code());
   ASSERT(am == ia || am == ia_w || am == db_w);
   ASSERT(!base.is(pc));
@@ -1952,7 +1960,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-1080.
   // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
   // first(15-12) | 1011(11-8) | (count * 2)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT_LE(first.code(), last.code());
   ASSERT(am == ia || am == ia_w || am == db_w);
   ASSERT(!base.is(pc));
@@ -1973,7 +1981,7 @@
   // Instruction details available in ARM DDI 0406A, A8-626.
   // cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) |
   // first(15-12) | 1010(11-8) | (count/2)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT_LE(first.code(), last.code());
   ASSERT(am == ia || am == ia_w || am == db_w);
   ASSERT(!base.is(pc));
@@ -1994,7 +2002,7 @@
   // Instruction details available in ARM DDI 0406A, A8-784.
   // cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) |
   // first(15-12) | 1011(11-8) | (count/2)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT_LE(first.code(), last.code());
   ASSERT(am == ia || am == ia_w || am == db_w);
   ASSERT(!base.is(pc));
@@ -2068,7 +2076,7 @@
 void Assembler::vmov(const DwVfpRegister dst,
                      double imm,
                      const Register scratch) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
 
   uint32_t enc;
   if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) {
@@ -2140,7 +2148,7 @@
                      const Condition cond) {
   // Sd = Sm
   // Instruction details available in ARM DDI 0406B, A8-642.
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int sd, d, sm, m;
   dst.split_code(&sd, &d);
   src.split_code(&sm, &m);
@@ -2155,7 +2163,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-938.
   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
   // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vm, m;
@@ -2173,7 +2181,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-940.
   // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) |
   // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT(index.index == 0 || index.index == 1);
   int vd, d;
   dst.split_code(&vd, &d);
@@ -2190,7 +2198,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-948.
   // cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) |
   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT(!src1.is(pc) && !src2.is(pc));
   int vm, m;
   dst.split_code(&vm, &m);
@@ -2207,7 +2215,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-948.
   // cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) |
   // Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT(!dst1.is(pc) && !dst2.is(pc));
   int vm, m;
   src.split_code(&vm, &m);
@@ -2223,7 +2231,7 @@
   // Instruction details available in ARM DDI 0406A, A8-642.
   // cond(31-28) | 1110(27-24)| 000(23-21) | op=0(20) | Vn(19-16) |
   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT(!src.is(pc));
   int sn, n;
   dst.split_code(&sn, &n);
@@ -2238,7 +2246,7 @@
   // Instruction details available in ARM DDI 0406A, A8-642.
   // cond(31-28) | 1110(27-24)| 000(23-21) | op=1(20) | Vn(19-16) |
   // Rt(15-12) | 1010(11-8) | N(7)=0 | 00(6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT(!dst.is(pc));
   int sn, n;
   src.split_code(&sn, &n);
@@ -2363,7 +2371,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(EncodeVCVT(F64, dst.code(), S32, src.code(), mode, cond));
 }
 
@@ -2372,7 +2380,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(EncodeVCVT(F32, dst.code(), S32, src.code(), mode, cond));
 }
 
@@ -2381,7 +2389,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(EncodeVCVT(F64, dst.code(), U32, src.code(), mode, cond));
 }
 
@@ -2390,7 +2398,7 @@
                              const DwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(EncodeVCVT(S32, dst.code(), F64, src.code(), mode, cond));
 }
 
@@ -2399,7 +2407,7 @@
                              const DwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(EncodeVCVT(U32, dst.code(), F64, src.code(), mode, cond));
 }
 
@@ -2408,7 +2416,7 @@
                              const SwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(EncodeVCVT(F64, dst.code(), F32, src.code(), mode, cond));
 }
 
@@ -2417,7 +2425,7 @@
                              const DwVfpRegister src,
                              VFPConversionMode mode,
                              const Condition cond) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(EncodeVCVT(F32, dst.code(), F64, src.code(), mode, cond));
 }
 
@@ -2428,7 +2436,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-968.
   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) |
   // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vm, m;
@@ -2445,7 +2453,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-524.
   // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) |
   // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vm, m;
@@ -2464,7 +2472,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-830.
   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vn, n;
@@ -2485,7 +2493,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-1086.
   // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vn, n;
@@ -2506,7 +2514,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-960.
   // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vn, n;
@@ -2563,7 +2571,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-882.
   // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) |
   // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vn, n;
@@ -2582,7 +2590,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-864.
   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) |
   // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   src1.split_code(&vd, &d);
   int vm, m;
@@ -2599,7 +2607,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-864.
   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) |
   // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   ASSERT(src2 == 0.0);
   int vd, d;
   src1.split_code(&vd, &d);
@@ -2611,7 +2619,7 @@
   // Instruction details available in ARM DDI 0406A, A8-652.
   // cond(31-28) | 1110 (27-24) | 1110(23-20)| 0001 (19-16) |
   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(cond | 0xE*B24 | 0xE*B20 |  B16 |
        dst.code()*B12 | 0xA*B8 | B4);
 }
@@ -2621,7 +2629,7 @@
   // Instruction details available in ARM DDI 0406A, A8-652.
   // cond(31-28) | 1110 (27-24) | 1111(23-20)| 0001 (19-16) |
   // Rt(15-12) | 1010 (11-8) | 0(7) | 00 (6-5) | 1(4) | 0000(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   emit(cond | 0xE*B24 | 0xF*B20 |  B16 |
        dst.code()*B12 | 0xA*B8 | B4);
 }
@@ -2633,7 +2641,7 @@
   // Instruction details available in ARM DDI 0406C.b, A8-1058.
   // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) |
   // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0)
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   int vd, d;
   dst.split_code(&vd, &d);
   int vm, m;
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 12cee54..045638e 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -48,7 +48,7 @@
 namespace internal {
 
 // CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
 class CpuFeatures : public AllStatic {
  public:
   // Detect features of the target CPU. Set safe defaults if the serializer
@@ -68,89 +68,23 @@
     return (supported_ & (1u << f)) != 0;
   }
 
-#ifdef DEBUG
-  // Check whether a feature is currently enabled.
-  static bool IsEnabled(CpuFeature f) {
+  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
     ASSERT(initialized_);
-    Isolate* isolate = Isolate::UncheckedCurrent();
-    if (isolate == NULL) {
-      // When no isolate is available, work as if we're running in
-      // release mode.
-      return IsSupported(f);
-    }
-    unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
-    return (enabled & (1u << f)) != 0;
+    return (found_by_runtime_probing_only_ &
+            (static_cast<uint64_t>(1) << f)) != 0;
   }
-#endif
 
-  // Enable a specified feature within a scope.
-  class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
-   public:
-    explicit Scope(CpuFeature f) {
-      unsigned mask = 1u << f;
-      // VFP2 and ARMv7 are implied by VFP3.
-      if (f == VFP3) mask |= 1u << VFP2 | 1u << ARMv7;
-      ASSERT(CpuFeatures::IsSupported(f));
-      ASSERT(!Serializer::enabled() ||
-             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
-      isolate_ = Isolate::UncheckedCurrent();
-      old_enabled_ = 0;
-      if (isolate_ != NULL) {
-        old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
-        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
-      }
-    }
-    ~Scope() {
-      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
-      if (isolate_ != NULL) {
-        isolate_->set_enabled_cpu_features(old_enabled_);
-      }
-    }
-
-   private:
-    Isolate* isolate_;
-    unsigned old_enabled_;
-#else
-
-   public:
-    explicit Scope(CpuFeature f) {}
-#endif
-  };
-
-  class TryForceFeatureScope BASE_EMBEDDED {
-   public:
-    explicit TryForceFeatureScope(CpuFeature f)
-        : old_supported_(CpuFeatures::supported_) {
-      if (CanForce()) {
-        CpuFeatures::supported_ |= (1u << f);
-      }
-    }
-
-    ~TryForceFeatureScope() {
-      if (CanForce()) {
-        CpuFeatures::supported_ = old_supported_;
-      }
-    }
-
-   private:
-    static bool CanForce() {
-      // It's only safe to temporarily force support of CPU features
-      // when there's only a single isolate, which is guaranteed when
-      // the serializer is enabled.
-      return Serializer::enabled();
-    }
-
-    const unsigned old_supported_;
-  };
+  static bool IsSafeForSnapshot(CpuFeature f) {
+    return (IsSupported(f) &&
+            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
+  }
 
  private:
 #ifdef DEBUG
   static bool initialized_;
 #endif
   static unsigned supported_;
-  static unsigned found_by_runtime_probing_;
+  static unsigned found_by_runtime_probing_only_;
 
   friend class ExternalReference;
   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 466c890..b2c2193 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -554,7 +554,7 @@
     __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
     __ tst(r3, Operand(kSmiTagMask));
     __ Assert(ne, "Unexpected initial map for Array function");
-    __ CompareObjectType(r1, r3, r4, MAP_TYPE);
+    __ CompareObjectType(r3, r3, r4, MAP_TYPE);
     __ Assert(eq, "Unexpected initial map for Array function");
 
     if (FLAG_optimize_constructed_arrays) {
@@ -1377,12 +1377,6 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
-  CpuFeatures::TryForceFeatureScope scope(VFP3);
-  if (!CPU::SupportsCrankshaft()) {
-    __ Abort("Unreachable code: Cannot optimize without VFP3 support.");
-    return;
-  }
-
   // Lookup the function in the JavaScript frame and push it as an
   // argument to the on-stack replacement function.
   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index fa8e57b..93dda9d 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -651,7 +651,7 @@
                                    Register scratch1,
                                    Register scratch2) {
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ mov(scratch1, Operand(r0, ASR, kSmiTagSize));
     __ vmov(d7.high(), scratch1);
     __ vcvt_f64_s32(d7, d7.high());
@@ -702,7 +702,7 @@
   // Handle loading a double from a heap number.
   if (CpuFeatures::IsSupported(VFP2) &&
       destination == kVFPRegisters) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     // Load the double from tagged HeapNumber to double register.
     __ sub(scratch1, object, Operand(kHeapObjectTag));
     __ vldr(dst, scratch1, HeapNumber::kValueOffset);
@@ -716,7 +716,7 @@
   // Handle loading a double from a smi.
   __ bind(&is_smi);
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     // Convert smi to double using VFP instructions.
     __ vmov(dst.high(), scratch1);
     __ vcvt_f64_s32(dst, dst.high());
@@ -792,7 +792,7 @@
   Label done;
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ vmov(single_scratch, int_scratch);
     __ vcvt_f64_s32(double_dst, single_scratch);
     if (destination == kCoreRegisters) {
@@ -886,18 +886,12 @@
 
   // Load the number.
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     // Load the double value.
     __ sub(scratch1, object, Operand(kHeapObjectTag));
     __ vldr(double_dst, scratch1, HeapNumber::kValueOffset);
 
-    __ EmitVFPTruncate(kRoundToZero,
-                       scratch1,
-                       double_dst,
-                       scratch2,
-                       double_scratch,
-                       kCheckForInexactConversion);
-
+    __ TestDoubleIsInt32(double_dst, double_scratch);
     // Jump to not_int32 if the operation did not succeed.
     __ b(ne, not_int32);
 
@@ -983,19 +977,13 @@
   // Object is a heap number.
   // Convert the floating point value to a 32-bit integer.
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
 
     // Load the double value.
     __ sub(scratch1, object, Operand(kHeapObjectTag));
     __ vldr(double_scratch0, scratch1, HeapNumber::kValueOffset);
 
-    __ EmitVFPTruncate(kRoundToZero,
-                       dst,
-                       double_scratch0,
-                       scratch1,
-                       double_scratch1,
-                       kCheckForInexactConversion);
-
+    __ TryDoubleToInt32Exact(dst, double_scratch0, double_scratch1);
     // Jump to not_int32 if the operation did not succeed.
     __ b(ne, not_int32);
   } else {
@@ -1118,7 +1106,7 @@
   __ push(lr);
   __ PrepareCallCFunction(0, 2, scratch);
   if (masm->use_eabi_hardfloat()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ vmov(d0, r0, r1);
     __ vmov(d1, r2, r3);
   }
@@ -1130,7 +1118,7 @@
   // Store answer in the overwritable heap number. Double returned in
   // registers r0 and r1 or in d0.
   if (masm->use_eabi_hardfloat()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ vstr(d0,
             FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
   } else {
@@ -1345,7 +1333,7 @@
   // Lhs is a smi, rhs is a number.
   if (CpuFeatures::IsSupported(VFP2)) {
     // Convert lhs to a double in d7.
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ SmiToDoubleVFPRegister(lhs, d7, r7, s15);
     // Load the double from rhs, tagged HeapNumber r0, to d6.
     __ sub(r7, rhs, Operand(kHeapObjectTag));
@@ -1384,7 +1372,7 @@
 
   // Rhs is a smi, lhs is a heap number.
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     // Load the double from lhs, tagged HeapNumber r1, to d7.
     __ sub(r7, lhs, Operand(kHeapObjectTag));
     __ vldr(d7, r7, HeapNumber::kValueOffset);
@@ -1496,7 +1484,7 @@
     __ push(lr);
     __ PrepareCallCFunction(0, 2, r5);
     if (masm->use_eabi_hardfloat()) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm, VFP2);
       __ vmov(d0, r0, r1);
       __ vmov(d1, r2, r3);
     }
@@ -1573,7 +1561,7 @@
   // Both are heap numbers.  Load them up then jump to the code we have
   // for that.
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ sub(r7, rhs, Operand(kHeapObjectTag));
     __ vldr(d6, r7, HeapNumber::kValueOffset);
     __ sub(r7, lhs, Operand(kHeapObjectTag));
@@ -1663,7 +1651,7 @@
   if (!object_is_smi) {
     __ JumpIfSmi(object, &is_smi);
     if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm, VFP2);
       __ CheckMap(object,
                   scratch1,
                   Heap::kHeapNumberMapRootIndex,
@@ -1814,7 +1802,7 @@
   Isolate* isolate = masm->isolate();
   if (CpuFeatures::IsSupported(VFP2)) {
     __ bind(&lhs_not_nan);
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     Label no_nan;
     // ARMv7 VFP3 instructions to implement double precision comparison.
     __ VFPCompareAndSetFlags(d7, d6);
@@ -1994,7 +1982,7 @@
     __ b(ne, &not_heap_number);
 
     if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm, VFP2);
 
       __ vldr(d1, FieldMemOperand(tos_, HeapNumber::kValueOffset));
       __ VFPCompareAndSetFlags(d1, 0.0);
@@ -2094,7 +2082,7 @@
   const Register scratch = r1;
 
   if (save_doubles_ == kSaveFPRegs) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     // Check CPU flags for number of registers, setting the Z condition flag.
     __ CheckFor32DRegs(scratch);
 
@@ -2114,7 +2102,7 @@
       ExternalReference::store_buffer_overflow_function(masm->isolate()),
       argument_count);
   if (save_doubles_ == kSaveFPRegs) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
 
     // Check CPU flags for number of registers, setting the Z condition flag.
     __ CheckFor32DRegs(scratch);
@@ -2350,7 +2338,7 @@
 
   if (CpuFeatures::IsSupported(VFP2)) {
     // Convert the int32 in r1 to the heap number in r0. r2 is corrupted.
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ vmov(s0, r1);
     __ vcvt_f64_s32(d0, s0);
     __ sub(r2, r0, Operand(kHeapObjectTag));
@@ -2745,7 +2733,7 @@
         // Using VFP registers:
         // d6: Left value
         // d7: Right value
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm, VFP2);
         switch (op) {
           case Token::ADD:
             __ vadd(d5, d6, d7);
@@ -2877,7 +2865,7 @@
       if (CpuFeatures::IsSupported(VFP2)) {
         // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
         // mentioned above SHR needs to always produce a positive result.
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm, VFP2);
         __ vmov(s0, r2);
         if (op == Token::SHR) {
           __ vcvt_f64_u32(d0, s0);
@@ -3069,7 +3057,7 @@
                                                    &transition);
 
       if (destination == FloatingPointHelper::kVFPRegisters) {
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm, VFP2);
         Label return_heap_number;
         switch (op_) {
           case Token::ADD:
@@ -3094,16 +3082,14 @@
           // Otherwise return a heap number if allowed, or jump to type
           // transition.
 
-          __ EmitVFPTruncate(kRoundToZero,
-                             scratch1,
-                             d5,
-                             scratch2,
-                             d8);
-
           if (result_type_ <= BinaryOpIC::INT32) {
+            __ TryDoubleToInt32Exact(scratch1, d5, d8);
             // If the ne condition is set, result does
             // not fit in a 32-bit integer.
             __ b(ne, &transition);
+          } else {
+            __ vcvt_s32_f64(s8, d5);
+            __ vmov(scratch1, s8);
           }
 
           // Check if the result fits in a smi.
@@ -3278,7 +3264,7 @@
                                                 mode_);
 
       if (CpuFeatures::IsSupported(VFP2)) {
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm, VFP2);
         if (op_ != Token::SHR) {
           // Convert the result to a floating point value.
           __ vmov(double_scratch.low(), r2);
@@ -3481,7 +3467,7 @@
   const bool tagged = (argument_type_ == TAGGED);
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     if (tagged) {
       // Argument is a number and is on stack and in r0.
       // Load argument and check if it is a smi.
@@ -3583,7 +3569,7 @@
     __ TailCallExternalReference(runtime_function, 1, 1);
   } else {
     ASSERT(CpuFeatures::IsSupported(VFP2));
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
 
     Label no_update;
     Label skip_cache;
@@ -3644,7 +3630,7 @@
 
 void TranscendentalCacheStub::GenerateCallCFunction(MacroAssembler* masm,
                                                     Register scratch) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(masm->IsEnabled(VFP2));
   Isolate* isolate = masm->isolate();
 
   __ push(lr);
@@ -3705,7 +3691,7 @@
 
 
 void MathPowStub::Generate(MacroAssembler* masm) {
-  CpuFeatures::Scope vfp2_scope(VFP2);
+  CpuFeatureScope vfp2_scope(masm, VFP2);
   const Register base = r1;
   const Register exponent = r2;
   const Register heapnumbermap = r5;
@@ -3931,21 +3917,15 @@
   // These stubs might already be in the snapshot, detect that and don't
   // regenerate, which would lead to code stub initialization state being messed
   // up.
-  Code* save_doubles_code = NULL;
-  Code* store_buffer_overflow_code = NULL;
-  if (!save_doubles.FindCodeInCache(&save_doubles_code, ISOLATE)) {
-    if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope2(VFP2);
-      save_doubles_code = *save_doubles.GetCode(isolate);
-      store_buffer_overflow_code = *stub.GetCode(isolate);
-    } else {
-      save_doubles_code = *save_doubles.GetCode(isolate);
-      store_buffer_overflow_code = *stub.GetCode(isolate);
-    }
+  Code* save_doubles_code;
+  if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
+    save_doubles_code = *save_doubles.GetCode(isolate);
     save_doubles_code->set_is_pregenerated(true);
+
+    Code* store_buffer_overflow_code = *stub.GetCode(isolate);
     store_buffer_overflow_code->set_is_pregenerated(true);
   }
-  ISOLATE->set_fp_stubs_generated(true);
+  isolate->set_fp_stubs_generated(true);
 }
 
 
@@ -4192,7 +4172,7 @@
   __ stm(db_w, sp, kCalleeSaved | lr.bit());
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     // Save callee-saved vfp registers.
     __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
     // Set up the reserved register for 0.0.
@@ -4346,7 +4326,7 @@
 #endif
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     // Restore callee-saved vfp registers.
     __ vldm(ia_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg);
   }
@@ -7090,7 +7070,7 @@
   // Inlining the double comparison and falling back to the general compare
   // stub if NaN is involved or VFP2 is unsupported.
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
 
     // Load left and right operand.
     Label done, left, left_smi, right_smi;
@@ -7425,13 +7405,14 @@
 }
 
 
-void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
-                                                        Label* miss,
-                                                        Label* done,
-                                                        Register receiver,
-                                                        Register properties,
-                                                        Handle<String> name,
-                                                        Register scratch0) {
+void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+                                                      Label* miss,
+                                                      Label* done,
+                                                      Register receiver,
+                                                      Register properties,
+                                                      Handle<Name> name,
+                                                      Register scratch0) {
+  ASSERT(name->IsUniqueName());
   // If names of slots in range from 1 to kProbes - 1 for the hash value are
   // not equal to the name and kProbes-th slot is not used (its name is the
   // undefined value), it guarantees the hash table doesn't contain the
@@ -7445,10 +7426,10 @@
     __ ldr(index, FieldMemOperand(properties, kCapacityOffset));
     __ sub(index, index, Operand(1));
     __ and_(index, index, Operand(
-        Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i))));
+        Smi::FromInt(name->Hash() + NameDictionary::GetProbeOffset(i))));
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
 
     Register entity_name = scratch0;
@@ -7468,21 +7449,23 @@
       __ LoadRoot(tmp, Heap::kTheHoleValueRootIndex);
 
       // Stop if found the property.
-      __ cmp(entity_name, Operand(Handle<String>(name)));
+      __ cmp(entity_name, Operand(Handle<Name>(name)));
       __ b(eq, miss);
 
-      Label the_hole;
+      Label good;
       __ cmp(entity_name, tmp);
-      __ b(eq, &the_hole);
+      __ b(eq, &good);
 
-      // Check if the entry name is not an internalized string.
+      // Check if the entry name is not a unique name.
       __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
       __ ldrb(entity_name,
               FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
       __ tst(entity_name, Operand(kIsInternalizedMask));
-      __ b(eq, miss);
+      __ b(ne, &good);
+      __ cmp(entity_name, Operand(SYMBOL_TYPE));
+      __ b(ne, miss);
 
-      __ bind(&the_hole);
+      __ bind(&good);
 
       // Restore the properties.
       __ ldr(properties,
@@ -7496,8 +7479,8 @@
 
   __ stm(db_w, sp, spill_mask);
   __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
-  __ mov(r1, Operand(Handle<String>(name)));
-  StringDictionaryLookupStub stub(NEGATIVE_LOOKUP);
+  __ mov(r1, Operand(Handle<Name>(name)));
+  NameDictionaryLookupStub stub(NEGATIVE_LOOKUP);
   __ CallStub(&stub);
   __ cmp(r0, Operand::Zero());
   __ ldm(ia_w, sp, spill_mask);
@@ -7507,23 +7490,23 @@
 }
 
 
-// Probe the string dictionary in the |elements| register. Jump to the
+// Probe the name dictionary in the |elements| register. Jump to the
 // |done| label if a property with the given name is found. Jump to
 // the |miss| label otherwise.
 // If lookup was successful |scratch2| will be equal to elements + 4 * index.
-void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
-                                                        Label* miss,
-                                                        Label* done,
-                                                        Register elements,
-                                                        Register name,
-                                                        Register scratch1,
-                                                        Register scratch2) {
+void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
+                                                      Label* miss,
+                                                      Label* done,
+                                                      Register elements,
+                                                      Register name,
+                                                      Register scratch1,
+                                                      Register scratch2) {
   ASSERT(!elements.is(scratch1));
   ASSERT(!elements.is(scratch2));
   ASSERT(!name.is(scratch1));
   ASSERT(!name.is(scratch2));
 
-  __ AssertString(name);
+  __ AssertName(name);
 
   // Compute the capacity mask.
   __ ldr(scratch1, FieldMemOperand(elements, kCapacityOffset));
@@ -7535,20 +7518,20 @@
   // cover ~93% of loads from dictionaries.
   for (int i = 0; i < kInlinedProbes; i++) {
     // Compute the masked index: (hash + i + i * i) & mask.
-    __ ldr(scratch2, FieldMemOperand(name, String::kHashFieldOffset));
+    __ ldr(scratch2, FieldMemOperand(name, Name::kHashFieldOffset));
     if (i > 0) {
       // Add the probe offset (i + i * i) left shifted to avoid right shifting
       // the hash in a separate instruction. The value hash + i + i * i is right
       // shifted in the following and instruction.
-      ASSERT(StringDictionary::GetProbeOffset(i) <
-             1 << (32 - String::kHashFieldOffset));
+      ASSERT(NameDictionary::GetProbeOffset(i) <
+             1 << (32 - Name::kHashFieldOffset));
       __ add(scratch2, scratch2, Operand(
-          StringDictionary::GetProbeOffset(i) << String::kHashShift));
+          NameDictionary::GetProbeOffset(i) << Name::kHashShift));
     }
-    __ and_(scratch2, scratch1, Operand(scratch2, LSR, String::kHashShift));
+    __ and_(scratch2, scratch1, Operand(scratch2, LSR, Name::kHashShift));
 
     // Scale the index by multiplying by the element size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     // scratch2 = scratch2 * 3.
     __ add(scratch2, scratch2, Operand(scratch2, LSL, 1));
 
@@ -7573,7 +7556,7 @@
     __ Move(r0, elements);
     __ Move(r1, name);
   }
-  StringDictionaryLookupStub stub(POSITIVE_LOOKUP);
+  NameDictionaryLookupStub stub(POSITIVE_LOOKUP);
   __ CallStub(&stub);
   __ cmp(r0, Operand::Zero());
   __ mov(scratch2, Operand(r2));
@@ -7584,15 +7567,15 @@
 }
 
 
-void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
+void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
   // we cannot call anything that could cause a GC from this stub.
   // Registers:
-  //  result: StringDictionary to probe
+  //  result: NameDictionary to probe
   //  r1: key
-  //  : StringDictionary to probe.
-  //  index_: will hold an index of entry if lookup is successful.
-  //          might alias with result_.
+  //  dictionary: NameDictionary to probe.
+  //  index: will hold an index of entry if lookup is successful.
+  //         might alias with result_.
   // Returns:
   //  result_ is zero if lookup failed, non zero otherwise.
 
@@ -7611,7 +7594,7 @@
   __ mov(mask, Operand(mask, ASR, kSmiTagSize));
   __ sub(mask, mask, Operand(1));
 
-  __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
+  __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset));
 
   __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
 
@@ -7622,17 +7605,17 @@
       // Add the probe offset (i + i * i) left shifted to avoid right shifting
       // the hash in a separate instruction. The value hash + i + i * i is right
       // shifted in the following and instruction.
-      ASSERT(StringDictionary::GetProbeOffset(i) <
-             1 << (32 - String::kHashFieldOffset));
+      ASSERT(NameDictionary::GetProbeOffset(i) <
+             1 << (32 - Name::kHashFieldOffset));
       __ add(index, hash, Operand(
-          StringDictionary::GetProbeOffset(i) << String::kHashShift));
+          NameDictionary::GetProbeOffset(i) << Name::kHashShift));
     } else {
       __ mov(index, Operand(hash));
     }
-    __ and_(index, mask, Operand(index, LSR, String::kHashShift));
+    __ and_(index, mask, Operand(index, LSR, Name::kHashShift));
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ add(index, index, Operand(index, LSL, 1));  // index *= 3.
 
     ASSERT_EQ(kSmiTagSize, 1);
@@ -7648,12 +7631,16 @@
     __ b(eq, &in_dictionary);
 
     if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
-      // Check if the entry name is not an internalized string.
+      // Check if the entry name is not a unique name.
+      Label cont;
       __ ldr(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
       __ ldrb(entry_key,
               FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
       __ tst(entry_key, Operand(kIsInternalizedMask));
-      __ b(eq, &maybe_in_dictionary);
+      __ b(ne, &cont);
+      __ cmp(entry_key, Operand(SYMBOL_TYPE));
+      __ b(ne, &maybe_in_dictionary);
+      __ bind(&cont);
     }
   }
 
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index f952756..a5d08af 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -471,7 +471,7 @@
       if (mode == kSaveFPRegs) {
         // Number of d-regs not known at snapshot time.
         ASSERT(!Serializer::enabled());
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm, VFP2);
         masm->sub(sp,
                   sp,
                   Operand(kDoubleSize * (DwVfpRegister::NumRegisters() - 1)));
@@ -489,7 +489,7 @@
       if (mode == kSaveFPRegs) {
         // Number of d-regs not known at snapshot time.
         ASSERT(!Serializer::enabled());
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm, VFP2);
         // Restore all VFP registers except d0.
         // TODO(hans): We should probably restore d0 too. And maybe use vldm.
         for (int i = DwVfpRegister::NumRegisters() - 1; i > 0; i--) {
@@ -745,11 +745,11 @@
 };
 
 
-class StringDictionaryLookupStub: public PlatformCodeStub {
+class NameDictionaryLookupStub: public PlatformCodeStub {
  public:
   enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
 
-  explicit StringDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
+  explicit NameDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
 
   void Generate(MacroAssembler* masm);
 
@@ -758,7 +758,7 @@
                                      Label* done,
                                      Register receiver,
                                      Register properties,
-                                     Handle<String> name,
+                                     Handle<Name> name,
                                      Register scratch0);
 
   static void GeneratePositiveLookup(MacroAssembler* masm,
@@ -776,14 +776,14 @@
   static const int kTotalProbes = 20;
 
   static const int kCapacityOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kCapacityIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kCapacityIndex * kPointerSize;
 
   static const int kElementsStartOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
 
-  Major MajorKey() { return StringDictionaryLookup; }
+  Major MajorKey() { return NameDictionaryLookup; }
 
   int MinorKey() {
     return LookupModeBits::encode(mode_);
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 6e3c635..ff97ab5 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -72,7 +72,7 @@
   MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
 
   {
-    CpuFeatures::Scope use_vfp(VFP2);
+    CpuFeatureScope use_vfp(&masm, VFP2);
     DwVfpRegister input = d0;
     DwVfpRegister result = d1;
     DwVfpRegister double_scratch1 = d2;
@@ -277,7 +277,7 @@
 
   // Normal smi, convert to double and store.
   if (vfp2_supported) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ vmov(s0, r9);
     __ vcvt_f64_s32(d0, s0);
     __ vstr(d0, r7, 0);
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
index 2e1e3e3..3753318 100644
--- a/src/arm/deoptimizer-arm.cc
+++ b/src/arm/deoptimizer-arm.cc
@@ -537,128 +537,6 @@
 }
 
 
-void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
-                                              int frame_index) {
-  Builtins* builtins = isolate_->builtins();
-  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
-  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
-  unsigned height = iterator->Next();
-  unsigned height_in_bytes = height * kPointerSize;
-  if (FLAG_trace_deopt) {
-    PrintF("  translating construct stub => height=%d\n", height_in_bytes);
-  }
-
-  unsigned fixed_frame_size = 8 * kPointerSize;
-  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
-
-  // Allocate and store the output frame description.
-  FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, function);
-  output_frame->SetFrameType(StackFrame::CONSTRUCT);
-
-  // Construct stub can not be topmost or bottommost.
-  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
-  ASSERT(output_[frame_index] == NULL);
-  output_[frame_index] = output_frame;
-
-  // The top address of the frame is computed from the previous
-  // frame's top and this frame's size.
-  uint32_t top_address;
-  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
-  output_frame->SetTop(top_address);
-
-  // Compute the incoming parameter translation.
-  int parameter_count = height;
-  unsigned output_offset = output_frame_size;
-  for (int i = 0; i < parameter_count; ++i) {
-    output_offset -= kPointerSize;
-    DoTranslateCommand(iterator, frame_index, output_offset);
-  }
-
-  // Read caller's PC from the previous frame.
-  output_offset -= kPointerSize;
-  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
-  output_frame->SetFrameSlot(output_offset, callers_pc);
-  if (FLAG_trace_deopt) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
-           top_address + output_offset, output_offset, callers_pc);
-  }
-
-  // Read caller's FP from the previous frame, and set this frame's FP.
-  output_offset -= kPointerSize;
-  intptr_t value = output_[frame_index - 1]->GetFp();
-  output_frame->SetFrameSlot(output_offset, value);
-  intptr_t fp_value = top_address + output_offset;
-  output_frame->SetFp(fp_value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
-           fp_value, output_offset, value);
-  }
-
-  // The context can be gotten from the previous frame.
-  output_offset -= kPointerSize;
-  value = output_[frame_index - 1]->GetContext();
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; context\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // A marker value is used in place of the function.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // The output frame reflects a JSConstructStubGeneric frame.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(construct_stub);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; code object\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // Number of incoming arguments.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
-           top_address + output_offset, output_offset, value, height - 1);
-  }
-
-  // Constructor function being invoked by the stub.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(function);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; constructor function\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // The newly allocated object was passed as receiver in the artificial
-  // constructor stub environment created by HEnvironment::CopyForInlining().
-  output_offset -= kPointerSize;
-  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  ASSERT(0 == output_offset);
-
-  uint32_t pc = reinterpret_cast<uint32_t>(
-      construct_stub->instruction_start() +
-      isolate_->heap()->construct_stub_deopt_pc_offset()->value());
-  output_frame->SetPc(pc);
-}
-
-
 // This code is very similar to ia32 code, but relies on register names (fp, sp)
 // and how the frame is laid out.
 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
@@ -876,7 +754,7 @@
       kDoubleSize * DwVfpRegister::kMaxNumAllocatableRegisters;
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     // Save all allocatable VFP registers before messing with them.
     ASSERT(kDoubleRegZero.code() == 14);
     ASSERT(kScratchDoubleReg.code() == 15);
@@ -951,7 +829,7 @@
   }
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     // Copy VFP registers to
     // double_registers_[DoubleRegister::kMaxNumAllocatableRegisters]
     int double_regs_offset = FrameDescription::double_registers_offset();
@@ -1031,7 +909,7 @@
   __ b(lt, &outer_push_loop);
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     // Check CPU flags for number of registers, setting the Z condition flag.
     __ CheckFor32DRegs(ip);
 
diff --git a/src/arm/frames-arm.h b/src/arm/frames-arm.h
index ee9fc0e..30f4057 100644
--- a/src/arm/frames-arm.h
+++ b/src/arm/frames-arm.h
@@ -149,14 +149,30 @@
 
 class ArgumentsAdaptorFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+
   static const int kFrameSize =
       StandardFrameConstants::kFixedFrameSize + kPointerSize;
 };
 
 
+class ConstructFrameConstants : public AllStatic {
+ public:
+  // FP-relative.
+  static const int kImplicitReceiverOffset = -6 * kPointerSize;
+  static const int kConstructorOffset      = -5 * kPointerSize;
+  static const int kLengthOffset           = -4 * kPointerSize;
+  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+
+  static const int kFrameSize =
+      StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize;
+};
+
+
 class InternalFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
 };
 
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 04634d6..eb1f988 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1646,8 +1646,6 @@
           }
           break;
         }
-        // Fall through.
-      case ObjectLiteral::Property::PROTOTYPE:
         // Duplicate receiver on stack.
         __ ldr(r0, MemOperand(sp));
         __ push(r0);
@@ -1661,6 +1659,18 @@
           __ Drop(3);
         }
         break;
+      case ObjectLiteral::Property::PROTOTYPE:
+        // Duplicate receiver on stack.
+        __ ldr(r0, MemOperand(sp));
+        __ push(r0);
+        VisitForStackValue(value);
+        if (property->emit_store()) {
+          __ CallRuntime(Runtime::kSetPrototype, 2);
+        } else {
+          __ Drop(2);
+        }
+        break;
+
       case ObjectLiteral::Property::GETTER:
         accessor_table.lookup(key)->second->getter = value;
         break;
@@ -3043,7 +3053,7 @@
     __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset));
     __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
 
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     // 0x41300000 is the top half of 1.0 x 2^20 as a double.
     // Create this constant using mov/orr to avoid PC relative load.
     __ mov(r1, Operand(0x41000000));
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index e8d0fab..84a11b6 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -64,12 +64,12 @@
 
 // Generated code falls through if the receiver is a regular non-global
 // JS object with slow properties and no interceptors.
-static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
-                                                  Register receiver,
-                                                  Register elements,
-                                                  Register t0,
-                                                  Register t1,
-                                                  Label* miss) {
+static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm,
+                                                Register receiver,
+                                                Register elements,
+                                                Register t0,
+                                                Register t1,
+                                                Label* miss) {
   // Register usage:
   //   receiver: holds the receiver on entry and is unchanged.
   //   elements: holds the property dictionary on fall through.
@@ -131,19 +131,19 @@
   Label done;
 
   // Probe the dictionary.
-  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
-                                                     miss,
-                                                     &done,
-                                                     elements,
-                                                     name,
-                                                     scratch1,
-                                                     scratch2);
+  NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                   miss,
+                                                   &done,
+                                                   elements,
+                                                   name,
+                                                   scratch1,
+                                                   scratch2);
 
   // If probing finds an entry check that the value is a normal
   // property.
   __ bind(&done);  // scratch2 == elements + 4 * index
-  const int kElementsStartOffset = StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+  const int kElementsStartOffset = NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
   const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
   __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
   __ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize));
@@ -180,19 +180,19 @@
   Label done;
 
   // Probe the dictionary.
-  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
-                                                     miss,
-                                                     &done,
-                                                     elements,
-                                                     name,
-                                                     scratch1,
-                                                     scratch2);
+  NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                   miss,
+                                                   &done,
+                                                   elements,
+                                                   name,
+                                                   scratch1,
+                                                   scratch2);
 
   // If probing finds an entry in the dictionary check that the value
   // is a normal property that is not read only.
   __ bind(&done);  // scratch2 == elements + 4 * index
-  const int kElementsStartOffset = StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+  const int kElementsStartOffset = NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
   const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
   const int kTypeAndReadOnlyMask =
       (PropertyDetails::TypeField::kMask |
@@ -303,22 +303,25 @@
 }
 
 
-// Checks whether a key is an array index string or an internalized string.
-// Falls through if a key is an internalized string.
-static void GenerateKeyStringCheck(MacroAssembler* masm,
-                                   Register key,
-                                   Register map,
-                                   Register hash,
-                                   Label* index_string,
-                                   Label* not_internalized) {
+// Checks whether a key is an array index string or a unique name.
+// Falls through if a key is a unique name.
+static void GenerateKeyNameCheck(MacroAssembler* masm,
+                                 Register key,
+                                 Register map,
+                                 Register hash,
+                                 Label* index_string,
+                                 Label* not_unique) {
   // The key is not a smi.
-  // Is it a string?
-  __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE);
-  __ b(ge, not_internalized);
+  Label unique;
+  // Is it a name?
+  __ CompareObjectType(key, map, hash, LAST_UNIQUE_NAME_TYPE);
+  __ b(hi, not_unique);
+  STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
+  __ b(eq, &unique);
 
   // Is the string an array index, with cached numeric value?
-  __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
-  __ tst(hash, Operand(String::kContainsCachedArrayIndexMask));
+  __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset));
+  __ tst(hash, Operand(Name::kContainsCachedArrayIndexMask));
   __ b(eq, index_string);
 
   // Is the string internalized?
@@ -326,7 +329,9 @@
   __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
   STATIC_ASSERT(kInternalizedTag != 0);
   __ tst(hash, Operand(kIsInternalizedMask));
-  __ b(eq, not_internalized);
+  __ b(eq, not_unique);
+
+  __ bind(&unique);
 }
 
 
@@ -427,7 +432,7 @@
   // Get the receiver of the function from the stack into r1.
   __ ldr(r1, MemOperand(sp, argc * kPointerSize));
 
-  GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
 
   // r0: elements
   // Search the dictionary - put result in register r1.
@@ -531,11 +536,11 @@
   __ ldr(r1, MemOperand(sp, argc * kPointerSize));
 
   Label do_call, slow_call, slow_load, slow_reload_receiver;
-  Label check_number_dictionary, check_string, lookup_monomorphic_cache;
-  Label index_smi, index_string;
+  Label check_number_dictionary, check_name, lookup_monomorphic_cache;
+  Label index_smi, index_name;
 
   // Check that the key is a smi.
-  __ JumpIfNotSmi(r2, &check_string);
+  __ JumpIfNotSmi(r2, &check_name);
   __ bind(&index_smi);
   // Now the key is known to be a smi. This place is also jumped to from below
   // where a numeric string is converted to a smi.
@@ -582,10 +587,10 @@
   __ mov(r1, r0);
   __ jmp(&do_call);
 
-  __ bind(&check_string);
-  GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call);
+  __ bind(&check_name);
+  GenerateKeyNameCheck(masm, r2, r0, r3, &index_name, &slow_call);
 
-  // The key is known to be internalized.
+  // The key is known to be a unique name.
   // If the receiver is a regular JS object with slow properties then do
   // a quick inline probe of the receiver's dictionary.
   // Otherwise do the monomorphic cache probe.
@@ -613,14 +618,14 @@
   __ bind(&slow_call);
   // This branch is taken if:
   // - the receiver requires boxing or access check,
-  // - the key is neither smi nor an internalized string,
+  // - the key is neither smi nor a unique name,
   // - the value loaded is not a function,
   // - there is hope that the runtime will create a monomorphic call stub
   //   that will get fetched next time.
   __ IncrementCounter(counters->keyed_call_generic_slow(), 1, r0, r3);
   GenerateMiss(masm, argc);
 
-  __ bind(&index_string);
+  __ bind(&index_name);
   __ IndexFromHash(r3, r2);
   // Now jump to the place where smi keys are handled.
   __ jmp(&index_smi);
@@ -633,10 +638,10 @@
   //  -- lr    : return address
   // -----------------------------------
 
-  // Check if the name is a string.
+  // Check if the name is really a name.
   Label miss;
   __ JumpIfSmi(r2, &miss);
-  __ IsObjectJSStringType(r2, r0, &miss);
+  __ IsObjectNameType(r2, r0, &miss);
 
   CallICBase::GenerateNormal(masm, argc);
   __ bind(&miss);
@@ -657,7 +662,8 @@
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(
-      Code::LOAD_IC, MONOMORPHIC, Code::HANDLER_FRAGMENT);
+      Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
+      Code::NORMAL, Code::LOAD_IC);
   Isolate::Current()->stub_cache()->GenerateProbe(
       masm, flags, r0, r2, r3, r4, r5, r6);
 
@@ -675,7 +681,7 @@
   // -----------------------------------
   Label miss;
 
-  GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
 
   // r1: elements
   GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4);
@@ -918,7 +924,7 @@
   //  -- r0     : key
   //  -- r1     : receiver
   // -----------------------------------
-  Label slow, check_string, index_smi, index_string, property_array_property;
+  Label slow, check_name, index_smi, index_name, property_array_property;
   Label probe_dictionary, check_number_dictionary;
 
   Register key = r0;
@@ -927,7 +933,7 @@
   Isolate* isolate = masm->isolate();
 
   // Check that the key is a smi.
-  __ JumpIfNotSmi(key, &check_string);
+  __ JumpIfNotSmi(key, &check_name);
   __ bind(&index_smi);
   // Now the key is known to be a smi. This place is also jumped to from below
   // where a numeric string is converted to a smi.
@@ -964,8 +970,8 @@
                       1, r2, r3);
   GenerateRuntimeGetProperty(masm);
 
-  __ bind(&check_string);
-  GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow);
+  __ bind(&check_name);
+  GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow);
 
   GenerateKeyedLoadReceiverCheck(
       masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow);
@@ -979,15 +985,15 @@
   __ b(eq, &probe_dictionary);
 
   // Load the map of the receiver, compute the keyed lookup cache hash
-  // based on 32 bits of the map pointer and the string hash.
+  // based on 32 bits of the map pointer and the name hash.
   __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
   __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
-  __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
-  __ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
+  __ ldr(r4, FieldMemOperand(r0, Name::kHashFieldOffset));
+  __ eor(r3, r3, Operand(r4, ASR, Name::kHashShift));
   int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
   __ And(r3, r3, Operand(mask));
 
-  // Load the key (consisting of map and internalized string) from the cache and
+  // Load the key (consisting of map and unique name) from the cache and
   // check for match.
   Label load_in_object_property;
   static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
@@ -1004,13 +1010,13 @@
     __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
     __ cmp(r2, r5);
     __ b(ne, &try_next_entry);
-    __ ldr(r5, MemOperand(r4, -kPointerSize));  // Load string
+    __ ldr(r5, MemOperand(r4, -kPointerSize));  // Load name
     __ cmp(r0, r5);
     __ b(eq, &hit_on_nth_entry[i]);
     __ bind(&try_next_entry);
   }
 
-  // Last entry: Load map and move r4 to string.
+  // Last entry: Load map and move r4 to name.
   __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex));
   __ cmp(r2, r5);
   __ b(ne, &slow);
@@ -1076,7 +1082,7 @@
       isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3);
   __ Ret();
 
-  __ bind(&index_string);
+  __ bind(&index_name);
   __ IndexFromHash(r3, key);
   // Now jump to the place where smi keys are handled.
   __ jmp(&index_smi);
@@ -1547,7 +1553,7 @@
   // -----------------------------------
   Label miss;
 
-  GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
 
   GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5);
   Counters* counters = masm->isolate()->counters();
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index d957594..a1f8351 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1226,6 +1226,13 @@
   if (instr->representation().IsDouble()) {
     return DoArithmeticD(Token::DIV, instr);
   } else if (instr->representation().IsInteger32()) {
+    if (instr->HasPowerOf2Divisor()) {
+      ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
+      LOperand* value = UseRegisterAtStart(instr->left());
+      LDivI* div =
+          new(zone()) LDivI(value, UseOrConstant(instr->right()));
+      return AssignEnvironment(DefineSameAsFirst(div));
+    }
     // TODO(1042) The fixed register allocation
     // is needed because we call TypeRecordingBinaryOpStub from
     // the generated code, which requires registers r0
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 8887391..6fd9797 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -196,7 +196,7 @@
   }
 
   if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     Comment(";;; Save clobbered callee double registers");
     int count = 0;
     BitVector* doubles = chunk()->allocated_double_registers();
@@ -1162,7 +1162,7 @@
   Label done;
 
   if (CpuFeatures::IsSupported(SUDIV)) {
-    CpuFeatures::Scope scope(SUDIV);
+    CpuFeatureScope scope(masm(), SUDIV);
     // Check for x % 0.
     if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
       __ cmp(right, Operand::Zero());
@@ -1208,7 +1208,7 @@
 
     Label vfp_modulo, both_positive, right_negative;
 
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
 
     // Check for x % 0.
     if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
@@ -1411,6 +1411,42 @@
     LDivI* instr_;
   };
 
+  if (instr->hydrogen()->HasPowerOf2Divisor()) {
+    Register dividend = ToRegister(instr->left());
+    int32_t divisor =
+        HConstant::cast(instr->hydrogen()->right())->Integer32Value();
+    int32_t test_value = 0;
+    int32_t power = 0;
+
+    if (divisor > 0) {
+      test_value = divisor - 1;
+      power = WhichPowerOf2(divisor);
+    } else {
+      // Check for (0 / -x) that will produce negative zero.
+      if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+        __ tst(dividend, Operand(dividend));
+        DeoptimizeIf(eq, instr->environment());
+      }
+      // Check for (kMinInt / -1).
+      if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+        __ cmp(dividend, Operand(kMinInt));
+        DeoptimizeIf(eq, instr->environment());
+      }
+      test_value = - divisor - 1;
+      power = WhichPowerOf2(-divisor);
+    }
+
+    if (test_value != 0) {
+      // Deoptimize if remainder is not 0.
+      __ tst(dividend, Operand(test_value));
+      DeoptimizeIf(ne, instr->environment());
+      __ mov(dividend, Operand(dividend, ASR, power));
+    }
+    if (divisor < 0) __ rsb(dividend, dividend, Operand(0));
+
+    return;
+  }
+
   const Register left = ToRegister(instr->left());
   const Register right = ToRegister(instr->right());
   const Register scratch = scratch0();
@@ -1531,7 +1567,7 @@
     __ teq(remainder, Operand(divisor), ne);
     __ sub(result, result, Operand(1), LeaveCC, mi);
   } else {
-    CpuFeatures::Scope scope(SUDIV);
+    CpuFeatureScope scope(masm(), SUDIV);
     const Register right = ToRegister(instr->right());
 
     // Check for x / 0.
@@ -1578,7 +1614,7 @@
                                       LOperand* left_argument,
                                       LOperand* right_argument,
                                       Token::Value op) {
-  CpuFeatures::Scope vfp_scope(VFP2);
+  CpuFeatureScope vfp_scope(masm(), VFP2);
   Register left = ToRegister(left_argument);
   Register right = ToRegister(right_argument);
 
@@ -1864,7 +1900,7 @@
 void LCodeGen::DoConstantD(LConstantD* instr) {
   ASSERT(instr->result()->IsDoubleRegister());
   DwVfpRegister result = ToDoubleRegister(instr->result());
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   double v = instr->value();
   __ Vmov(result, v, scratch0());
 }
@@ -2042,7 +2078,7 @@
     __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition));
   } else {
     ASSERT(instr->hydrogen()->representation().IsDouble());
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     DwVfpRegister left_reg = ToDoubleRegister(left);
     DwVfpRegister right_reg = ToDoubleRegister(right);
     DwVfpRegister result_reg = ToDoubleRegister(instr->result());
@@ -2088,7 +2124,7 @@
 
 
 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   DwVfpRegister left = ToDoubleRegister(instr->left());
   DwVfpRegister right = ToDoubleRegister(instr->right());
   DwVfpRegister result = ToDoubleRegister(instr->result());
@@ -2179,7 +2215,7 @@
     __ cmp(reg, Operand::Zero());
     EmitBranch(true_block, false_block, ne);
   } else if (r.IsDouble()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     DwVfpRegister reg = ToDoubleRegister(instr->value());
     Register scratch = scratch0();
 
@@ -2265,7 +2301,7 @@
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm(), VFP2);
         // heap number -> false iff +0, -0, or NaN.
         DwVfpRegister dbl_scratch = double_scratch0();
         Label not_heap_number;
@@ -2345,7 +2381,7 @@
     EmitGoto(next_block);
   } else {
     if (instr->is_double()) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm(), VFP2);
       // Compare left and right operands as doubles and load the
       // resulting flags into the normal status register.
       __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right));
@@ -2901,7 +2937,7 @@
     __ CallRuntime(Runtime::kTraceExit, 1);
   }
   if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     ASSERT(NeedsEagerFrame());
     BitVector* doubles = chunk()->allocated_double_registers();
     BitVector::Iterator save_iterator(doubles);
@@ -3276,7 +3312,7 @@
         : Operand(key, LSL, shift_size);
     __ add(scratch0(), external_pointer, operand);
     if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm(), VFP2);
       if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
         __ vldr(kScratchDoubleReg.low(), scratch0(), additional_offset);
         __ vcvt_f64_f32(result, kScratchDoubleReg.low());
@@ -3401,7 +3437,7 @@
     __ add(elements, elements, Operand(key, LSL, shift_size));
   }
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     __ add(elements, elements, Operand(base_offset));
     __ vldr(result, elements, 0);
     if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -3858,7 +3894,7 @@
 
 
 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   // Class for deferred case.
   class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
    public:
@@ -3895,99 +3931,70 @@
 
 
 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   DwVfpRegister input = ToDoubleRegister(instr->value());
   Register result = ToRegister(instr->result());
-  Register scratch = scratch0();
+  Register input_high = scratch0();
+  Label done, exact;
 
-  __ EmitVFPTruncate(kRoundToMinusInf,
-                     result,
-                     input,
-                     scratch,
-                     double_scratch0());
-  DeoptimizeIf(ne, instr->environment());
+  __ vmov(input_high, input.high());
+  __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact);
+  DeoptimizeIf(al, instr->environment());
 
+  __ bind(&exact);
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
     // Test for -0.
-    Label done;
     __ cmp(result, Operand::Zero());
     __ b(ne, &done);
-    __ vmov(scratch, input.high());
-    __ tst(scratch, Operand(HeapNumber::kSignMask));
-    DeoptimizeIf(ne, instr->environment());
-    __ bind(&done);
-  }
-}
-
-
-void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(VFP2);
-  DwVfpRegister input = ToDoubleRegister(instr->value());
-  Register result = ToRegister(instr->result());
-  DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
-  Register scratch = scratch0();
-  Label done, check_sign_on_zero;
-
-  // Extract exponent bits.
-  __ vmov(result, input.high());
-  __ ubfx(scratch,
-          result,
-          HeapNumber::kExponentShift,
-          HeapNumber::kExponentBits);
-
-  // If the number is in ]-0.5, +0.5[, the result is +/- 0.
-  __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2));
-  __ mov(result, Operand::Zero(), LeaveCC, le);
-  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    __ b(le, &check_sign_on_zero);
-  } else {
-    __ b(le, &done);
-  }
-
-  // The following conversion will not work with numbers
-  // outside of ]-2^32, 2^32[.
-  __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32));
-  DeoptimizeIf(ge, instr->environment());
-
-  __ Vmov(double_scratch0(), 0.5, scratch);
-  __ vadd(double_scratch0(), input, double_scratch0());
-
-  // Save the original sign for later comparison.
-  __ and_(scratch, result, Operand(HeapNumber::kSignMask));
-
-  // Check sign of the result: if the sign changed, the input
-  // value was in ]0.5, 0[ and the result should be -0.
-  __ vmov(result, double_scratch0().high());
-  __ eor(result, result, Operand(scratch), SetCC);
-  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    __ cmp(input_high, Operand::Zero());
     DeoptimizeIf(mi, instr->environment());
-  } else {
-    __ mov(result, Operand::Zero(), LeaveCC, mi);
-    __ b(mi, &done);
-  }
-
-  __ EmitVFPTruncate(kRoundToMinusInf,
-                     result,
-                     double_scratch0(),
-                     scratch,
-                     double_scratch1);
-  DeoptimizeIf(ne, instr->environment());
-
-  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
-    // Test for -0.
-    __ cmp(result, Operand::Zero());
-    __ b(ne, &done);
-    __ bind(&check_sign_on_zero);
-    __ vmov(scratch, input.high());
-    __ tst(scratch, Operand(HeapNumber::kSignMask));
-    DeoptimizeIf(ne, instr->environment());
   }
   __ bind(&done);
 }
 
 
+void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
+  CpuFeatureScope scope(masm(), VFP2);
+  DwVfpRegister input = ToDoubleRegister(instr->value());
+  Register result = ToRegister(instr->result());
+  DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
+  DwVfpRegister input_plus_dot_five = double_scratch1;
+  Register input_high = scratch0();
+  DwVfpRegister dot_five = double_scratch0();
+  Label convert, done;
+
+  __ Vmov(dot_five, 0.5, scratch0());
+  __ vabs(double_scratch1, input);
+  __ VFPCompareAndSetFlags(double_scratch1, dot_five);
+  // If input is in [-0.5, -0], the result is -0.
+  // If input is in [+0, +0.5[, the result is +0.
+  // If the input is +0.5, the result is 1.
+  __ b(hi, &convert);  // Out of [-0.5, +0.5].
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    __ vmov(input_high, input.high());
+    __ cmp(input_high, Operand::Zero());
+    DeoptimizeIf(mi, instr->environment());  // [-0.5, -0].
+  }
+  __ VFPCompareAndSetFlags(input, dot_five);
+  __ mov(result, Operand(1), LeaveCC, eq);  // +0.5.
+  // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on
+  // flag kBailoutOnMinusZero.
+  __ mov(result, Operand::Zero(), LeaveCC, ne);
+  __ b(&done);
+
+  __ bind(&convert);
+  __ vadd(input_plus_dot_five, input, dot_five);
+  __ vmov(input_high, input_plus_dot_five.high());
+  // Reuse dot_five (double_scratch0) as we no longer need this value.
+  __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(),
+                   &done, &done);
+  DeoptimizeIf(al, instr->environment());
+  __ bind(&done);
+}
+
+
 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   DwVfpRegister input = ToDoubleRegister(instr->value());
   DwVfpRegister result = ToDoubleRegister(instr->result());
   __ vsqrt(result, input);
@@ -3995,7 +4002,7 @@
 
 
 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   DwVfpRegister input = ToDoubleRegister(instr->value());
   DwVfpRegister result = ToDoubleRegister(instr->result());
   DwVfpRegister temp = ToDoubleRegister(instr->temp());
@@ -4017,7 +4024,7 @@
 
 
 void LCodeGen::DoPower(LPower* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   Representation exponent_type = instr->hydrogen()->right()->representation();
   // Having marked this as a call, we can use any registers.
   // Just make sure that the input/output registers are the expected ones.
@@ -4050,7 +4057,7 @@
 
 
 void LCodeGen::DoRandom(LRandom* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   class DeferredDoRandom: public LDeferredCode {
    public:
     DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
@@ -4129,7 +4136,7 @@
 
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   DwVfpRegister input = ToDoubleRegister(instr->value());
   DwVfpRegister result = ToDoubleRegister(instr->result());
   DwVfpRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
@@ -4420,7 +4427,7 @@
 
 
 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   Register external_pointer = ToRegister(instr->elements());
   Register key = no_reg;
   ElementsKind elements_kind = instr->elements_kind();
@@ -4441,7 +4448,7 @@
 
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
       elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
-    CpuFeatures::Scope scope(VFP3);
+    CpuFeatureScope scope(masm(), VFP3);
     DwVfpRegister value(ToDoubleRegister(instr->value()));
     Operand operand(key_is_constant
                     ? Operand(constant_key << element_size_shift)
@@ -4491,7 +4498,7 @@
 
 
 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   DwVfpRegister value = ToDoubleRegister(instr->value());
   Register elements = ToRegister(instr->elements());
   Register key = no_reg;
@@ -4792,7 +4799,7 @@
 
 
 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   LOperand* input = instr->value();
   ASSERT(input->IsRegister() || input->IsStackSlot());
   LOperand* output = instr->result();
@@ -4810,7 +4817,7 @@
 
 
 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   LOperand* input = instr->value();
   LOperand* output = instr->result();
 
@@ -4930,7 +4937,7 @@
       __ eor(src, src, Operand(0x80000000));
     }
     if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm(), VFP2);
       __ vmov(flt_scratch, src);
       __ vcvt_f64_s32(dbl_scratch, flt_scratch);
     } else {
@@ -4942,7 +4949,7 @@
     }
   } else {
     if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm(), VFP2);
       __ vmov(flt_scratch, src);
       __ vcvt_f64_u32(dbl_scratch, flt_scratch);
     } else {
@@ -4983,7 +4990,7 @@
   // number.
   __ bind(&done);
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset);
   } else {
     __ str(sfpd_lo, MemOperand(dst, HeapNumber::kMantissaOffset));
@@ -5022,7 +5029,7 @@
   Label done;
   if (convert_hole) {
     if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm(), VFP2);
       DwVfpRegister input_reg = ToDoubleRegister(instr->value());
       __ VFPCompareAndSetFlags(input_reg, input_reg);
       __ b(vc, &no_special_nan_handling);
@@ -5074,7 +5081,7 @@
   }
   __ bind(deferred->exit());
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     __ vstr(input_reg, reg, HeapNumber::kValueOffset);
   } else {
     __ str(sfpd_lo, MemOperand(reg, HeapNumber::kValueOffset));
@@ -5129,7 +5136,7 @@
   Register scratch = scratch0();
   SwVfpRegister flt_scratch = double_scratch0().low();
   ASSERT(!result_reg.is(double_scratch0()));
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
 
   Label load_smi, heap_number, done;
 
@@ -5218,7 +5225,7 @@
   __ cmp(scratch1, Operand(ip));
 
   if (instr->truncating()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm(), VFP2);
     Register scratch3 = ToRegister(instr->temp2());
     ASSERT(!scratch3.is(input_reg) &&
            !scratch3.is(scratch1) &&
@@ -5247,18 +5254,13 @@
                         scratch3);
 
   } else {
-    CpuFeatures::Scope scope(VFP3);
+    CpuFeatureScope scope(masm(), VFP3);
     // Deoptimize if we don't have a heap number.
     DeoptimizeIf(ne, instr->environment());
 
     __ sub(ip, input_reg, Operand(kHeapObjectTag));
     __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
-    __ EmitVFPTruncate(kRoundToZero,
-                       input_reg,
-                       double_scratch,
-                       scratch1,
-                       double_scratch2,
-                       kCheckForInexactConversion);
+    __ TryDoubleToInt32Exact(input_reg, double_scratch, double_scratch2);
     DeoptimizeIf(ne, instr->environment());
 
     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
@@ -5354,15 +5356,8 @@
                         scratch2,
                         scratch3);
   } else {
-    __ EmitVFPTruncate(kRoundToMinusInf,
-                       result_reg,
-                       double_input,
-                       scratch1,
-                       double_scratch,
-                       kCheckForInexactConversion);
-
-    // Deoptimize if we had a vfp invalid exception,
-    // including inexact operation.
+    __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
+    // Deoptimize if the input wasn't a int32 (inside a double).
     DeoptimizeIf(ne, instr->environment());
   }
     __ bind(&done);
@@ -5475,7 +5470,7 @@
 
 
 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
-  CpuFeatures::Scope vfp_scope(VFP2);
+  CpuFeatureScope vfp_scope(masm(), VFP2);
   DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped());
   Register result_reg = ToRegister(instr->result());
   DwVfpRegister temp_reg = ToDoubleRegister(instr->temp());
@@ -5484,7 +5479,7 @@
 
 
 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   Register unclamped_reg = ToRegister(instr->unclamped());
   Register result_reg = ToRegister(instr->result());
   __ ClampUint8(result_reg, unclamped_reg);
@@ -5492,7 +5487,7 @@
 
 
 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(masm(), VFP2);
   Register scratch = scratch0();
   Register input_reg = ToRegister(instr->unclamped());
   Register result_reg = ToRegister(instr->result());
diff --git a/src/arm/lithium-gap-resolver-arm.cc b/src/arm/lithium-gap-resolver-arm.cc
index 4df1338..a65ab7e 100644
--- a/src/arm/lithium-gap-resolver-arm.cc
+++ b/src/arm/lithium-gap-resolver-arm.cc
@@ -171,10 +171,10 @@
   } else if (source->IsStackSlot()) {
     __ ldr(kSavedValueRegister, cgen_->ToMemOperand(source));
   } else if (source->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(cgen_->masm(), VFP2);
     __ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source));
   } else if (source->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(cgen_->masm(), VFP2);
     __ vldr(kScratchDoubleReg, cgen_->ToMemOperand(source));
   } else {
     UNREACHABLE();
@@ -194,10 +194,10 @@
   } else if (saved_destination_->IsStackSlot()) {
     __ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
   } else if (saved_destination_->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(cgen_->masm(), VFP2);
     __ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg);
   } else if (saved_destination_->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(cgen_->masm(), VFP2);
     __ vstr(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_));
   } else {
     UNREACHABLE();
@@ -233,7 +233,7 @@
       MemOperand destination_operand = cgen_->ToMemOperand(destination);
       if (in_cycle_) {
         if (!destination_operand.OffsetIsUint12Encodable()) {
-          CpuFeatures::Scope scope(VFP2);
+          CpuFeatureScope scope(cgen_->masm(), VFP2);
             // ip is overwritten while saving the value to the destination.
           // Therefore we can't use ip.  It is OK if the read from the source
           // destroys ip, since that happens before the value is read.
@@ -272,7 +272,7 @@
     }
 
   } else if (source->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(cgen_->masm(), VFP2);
     DwVfpRegister source_register = cgen_->ToDoubleRegister(source);
     if (destination->IsDoubleRegister()) {
       __ vmov(cgen_->ToDoubleRegister(destination), source_register);
@@ -282,7 +282,7 @@
     }
 
   } else if (source->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(cgen_->masm(), VFP2);
       MemOperand source_operand = cgen_->ToMemOperand(source);
     if (destination->IsDoubleRegister()) {
       __ vldr(cgen_->ToDoubleRegister(destination), source_operand);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 326f555..2265d03 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -292,7 +292,7 @@
 
 void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src) {
   ASSERT(CpuFeatures::IsSupported(VFP2));
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(this, VFP2);
   if (!dst.is(src)) {
     vmov(dst, src);
   }
@@ -717,7 +717,7 @@
 
   // Generate two ldr instructions if ldrd is not available.
   if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) {
-    CpuFeatures::Scope scope(ARMv7);
+    CpuFeatureScope scope(this, ARMv7);
     ldrd(dst1, dst2, src, cond);
   } else {
     if ((src.am() == Offset) || (src.am() == NegOffset)) {
@@ -759,7 +759,7 @@
 
   // Generate two str instructions if strd is not available.
   if (CpuFeatures::IsSupported(ARMv7) && !predictable_code_size()) {
-    CpuFeatures::Scope scope(ARMv7);
+    CpuFeatureScope scope(this, ARMv7);
     strd(src1, src2, dst, cond);
   } else {
     MemOperand dst2(dst);
@@ -813,7 +813,7 @@
 void MacroAssembler::Vmov(const DwVfpRegister dst,
                           const double imm,
                           const Register scratch) {
-  ASSERT(CpuFeatures::IsEnabled(VFP2));
+  ASSERT(IsEnabled(VFP2));
   static const DoubleRepresentation minus_zero(-0.0);
   static const DoubleRepresentation zero(0.0);
   DoubleRepresentation value(imm);
@@ -875,7 +875,7 @@
 
   // Optionally save all double registers.
   if (save_doubles) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(this, VFP2);
     // Check CPU flags for number of registers, setting the Z condition flag.
     CheckFor32DRegs(ip);
 
@@ -940,7 +940,7 @@
                                     Register argument_count) {
   // Optionally restore all double registers.
   if (save_doubles) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(this, VFP2);
     // Calculate the stack location of the saved doubles and restore them.
     const int offset = 2 * kPointerSize;
     sub(r3, fp,
@@ -1225,6 +1225,16 @@
 }
 
 
+void MacroAssembler::IsObjectNameType(Register object,
+                                      Register scratch,
+                                      Label* fail) {
+  ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+  ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  cmp(scratch, Operand(LAST_NAME_TYPE));
+  b(hi, fail);
+}
+
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
 void MacroAssembler::DebugBreak() {
   mov(r0, Operand::Zero());
@@ -2070,7 +2080,7 @@
                                           scratch4,
                                           s2);
   if (destination == FloatingPointHelper::kVFPRegisters) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(this, VFP2);
     vstr(d0, scratch1, 0);
   } else {
     str(mantissa_reg, MemOperand(scratch1, 0));
@@ -2436,7 +2446,7 @@
                                     DwVfpRegister double_scratch,
                                     Label *not_int32) {
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(this, VFP2);
     sub(scratch, source, Operand(kHeapObjectTag));
     vldr(double_scratch, scratch, HeapNumber::kValueOffset);
     vcvt_s32_f64(double_scratch.low(), double_scratch);
@@ -2525,74 +2535,76 @@
 }
 
 
-void MacroAssembler::TryFastDoubleToInt32(Register result,
-                                          DwVfpRegister double_input,
-                                          DwVfpRegister double_scratch,
-                                          Label* done) {
+void MacroAssembler::TestDoubleIsInt32(DwVfpRegister double_input,
+                                       DwVfpRegister double_scratch) {
   ASSERT(!double_input.is(double_scratch));
+  ASSERT(CpuFeatures::IsSupported(VFP2));
+  CpuFeatureScope scope(this, VFP2);
+
+  vcvt_s32_f64(double_scratch.low(), double_input);
+  vcvt_f64_s32(double_scratch, double_scratch.low());
+  VFPCompareAndSetFlags(double_input, double_scratch);
+}
+
+
+void MacroAssembler::TryDoubleToInt32Exact(Register result,
+                                           DwVfpRegister double_input,
+                                           DwVfpRegister double_scratch) {
+  ASSERT(!double_input.is(double_scratch));
+  ASSERT(CpuFeatures::IsSupported(VFP2));
+  CpuFeatureScope scope(this, VFP2);
 
   vcvt_s32_f64(double_scratch.low(), double_input);
   vmov(result, double_scratch.low());
   vcvt_f64_s32(double_scratch, double_scratch.low());
   VFPCompareAndSetFlags(double_input, double_scratch);
-  b(eq, done);
 }
 
 
-void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode,
-                                     Register result,
-                                     DwVfpRegister double_input,
-                                     Register scratch,
-                                     DwVfpRegister double_scratch,
-                                     CheckForInexactConversion check_inexact) {
-  ASSERT(!result.is(scratch));
+void MacroAssembler::TryInt32Floor(Register result,
+                                   DwVfpRegister double_input,
+                                   Register input_high,
+                                   DwVfpRegister double_scratch,
+                                   Label* done,
+                                   Label* exact) {
+  ASSERT(!result.is(input_high));
   ASSERT(!double_input.is(double_scratch));
-
   ASSERT(CpuFeatures::IsSupported(VFP2));
-  CpuFeatures::Scope scope(VFP2);
-  Register prev_fpscr = result;
-  Label done;
+  CpuFeatureScope scope(this, VFP2);
+  Label negative, exception;
 
-  // Test for values that can be exactly represented as a signed 32-bit integer.
-  TryFastDoubleToInt32(result, double_input, double_scratch, &done);
+  // Test for NaN and infinities.
+  Sbfx(result, input_high,
+       HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+  cmp(result, Operand(-1));
+  b(eq, &exception);
+  // Test for values that can be exactly represented as a
+  // signed 32-bit integer.
+  TryDoubleToInt32Exact(result, double_input, double_scratch);
+  // If exact, return (result already fetched).
+  b(eq, exact);
+  cmp(input_high, Operand::Zero());
+  b(mi, &negative);
 
-  // Convert to integer, respecting rounding mode.
-  int32_t check_inexact_conversion =
-    (check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0;
+  // Input is in ]+0, +inf[.
+  // If result equals 0x7fffffff input was out of range or
+  // in ]0x7fffffff, 0x80000000[. We ignore this last case which
+  // could fits into an int32, that means we always think input was
+  // out of range and always go to exception.
+  // If result < 0x7fffffff, go to done, result fetched.
+  cmn(result, Operand(1));
+  b(mi, &exception);
+  b(done);
 
-  // Set custom FPCSR:
-  //  - Set rounding mode.
-  //  - Clear vfp cumulative exception flags.
-  //  - Make sure Flush-to-zero mode control bit is unset.
-  vmrs(prev_fpscr);
-  bic(scratch,
-      prev_fpscr,
-      Operand(kVFPExceptionMask |
-              check_inexact_conversion |
-              kVFPRoundingModeMask |
-              kVFPFlushToZeroMask));
-  // 'Round To Nearest' is encoded by 0b00 so no bits need to be set.
-  if (rounding_mode != kRoundToNearest) {
-    orr(scratch, scratch, Operand(rounding_mode));
-  }
-  vmsr(scratch);
-
-  // Convert the argument to an integer.
-  vcvt_s32_f64(double_scratch.low(),
-               double_input,
-               (rounding_mode == kRoundToZero) ? kDefaultRoundToZero
-                                               : kFPSCRRounding);
-
-  // Retrieve FPSCR.
-  vmrs(scratch);
-  // Restore FPSCR.
-  vmsr(prev_fpscr);
-  // Move the converted value into the result register.
-  vmov(result, double_scratch.low());
-  // Check for vfp exceptions.
-  tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion));
-
-  bind(&done);
+  // Input is in ]-inf, -0[.
+  // If x is a non integer negative number,
+  // floor(x) <=> round_to_zero(x) - 1.
+  bind(&negative);
+  sub(result, result, Operand(1), SetCC);
+  // If result is still negative, go to done, result fetched.
+  // Else, we had an overflow and we fall through exception.
+  b(mi, done);
+  bind(&exception);
 }
 
 
@@ -2675,7 +2687,7 @@
                                       Register scratch,
                                       Register input_high,
                                       Register input_low) {
-  CpuFeatures::Scope scope(VFP2);
+  CpuFeatureScope scope(this, VFP2);
   ASSERT(!input_high.is(result));
   ASSERT(!input_low.is(result));
   ASSERT(!input_low.is(input_high));
@@ -2687,33 +2699,25 @@
   Label done;
 
   // Test if the value can be exactly represented as a signed integer.
-  vcvt_s32_f64(double_scratch.low(), double_input);
-  vmov(result, double_scratch.low());
-  vcvt_f64_s32(double_scratch, double_scratch.low());
-  // Note: this comparison is cheaper than reading the FPSCR exception bits.
-  VFPCompareAndSetFlags(double_input, double_scratch);
+  TryDoubleToInt32Exact(result, double_input, double_scratch);
   b(eq, &done);
 
   // Check the exception flags. If they are not set, we are done.
   // If they are set, it could be because of the conversion above, or because
   // they were set before this code.
   vmrs(scratch);
-  tst(scratch, Operand(kVFPOverflowExceptionBit |
-                       kVFPUnderflowExceptionBit |
-                       kVFPInvalidOpExceptionBit));
+  tst(scratch, Operand(kVFPInvalidOpExceptionBit));
   b(eq, &done);
 
   // Clear cumulative exception flags.
-  bic(scratch, scratch, Operand(kVFPExceptionMask));
+  bic(scratch, scratch, Operand(kVFPInvalidOpExceptionBit));
   vmsr(scratch);
   // Try a conversion to a signed integer.
   vcvt_s32_f64(double_scratch.low(), double_input);
   // Retrieve the FPSCR.
   vmrs(scratch);
-  // Check for overflow and NaNs.
-  tst(scratch, Operand(kVFPOverflowExceptionBit |
-                       kVFPUnderflowExceptionBit |
-                       kVFPInvalidOpExceptionBit));
+  // Check for invalid conversions (out of range and NaNs).
+  tst(scratch, Operand(kVFPInvalidOpExceptionBit));
   // If we had no exceptions we are done.
   b(eq, &done);
 
@@ -3196,6 +3200,20 @@
 }
 
 
+void MacroAssembler::AssertName(Register object) {
+  if (emit_debug_code()) {
+    STATIC_ASSERT(kSmiTag == 0);
+    tst(object, Operand(kSmiTagMask));
+    Check(ne, "Operand is a smi and not a name");
+    push(object);
+    ldr(object, FieldMemOperand(object, HeapObject::kMapOffset));
+    CompareInstanceType(object, object, LAST_NAME_TYPE);
+    pop(object);
+    Check(le, "Operand is not a name");
+  }
+}
+
+
 
 void MacroAssembler::AssertRootValue(Register src,
                                      Heap::RootListIndex root_value_index,
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 0826b7d..cf2f045 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -578,6 +578,10 @@
                             Register scratch,
                             Label* fail);
 
+  void IsObjectNameType(Register object,
+                        Register scratch,
+                        Label* fail);
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // ---------------------------------------------------------------------------
   // Debugger Support
@@ -940,27 +944,26 @@
                       DwVfpRegister double_scratch,
                       Label *not_int32);
 
-  // Try to convert a double to a signed 32-bit integer. If the double value
-  // can be exactly represented as an integer, the code jumps to 'done' and
-  // 'result' contains the integer value. Otherwise, the code falls through.
-  void TryFastDoubleToInt32(Register result,
-                            DwVfpRegister double_input,
-                            DwVfpRegister double_scratch,
-                            Label* done);
+  // Check if a double can be exactly represented as a signed 32-bit integer.
+  // Z flag set to one if true.
+  void TestDoubleIsInt32(DwVfpRegister double_input,
+                         DwVfpRegister double_scratch);
 
-  // Truncates a double using a specific rounding mode, and writes the value
-  // to the result register.
-  // Clears the z flag (ne condition) if an overflow occurs.
-  // If kCheckForInexactConversion is passed, the z flag is also cleared if the
-  // conversion was inexact, i.e. if the double value could not be converted
-  // exactly to a 32-bit integer.
-  void EmitVFPTruncate(VFPRoundingMode rounding_mode,
-                       Register result,
-                       DwVfpRegister double_input,
-                       Register scratch,
-                       DwVfpRegister double_scratch,
-                       CheckForInexactConversion check
-                           = kDontCheckForInexactConversion);
+  // Try to convert a double to a signed 32-bit integer.
+  // Z flag set to one and result assigned if the conversion is exact.
+  void TryDoubleToInt32Exact(Register result,
+                             DwVfpRegister double_input,
+                             DwVfpRegister double_scratch);
+
+  // Floor a double and writes the value to the result register.
+  // Go to exact if the conversion is exact (to be able to test -0),
+  // fall through calling code if an overflow occurred, else go to done.
+  void TryInt32Floor(Register result,
+                     DwVfpRegister double_input,
+                     Register input_high,
+                     DwVfpRegister double_scratch,
+                     Label* done,
+                     Label* exact);
 
   // Helper for EmitECMATruncate.
   // This will truncate a floating-point value outside of the signed 32bit
@@ -1221,9 +1224,12 @@
   void AssertNotSmi(Register object);
   void AssertSmi(Register object);
 
-  // Abort execution if argument is a string, enabled via --debug-code.
+  // Abort execution if argument is not a string, enabled via --debug-code.
   void AssertString(Register object);
 
+  // Abort execution if argument is not a name, enabled via --debug-code.
+  void AssertName(Register object);
+
   // Abort execution if argument is not the root value with the given index,
   // enabled via --debug-code.
   void AssertRootValue(Register src,
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 03aa359..f30706e 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -130,14 +130,14 @@
 // the property. This function may return false negatives, so miss_label
 // must always call a backup property check that is complete.
 // This function is safe to call if the receiver has fast properties.
-// Name must be internalized and receiver must be a heap object.
+// Name must be unique and receiver must be a heap object.
 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
                                              Label* miss_label,
                                              Register receiver,
-                                             Handle<String> name,
+                                             Handle<Name> name,
                                              Register scratch0,
                                              Register scratch1) {
-  ASSERT(name->IsInternalizedString());
+  ASSERT(name->IsUniqueName());
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
   __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
@@ -173,13 +173,13 @@
   __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
 
 
-  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
-                                                     miss_label,
-                                                     &done,
-                                                     receiver,
-                                                     properties,
-                                                     name,
-                                                     scratch1);
+  NameDictionaryLookupStub::GenerateNegativeLookup(masm,
+                                                   miss_label,
+                                                   &done,
+                                                   receiver,
+                                                   properties,
+                                                   name,
+                                                   scratch1);
   __ bind(&done);
   __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
 }
@@ -228,7 +228,7 @@
   __ JumpIfSmi(receiver, &miss);
 
   // Get the map of the receiver and compute the hash.
-  __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
+  __ ldr(scratch, FieldMemOperand(name, Name::kHashFieldOffset));
   __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
   __ add(scratch, scratch, Operand(ip));
   uint32_t mask = kPrimaryTableSize - 1;
@@ -443,7 +443,7 @@
                                       Handle<JSObject> object,
                                       int index,
                                       Handle<Map> transition,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Register receiver_reg,
                                       Register name_reg,
                                       Register scratch1,
@@ -774,7 +774,7 @@
   void Compile(MacroAssembler* masm,
                Handle<JSObject> object,
                Handle<JSObject> holder,
-               Handle<String> name,
+               Handle<Name> name,
                LookupResult* lookup,
                Register receiver,
                Register scratch1,
@@ -805,7 +805,7 @@
                         Register scratch3,
                         Handle<JSObject> interceptor_holder,
                         LookupResult* lookup,
-                        Handle<String> name,
+                        Handle<Name> name,
                         const CallOptimization& optimization,
                         Label* miss_label) {
     ASSERT(optimization.is_constant_call());
@@ -899,7 +899,7 @@
                       Register scratch1,
                       Register scratch2,
                       Register scratch3,
-                      Handle<String> name,
+                      Handle<Name> name,
                       Handle<JSObject> interceptor_holder,
                       Label* miss_label) {
     Register holder =
@@ -956,7 +956,7 @@
 // property.
 static void GenerateCheckPropertyCell(MacroAssembler* masm,
                                       Handle<GlobalObject> global,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Register scratch,
                                       Label* miss) {
   Handle<JSGlobalPropertyCell> cell =
@@ -976,7 +976,7 @@
 static void GenerateCheckPropertyCells(MacroAssembler* masm,
                                        Handle<JSObject> object,
                                        Handle<JSObject> holder,
-                                       Handle<String> name,
+                                       Handle<Name> name,
                                        Register scratch,
                                        Label* miss) {
   Handle<JSObject> current = object;
@@ -1004,7 +1004,7 @@
                             Register scratch1,
                             Register scratch2) {
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     __ vmov(s0, ival);
     __ add(scratch1, dst, Operand(wordoffset, LSL, 2));
     __ vcvt_f32_s32(s0, s0);
@@ -1078,7 +1078,7 @@
                                        Register holder_reg,
                                        Register scratch1,
                                        Register scratch2,
-                                       Handle<String> name,
+                                       Handle<Name> name,
                                        int save_at_depth,
                                        Label* miss,
                                        PrototypeCheckType check) {
@@ -1110,11 +1110,12 @@
     if (!current->HasFastProperties() &&
         !current->IsJSGlobalObject() &&
         !current->IsJSGlobalProxy()) {
-      if (!name->IsInternalizedString()) {
-        name = factory()->InternalizeString(name);
+      if (!name->IsUniqueName()) {
+        ASSERT(name->IsString());
+        name = factory()->InternalizeString(Handle<String>::cast(name));
       }
       ASSERT(current->property_dictionary()->FindEntry(*name) ==
-             StringDictionary::kNotFound);
+             NameDictionary::kNotFound);
 
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
                                        scratch1, scratch2);
@@ -1198,7 +1199,7 @@
     Handle<JSObject> object,
     Register object_reg,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     Label* success,
     Handle<ExecutableAccessorInfo> callback) {
   Label miss;
@@ -1216,20 +1217,20 @@
 
     // Probe the dictionary.
     Label probe_done;
-    StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
-                                                       &miss,
-                                                       &probe_done,
-                                                       dictionary,
-                                                       this->name(),
-                                                       scratch2(),
-                                                       scratch3());
+    NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
+                                                     &miss,
+                                                     &probe_done,
+                                                     dictionary,
+                                                     this->name(),
+                                                     scratch2(),
+                                                     scratch3());
     __ bind(&probe_done);
 
     // If probing finds an entry in the dictionary, scratch3 contains the
     // pointer into the dictionary. Check that the value is the callback.
     Register pointer = scratch3();
-    const int kElementsStartOffset = StringDictionary::kHeaderSize +
-        StringDictionary::kElementsStartIndex * kPointerSize;
+    const int kElementsStartOffset = NameDictionary::kHeaderSize +
+        NameDictionary::kElementsStartIndex * kPointerSize;
     const int kValueOffset = kElementsStartOffset + kPointerSize;
     __ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset));
     __ cmp(scratch2(), Operand(callback));
@@ -1244,7 +1245,7 @@
 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
     Handle<JSObject> object,
     Handle<JSObject> last,
-    Handle<String> name,
+    Handle<Name> name,
     Label* success,
     Handle<GlobalObject> global) {
   Label miss;
@@ -1301,7 +1302,7 @@
   __ Push(reg, scratch3());
   __ mov(scratch3(), Operand(ExternalReference::isolate_address()));
   __ Push(scratch3(), name());
-  __ mov(r0, sp);  // r0 = Handle<String>
+  __ mov(r0, sp);  // r0 = Handle<Name>
 
   const int kApiStackSpace = 1;
   FrameScope frame_scope(masm(), StackFrame::MANUAL);
@@ -1328,7 +1329,7 @@
     Handle<JSObject> object,
     Handle<JSObject> interceptor_holder,
     LookupResult* lookup,
-    Handle<String> name) {
+    Handle<Name> name) {
   ASSERT(interceptor_holder->HasNamedInterceptor());
   ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
 
@@ -1412,7 +1413,7 @@
 }
 
 
-void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
   if (kind_ == Code::KEYED_CALL_IC) {
     __ cmp(r2, Operand(name));
     __ b(ne, miss);
@@ -1422,7 +1423,7 @@
 
 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
                                                    Handle<JSObject> holder,
-                                                   Handle<String> name,
+                                                   Handle<Name> name,
                                                    Label* miss) {
   ASSERT(holder->IsGlobalObject());
 
@@ -1480,7 +1481,7 @@
 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
-                                                Handle<String> name) {
+                                                Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -2117,7 +2118,7 @@
     return Handle<Code>::null();
   }
 
-  CpuFeatures::Scope scope_vfp2(VFP2);
+  CpuFeatureScope scope_vfp2(masm(), VFP2);
   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.
@@ -2150,10 +2151,7 @@
 
   __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
 
-  Label wont_fit_smi, no_vfp_exception, restore_fpscr_and_return;
-
-  // If vfp3 is enabled, we use the fpu rounding with the RM (round towards
-  // minus infinity) mode.
+  Label smi_check, just_return;
 
   // Load the HeapNumber value.
   // We will need access to the value in the core registers, so we load it
@@ -2163,73 +2161,46 @@
   __ Ldrd(r4, r5, FieldMemOperand(r0, HeapNumber::kValueOffset));
   __ vmov(d1, r4, r5);
 
-  // Backup FPSCR.
-  __ vmrs(r3);
-  // Set custom FPCSR:
-  //  - Set rounding mode to "Round towards Minus Infinity"
-  //    (i.e. bits [23:22] = 0b10).
-  //  - Clear vfp cumulative exception flags (bits [3:0]).
-  //  - Make sure Flush-to-zero mode control bit is unset (bit 22).
-  __ bic(r9, r3,
-      Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask));
-  __ orr(r9, r9, Operand(kRoundToMinusInf));
-  __ vmsr(r9);
-
-  // Convert the argument to an integer.
-  __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
-
-  // Use vcvt latency to start checking for special cases.
-  // Get the argument exponent and clear the sign bit.
-  __ bic(r6, r5, Operand(HeapNumber::kSignMask));
-  __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord));
-
-  // Retrieve FPSCR and check for vfp exceptions.
-  __ vmrs(r9);
-  __ tst(r9, Operand(kVFPExceptionMask));
-  __ b(&no_vfp_exception, eq);
-
-  // Check for NaN, Infinity, and -Infinity.
+  // Check for NaN, Infinities and -0.
   // They are invariant through a Math.Floor call, so just
   // return the original argument.
-  __ sub(r7, r6, Operand(HeapNumber::kExponentMask
-        >> HeapNumber::kMantissaBitsInTopWord), SetCC);
-  __ b(&restore_fpscr_and_return, eq);
-  // We had an overflow or underflow in the conversion. Check if we
-  // have a big exponent.
-  __ cmp(r7, Operand(HeapNumber::kMantissaBits));
-  // If greater or equal, the argument is already round and in r0.
-  __ b(&restore_fpscr_and_return, ge);
-  __ b(&wont_fit_smi);
+  __ Sbfx(r3, r5, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+  __ cmp(r3, Operand(-1));
+  __ b(eq, &just_return);
+  __ eor(r3, r5, Operand(0x80000000u));
+  __ orr(r3, r3, r4, SetCC);
+  __ b(eq, &just_return);
+  // Test for values that can be exactly represented as a
+  // signed 32-bit integer.
+  __ TryDoubleToInt32Exact(r0, d1, d2);
+  // If exact, check smi
+  __ b(eq, &smi_check);
+  __ cmp(r5, Operand(0));
 
-  __ bind(&no_vfp_exception);
-  // Move the result back to general purpose register r0.
-  __ vmov(r0, s0);
-  // Check if the result fits into a smi.
+  // If input is in ]+0, +inf[, the cmp has cleared overflow and negative
+  // (V=0 and N=0), the two following instructions won't execute and
+  // we fall through smi_check to check if the result can fit into a smi.
+
+  // If input is in ]-inf, -0[, sub one and, go to slow if we have
+  // an overflow. Else we fall through smi check.
+  // Hint: if x is a negative, non integer number,
+  // floor(x) <=> round_to_zero(x) - 1.
+  __ sub(r0, r0, Operand(1), SetCC, mi);
+  __ b(vs, &slow);
+
+  __ bind(&smi_check);
+  // Check if the result can fit into an smi. If we had an overflow,
+  // the result is either 0x80000000 or 0x7FFFFFFF and won't fit into an smi.
   __ add(r1, r0, Operand(0x40000000), SetCC);
-  __ b(&wont_fit_smi, mi);
+  // If result doesn't fit into an smi, branch to slow.
+  __ b(&slow, mi);
   // Tag the result.
-  STATIC_ASSERT(kSmiTag == 0);
   __ mov(r0, Operand(r0, LSL, kSmiTagSize));
 
-  // Check for -0.
-  __ cmp(r0, Operand::Zero());
-  __ b(&restore_fpscr_and_return, ne);
-  // r5 already holds the HeapNumber exponent.
-  __ tst(r5, Operand(HeapNumber::kSignMask));
-  // If our HeapNumber is negative it was -0, so load its address and return.
-  // Else r0 is loaded with 0, so we can also just return.
-  __ ldr(r0, MemOperand(sp, 0 * kPointerSize), ne);
-
-  __ bind(&restore_fpscr_and_return);
-  // Restore FPSCR and return.
-  __ vmsr(r3);
+  __ bind(&just_return);
   __ Drop(argc + 1);
   __ Ret();
 
-  __ bind(&wont_fit_smi);
-  // Restore FPCSR and fall to slow case.
-  __ vmsr(r3);
-
   __ bind(&slow);
   // Tail call the full function. We do not have to patch the receiver
   // because the function makes no use of it.
@@ -2397,7 +2368,7 @@
 
 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
                                               Handle<JSObject> holder,
-                                              Handle<String> name,
+                                              Handle<Name> name,
                                               CheckType check,
                                               Label* success) {
   // ----------- S t a t e -------------
@@ -2509,13 +2480,13 @@
 Handle<Code> CallStubCompiler::CompileCallConstant(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     CheckType check,
     Handle<JSFunction> function) {
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
                                           Handle<JSGlobalPropertyCell>::null(),
-                                          function, name);
+                                          function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2526,7 +2497,6 @@
   __ bind(&success);
   CompileHandlerBackend(function);
 
-
   // Return the generated code.
   return GetCode(function);
 }
@@ -2534,7 +2504,7 @@
 
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
-                                                      Handle<String> name) {
+                                                      Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -2575,13 +2545,14 @@
     Handle<GlobalObject> holder,
     Handle<JSGlobalPropertyCell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
   // -----------------------------------
   if (HasCustomCallGenerator(function)) {
-    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
+    Handle<Code> code = CompileCustomCall(
+        object, holder, cell, function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2631,7 +2602,7 @@
 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
                                                   int index,
                                                   Handle<Map> transition,
-                                                  Handle<String> name) {
+                                                  Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : receiver
@@ -2659,7 +2630,7 @@
 
 
 Handle<Code> StoreStubCompiler::CompileStoreCallback(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<ExecutableAccessorInfo> callback) {
@@ -2743,7 +2714,7 @@
 
 
 Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<JSFunction> setter) {
@@ -2772,7 +2743,7 @@
 
 Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
     Handle<JSObject> receiver,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : receiver
@@ -2818,7 +2789,7 @@
 Handle<Code> StoreStubCompiler::CompileStoreGlobal(
     Handle<GlobalObject> object,
     Handle<JSGlobalPropertyCell> cell,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : receiver
@@ -2864,7 +2835,7 @@
 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
     Handle<JSObject> object,
     Handle<JSObject> last,
-    Handle<String> name,
+    Handle<Name> name,
     Handle<GlobalObject> global) {
   Label success;
 
@@ -2877,7 +2848,7 @@
   __ Ret();
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
+  return GetCode(kind(), Code::NONEXISTENT, name);
 }
 
 
@@ -2895,7 +2866,7 @@
 }
 
 
-void KeyedLoadStubCompiler::GenerateNameCheck(Handle<String> name,
+void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
                                               Register name_reg,
                                               Label* miss) {
   __ cmp(name_reg, Operand(name));
@@ -2944,7 +2915,7 @@
     Handle<JSObject> object,
     Handle<GlobalObject> global,
     Handle<JSGlobalPropertyCell> cell,
-    Handle<String> name,
+    Handle<Name> name,
     bool is_dont_delete) {
   Label success, miss;
 
@@ -2973,7 +2944,7 @@
   __ Ret();
 
   // Return the generated code.
-  return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
+  return GetICCode(kind(), Code::NORMAL, name);
 }
 
 
@@ -3001,14 +2972,14 @@
   __ Jump(ic, RelocInfo::CODE_TARGET);
 
   // Return the generated code.
-  return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
+  return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
 }
 
 
 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
     MapHandleList* receiver_maps,
     CodeHandleList* handlers,
-    Handle<String> name,
+    Handle<Name> name,
     Code::StubType type,
     IcCheckType check) {
   Label miss;
@@ -3034,14 +3005,14 @@
   // Return the generated code.
   InlineCacheState state =
       receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
-  return GetCode(Code::IC_FRAGMENT, type, name, state);
+  return GetICCode(kind(), type, name, state);
 }
 
 
 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
                                                        int index,
                                                        Handle<Map> transition,
-                                                       Handle<String> name) {
+                                                       Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : name
@@ -3093,7 +3064,7 @@
   Handle<Code> stub =
       KeyedStoreElementStub(is_js_array,
                             elements_kind,
-                            grow_mode_).GetCode(isolate());
+                            store_mode_).GetCode(isolate());
 
   __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK);
 
@@ -3378,7 +3349,7 @@
                                 DwVfpRegister double_scratch1,
                                 Label* fail) {
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(masm, VFP2);
     Label key_ok;
     // Check for smi or a smi inside a heap number.  We convert the heap
     // number and check if the conversion is exact and fits into the smi
@@ -3391,12 +3362,7 @@
                 DONT_DO_SMI_CHECK);
     __ sub(ip, key, Operand(kHeapObjectTag));
     __ vldr(double_scratch0, ip, HeapNumber::kValueOffset);
-    __ EmitVFPTruncate(kRoundToZero,
-                       scratch0,
-                       double_scratch0,
-                       scratch1,
-                       double_scratch1,
-                       kCheckForInexactConversion);
+    __ TryDoubleToInt32Exact(scratch0, double_scratch0, double_scratch1);
     __ b(ne, fail);
     __ TrySmiTag(scratch0, fail, scratch1);
     __ mov(key, scratch0);
@@ -3490,7 +3456,7 @@
           d0, r6, r7,  // These are: double_dst, dst_mantissa, dst_exponent.
           r4, s2);  // These are: scratch2, single_scratch.
       if (destination == FloatingPointHelper::kVFPRegisters) {
-        CpuFeatures::Scope scope(VFP2);
+        CpuFeatureScope scope(masm, VFP2);
         __ vstr(d0, r3, 0);
       } else {
         __ str(r6, MemOperand(r3, 0));
@@ -3526,7 +3492,7 @@
     // +/-Infinity into integer arrays basically undefined. For more
     // reproducible behavior, convert these to zero.
     if (CpuFeatures::IsSupported(VFP2)) {
-      CpuFeatures::Scope scope(VFP2);
+      CpuFeatureScope scope(masm, VFP2);
 
       if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
         // vldr requires offset to be a multiple of 4 so we can not
@@ -3756,7 +3722,7 @@
     MacroAssembler* masm,
     bool is_js_array,
     ElementsKind elements_kind,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : key
@@ -3796,7 +3762,7 @@
   }
   // Compare smis.
   __ cmp(key_reg, scratch);
-  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (is_js_array && IsGrowStoreMode(store_mode)) {
     __ b(hs, &grow);
   } else {
     __ b(hs, &miss_force_generic);
@@ -3849,7 +3815,7 @@
   Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
   __ Jump(ic_miss, RelocInfo::CODE_TARGET);
 
-  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (is_js_array && IsGrowStoreMode(store_mode)) {
     // Grow the array by a single element if possible.
     __ bind(&grow);
 
@@ -3921,7 +3887,7 @@
 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
     MacroAssembler* masm,
     bool is_js_array,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : key
@@ -3967,7 +3933,7 @@
   // Compare smis, unsigned compare catches both negative and out-of-bound
   // indexes.
   __ cmp(key_reg, scratch1);
-  if (grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (IsGrowStoreMode(store_mode)) {
     __ b(hs, &grow);
   } else {
     __ b(hs, &miss_force_generic);
@@ -3995,7 +3961,7 @@
   Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
   __ Jump(ic_miss, RelocInfo::CODE_TARGET);
 
-  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (is_js_array && IsGrowStoreMode(store_mode)) {
     // Grow the array by a single element if possible.
     __ bind(&grow);
 
diff --git a/src/array.js b/src/array.js
index 9b0bfe1..1ec6433 100644
--- a/src/array.js
+++ b/src/array.js
@@ -885,7 +885,7 @@
   // of a prototype property.
   var CopyFromPrototype = function CopyFromPrototype(obj, length) {
     var max = 0;
-    for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
+    for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
       var indices = %GetArrayKeys(proto, length);
       if (indices.length > 0) {
         if (indices[0] == -1) {
@@ -916,7 +916,7 @@
   // where a prototype of obj has an element. I.e., shadow all prototype
   // elements in that range.
   var ShadowPrototypeElements = function(obj, from, to) {
-    for (var proto = obj.__proto__; proto; proto = proto.__proto__) {
+    for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) {
       var indices = %GetArrayKeys(proto, to);
       if (indices.length > 0) {
         if (indices[0] == -1) {
@@ -986,7 +986,7 @@
     }
     for (i = length - num_holes; i < length; i++) {
       // For compatability with Webkit, do not expose elements in the prototype.
-      if (i in obj.__proto__) {
+      if (i in %GetPrototype(obj)) {
         obj[i] = void 0;
       } else {
         delete obj[i];
diff --git a/src/assembler.cc b/src/assembler.cc
index b3640c3..8d8208d 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -115,6 +115,7 @@
 AssemblerBase::AssemblerBase(Isolate* isolate, void* buffer, int buffer_size)
     : isolate_(isolate),
       jit_cookie_(0),
+      enabled_cpu_features_(0),
       emit_debug_code_(FLAG_debug_code),
       predictable_code_size_(false) {
   if (FLAG_mask_constants_with_cookie && isolate != NULL)  {
@@ -180,6 +181,34 @@
 
 
 // -----------------------------------------------------------------------------
+// Implementation of CpuFeatureScope
+
+#ifdef DEBUG
+CpuFeatureScope::CpuFeatureScope(AssemblerBase* assembler, CpuFeature f)
+    : assembler_(assembler) {
+  ASSERT(CpuFeatures::IsSafeForSnapshot(f));
+  old_enabled_ = assembler_->enabled_cpu_features();
+  uint64_t mask = static_cast<uint64_t>(1) << f;
+  // TODO(svenpanne) This special case below doesn't belong here!
+#if V8_TARGET_ARCH_ARM
+  // VFP2 and ARMv7 are implied by VFP3.
+  if (f == VFP3) {
+    mask |=
+        static_cast<uint64_t>(1) << VFP2 |
+        static_cast<uint64_t>(1) << ARMv7;
+  }
+#endif
+  assembler_->set_enabled_cpu_features(old_enabled_ | mask);
+}
+
+
+CpuFeatureScope::~CpuFeatureScope() {
+  assembler_->set_enabled_cpu_features(old_enabled_);
+}
+#endif
+
+
+// -----------------------------------------------------------------------------
 // Implementation of Label
 
 int Label::pos() const {
diff --git a/src/assembler.h b/src/assembler.h
index 06c3b76..0fee67a 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -68,6 +68,14 @@
   bool predictable_code_size() const { return predictable_code_size_; }
   void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
 
+  uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
+  void set_enabled_cpu_features(uint64_t features) {
+    enabled_cpu_features_ = features;
+  }
+  bool IsEnabled(CpuFeature f) {
+    return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
+  }
+
   // Overwrite a host NaN with a quiet target NaN.  Used by mksnapshot for
   // cross-snapshotting.
   static void QuietNaN(HeapObject* nan) { }
@@ -89,6 +97,7 @@
  private:
   Isolate* isolate_;
   int jit_cookie_;
+  uint64_t enabled_cpu_features_;
   bool emit_debug_code_;
   bool predictable_code_size_;
 };
@@ -109,6 +118,22 @@
 };
 
 
+// Enable a specified feature within a scope.
+class CpuFeatureScope BASE_EMBEDDED {
+ public:
+#ifdef DEBUG
+  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f);
+  ~CpuFeatureScope();
+
+ private:
+  AssemblerBase* assembler_;
+  uint64_t old_enabled_;
+#else
+  CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) {}
+#endif
+};
+
+
 // -----------------------------------------------------------------------------
 // Labels represent pc locations; they are typically jump or call targets.
 // After declaration, a label can be freely used to denote known or (yet)
diff --git a/src/atomicops.h b/src/atomicops.h
index da33b29..ebca91d 100644
--- a/src/atomicops.h
+++ b/src/atomicops.h
@@ -58,7 +58,7 @@
 #ifdef V8_HOST_ARCH_64_BIT
 // We need to be able to go between Atomic64 and AtomicWord implicitly.  This
 // means Atomic64 and AtomicWord should be the same type on 64-bit.
-#if defined(__APPLE__)
+#if defined(__ILP32__) || defined(__APPLE__)
 // MacOS is an exception to the implicit conversion rule above,
 // because it uses long for intptr_t.
 typedef int64_t Atomic64;
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index fcb1de9..3ef8d37 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -493,8 +493,7 @@
 
     Handle<Foreign> object_prototype(
         factory->NewForeign(&Accessors::ObjectPrototype));
-    PropertyAttributes attribs = static_cast<PropertyAttributes>(
-        DONT_ENUM | DONT_DELETE);
+    PropertyAttributes attribs = static_cast<PropertyAttributes>(DONT_ENUM);
     object_prototype_map->set_instance_descriptors(*prototype_descriptors);
 
     {  // Add __proto__.
@@ -2294,7 +2293,7 @@
       switch (details.type()) {
         case FIELD: {
           HandleScope inner(isolate());
-          Handle<String> key = Handle<String>(descs->GetKey(i));
+          Handle<Name> key = Handle<Name>(descs->GetKey(i));
           int index = descs->GetFieldIndex(i);
           Handle<Object> value = Handle<Object>(from->FastPropertyAt(index),
                                                 isolate());
@@ -2305,7 +2304,7 @@
         }
         case CONSTANT_FUNCTION: {
           HandleScope inner(isolate());
-          Handle<String> key = Handle<String>(descs->GetKey(i));
+          Handle<Name> key = Handle<Name>(descs->GetKey(i));
           Handle<JSFunction> fun =
               Handle<JSFunction>(descs->GetConstantFunction(i));
           CHECK_NOT_EMPTY_HANDLE(isolate(),
@@ -2321,7 +2320,7 @@
           HandleScope inner(isolate());
           ASSERT(!to->HasFastProperties());
           // Add to dictionary.
-          Handle<String> key = Handle<String>(descs->GetKey(i));
+          Handle<Name> key = Handle<Name>(descs->GetKey(i));
           Handle<Object> callbacks(descs->GetCallbacksObject(i), isolate());
           PropertyDetails d = PropertyDetails(details.attributes(),
                                               CALLBACKS,
@@ -2341,19 +2340,19 @@
       }
     }
   } else {
-    Handle<StringDictionary> properties =
-        Handle<StringDictionary>(from->property_dictionary());
+    Handle<NameDictionary> properties =
+        Handle<NameDictionary>(from->property_dictionary());
     int capacity = properties->Capacity();
     for (int i = 0; i < capacity; i++) {
       Object* raw_key(properties->KeyAt(i));
       if (properties->IsKey(raw_key)) {
-        ASSERT(raw_key->IsString());
+        ASSERT(raw_key->IsName());
         // If the property is already there we skip it.
         LookupResult result(isolate());
-        to->LocalLookup(String::cast(raw_key), &result);
+        to->LocalLookup(Name::cast(raw_key), &result);
         if (result.IsFound()) continue;
         // Set the property.
-        Handle<String> key = Handle<String>(String::cast(raw_key));
+        Handle<Name> key = Handle<Name>(Name::cast(raw_key));
         Handle<Object> value = Handle<Object>(properties->ValueAt(i),
                                               isolate());
         if (value->IsJSGlobalPropertyCell()) {
diff --git a/src/builtins.h b/src/builtins.h
index 15abeb1..83b134c 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -133,7 +133,7 @@
   V(LoadIC_PreMonomorphic,          LOAD_IC, PREMONOMORPHIC,            \
                                     Code::kNoExtraICState)              \
   V(LoadIC_Normal,                  LOAD_IC, MONOMORPHIC,               \
-                                    Code::IC_FRAGMENT)                  \
+                                    Code::kNoExtraICState)              \
   V(LoadIC_Megamorphic,             LOAD_IC, MEGAMORPHIC,               \
                                     Code::kNoExtraICState)              \
   V(LoadIC_Getter_ForDeopt,         LOAD_IC, MONOMORPHIC,               \
diff --git a/src/circular-queue.cc b/src/circular-queue.cc
index 2818ce9..928c3f0 100644
--- a/src/circular-queue.cc
+++ b/src/circular-queue.cc
@@ -33,16 +33,18 @@
 namespace internal {
 
 
-SamplingCircularQueue::SamplingCircularQueue(
-    int record_size_in_bytes,
-    int desired_chunk_size_in_bytes,
-    int buffer_size_in_chunks,
-    bool keep_producer_consumer_distance)
+SamplingCircularQueue::SamplingCircularQueue(int record_size_in_bytes,
+                                             int desired_chunk_size_in_bytes,
+                                             int buffer_size_in_chunks)
     : record_size_(record_size_in_bytes / sizeof(Cell)),
       chunk_size_in_bytes_(desired_chunk_size_in_bytes / record_size_in_bytes *
                         record_size_in_bytes),
       chunk_size_(chunk_size_in_bytes_ / sizeof(Cell)),
       buffer_size_(chunk_size_ * buffer_size_in_chunks),
+      // The distance ensures that producer and consumer never step on
+      // each other's chunks and helps eviction of produced data from
+      // the CPU cache (having that chunk size is bigger than the cache.)
+      producer_consumer_distance_(2 * chunk_size_),
       buffer_(NewArray<Cell>(buffer_size_ + 1)) {
   ASSERT(buffer_size_in_chunks > 2);
   // Clean up the whole buffer to avoid encountering a random kEnd
@@ -72,13 +74,7 @@
   ASSERT(reinterpret_cast<byte*>(consumer_pos_ + 1) <=
          positions_ + positions_size);
   consumer_pos_->dequeue_chunk_pos = buffer_;
-  consumer_pos_->dequeue_chunk_poll_pos = buffer_;
-  // The distance ensures that producer and consumer never step on
-  // each other's chunks and helps eviction of produced data from
-  // the CPU cache (having that chunk size is bigger than the cache.)
-  if (keep_producer_consumer_distance) {
-    consumer_pos_->dequeue_chunk_poll_pos += 2 * chunk_size_;
-  }
+  consumer_pos_->dequeue_chunk_poll_pos = buffer_ + producer_consumer_distance_;
   consumer_pos_->dequeue_pos = NULL;
 }
 
diff --git a/src/circular-queue.h b/src/circular-queue.h
index a8eb524..73afc68 100644
--- a/src/circular-queue.h
+++ b/src/circular-queue.h
@@ -47,8 +47,7 @@
   // Executed on the application thread.
   SamplingCircularQueue(int record_size_in_bytes,
                         int desired_chunk_size_in_bytes,
-                        int buffer_size_in_chunks,
-                        bool keep_producer_consumer_distance = true);
+                        int buffer_size_in_chunks);
   ~SamplingCircularQueue();
 
   // Enqueue returns a pointer to a memory location for storing the next
@@ -89,6 +88,7 @@
   const int chunk_size_in_bytes_;
   const int chunk_size_;
   const int buffer_size_;
+  const int producer_consumer_distance_;
   Cell* buffer_;
   byte* positions_;
   ProducerPosition* producer_pos_;
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 491e255..17c1f27 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -59,9 +59,9 @@
   CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub)
       : HGraphBuilder(&info_), info_(stub, isolate), context_(NULL) {
     int major_key = stub->MajorKey();
-    descriptor_ = info_.isolate()->code_stub_interface_descriptor(major_key);
+    descriptor_ = isolate->code_stub_interface_descriptor(major_key);
     if (descriptor_->register_param_count_ < 0) {
-      stub->InitializeInterfaceDescriptor(info_.isolate(), descriptor_);
+      stub->InitializeInterfaceDescriptor(isolate, descriptor_);
     }
     parameters_.Reset(new HParameter*[descriptor_->register_param_count_]);
   }
@@ -88,7 +88,7 @@
     const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
     PrintF("-----------------------------------------------------------\n");
     PrintF("Compiling stub %s using hydrogen\n", name);
-    HTracer::Instance()->TraceCompilation(&info_);
+    isolate()->GetHTracer()->TraceCompilation(&info_);
   }
 
   Zone* zone = this->zone();
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 4a401cd..95bc1e9 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -101,7 +101,8 @@
       static_cast<Code::Kind>(GetCodeKind()),
       GetICState(),
       GetExtraICState(),
-      GetStubType());
+      GetStubType(),
+      GetStubFlags());
   Handle<Code> new_object = factory->NewCode(
       desc, flags, masm.CodeObject(), NeedsImmovableCode());
   return new_object;
@@ -441,14 +442,14 @@
       KeyedStoreStubCompiler::GenerateStoreFastElement(masm,
                                                        is_js_array_,
                                                        elements_kind_,
-                                                       grow_mode_);
+                                                       store_mode_);
     }
       break;
     case FAST_DOUBLE_ELEMENTS:
     case FAST_HOLEY_DOUBLE_ELEMENTS:
       KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
                                                              is_js_array_,
-                                                             grow_mode_);
+                                                             store_mode_);
       break;
     case EXTERNAL_BYTE_ELEMENTS:
     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
@@ -592,13 +593,13 @@
       KeyedStoreStubCompiler::GenerateStoreFastElement(masm,
                                                        is_jsarray_,
                                                        to_,
-                                                       grow_mode_);
+                                                       store_mode_);
     } else if (IsFastSmiElementsKind(from_) &&
                IsFastDoubleElementsKind(to_)) {
       ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, &fail);
       KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
                                                              is_jsarray_,
-                                                             grow_mode_);
+                                                             store_mode_);
     } else if (IsFastDoubleElementsKind(from_)) {
       ASSERT(to_ == FAST_HOLEY_DOUBLE_ELEMENTS);
       ElementsTransitionGenerator::
diff --git a/src/code-stubs.h b/src/code-stubs.h
index f7a4eaa..8591adb 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -78,7 +78,7 @@
   V(ArrayNArgumentsConstructor)          \
   V(KeyedStoreElement)                   \
   V(DebuggerStatement)                   \
-  V(StringDictionaryLookup)              \
+  V(NameDictionaryLookup)                \
   V(ElementsTransitionAndStore)          \
   V(TransitionElementsKind)              \
   V(StoreArrayLiteralElement)            \
@@ -251,6 +251,7 @@
   virtual Handle<Code> GenerateCode();
 
   virtual int GetCodeKind() { return Code::STUB; }
+  virtual int GetStubFlags() { return -1; }
 
  protected:
   // Generates the assembler code for the stub.
@@ -662,11 +663,8 @@
 class HandlerStub: public ICStub {
  public:
   explicit HandlerStub(Code::Kind kind) : ICStub(kind) { }
-
- protected:
-  virtual Code::ExtraICState GetExtraICState() {
-    return Code::HANDLER_FRAGMENT;
-  }
+  virtual int GetCodeKind() { return Code::STUB; }
+  virtual int GetStubFlags() { return kind(); }
 };
 
 
@@ -1402,31 +1400,31 @@
  public:
   KeyedStoreElementStub(bool is_js_array,
                         ElementsKind elements_kind,
-                        KeyedAccessGrowMode grow_mode)
+                        KeyedAccessStoreMode store_mode)
       : is_js_array_(is_js_array),
         elements_kind_(elements_kind),
-        grow_mode_(grow_mode),
+        store_mode_(store_mode),
         fp_registers_(CanUseFPRegisters()) { }
 
   Major MajorKey() { return KeyedStoreElement; }
   int MinorKey() {
     return ElementsKindBits::encode(elements_kind_) |
         IsJSArrayBits::encode(is_js_array_) |
-        GrowModeBits::encode(grow_mode_) |
+        StoreModeBits::encode(store_mode_) |
         FPRegisters::encode(fp_registers_);
   }
 
   void Generate(MacroAssembler* masm);
 
  private:
-  class ElementsKindBits: public BitField<ElementsKind,    0, 8> {};
-  class GrowModeBits: public BitField<KeyedAccessGrowMode, 8, 1> {};
-  class IsJSArrayBits: public BitField<bool,               9, 1> {};
-  class FPRegisters: public BitField<bool,                10, 1> {};
+  class ElementsKindBits: public BitField<ElementsKind,      0, 8> {};
+  class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
+  class IsJSArrayBits: public BitField<bool,                12, 1> {};
+  class FPRegisters: public BitField<bool,                  13, 1> {};
 
   bool is_js_array_;
   ElementsKind elements_kind_;
-  KeyedAccessGrowMode grow_mode_;
+  KeyedAccessStoreMode store_mode_;
   bool fp_registers_;
 
   DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
@@ -1509,19 +1507,19 @@
                                  ElementsKind to,
                                  bool is_jsarray,
                                  StrictModeFlag strict_mode,
-                                 KeyedAccessGrowMode grow_mode)
+                                 KeyedAccessStoreMode store_mode)
       : from_(from),
         to_(to),
         is_jsarray_(is_jsarray),
         strict_mode_(strict_mode),
-        grow_mode_(grow_mode) {}
+        store_mode_(store_mode) {}
 
  private:
-  class FromBits:       public BitField<ElementsKind,      0, 8> {};
-  class ToBits:         public BitField<ElementsKind,      8, 8> {};
-  class IsJSArrayBits:  public BitField<bool,              16, 1> {};
-  class StrictModeBits: public BitField<StrictModeFlag,    17, 1> {};
-  class GrowModeBits: public BitField<KeyedAccessGrowMode, 18, 1> {};
+  class FromBits:       public BitField<ElementsKind,        0, 8> {};
+  class ToBits:         public BitField<ElementsKind,        8, 8> {};
+  class IsJSArrayBits:  public BitField<bool,                16, 1> {};
+  class StrictModeBits: public BitField<StrictModeFlag,      17, 1> {};
+  class StoreModeBits: public BitField<KeyedAccessStoreMode, 18, 4> {};
 
   Major MajorKey() { return ElementsTransitionAndStore; }
   int MinorKey() {
@@ -1529,7 +1527,7 @@
         ToBits::encode(to_) |
         IsJSArrayBits::encode(is_jsarray_) |
         StrictModeBits::encode(strict_mode_) |
-        GrowModeBits::encode(grow_mode_);
+        StoreModeBits::encode(store_mode_);
   }
 
   void Generate(MacroAssembler* masm);
@@ -1538,7 +1536,7 @@
   ElementsKind to_;
   bool is_jsarray_;
   StrictModeFlag strict_mode_;
-  KeyedAccessGrowMode grow_mode_;
+  KeyedAccessStoreMode store_mode_;
 
   DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
 };
diff --git a/src/collection.js b/src/collection.js
index b3c2db7..c872efb 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -197,7 +197,7 @@
     throw MakeTypeError('incompatible_method_receiver',
                         ['WeakMap.prototype.get', this]);
   }
-  if (!IS_SPEC_OBJECT(key)) {
+  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
   return %WeakMapGet(this, key);
@@ -209,7 +209,7 @@
     throw MakeTypeError('incompatible_method_receiver',
                         ['WeakMap.prototype.set', this]);
   }
-  if (!IS_SPEC_OBJECT(key)) {
+  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
   return %WeakMapSet(this, key, value);
@@ -221,7 +221,7 @@
     throw MakeTypeError('incompatible_method_receiver',
                         ['WeakMap.prototype.has', this]);
   }
-  if (!IS_SPEC_OBJECT(key)) {
+  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
   return %WeakMapHas(this, key);
@@ -233,7 +233,7 @@
     throw MakeTypeError('incompatible_method_receiver',
                         ['WeakMap.prototype.delete', this]);
   }
-  if (!IS_SPEC_OBJECT(key)) {
+  if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
   return %WeakMapDelete(this, key);
diff --git a/src/compiler.cc b/src/compiler.cc
index a381c3a..100d100 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -234,9 +234,9 @@
            compilation_time);
   }
   if (FLAG_hydrogen_stats) {
-    HStatistics::Instance()->IncrementSubtotals(time_taken_to_create_graph_,
-                                                time_taken_to_optimize_,
-                                                time_taken_to_codegen_);
+    isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_create_graph_,
+                                                    time_taken_to_optimize_,
+                                                    time_taken_to_codegen_);
   }
 }
 
@@ -277,7 +277,7 @@
   // Fall back to using the full code generator if it's not possible
   // to use the Hydrogen-based optimizing compiler. We already have
   // generated code for this from the shared function object.
-  if (AlwaysFullCompiler(info()->isolate())) {
+  if (AlwaysFullCompiler(isolate())) {
     info()->SetCode(code);
     return SetLastStatus(BAILED_OUT);
   }
@@ -330,7 +330,7 @@
   // performance of the hydrogen-based compiler.
   bool should_recompile = !info()->shared_info()->has_deoptimization_support();
   if (should_recompile || FLAG_hydrogen_stats) {
-    HPhase phase(HPhase::kFullCodeGen);
+    HPhase phase(HPhase::kFullCodeGen, isolate());
     CompilationInfoWithZone unoptimized(info()->shared_info());
     // Note that we use the same AST that we will use for generating the
     // optimized code.
@@ -360,18 +360,18 @@
   if (FLAG_trace_hydrogen) {
     PrintF("-----------------------------------------------------------\n");
     PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
-    HTracer::Instance()->TraceCompilation(info());
+    isolate()->GetHTracer()->TraceCompilation(info());
   }
   Handle<Context> native_context(
       info()->closure()->context()->native_context());
   oracle_ = new(info()->zone()) TypeFeedbackOracle(
-      code, native_context, info()->isolate(), info()->zone());
+      code, native_context, isolate(), info()->zone());
   graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info(), oracle_);
 
   Timer t(this, &time_taken_to_create_graph_);
   graph_ = graph_builder_->CreateGraph();
 
-  if (info()->isolate()->has_pending_exception()) {
+  if (isolate()->has_pending_exception()) {
     info()->SetCode(Handle<Code>::null());
     return SetLastStatus(FAILED);
   }
@@ -963,6 +963,17 @@
 
 void Compiler::InstallOptimizedCode(OptimizingCompiler* optimizing_compiler) {
   SmartPointer<CompilationInfo> info(optimizing_compiler->info());
+  // Function may have been optimized meanwhile by OSR.
+  if (FLAG_use_osr) {
+    // Function may have already been optimized meanwhile by OSR.
+    if (!info->code().is_null() &&
+        info->code()->kind() == Code::OPTIMIZED_FUNCTION) {
+      return;
+    }
+    // OSR may also have caused optimization to be disabled.
+    if (info->shared_info()->optimization_disabled()) return;
+  }
+
   Isolate* isolate = info->isolate();
   VMState state(isolate, PARALLEL_COMPILER);
   Logger::TimerEventScope timer(
diff --git a/src/compiler.h b/src/compiler.h
index 4d7644c..0191bb2 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -49,7 +49,7 @@
   CompilationInfo(Handle<JSFunction> closure, Zone* zone);
   CompilationInfo(HydrogenCodeStub* stub, Isolate* isolate, Zone* zone);
 
-  virtual ~CompilationInfo();
+  ~CompilationInfo();
 
   Isolate* isolate() {
     ASSERT(Isolate::Current() == isolate_);
@@ -349,8 +349,6 @@
 // Zone on construction and deallocates it on exit.
 class CompilationInfoWithZone: public CompilationInfo {
  public:
-  INLINE(void* operator new(size_t size)) { return Malloced::New(size); }
-
   explicit CompilationInfoWithZone(Handle<Script> script)
       : CompilationInfo(script, &zone_),
         zone_(script->GetIsolate()),
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index 3d5e697..7d56b8d 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -45,25 +45,20 @@
 static const int kProfilerStackSize = 64 * KB;
 
 
-ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator,
-                                                 Sampler* sampler,
-                                                 int period_in_useconds)
+ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
     : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
       generator_(generator),
-      sampler_(sampler),
       running_(true),
-      period_in_useconds_(period_in_useconds),
       ticks_buffer_(sizeof(TickSampleEventRecord),
                     kTickSamplesBufferChunkSize,
-                    kTickSamplesBufferChunksCount,
-                    !Sampler::CanSampleOnProfilerEventsProcessorThread()),
+                    kTickSamplesBufferChunksCount),
       enqueue_order_(0) {
 }
 
 
 void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
                                                   const char* prefix,
-                                                  String* name,
+                                                  Name* name,
                                                   Address start) {
   if (FilterOutCodeCreateEvent(tag)) return;
   CodeEventsContainer evt_rec;
@@ -79,7 +74,7 @@
 
 
 void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                                              String* name,
+                                              Name* name,
                                               String* resource_name,
                                               int line_number,
                                               Address start,
@@ -244,42 +239,17 @@
 }
 
 
-void ProfilerEventsProcessor::ProcessEventsAndDoSample(
-    unsigned* dequeue_order) {
-  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(*dequeue_order)) {
-      // All ticks of the current dequeue_order are processed,
-      // proceed to the next code event.
-      ProcessCodeEvent(dequeue_order);
-    }
-  }
-  // Schedule next sample. sampler_ is NULL in tests.
-  if (sampler_)
-    sampler_->DoSample();
-}
-
-
-void ProfilerEventsProcessor::ProcessEventsAndYield(unsigned* dequeue_order) {
-  if (ProcessTicks(*dequeue_order)) {
-    // All ticks of the current dequeue_order are processed,
-    // proceed to the next code event.
-    ProcessCodeEvent(dequeue_order);
-  }
-  YieldCPU();
-}
-
-
 void ProfilerEventsProcessor::Run() {
   unsigned dequeue_order = 0;
 
   while (running_) {
-    if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
-      ProcessEventsAndDoSample(&dequeue_order);
-    } else {
-      ProcessEventsAndYield(&dequeue_order);
+    // Process ticks until we have any.
+    if (ProcessTicks(dequeue_order)) {
+      // All ticks of the current dequeue_order are processed,
+      // proceed to the next code event.
+      ProcessCodeEvent(&dequeue_order);
     }
+    YieldCPU();
   }
 
   // Process remaining tick events.
@@ -372,7 +342,7 @@
 }
 
 
-void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
+void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
   Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
       Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
 }
@@ -386,7 +356,7 @@
 
 
 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
-                           Code* code, String* name) {
+                           Code* code, Name* name) {
   Isolate* isolate = Isolate::Current();
   isolate->cpu_profiler()->processor_->CodeCreateEvent(
       tag,
@@ -402,7 +372,7 @@
 void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
                                   Code* code,
                                   SharedFunctionInfo* shared,
-                                  String* name) {
+                                  Name* name) {
   Isolate* isolate = Isolate::Current();
   isolate->cpu_profiler()->processor_->CodeCreateEvent(
       tag,
@@ -455,7 +425,7 @@
 }
 
 
-void CpuProfiler::GetterCallbackEvent(String* name, Address entry_point) {
+void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
   Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
       Logger::CALLBACK_TAG, "get ", name, entry_point);
 }
@@ -471,7 +441,7 @@
 }
 
 
-void CpuProfiler::SetterCallbackEvent(String* name, Address entry_point) {
+void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
   Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
       Logger::CALLBACK_TAG, "set ", name, entry_point);
 }
@@ -516,15 +486,13 @@
   if (processor_ == NULL) {
     Isolate* isolate = Isolate::Current();
 
-    Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
     // Disable logging when using the new implementation.
     saved_logging_nesting_ = isolate->logger()->logging_nesting_;
     isolate->logger()->logging_nesting_ = 0;
     generator_ = new ProfileGenerator(profiles_);
-    processor_ = new ProfilerEventsProcessor(generator_,
-                                             sampler,
-                                             FLAG_cpu_profiler_sampling_period);
+    processor_ = new ProfilerEventsProcessor(generator_);
     is_profiling_ = true;
+    processor_->Start();
     // Enumerate stuff we already have in the heap.
     if (isolate->heap()->HasBeenSetUp()) {
       if (!FLAG_prof_browser_mode) {
@@ -537,13 +505,12 @@
       isolate->logger()->LogAccessorCallbacks();
     }
     // Enable stack sampling.
+    Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
     if (!sampler->IsActive()) {
       sampler->Start();
       need_to_stop_sampler_ = true;
     }
-    sampler->SetHasProcessingThread(true);
     sampler->IncreaseProfilingDepth();
-    processor_->Start();
   }
 }
 
@@ -581,7 +548,6 @@
   Logger* logger = Isolate::Current()->logger();
   Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
   sampler->DecreaseProfilingDepth();
-  sampler->SetHasProcessingThread(false);
   if (need_to_stop_sampler_) {
     sampler->Stop();
     need_to_stop_sampler_ = false;
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index 187cbbf..3dc766b 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -124,9 +124,7 @@
 // methods called by event producers: VM and stack sampler threads.
 class ProfilerEventsProcessor : public Thread {
  public:
-  ProfilerEventsProcessor(ProfileGenerator* generator,
-                          Sampler* sampler,
-                          int period_in_useconds);
+  explicit ProfilerEventsProcessor(ProfileGenerator* generator);
   virtual ~ProfilerEventsProcessor() {}
 
   // Thread control.
@@ -136,10 +134,10 @@
 
   // Events adding methods. Called by VM threads.
   void CallbackCreateEvent(Logger::LogEventsAndTags tag,
-                           const char* prefix, String* name,
+                           const char* prefix, Name* name,
                            Address start);
   void CodeCreateEvent(Logger::LogEventsAndTags tag,
-                       String* name,
+                       Name* name,
                        String* resource_name, int line_number,
                        Address start, unsigned size,
                        Address shared);
@@ -175,16 +173,11 @@
   // Called from events processing thread (Run() method.)
   bool ProcessCodeEvent(unsigned* dequeue_order);
   bool ProcessTicks(unsigned dequeue_order);
-  void ProcessEventsAndDoSample(unsigned* dequeue_order);
-  void ProcessEventsAndYield(unsigned* dequeue_order);
 
   INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag));
 
   ProfileGenerator* generator_;
-  Sampler* sampler_;
   bool running_;
-  // Sampling period in microseconds.
-  const int period_in_useconds_;
   UnboundQueue<CodeEventsContainer> events_buffer_;
   SamplingCircularQueue ticks_buffer_;
   UnboundQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
@@ -229,15 +222,15 @@
 
   // Must be called via PROFILE macro, otherwise will crash when
   // profiling is not enabled.
-  static void CallbackEvent(String* name, Address entry_point);
+  static void CallbackEvent(Name* name, Address entry_point);
   static void CodeCreateEvent(Logger::LogEventsAndTags tag,
                               Code* code, const char* comment);
   static void CodeCreateEvent(Logger::LogEventsAndTags tag,
-                              Code* code, String* name);
+                              Code* code, Name* name);
   static void CodeCreateEvent(Logger::LogEventsAndTags tag,
                               Code* code,
                               SharedFunctionInfo* shared,
-                              String* name);
+                              Name* name);
   static void CodeCreateEvent(Logger::LogEventsAndTags tag,
                               Code* code,
                               SharedFunctionInfo* shared,
@@ -247,9 +240,9 @@
   static void CodeMovingGCEvent() {}
   static void CodeMoveEvent(Address from, Address to);
   static void CodeDeleteEvent(Address from);
-  static void GetterCallbackEvent(String* name, Address entry_point);
+  static void GetterCallbackEvent(Name* name, Address entry_point);
   static void RegExpCodeCreateEvent(Code* code, String* source);
-  static void SetterCallbackEvent(String* name, Address entry_point);
+  static void SetterCallbackEvent(Name* name, Address entry_point);
   static void SharedFunctionInfoMoveEvent(Address from, Address to);
 
   static INLINE(bool is_profiling(Isolate* isolate)) {
diff --git a/src/d8.js b/src/d8.js
index 3cb1819..6a4ecb7 100644
--- a/src/d8.js
+++ b/src/d8.js
@@ -71,7 +71,7 @@
         result.push(name);
       }
     }
-    current = ToInspectableObject(current.__proto__);
+    current = ToInspectableObject(Object.getPrototypeOf(current));
   }
   return result;
 }
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index c0b5945..21ffe07 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -922,6 +922,139 @@
 }
 
 
+void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
+                                              int frame_index) {
+  Builtins* builtins = isolate_->builtins();
+  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
+  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
+  unsigned height = iterator->Next();
+  unsigned height_in_bytes = height * kPointerSize;
+  if (trace_) {
+    PrintF("  translating construct stub => height=%d\n", height_in_bytes);
+  }
+
+  unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize;
+  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
+
+  // Allocate and store the output frame description.
+  FrameDescription* output_frame =
+      new(output_frame_size) FrameDescription(output_frame_size, function);
+  output_frame->SetFrameType(StackFrame::CONSTRUCT);
+
+  // Construct stub can not be topmost or bottommost.
+  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
+  ASSERT(output_[frame_index] == NULL);
+  output_[frame_index] = output_frame;
+
+  // The top address of the frame is computed from the previous
+  // frame's top and this frame's size.
+  intptr_t top_address;
+  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
+  output_frame->SetTop(top_address);
+
+  // Compute the incoming parameter translation.
+  int parameter_count = height;
+  unsigned output_offset = output_frame_size;
+  for (int i = 0; i < parameter_count; ++i) {
+    output_offset -= kPointerSize;
+    DoTranslateCommand(iterator, frame_index, output_offset);
+  }
+
+  // Read caller's PC from the previous frame.
+  output_offset -= kPointerSize;
+  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
+  output_frame->SetFrameSlot(output_offset, callers_pc);
+  if (trace_) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+           V8PRIxPTR " ; caller's pc\n",
+           top_address + output_offset, output_offset, callers_pc);
+  }
+
+  // Read caller's FP from the previous frame, and set this frame's FP.
+  output_offset -= kPointerSize;
+  intptr_t value = output_[frame_index - 1]->GetFp();
+  output_frame->SetFrameSlot(output_offset, value);
+  intptr_t fp_value = top_address + output_offset;
+  output_frame->SetFp(fp_value);
+  if (trace_) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+           V8PRIxPTR " ; caller's fp\n",
+           fp_value, output_offset, value);
+  }
+
+  // The context can be gotten from the previous frame.
+  output_offset -= kPointerSize;
+  value = output_[frame_index - 1]->GetContext();
+  output_frame->SetFrameSlot(output_offset, value);
+  if (trace_) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+           V8PRIxPTR " ; context\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // A marker value is used in place of the function.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
+  output_frame->SetFrameSlot(output_offset, value);
+  if (trace_) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+           V8PRIxPTR " ; function (construct sentinel)\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // The output frame reflects a JSConstructStubGeneric frame.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(construct_stub);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (trace_) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+           V8PRIxPTR " ; code object\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  // Number of incoming arguments.
+  output_offset -= kPointerSize;
+  value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
+  output_frame->SetFrameSlot(output_offset, value);
+  if (trace_) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+           V8PRIxPTR " ; argc (%d)\n",
+           top_address + output_offset, output_offset, value, height - 1);
+  }
+
+  // Constructor function being invoked by the stub (only present on some
+  // architectures, indicated by kConstructorOffset).
+  if (ConstructFrameConstants::kConstructorOffset != kMinInt) {
+    output_offset -= kPointerSize;
+    value = reinterpret_cast<intptr_t>(function);
+    output_frame->SetFrameSlot(output_offset, value);
+    if (trace_) {
+      PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+             V8PRIxPTR " ; constructor function\n",
+             top_address + output_offset, output_offset, value);
+    }
+  }
+
+  // The newly allocated object was passed as receiver in the artificial
+  // constructor stub environment created by HEnvironment::CopyForInlining().
+  output_offset -= kPointerSize;
+  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
+  output_frame->SetFrameSlot(output_offset, value);
+  if (trace_) {
+    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+           V8PRIxPTR " ; allocated receiver\n",
+           top_address + output_offset, output_offset, value);
+  }
+
+  ASSERT(0 == output_offset);
+
+  intptr_t pc = reinterpret_cast<intptr_t>(
+      construct_stub->instruction_start() +
+      isolate_->heap()->construct_stub_deopt_pc_offset()->value());
+  output_frame->SetPc(pc);
+}
+
+
 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
                                              int frame_index,
                                              bool is_setter_stub_frame) {
diff --git a/src/factory.cc b/src/factory.cc
index bb0e85f..943902e 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -70,11 +70,11 @@
 }
 
 
-Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
+Handle<NameDictionary> Factory::NewNameDictionary(int at_least_space_for) {
   ASSERT(0 <= at_least_space_for);
   CALL_HEAP_FUNCTION(isolate(),
-                     StringDictionary::Allocate(at_least_space_for),
-                     StringDictionary);
+                     NameDictionary::Allocate(at_least_space_for),
+                     NameDictionary);
 }
 
 
@@ -369,6 +369,12 @@
 }
 
 
+Handle<DeclaredAccessorDescriptor> Factory::NewDeclaredAccessorDescriptor() {
+  return Handle<DeclaredAccessorDescriptor>::cast(
+      NewStruct(DECLARED_ACCESSOR_DESCRIPTOR_TYPE));
+}
+
+
 Handle<DeclaredAccessorInfo> Factory::NewDeclaredAccessorInfo() {
   Handle<DeclaredAccessorInfo> info =
       Handle<DeclaredAccessorInfo>::cast(
diff --git a/src/factory.h b/src/factory.h
index 3651d36..8695bcd 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -60,7 +60,7 @@
   Handle<UnseededNumberDictionary> NewUnseededNumberDictionary(
       int at_least_space_for);
 
-  Handle<StringDictionary> NewStringDictionary(int at_least_space_for);
+  Handle<NameDictionary> NewNameDictionary(int at_least_space_for);
 
   Handle<ObjectHashSet> NewObjectHashSet(int at_least_space_for);
 
@@ -205,6 +205,8 @@
   // the old generation).
   Handle<Struct> NewStruct(InstanceType type);
 
+  Handle<DeclaredAccessorDescriptor> NewDeclaredAccessorDescriptor();
+
   Handle<DeclaredAccessorInfo> NewDeclaredAccessorInfo();
 
   Handle<ExecutableAccessorInfo> NewExecutableAccessorInfo();
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index dcc6c2c..a385671 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -248,6 +248,8 @@
 DEFINE_bool(trace_parallel_recompilation, false, "track parallel recompilation")
 DEFINE_int(parallel_recompilation_queue_length, 2,
            "the length of the parallel compilation queue")
+DEFINE_int(parallel_recompilation_delay, 0,
+           "artificial compilation delay in ms")
 DEFINE_bool(manual_parallel_recompilation, false,
             "disable automatic optimization")
 DEFINE_implication(manual_parallel_recompilation, parallel_recompilation)
@@ -370,10 +372,6 @@
 
 DEFINE_bool(cache_prototype_transitions, true, "cache prototype transitions")
 
-// cpu-profiler.cc
-DEFINE_int(cpu_profiler_sampling_period, 1000,
-           "CPU profiler sampling period in microseconds")
-
 // debug.cc
 DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
 DEFINE_bool(trace_js_array_abuse, false,
diff --git a/src/global-handles.cc b/src/global-handles.cc
index 299449a..a6347bb 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -113,10 +113,10 @@
   void Release(GlobalHandles* global_handles) {
     ASSERT(state() != FREE);
     set_state(FREE);
-    // TODO(176056): Enable as soon as WebKit bindings are fixed.
-#ifdef DEBUG_TODO
-    // Zap the values for eager trapping.
+    // TODO(mstarzinger): Put behind debug flag once embedders are stabilized.
     object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue);
+#ifdef DEBUG
+    // Zap the values for eager trapping.
     class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
     set_independent(false);
     set_partially_dependent(false);
diff --git a/src/handles.cc b/src/handles.cc
index 7496cc1..2958d2c 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -260,7 +260,7 @@
 
 
 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
-                                          Handle<String> key,
+                                          Handle<Name> key,
                                           Handle<Object> value,
                                           PropertyAttributes attributes,
                                           StrictModeFlag strict_mode) {
@@ -291,7 +291,7 @@
 
 Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
                                           Handle<JSObject> holder,
-                                          Handle<String> name,
+                                          Handle<Name> name,
                                           PropertyAttributes* attributes) {
   Isolate* isolate = receiver->GetIsolate();
   CALL_HEAP_FUNCTION(isolate,
@@ -551,6 +551,7 @@
 
 
 // Compute the property keys from the interceptor.
+// TODO(rossberg): support symbols in API, and filter here if needed.
 v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSReceiver> receiver,
                                                  Handle<JSObject> object) {
   Isolate* isolate = receiver->GetIsolate();
@@ -754,10 +755,10 @@
       // to kInvalidEnumCache, this means that the map itself has never used the
       // present enum cache. The first step to using the cache is to set the
       // enum length of the map by counting the number of own descriptors that
-      // are not DONT_ENUM.
+      // are not DONT_ENUM or SYMBOLIC.
       if (own_property_count == Map::kInvalidEnumCache) {
         own_property_count = object->map()->NumberOfDescribedProperties(
-            OWN_DESCRIPTORS, DONT_ENUM);
+            OWN_DESCRIPTORS, DONT_SHOW);
 
         if (cache_result) object->map()->SetEnumLength(own_property_count);
       }
@@ -784,7 +785,7 @@
     }
 
     isolate->counters()->enum_cache_misses()->Increment();
-    int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS, DONT_ENUM);
+    int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS, DONT_SHOW);
 
     Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(num_enum);
@@ -798,9 +799,10 @@
 
     for (int i = 0; i < descs->number_of_descriptors(); i++) {
       PropertyDetails details = descs->GetDetails(i);
-      if (!details.IsDontEnum()) {
+      Object* key = descs->GetKey(i);
+      if (!(details.IsDontEnum() || key->IsSymbol())) {
         if (i < real_size) ++enum_size;
-        storage->set(index, descs->GetKey(i));
+        storage->set(index, key);
         if (!indices.is_null()) {
           if (details.type() != FIELD) {
             indices = Handle<FixedArray>();
@@ -831,7 +833,7 @@
 
     return ReduceFixedArrayTo(storage, enum_size);
   } else {
-    Handle<StringDictionary> dictionary(object->property_dictionary());
+    Handle<NameDictionary> dictionary(object->property_dictionary());
 
     int length = dictionary->NumberOfElements();
     if (length == 0) {
@@ -852,7 +854,7 @@
     // many properties were added but subsequently deleted.
     int next_enumeration = dictionary->NextEnumerationIndex();
     if (!object->IsGlobalObject() && next_enumeration > (length * 3) / 2) {
-      StringDictionary::DoGenerateNewEnumerationIndices(dictionary);
+      NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
       next_enumeration = dictionary->NextEnumerationIndex();
     }
 
@@ -860,7 +862,7 @@
         isolate->factory()->NewFixedArray(next_enumeration);
 
     storage = Handle<FixedArray>(dictionary->CopyEnumKeysTo(*storage));
-    ASSERT(storage->length() == object->NumberOfLocalProperties(DONT_ENUM));
+    ASSERT(storage->length() == object->NumberOfLocalProperties(DONT_SHOW));
     return storage;
   }
 }
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 916a6a2..3644876 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -320,8 +320,8 @@
 }
 
 
-bool Heap::InNewSpace(Address addr) {
-  return new_space_.Contains(addr);
+bool Heap::InNewSpace(Address address) {
+  return new_space_.Contains(address);
 }
 
 
@@ -335,6 +335,16 @@
 }
 
 
+bool Heap::InOldPointerSpace(Address address) {
+  return old_pointer_space_->Contains(address);
+}
+
+
+bool Heap::InOldPointerSpace(Object* object) {
+  return InOldPointerSpace(reinterpret_cast<Address>(object));
+}
+
+
 bool Heap::OldGenerationAllocationLimitReached() {
   if (!incremental_marking()->IsStopped()) return false;
   return OldGenerationSpaceAvailable() < 0;
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 9e96685..5f46678 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1320,7 +1320,7 @@
         case FIELD: {
           int index = descs->GetFieldIndex(i);
 
-          String* k = descs->GetKey(i);
+          Name* k = descs->GetKey(i);
           if (index < js_obj->map()->inobject_properties()) {
             Object* value = js_obj->InObjectPropertyAt(index);
             if (k != heap_->hidden_string()) {
@@ -1378,7 +1378,7 @@
       }
     }
   } else {
-    StringDictionary* dictionary = js_obj->property_dictionary();
+    NameDictionary* dictionary = js_obj->property_dictionary();
     int length = dictionary->Capacity();
     for (int i = 0; i < length; ++i) {
       Object* k = dictionary->KeyAt(i);
@@ -1688,19 +1688,20 @@
 
 void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
                                           int parent_entry,
-                                          String* reference_name,
+                                          Name* reference_name,
                                           Object* child_obj,
                                           const char* name_format_string,
                                           int field_offset) {
   HeapEntry* child_entry = GetEntry(child_obj);
   if (child_entry != NULL) {
-    HeapGraphEdge::Type type = reference_name->length() > 0 ?
-        HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
-    const char* name = name_format_string  != NULL ?
-        collection_->names()->GetFormatted(
-            name_format_string,
-            *reference_name->ToCString(DISALLOW_NULLS,
-                                       ROBUST_STRING_TRAVERSAL)) :
+    HeapGraphEdge::Type type =
+        reference_name->IsSymbol() || String::cast(reference_name)->length() > 0
+            ? HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
+    const char* name = name_format_string != NULL && reference_name->IsString()
+        ? collection_->names()->GetFormatted(
+              name_format_string,
+              *String::cast(reference_name)->ToCString(
+                  DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)) :
         collection_->names()->GetName(reference_name);
 
     filler_->SetNamedReference(type,
diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h
index 77c659a..fe15715 100644
--- a/src/heap-snapshot-generator.h
+++ b/src/heap-snapshot-generator.h
@@ -512,7 +512,7 @@
                         int field_offset);
   void SetPropertyReference(HeapObject* parent_obj,
                             int parent,
-                            String* reference_name,
+                            Name* reference_name,
                             Object* child,
                             const char* name_format_string = NULL,
                             int field_offset = -1);
diff --git a/src/heap.cc b/src/heap.cc
index 7ce9263..4f85705 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2865,14 +2865,14 @@
   CreateFixedStubs();
 
   // Allocate the dictionary of intrinsic function names.
-  { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions);
+  { MaybeObject* maybe_obj = NameDictionary::Allocate(Runtime::kNumFunctions);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
   { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(this,
                                                                        obj);
     if (!maybe_obj->ToObject(&obj)) return false;
   }
-  set_intrinsic_function_names(StringDictionary::cast(obj));
+  set_intrinsic_function_names(NameDictionary::cast(obj));
 
   { MaybeObject* maybe_obj = AllocateInitialNumberStringCache();
     if (!maybe_obj->ToObject(&obj)) return false;
@@ -4066,9 +4066,9 @@
 static bool HasDuplicates(DescriptorArray* descriptors) {
   int count = descriptors->number_of_descriptors();
   if (count > 1) {
-    String* prev_key = descriptors->GetKey(0);
+    Name* prev_key = descriptors->GetKey(0);
     for (int i = 1; i != count; i++) {
-      String* current_key = descriptors->GetKey(i);
+      Name* current_key = descriptors->GetKey(i);
       if (prev_key == current_key) return true;
       prev_key = current_key;
     }
@@ -4521,9 +4521,9 @@
   int initial_size = map->instance_type() == JS_GLOBAL_OBJECT_TYPE ? 64 : 512;
 
   // Allocate a dictionary object for backing storage.
-  StringDictionary* dictionary;
+  NameDictionary* dictionary;
   MaybeObject* maybe_dictionary =
-      StringDictionary::Allocate(
+      NameDictionary::Allocate(
           map->NumberOfOwnDescriptors() * 2 + initial_size);
   if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
 
@@ -7443,7 +7443,7 @@
 }
 
 
-int KeyedLookupCache::Hash(Map* map, String* name) {
+int KeyedLookupCache::Hash(Map* map, Name* name) {
   // Uses only lower 32 bits if pointers are larger.
   uintptr_t addr_hash =
       static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift;
@@ -7451,7 +7451,7 @@
 }
 
 
-int KeyedLookupCache::Lookup(Map* map, String* name) {
+int KeyedLookupCache::Lookup(Map* map, Name* name) {
   int index = (Hash(map, name) & kHashMask);
   for (int i = 0; i < kEntriesPerBucket; i++) {
     Key& key = keys_[index + i];
@@ -7463,37 +7463,43 @@
 }
 
 
-void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
-  String* internalized_name;
-  if (HEAP->InternalizeStringIfExists(name, &internalized_name)) {
-    int index = (Hash(map, internalized_name) & kHashMask);
-    // After a GC there will be free slots, so we use them in order (this may
-    // help to get the most frequently used one in position 0).
-    for (int i = 0; i< kEntriesPerBucket; i++) {
-      Key& key = keys_[index];
-      Object* free_entry_indicator = NULL;
-      if (key.map == free_entry_indicator) {
-        key.map = map;
-        key.name = internalized_name;
-        field_offsets_[index + i] = field_offset;
-        return;
-      }
+void KeyedLookupCache::Update(Map* map, Name* name, int field_offset) {
+  if (!name->IsUniqueName()) {
+    String* internalized_string;
+    if (!HEAP->InternalizeStringIfExists(
+            String::cast(name), &internalized_string)) {
+      return;
     }
-    // No free entry found in this bucket, so we move them all down one and
-    // put the new entry at position zero.
-    for (int i = kEntriesPerBucket - 1; i > 0; i--) {
-      Key& key = keys_[index + i];
-      Key& key2 = keys_[index + i - 1];
-      key = key2;
-      field_offsets_[index + i] = field_offsets_[index + i - 1];
-    }
-
-    // Write the new first entry.
-    Key& key = keys_[index];
-    key.map = map;
-    key.name = internalized_name;
-    field_offsets_[index] = field_offset;
+    name = internalized_string;
   }
+
+  int index = (Hash(map, name) & kHashMask);
+  // After a GC there will be free slots, so we use them in order (this may
+  // help to get the most frequently used one in position 0).
+  for (int i = 0; i< kEntriesPerBucket; i++) {
+    Key& key = keys_[index];
+    Object* free_entry_indicator = NULL;
+    if (key.map == free_entry_indicator) {
+      key.map = map;
+      key.name = name;
+      field_offsets_[index + i] = field_offset;
+      return;
+    }
+  }
+  // No free entry found in this bucket, so we move them all down one and
+  // put the new entry at position zero.
+  for (int i = kEntriesPerBucket - 1; i > 0; i--) {
+    Key& key = keys_[index + i];
+    Key& key2 = keys_[index + i - 1];
+    key = key2;
+    field_offsets_[index + i] = field_offsets_[index + i - 1];
+  }
+
+  // Write the new first entry.
+  Key& key = keys_[index];
+  key.map = map;
+  key.name = name;
+  field_offsets_[index] = field_offset;
 }
 
 
diff --git a/src/heap.h b/src/heap.h
index a5ff86e..456e9d8 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -160,7 +160,7 @@
   V(Object, last_script_id, LastScriptId)                                      \
   V(Script, empty_script, EmptyScript)                                         \
   V(Smi, real_stack_limit, RealStackLimit)                                     \
-  V(StringDictionary, intrinsic_function_names, IntrinsicFunctionNames)        \
+  V(NameDictionary, intrinsic_function_names, IntrinsicFunctionNames)        \
   V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset)     \
   V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset)           \
   V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset)                 \
@@ -226,8 +226,6 @@
     "KeyedLoadElementMonomorphic")                                       \
   V(KeyedStoreElementMonomorphic_string,                                 \
     "KeyedStoreElementMonomorphic")                                      \
-  V(KeyedStoreAndGrowElementMonomorphic_string,                          \
-    "KeyedStoreAndGrowElementMonomorphic")                               \
   V(stack_overflow_string, "kStackOverflowBoilerplate")                  \
   V(illegal_access_string, "illegal access")                             \
   V(out_of_memory_string, "out-of-memory")                               \
@@ -266,7 +264,7 @@
   V(infinity_string, "Infinity")                                         \
   V(minus_infinity_string, "-Infinity")                                  \
   V(hidden_stack_trace_string, "v8::hidden_stack_trace")                 \
-  V(query_colon_string, "(?:)")                                          \
+  V(query_colon_string, "(?:)")
 
 // Forward declarations.
 class GCTracer;
@@ -1312,11 +1310,15 @@
 
   // Returns whether the object resides in new space.
   inline bool InNewSpace(Object* object);
-  inline bool InNewSpace(Address addr);
-  inline bool InNewSpacePage(Address addr);
+  inline bool InNewSpace(Address address);
+  inline bool InNewSpacePage(Address address);
   inline bool InFromSpace(Object* object);
   inline bool InToSpace(Object* object);
 
+  // Returns whether the object resides in old pointer space.
+  inline bool InOldPointerSpace(Address address);
+  inline bool InOldPointerSpace(Object* object);
+
   // Checks whether an address/object in the heap (including auxiliary
   // area and unused area).
   bool Contains(Address addr);
@@ -1697,6 +1699,12 @@
     return sweeping_complete;
   }
 
+  bool EnsureSweepersProgressed(int step_size) {
+    bool sweeping_complete = old_data_space()->EnsureSweeperProgress(step_size);
+    sweeping_complete &= old_pointer_space()->EnsureSweeperProgress(step_size);
+    return sweeping_complete;
+  }
+
   ExternalStringTable* external_string_table() {
     return &external_string_table_;
   }
@@ -2496,10 +2504,10 @@
 class KeyedLookupCache {
  public:
   // Lookup field offset for (map, name). If absent, -1 is returned.
-  int Lookup(Map* map, String* name);
+  int Lookup(Map* map, Name* name);
 
   // Update an element in the cache.
-  void Update(Map* map, String* name, int field_offset);
+  void Update(Map* map, Name* name, int field_offset);
 
   // Clear the cache.
   void Clear();
@@ -2524,7 +2532,7 @@
     }
   }
 
-  static inline int Hash(Map* map, String* name);
+  static inline int Hash(Map* map, Name* name);
 
   // Get the address of the keys and field_offsets arrays.  Used in
   // generated code to perform cache lookups.
@@ -2538,7 +2546,7 @@
 
   struct Key {
     Map* map;
-    String* name;
+    Name* name;
   };
 
   Key keys_[kLength];
@@ -2558,8 +2566,8 @@
  public:
   // Lookup descriptor index for (map, name).
   // If absent, kAbsent is returned.
-  int Lookup(Map* source, String* name) {
-    if (!StringShape(name).IsInternalized()) return kAbsent;
+  int Lookup(Map* source, Name* name) {
+    if (!name->IsUniqueName()) return kAbsent;
     int index = Hash(source, name);
     Key& key = keys_[index];
     if ((key.source == source) && (key.name == name)) return results_[index];
@@ -2567,9 +2575,9 @@
   }
 
   // Update an element in the cache.
-  void Update(Map* source, String* name, int result) {
+  void Update(Map* source, Name* name, int result) {
     ASSERT(result != kAbsent);
-    if (StringShape(name).IsInternalized()) {
+    if (name->IsUniqueName()) {
       int index = Hash(source, name);
       Key& key = keys_[index];
       key.source = source;
@@ -2592,7 +2600,7 @@
     }
   }
 
-  static int Hash(Object* source, String* name) {
+  static int Hash(Object* source, Name* name) {
     // Uses only lower 32 bits if pointers are larger.
     uint32_t source_hash =
         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(source))
@@ -2606,7 +2614,7 @@
   static const int kLength = 64;
   struct Key {
     Map* source;
-    String* name;
+    Name* name;
   };
 
   Key keys_[kLength];
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 4b54c21..eca1aea 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -78,7 +78,7 @@
 
 Isolate* HValue::isolate() const {
   ASSERT(block() != NULL);
-  return block()->graph()->isolate();
+  return block()->isolate();
 }
 
 
@@ -930,12 +930,14 @@
 void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
   ASSERT(CheckFlag(kFlexibleRepresentation));
   Representation r;
+  HValue* actual_length = length()->ActualValue();
+  HValue* actual_index = index()->ActualValue();
   if (key_mode_ == DONT_ALLOW_SMI_KEY ||
-      !length()->representation().IsTagged()) {
+      !actual_length->representation().IsTagged()) {
     r = Representation::Integer32();
-  } else if (index()->representation().IsTagged() ||
-      (index()->ActualValue()->IsConstant() &&
-       HConstant::cast(index()->ActualValue())->HasSmiValue())) {
+  } else if (actual_index->representation().IsTagged() ||
+      (actual_index->IsConstant() &&
+       HConstant::cast(actual_index)->HasSmiValue())) {
     // If the index is tagged, or a constant that holds a Smi, allow the length
     // to be tagged, since it is usually already tagged from loading it out of
     // the length field of a JSArray. This allows for direct comparison without
@@ -1410,8 +1412,9 @@
 
 
 void HCheckPrototypeMaps::PrintDataTo(StringStream* stream) {
-  stream->Add("[receiver_prototype=%p,holder=%p]",
-              *prototypes_.first(), *prototypes_.last());
+  stream->Add("[receiver_prototype=%p,holder=%p]%s",
+              *prototypes_.first(), *prototypes_.last(),
+              CanOmitPrototypeChecks() ? " (omitted)" : "");
 }
 
 
@@ -2566,8 +2569,9 @@
 
 void HCheckSmiOrInt32::InferRepresentation(HInferRepresentation* h_infer) {
   ASSERT(CheckFlag(kFlexibleRepresentation));
-  Representation r = value()->representation().IsTagged()
-      ? Representation::Tagged() : Representation::Integer32();
+  ASSERT(UseCount() == 1);
+  HUseIterator use = uses();
+  Representation r = use.value()->RequiredInputRepresentation(use.index());
   UpdateRepresentation(r, h_infer, "checksmiorint32");
 }
 
@@ -2657,6 +2661,11 @@
 }
 
 
+void HAllocate::PrintDataTo(StringStream* stream) {
+  size()->PrintNameTo(stream);
+}
+
+
 HType HFastLiteral::CalculateInferredType() {
   // TODO(mstarzinger): Be smarter, could also be JSArray here.
   return HType::JSObject();
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index cef8a54..fc396a7 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -2868,7 +2868,7 @@
   }
 
   virtual HValue* Canonicalize() {
-    if (representation().IsTagged() && !type().IsSmi()) {
+    if (representation().IsTagged() && !value()->type().IsSmi()) {
       return this;
     } else {
       return value();
@@ -4672,6 +4672,8 @@
     return (flags_ & ALLOCATE_DOUBLE_ALIGNED) != 0;
   }
 
+  virtual void PrintDataTo(StringStream* stream);
+
   DECLARE_CONCRETE_INSTRUCTION(Allocate)
 
  private:
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 2754fa3..c2f3951 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -75,6 +75,11 @@
       is_osr_entry_(false) { }
 
 
+Isolate* HBasicBlock::isolate() const {
+  return graph_->isolate();
+}
+
+
 void HBasicBlock::AttachLoopInformation() {
   ASSERT(!IsLoopHeader());
   loop_information_ = new(zone()) HLoopInformation(this, zone());
@@ -829,8 +834,8 @@
 
 HGraph* HGraphBuilder::CreateGraph() {
   graph_ = new(zone()) HGraph(info_);
-  if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info_);
-  HPhase phase("H_Block building");
+  if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
+  HPhase phase("H_Block building", isolate());
   set_current_block(graph()->entry_block());
   if (!BuildGraph()) return NULL;
   return graph_;
@@ -1001,7 +1006,7 @@
       AddInstruction(new(zone) HLoadElements(object, mapcheck));
   if (is_store && (fast_elements || fast_smi_only_elements)) {
     HCheckMaps* check_cow_map = new(zone) HCheckMaps(
-        elements, graph()->isolate()->factory()->fixed_array_map(), zone);
+        elements, isolate()->factory()->fixed_array_map(), zone);
     check_cow_map->ClearGVNFlag(kDependsOnElementsKind);
     AddInstruction(check_cow_map);
   }
@@ -1066,16 +1071,14 @@
   HValue* elements =
       AddInstruction(new(zone) HAllocate(context, total_size,
                                          HType::JSArray(), flags));
-  Isolate* isolate = graph()->isolate();
 
-  Factory* factory = isolate->factory();
+  Factory* factory = isolate()->factory();
   Handle<Map> map = IsFastDoubleElementsKind(kind)
       ? factory->fixed_double_array_map()
       : factory->fixed_array_map();
   BuildStoreMap(elements, map, BailoutId::StubEntry());
 
-  Handle<String> fixed_array_length_field_name =
-      isolate->factory()->length_field_string();
+  Handle<String> fixed_array_length_field_name = factory->length_field_string();
   HInstruction* store_length =
       new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
                                  capacity, true, FixedArray::kLengthOffset);
@@ -1090,8 +1093,7 @@
                                            HValue* map,
                                            BailoutId id) {
   Zone* zone = this->zone();
-  Isolate* isolate = graph()->isolate();
-  Factory* factory = isolate->factory();
+  Factory* factory = isolate()->factory();
   Handle<String> map_field_name = factory->map_field_string();
   HInstruction* store_map =
       new(zone) HStoreNamedField(object, map_field_name, map,
@@ -1553,7 +1555,7 @@
 
 
 void HGraph::OrderBlocks() {
-  HPhase phase("H_Block ordering");
+  HPhase phase("H_Block ordering", isolate());
   BitVector visited(blocks_.length(), zone());
 
   ZoneList<HBasicBlock*> reverse_result(8, zone());
@@ -9380,7 +9382,7 @@
     return HandleLiteralCompareTypeof(expr, typeof_expr, check);
   }
   HValue* sub_expr = NULL;
-  Factory* f = graph()->isolate()->factory();
+  Factory* f = isolate()->factory();
   if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) {
     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
   }
@@ -10511,7 +10513,7 @@
 
 
 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
-  AllowHandleDereference allow_handle_deref(chunk->graph()->isolate());
+  AllowHandleDereference allow_handle_deref(chunk->isolate());
   Trace(name, chunk->graph(), chunk);
 }
 
@@ -10713,7 +10715,7 @@
 
 
 void HTracer::FlushToFile() {
-  AppendChars(filename_, *trace_.ToCString(), trace_.length(), false);
+  AppendChars(filename_.start(), *trace_.ToCString(), trace_.length(), false);
   trace_.Reset();
 }
 
@@ -10798,10 +10800,33 @@
 
 const char* const HPhase::kFullCodeGen = "Full code generator";
 
-void HPhase::Begin(const char* name,
-                   HGraph* graph,
-                   LChunk* chunk,
-                   LAllocator* allocator) {
+
+HPhase::HPhase(const char* name, Isolate* isolate) {
+  Init(isolate, name, NULL, NULL, NULL);
+}
+
+
+HPhase::HPhase(const char* name, HGraph* graph) {
+  Init(graph->isolate(), name, graph, NULL, NULL);
+}
+
+
+HPhase::HPhase(const char* name, LChunk* chunk) {
+  Init(chunk->isolate(), name, NULL, chunk, NULL);
+}
+
+
+HPhase::HPhase(const char* name, LAllocator* allocator) {
+  Init(allocator->isolate(), name, NULL, NULL, allocator);
+}
+
+
+void HPhase::Init(Isolate* isolate,
+                  const char* name,
+                  HGraph* graph,
+                  LChunk* chunk,
+                  LAllocator* allocator) {
+  isolate_ = isolate;
   name_ = name;
   graph_ = graph;
   chunk_ = chunk;
@@ -10809,26 +10834,32 @@
   if (allocator != NULL && chunk_ == NULL) {
     chunk_ = allocator->chunk();
   }
-  if (FLAG_hydrogen_stats) start_ = OS::Ticks();
-  start_allocation_size_ = Zone::allocation_size_;
+  if (FLAG_hydrogen_stats) {
+    start_ticks_ = OS::Ticks();
+    start_allocation_size_ = Zone::allocation_size_;
+  }
 }
 
 
-void HPhase::End() const {
+HPhase::~HPhase() {
   if (FLAG_hydrogen_stats) {
-    int64_t end = OS::Ticks();
+    int64_t ticks = OS::Ticks() - start_ticks_;
     unsigned size = Zone::allocation_size_ - start_allocation_size_;
-    HStatistics::Instance()->SaveTiming(name_, end - start_, size);
+    isolate_->GetHStatistics()->SaveTiming(name_, ticks, size);
   }
 
   // Produce trace output if flag is set so that the first letter of the
   // phase name matches the command line parameter FLAG_trace_phase.
   if (FLAG_trace_hydrogen &&
       OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) {
-    if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_);
-    if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_);
+    if (graph_ != NULL) {
+      isolate_->GetHTracer()->TraceHydrogen(name_, graph_);
+    }
+    if (chunk_ != NULL) {
+      isolate_->GetHTracer()->TraceLithium(name_, chunk_);
+    }
     if (allocator_ != NULL) {
-      HTracer::Instance()->TraceLiveRanges(name_, allocator_);
+      isolate_->GetHTracer()->TraceLiveRanges(name_, allocator_);
     }
   }
 
diff --git a/src/hydrogen.h b/src/hydrogen.h
index a9829a0..b3a056f 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -61,6 +61,7 @@
   int block_id() const { return block_id_; }
   void set_block_id(int id) { block_id_ = id; }
   HGraph* graph() const { return graph_; }
+  Isolate* isolate() const;
   const ZoneList<HPhi*>* phis() const { return &phis_; }
   HInstruction* first() const { return first_; }
   HInstruction* last() const { return last_; }
@@ -870,7 +871,8 @@
     return current_block()->last_environment();
   }
   Zone* zone() const { return info_->zone(); }
-  HGraph* graph() { return graph_; }
+  HGraph* graph() const { return graph_; }
+  Isolate* isolate() const { return graph_->isolate(); }
 
   HGraph* CreateGraph();
 
@@ -1534,26 +1536,6 @@
 
 class HStatistics: public Malloced {
  public:
-  void Initialize(CompilationInfo* info);
-  void Print();
-  void SaveTiming(const char* name, int64_t ticks, unsigned size);
-  static HStatistics* Instance() {
-    static SetOncePointer<HStatistics> instance;
-    if (!instance.is_set()) {
-      instance.set(new HStatistics());
-    }
-    return instance.get();
-  }
-
-  void IncrementSubtotals(int64_t create_graph,
-                          int64_t optimize_graph,
-                          int64_t generate_code) {
-    create_graph_ += create_graph;
-    optimize_graph_ += optimize_graph;
-    generate_code_ += generate_code;
-  }
-
- private:
   HStatistics()
       : timing_(5),
         names_(5),
@@ -1565,6 +1547,19 @@
         full_code_gen_(0),
         source_size_(0) { }
 
+  void Initialize(CompilationInfo* info);
+  void Print();
+  void SaveTiming(const char* name, int64_t ticks, unsigned size);
+
+  void IncrementSubtotals(int64_t create_graph,
+                          int64_t optimize_graph,
+                          int64_t generate_code) {
+    create_graph_ += create_graph;
+    optimize_graph_ += optimize_graph;
+    generate_code_ += generate_code;
+  }
+
+ private:
   List<int64_t> timing_;
   List<const char*> names_;
   List<unsigned> sizes_;
@@ -1581,52 +1576,45 @@
  public:
   static const char* const kFullCodeGen;
 
-  explicit HPhase(const char* name) { Begin(name, NULL, NULL, NULL); }
-  HPhase(const char* name, HGraph* graph) {
-    Begin(name, graph, NULL, NULL);
-  }
-  HPhase(const char* name, LChunk* chunk) {
-    Begin(name, NULL, chunk, NULL);
-  }
-  HPhase(const char* name, LAllocator* allocator) {
-    Begin(name, NULL, NULL, allocator);
-  }
-
-  ~HPhase() {
-    End();
-  }
+  HPhase(const char* name, Isolate* isolate);
+  HPhase(const char* name, HGraph* graph);
+  HPhase(const char* name, LChunk* chunk);
+  HPhase(const char* name, LAllocator* allocator);
+  ~HPhase();
 
  private:
-  void Begin(const char* name,
-             HGraph* graph,
-             LChunk* chunk,
-             LAllocator* allocator);
-  void End() const;
+  void Init(Isolate* isolate,
+            const char* name,
+            HGraph* graph,
+            LChunk* chunk,
+            LAllocator* allocator);
 
-  int64_t start_;
+  Isolate* isolate_;
   const char* name_;
   HGraph* graph_;
   LChunk* chunk_;
   LAllocator* allocator_;
+  int64_t start_ticks_;
   unsigned start_allocation_size_;
 };
 
 
 class HTracer: public Malloced {
  public:
+  explicit HTracer(int isolate_id)
+      : trace_(&string_allocator_), indent_(0) {
+    OS::SNPrintF(filename_,
+                 "hydrogen-%d-%d.cfg",
+                 OS::GetCurrentProcessId(),
+                 isolate_id);
+    WriteChars(filename_.start(), "", 0, false);
+  }
+
   void TraceCompilation(CompilationInfo* info);
   void TraceHydrogen(const char* name, HGraph* graph);
   void TraceLithium(const char* name, LChunk* chunk);
   void TraceLiveRanges(const char* name, LAllocator* allocator);
 
-  static HTracer* Instance() {
-    static SetOncePointer<HTracer> instance;
-    if (!instance.is_set()) {
-      instance.set(new HTracer("hydrogen.cfg"));
-    }
-    return instance.get();
-  }
-
  private:
   class Tag BASE_EMBEDDED {
    public:
@@ -1651,11 +1639,6 @@
     const char* name_;
   };
 
-  explicit HTracer(const char* filename)
-      : filename_(filename), trace_(&string_allocator_), indent_(0) {
-    WriteChars(filename, "", 0, false);
-  }
-
   void TraceLiveRange(LiveRange* range, const char* type, Zone* zone);
   void Trace(const char* name, HGraph* graph, LChunk* chunk);
   void FlushToFile();
@@ -1691,7 +1674,7 @@
     }
   }
 
-  const char* filename_;
+  EmbeddedVector<char, 64> filename_;
   HeapStringAllocator string_allocator_;
   StringStream trace_;
   int indent_;
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index 123383c..d926316 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -52,7 +52,7 @@
 bool CpuFeatures::initialized_ = false;
 #endif
 uint64_t CpuFeatures::supported_ = 0;
-uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
+uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0;
 
 
 ExternalReference ExternalReference::cpu_features() {
@@ -146,7 +146,7 @@
   __ bind(&cpuid);
   __ mov(eax, 1);
   supported_ = (1 << CPUID);
-  { Scope fscope(CPUID);
+  { CpuFeatureScope fscope(&assm, CPUID);
     __ cpuid();
   }
   supported_ = 0;
@@ -169,11 +169,10 @@
 
   typedef uint64_t (*F0)();
   F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
-  supported_ = probe();
-  found_by_runtime_probing_ = supported_;
-  uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
-  supported_ |= os_guarantees;
-  found_by_runtime_probing_ &= ~os_guarantees;
+  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;
 }
@@ -475,7 +474,7 @@
 
 
 void Assembler::cpuid() {
-  ASSERT(CpuFeatures::IsEnabled(CPUID));
+  ASSERT(IsEnabled(CPUID));
   EnsureSpace ensure_space(this);
   EMIT(0x0F);
   EMIT(0xA2);
@@ -697,7 +696,7 @@
 
 
 void Assembler::cmov(Condition cc, Register dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(CMOV));
+  ASSERT(IsEnabled(CMOV));
   EnsureSpace ensure_space(this);
   // Opcode: 0f 40 + cc /r.
   EMIT(0x0F);
@@ -1306,7 +1305,7 @@
 
 
 void Assembler::rdtsc() {
-  ASSERT(CpuFeatures::IsEnabled(RDTSC));
+  ASSERT(IsEnabled(RDTSC));
   EnsureSpace ensure_space(this);
   EMIT(0x0F);
   EMIT(0x31);
@@ -1660,7 +1659,7 @@
 
 
 void Assembler::fisttp_s(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   EMIT(0xDB);
   emit_operand(ecx, adr);
@@ -1668,7 +1667,7 @@
 
 
 void Assembler::fisttp_d(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   EMIT(0xDD);
   emit_operand(ecx, adr);
@@ -1930,7 +1929,7 @@
 
 
 void Assembler::cvttss2si(Register dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF3);
   EMIT(0x0F);
@@ -1940,7 +1939,7 @@
 
 
 void Assembler::cvttsd2si(Register dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -1950,7 +1949,7 @@
 
 
 void Assembler::cvtsd2si(Register dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -1960,7 +1959,7 @@
 
 
 void Assembler::cvtsi2sd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -1970,7 +1969,7 @@
 
 
 void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF3);
   EMIT(0x0F);
@@ -1980,7 +1979,7 @@
 
 
 void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -1990,7 +1989,7 @@
 
 
 void Assembler::addsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2000,7 +1999,7 @@
 
 
 void Assembler::addsd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2010,7 +2009,7 @@
 
 
 void Assembler::mulsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2020,7 +2019,7 @@
 
 
 void Assembler::mulsd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2030,7 +2029,7 @@
 
 
 void Assembler::subsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2040,7 +2039,7 @@
 
 
 void Assembler::divsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2050,7 +2049,7 @@
 
 
 void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2095,7 +2094,7 @@
 
 
 void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2105,7 +2104,7 @@
 
 
 void Assembler::ucomisd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2115,7 +2114,7 @@
 
 
 void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2127,7 +2126,7 @@
 }
 
 void Assembler::movmskpd(Register dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2137,7 +2136,7 @@
 
 
 void Assembler::movmskps(Register dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x0F);
   EMIT(0x50);
@@ -2146,7 +2145,7 @@
 
 
 void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2156,7 +2155,7 @@
 
 
 void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2167,7 +2166,7 @@
 
 
 void Assembler::movaps(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x0F);
   EMIT(0x28);
@@ -2176,7 +2175,7 @@
 
 
 void Assembler::movdqa(const Operand& dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2186,7 +2185,7 @@
 
 
 void Assembler::movdqa(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2196,7 +2195,7 @@
 
 
 void Assembler::movdqu(const Operand& dst, XMMRegister src ) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF3);
   EMIT(0x0F);
@@ -2206,7 +2205,7 @@
 
 
 void Assembler::movdqu(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF3);
   EMIT(0x0F);
@@ -2216,7 +2215,7 @@
 
 
 void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2227,7 +2226,7 @@
 
 
 void Assembler::movntdq(const Operand& dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2260,7 +2259,7 @@
 
 
 void Assembler::movsd(const Operand& dst, XMMRegister src ) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);  // double
   EMIT(0x0F);
@@ -2270,7 +2269,7 @@
 
 
 void Assembler::movsd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);  // double
   EMIT(0x0F);
@@ -2280,7 +2279,7 @@
 
 
 void Assembler::movsd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF2);
   EMIT(0x0F);
@@ -2290,7 +2289,7 @@
 
 
 void Assembler::movss(const Operand& dst, XMMRegister src ) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF3);  // float
   EMIT(0x0F);
@@ -2300,7 +2299,7 @@
 
 
 void Assembler::movss(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF3);  // float
   EMIT(0x0F);
@@ -2310,7 +2309,7 @@
 
 
 void Assembler::movss(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0xF3);
   EMIT(0x0F);
@@ -2320,7 +2319,7 @@
 
 
 void Assembler::movd(XMMRegister dst, const Operand& src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2330,7 +2329,7 @@
 
 
 void Assembler::movd(const Operand& dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2353,7 +2352,7 @@
 
 
 void Assembler::pand(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2363,7 +2362,7 @@
 
 
 void Assembler::pxor(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2373,7 +2372,7 @@
 
 
 void Assembler::por(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2383,7 +2382,7 @@
 
 
 void Assembler::ptest(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2394,7 +2393,7 @@
 
 
 void Assembler::psllq(XMMRegister reg, int8_t shift) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2405,7 +2404,7 @@
 
 
 void Assembler::psllq(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2415,7 +2414,7 @@
 
 
 void Assembler::psrlq(XMMRegister reg, int8_t shift) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2426,7 +2425,7 @@
 
 
 void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2436,7 +2435,7 @@
 
 
 void Assembler::pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  ASSERT(IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2447,7 +2446,7 @@
 
 
 void Assembler::pextrd(const Operand& dst, XMMRegister src, int8_t offset) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
@@ -2459,7 +2458,7 @@
 
 
 void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   EMIT(0x66);
   EMIT(0x0F);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 315bc17..a3da9af 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -505,10 +505,10 @@
 
 
 // CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
 // Example:
-//   if (CpuFeatures::IsSupported(SSE2)) {
-//     CpuFeatures::Scope fscope(SSE2);
+//   if (assembler->IsSupported(SSE2)) {
+//     CpuFeatureScope fscope(assembler, SSE2);
 //     // Generate SSE2 floating point code.
 //   } else {
 //     // Generate standard x87 floating point code.
@@ -530,87 +530,23 @@
     return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
   }
 
-#ifdef DEBUG
-  // Check whether a feature is currently enabled.
-  static bool IsEnabled(CpuFeature f) {
+  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
     ASSERT(initialized_);
-    Isolate* isolate = Isolate::UncheckedCurrent();
-    if (isolate == NULL) {
-      // When no isolate is available, work as if we're running in
-      // release mode.
-      return IsSupported(f);
-    }
-    uint64_t enabled = isolate->enabled_cpu_features();
-    return (enabled & (static_cast<uint64_t>(1) << f)) != 0;
+    return (found_by_runtime_probing_only_ &
+            (static_cast<uint64_t>(1) << f)) != 0;
   }
-#endif
 
-  // Enable a specified feature within a scope.
-  class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
-   public:
-    explicit Scope(CpuFeature f) {
-      uint64_t mask = static_cast<uint64_t>(1) << f;
-      ASSERT(CpuFeatures::IsSupported(f));
-      ASSERT(!Serializer::enabled() ||
-             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
-      isolate_ = Isolate::UncheckedCurrent();
-      old_enabled_ = 0;
-      if (isolate_ != NULL) {
-        old_enabled_ = isolate_->enabled_cpu_features();
-        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
-      }
-    }
-    ~Scope() {
-      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
-      if (isolate_ != NULL) {
-        isolate_->set_enabled_cpu_features(old_enabled_);
-      }
-    }
-
-   private:
-    Isolate* isolate_;
-    uint64_t old_enabled_;
-#else
-
-   public:
-    explicit Scope(CpuFeature f) {}
-#endif
-  };
-
-  class TryForceFeatureScope BASE_EMBEDDED {
-   public:
-    explicit TryForceFeatureScope(CpuFeature f)
-        : old_supported_(CpuFeatures::supported_) {
-      if (CanForce()) {
-        CpuFeatures::supported_ |= (static_cast<uint64_t>(1) << f);
-      }
-    }
-
-    ~TryForceFeatureScope() {
-      if (CanForce()) {
-        CpuFeatures::supported_ = old_supported_;
-      }
-    }
-
-   private:
-    static bool CanForce() {
-      // It's only safe to temporarily force support of CPU features
-      // when there's only a single isolate, which is guaranteed when
-      // the serializer is enabled.
-      return Serializer::enabled();
-    }
-
-    const uint64_t old_supported_;
-  };
+  static bool IsSafeForSnapshot(CpuFeature f) {
+    return (IsSupported(f) &&
+            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
+  }
 
  private:
 #ifdef DEBUG
   static bool initialized_;
 #endif
   static uint64_t supported_;
-  static uint64_t found_by_runtime_probing_;
+  static uint64_t found_by_runtime_probing_only_;
 
   friend class ExternalReference;
   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index e3b2b7b..7ce211d 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -643,6 +643,8 @@
 
 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
   // TODO(kasperl): Do we need to save/restore the XMM registers too?
+  // TODO(mvstanton): We should save these regs, do this in a future
+  // checkin.
 
   // For now, we are relying on the fact that Runtime::NotifyOSR
   // doesn't do any garbage collection which allows us to save/restore
@@ -1792,12 +1794,6 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
-  CpuFeatures::TryForceFeatureScope scope(SSE2);
-  if (!CpuFeatures::IsSupported(SSE2) && FLAG_debug_code) {
-    __ Abort("Unreachable code: Cannot optimize without SSE2 support.");
-    return;
-  }
-
   // Get the loop depth of the stack guard check. This is recorded in
   // a test(eax, depth) instruction right after the call.
   Label stack_check;
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 1329a3e..1b27540 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -653,7 +653,7 @@
   // restore them.
   __ pushad();
   if (save_doubles_ == kSaveFPRegs) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm, SSE2);
     __ sub(esp, Immediate(kDoubleSize * XMMRegister::kNumRegisters));
     for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
       XMMRegister reg = XMMRegister::from_code(i);
@@ -670,7 +670,7 @@
       ExternalReference::store_buffer_overflow_function(masm->isolate()),
       argument_count);
   if (save_doubles_ == kSaveFPRegs) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm, SSE2);
     for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
       XMMRegister reg = XMMRegister::from_code(i);
       __ movdbl(reg, Operand(esp, i * kDoubleSize));
@@ -820,7 +820,7 @@
   __ cmp(scratch2, Immediate(kResultIsZeroExponent));
   __ j(above, &done);
   if (use_sse3) {
-    CpuFeatures::Scope scope(SSE3);
+    CpuFeatureScope scope(masm, SSE3);
     // Check whether the exponent is too big for a 64 bit signed integer.
     static const uint32_t kTooBigExponent = 63;
     __ cmp(scratch2, Immediate(kTooBigExponent));
@@ -1183,7 +1183,7 @@
     __ bind(&heapnumber_allocated);
   }
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(masm, SSE2);
     __ cvtsi2sd(xmm0, ecx);
     __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
   } else {
@@ -1568,7 +1568,7 @@
         } else {
           ASSERT_EQ(Token::SHL, op);
           if (CpuFeatures::IsSupported(SSE2)) {
-            CpuFeatures::Scope use_sse2(SSE2);
+            CpuFeatureScope use_sse2(masm, SSE2);
             __ cvtsi2sd(xmm0, left);
             __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
           } else {
@@ -1612,7 +1612,7 @@
         }
         __ AllocateHeapNumber(ecx, ebx, no_reg, slow);
         if (CpuFeatures::IsSupported(SSE2)) {
-          CpuFeatures::Scope use_sse2(SSE2);
+          CpuFeatureScope use_sse2(masm, SSE2);
           FloatingPointHelper::LoadSSE2Smis(masm, ebx);
           switch (op) {
             case Token::ADD: __ addsd(xmm0, xmm1); break;
@@ -1777,7 +1777,7 @@
       Label not_floats;
       Label not_int32;
       if (CpuFeatures::IsSupported(SSE2)) {
-        CpuFeatures::Scope use_sse2(SSE2);
+        CpuFeatureScope use_sse2(masm, SSE2);
         // It could be that only SMIs have been seen at either the left
         // or the right operand. For precise type feedback, patch the IC
         // again if this changes.
@@ -1908,7 +1908,7 @@
         }
         // Store the result in the HeapNumber and return.
         if (CpuFeatures::IsSupported(SSE2)) {
-          CpuFeatures::Scope use_sse2(SSE2);
+          CpuFeatureScope use_sse2(masm, SSE2);
           __ cvtsi2sd(xmm0, ebx);
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
         } else {
@@ -1998,7 +1998,7 @@
     case Token::DIV: {
       Label not_floats;
       if (CpuFeatures::IsSupported(SSE2)) {
-        CpuFeatures::Scope use_sse2(SSE2);
+        CpuFeatureScope use_sse2(masm, SSE2);
 
         // It could be that only SMIs have been seen at either the left
         // or the right operand. For precise type feedback, patch the IC
@@ -2125,7 +2125,7 @@
         }
         // Store the result in the HeapNumber and return.
         if (CpuFeatures::IsSupported(SSE2)) {
-          CpuFeatures::Scope use_sse2(SSE2);
+          CpuFeatureScope use_sse2(masm, SSE2);
           __ cvtsi2sd(xmm0, ebx);
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
         } else {
@@ -2205,7 +2205,7 @@
     case Token::DIV: {
       Label not_floats;
       if (CpuFeatures::IsSupported(SSE2)) {
-        CpuFeatures::Scope use_sse2(SSE2);
+        CpuFeatureScope use_sse2(masm, SSE2);
         FloatingPointHelper::LoadSSE2Operands(masm, &not_floats);
 
         switch (op_) {
@@ -2306,7 +2306,7 @@
         }
         // Store the result in the HeapNumber and return.
         if (CpuFeatures::IsSupported(SSE2)) {
-          CpuFeatures::Scope use_sse2(SSE2);
+          CpuFeatureScope use_sse2(masm, SSE2);
           __ cvtsi2sd(xmm0, ebx);
           __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
         } else {
@@ -2476,9 +2476,9 @@
 
     __ bind(&loaded);
   } else {  // UNTAGGED.
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm, SSE2);
     if (CpuFeatures::IsSupported(SSE4_1)) {
-      CpuFeatures::Scope sse4_scope(SSE4_1);
+      CpuFeatureScope sse4_scope(masm, SSE4_1);
       __ pextrd(edx, xmm1, 0x1);  // copy xmm1[63..32] to edx.
     } else {
       __ pshufd(xmm0, xmm1, 0x1);
@@ -2549,7 +2549,7 @@
     __ fstp(0);
     __ ret(kPointerSize);
   } else {  // UNTAGGED.
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm, SSE2);
     __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
     __ Ret();
   }
@@ -2562,7 +2562,7 @@
   if (tagged) {
     __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
   } else {  // UNTAGGED.
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm, SSE2);
     __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
     __ sub(esp, Immediate(kDoubleSize));
     __ movdbl(Operand(esp, 0), xmm1);
@@ -2577,7 +2577,7 @@
   if (tagged) {
     __ ret(kPointerSize);
   } else {  // UNTAGGED.
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm, SSE2);
     __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
     __ Ret();
 
@@ -2610,7 +2610,7 @@
         ExternalReference(RuntimeFunction(), masm->isolate());
     __ TailCallExternalReference(runtime, 1, 1);
   } else {  // UNTAGGED.
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm, SSE2);
     __ bind(&runtime_call_clear_stack);
     __ bind(&runtime_call);
     __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
@@ -2776,7 +2776,7 @@
 
   // Get the untagged integer version of the edx heap number in ecx.
   if (left_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(masm, SSE2);
     ConvertHeapNumberToInt32(masm, edx, conversion_failure);
   } else {
     IntegerConvert(masm, edx, use_sse3, conversion_failure);
@@ -2811,7 +2811,7 @@
   // Get the untagged integer version of the eax heap number in ecx.
 
   if (right_type == BinaryOpIC::INT32 && CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(masm, SSE2);
     ConvertHeapNumberToInt32(masm, eax, conversion_failure);
   } else {
     IntegerConvert(masm, eax, use_sse3, conversion_failure);
@@ -3019,7 +3019,7 @@
 
 
 void MathPowStub::Generate(MacroAssembler* masm) {
-  CpuFeatures::Scope use_sse2(SSE2);
+  CpuFeatureScope use_sse2(masm, SSE2);
   Factory* factory = masm->isolate()->factory();
   const Register exponent = eax;
   const Register base = edx;
@@ -3363,7 +3363,7 @@
   Register value = eax;
   Register scratch = ebx;
 
-  if (kind() == Code::KEYED_LOAD_IC) {
+  if (kind() == Code::KEYED_STORE_IC) {
     __ cmp(ecx, Immediate(masm->isolate()->factory()->length_string()));
     __ j(not_equal, &miss);
   }
@@ -4407,7 +4407,7 @@
                         FixedArray::kHeaderSize));
     __ JumpIfSmi(probe, not_found);
     if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope fscope(SSE2);
+      CpuFeatureScope fscope(masm, SSE2);
       __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
       __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
       __ ucomisd(xmm0, xmm1);
@@ -4667,8 +4667,8 @@
   Label non_number_comparison;
   Label unordered;
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope use_sse2(SSE2);
-    CpuFeatures::Scope use_cmov(CMOV);
+    CpuFeatureScope use_sse2(masm, SSE2);
+    CpuFeatureScope use_cmov(masm, CMOV);
 
     FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
     __ ucomisd(xmm0, xmm1);
@@ -6890,8 +6890,8 @@
   // Inlining the double comparison and falling back to the general compare
   // stub if NaN is involved or SSE2 or CMOV is unsupported.
   if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) {
-    CpuFeatures::Scope scope1(SSE2);
-    CpuFeatures::Scope scope2(CMOV);
+    CpuFeatureScope scope1(masm, SSE2);
+    CpuFeatureScope scope2(masm, CMOV);
 
     // Load left and right operand.
     Label done, left, left_smi, right_smi;
@@ -7233,14 +7233,14 @@
 // the property. This function may return false negatives, so miss_label
 // must always call a backup property check that is complete.
 // This function is safe to call if the receiver has fast properties.
-// Name must be an internalized string and receiver must be a heap object.
-void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
-                                                        Label* miss,
-                                                        Label* done,
-                                                        Register properties,
-                                                        Handle<String> name,
-                                                        Register r0) {
-  ASSERT(name->IsInternalizedString());
+// Name must be a unique name and receiver must be a heap object.
+void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+                                                      Label* miss,
+                                                      Label* done,
+                                                      Register properties,
+                                                      Handle<Name> name,
+                                                      Register r0) {
+  ASSERT(name->IsUniqueName());
 
   // If names of slots in range from 1 to kProbes - 1 for the hash value are
   // not equal to the name and kProbes-th slot is not used (its name is the
@@ -7255,10 +7255,10 @@
     __ dec(index);
     __ and_(index,
             Immediate(Smi::FromInt(name->Hash() +
-                                   StringDictionary::GetProbeOffset(i))));
+                                   NameDictionary::GetProbeOffset(i))));
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ lea(index, Operand(index, index, times_2, 0));  // index *= 3.
     Register entity_name = r0;
     // Having undefined at this place means the name is not contained.
@@ -7269,26 +7269,26 @@
     __ j(equal, done);
 
     // Stop if found the property.
-    __ cmp(entity_name, Handle<String>(name));
+    __ cmp(entity_name, Handle<Name>(name));
     __ j(equal, miss);
 
-    Label the_hole;
+    Label good;
     // Check for the hole and skip.
     __ cmp(entity_name, masm->isolate()->factory()->the_hole_value());
-    __ j(equal, &the_hole, Label::kNear);
+    __ j(equal, &good, Label::kNear);
 
-    // Check if the entry name is not an internalized string.
+    // Check if the entry name is not a unique name.
     __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
     __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
               kIsInternalizedMask);
-    __ j(zero, miss);
-    __ bind(&the_hole);
+    __ j(not_zero, &good);
+    __ cmpb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+            static_cast<uint8_t>(SYMBOL_TYPE));
+    __ j(not_equal, miss);
+    __ bind(&good);
   }
 
-  StringDictionaryLookupStub stub(properties,
-                                  r0,
-                                  r0,
-                                  StringDictionaryLookupStub::NEGATIVE_LOOKUP);
+  NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP);
   __ push(Immediate(Handle<Object>(name)));
   __ push(Immediate(name->Hash()));
   __ CallStub(&stub);
@@ -7298,23 +7298,23 @@
 }
 
 
-// Probe the string dictionary in the |elements| register. Jump to the
+// Probe the name dictionary in the |elements| register. Jump to the
 // |done| label if a property with the given name is found leaving the
 // index into the dictionary in |r0|. Jump to the |miss| label
 // otherwise.
-void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
-                                                        Label* miss,
-                                                        Label* done,
-                                                        Register elements,
-                                                        Register name,
-                                                        Register r0,
-                                                        Register r1) {
+void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
+                                                      Label* miss,
+                                                      Label* done,
+                                                      Register elements,
+                                                      Register name,
+                                                      Register r0,
+                                                      Register r1) {
   ASSERT(!elements.is(r0));
   ASSERT(!elements.is(r1));
   ASSERT(!name.is(r0));
   ASSERT(!name.is(r1));
 
-  __ AssertString(name);
+  __ AssertName(name);
 
   __ mov(r1, FieldOperand(elements, kCapacityOffset));
   __ shr(r1, kSmiTagSize);  // convert smi to int
@@ -7325,15 +7325,15 @@
   // cover ~93% of loads from dictionaries.
   for (int i = 0; i < kInlinedProbes; i++) {
     // Compute the masked index: (hash + i + i * i) & mask.
-    __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
-    __ shr(r0, String::kHashShift);
+    __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
+    __ shr(r0, Name::kHashShift);
     if (i > 0) {
-      __ add(r0, Immediate(StringDictionary::GetProbeOffset(i)));
+      __ add(r0, Immediate(NameDictionary::GetProbeOffset(i)));
     }
     __ and_(r0, r1);
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ lea(r0, Operand(r0, r0, times_2, 0));  // r0 = r0 * 3
 
     // Check if the key is identical to the name.
@@ -7344,13 +7344,10 @@
     __ j(equal, done);
   }
 
-  StringDictionaryLookupStub stub(elements,
-                                  r1,
-                                  r0,
-                                  POSITIVE_LOOKUP);
+  NameDictionaryLookupStub stub(elements, r1, r0, POSITIVE_LOOKUP);
   __ push(name);
-  __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
-  __ shr(r0, String::kHashShift);
+  __ mov(r0, FieldOperand(name, Name::kHashFieldOffset));
+  __ shr(r0, Name::kHashShift);
   __ push(r0);
   __ CallStub(&stub);
 
@@ -7360,7 +7357,7 @@
 }
 
 
-void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
+void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
   // we cannot call anything that could cause a GC from this stub.
   // Stack frame on entry:
@@ -7368,7 +7365,7 @@
   //  esp[1 * kPointerSize]: key's hash.
   //  esp[2 * kPointerSize]: key.
   // Registers:
-  //  dictionary_: StringDictionary to probe.
+  //  dictionary_: NameDictionary to probe.
   //  result_: used as scratch.
   //  index_: will hold an index of entry if lookup is successful.
   //          might alias with result_.
@@ -7393,12 +7390,12 @@
     // Compute the masked index: (hash + i + i * i) & mask.
     __ mov(scratch, Operand(esp, 2 * kPointerSize));
     if (i > 0) {
-      __ add(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
+      __ add(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
     }
     __ and_(scratch, Operand(esp, 0));
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ lea(index_, Operand(scratch, scratch, times_2, 0));  // index *= 3.
 
     // Having undefined at this place means the name is not contained.
@@ -7415,15 +7412,20 @@
     __ j(equal, &in_dictionary);
 
     if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
-      // If we hit a key that is not an internalized string during negative
+      // If we hit a key that is not a unique name during negative
       // lookup we have to bailout as this key might be equal to the
       // key we are looking for.
 
-      // Check if the entry name is not an internalized string.
+      // Check if the entry name is not a unique name.
+      Label cont;
       __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
       __ test_b(FieldOperand(scratch, Map::kInstanceTypeOffset),
                 kIsInternalizedMask);
-      __ j(zero, &maybe_in_dictionary);
+      __ j(not_zero, &cont);
+      __ cmpb(FieldOperand(scratch, Map::kInstanceTypeOffset),
+              static_cast<uint8_t>(SYMBOL_TYPE));
+      __ j(not_equal, &maybe_in_dictionary);
+      __ bind(&cont);
     }
   }
 
@@ -7514,11 +7516,9 @@
 
 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
     Isolate* isolate) {
-  StoreBufferOverflowStub stub1(kDontSaveFPRegs);
-  stub1.GetCode(isolate)->set_is_pregenerated(true);
-
-  CpuFeatures::TryForceFeatureScope scope(SSE2);
-  if (CpuFeatures::IsSupported(SSE2)) {
+  StoreBufferOverflowStub stub(kDontSaveFPRegs);
+  stub.GetCode(isolate)->set_is_pregenerated(true);
+  if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
     StoreBufferOverflowStub stub2(kSaveFPRegs);
     stub2.GetCode(isolate)->set_is_pregenerated(true);
   }
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index e6bb38a..c2ae5f0 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -64,7 +64,9 @@
 class StoreBufferOverflowStub: public PlatformCodeStub {
  public:
   explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
-      : save_doubles_(save_fp) { }
+      : save_doubles_(save_fp) {
+    ASSERT(CpuFeatures::IsSafeForSnapshot(SSE2) || save_fp == kDontSaveFPRegs);
+  }
 
   void Generate(MacroAssembler* masm);
 
@@ -320,14 +322,14 @@
 };
 
 
-class StringDictionaryLookupStub: public PlatformCodeStub {
+class NameDictionaryLookupStub: public PlatformCodeStub {
  public:
   enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
 
-  StringDictionaryLookupStub(Register dictionary,
-                             Register result,
-                             Register index,
-                             LookupMode mode)
+  NameDictionaryLookupStub(Register dictionary,
+                           Register result,
+                           Register index,
+                           LookupMode mode)
       : dictionary_(dictionary), result_(result), index_(index), mode_(mode) { }
 
   void Generate(MacroAssembler* masm);
@@ -336,7 +338,7 @@
                                      Label* miss,
                                      Label* done,
                                      Register properties,
-                                     Handle<String> name,
+                                     Handle<Name> name,
                                      Register r0);
 
   static void GeneratePositiveLookup(MacroAssembler* masm,
@@ -354,14 +356,14 @@
   static const int kTotalProbes = 20;
 
   static const int kCapacityOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kCapacityIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kCapacityIndex * kPointerSize;
 
   static const int kElementsStartOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
 
-  Major MajorKey() { return StringDictionaryLookup; }
+  Major MajorKey() { return NameDictionaryLookup; }
 
   int MinorKey() {
     return DictionaryBits::encode(dictionary_.code()) |
@@ -397,6 +399,7 @@
         regs_(object,   // An input reg.
               address,  // An input reg.
               value) {  // One scratch reg.
+    ASSERT(CpuFeatures::IsSafeForSnapshot(SSE2) || fp_mode == kDontSaveFPRegs);
   }
 
   enum Mode {
@@ -540,7 +543,7 @@
       if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->push(eax);
       if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->push(edx);
       if (mode == kSaveFPRegs) {
-        CpuFeatures::Scope scope(SSE2);
+        CpuFeatureScope scope(masm, SSE2);
         masm->sub(esp,
                   Immediate(kDoubleSize * (XMMRegister::kNumRegisters - 1)));
         // Save all XMM registers except XMM0.
@@ -554,7 +557,7 @@
     inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
                                            SaveFPRegsMode mode) {
       if (mode == kSaveFPRegs) {
-        CpuFeatures::Scope scope(SSE2);
+        CpuFeatureScope scope(masm, SSE2);
         // Restore all XMM registers except XMM0.
         for (int i = XMMRegister::kNumRegisters - 1; i > 0; i--) {
           XMMRegister reg = XMMRegister::from_code(i);
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 5368811..b3fce81 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -114,7 +114,7 @@
   // esp[1 * kPointerSize]: raw double input
   // esp[0 * kPointerSize]: return address
   {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(&masm, SSE2);
     XMMRegister input = xmm1;
     XMMRegister result = xmm2;
     __ movdbl(input, Operand(esp, 1 * kPointerSize));
@@ -154,7 +154,7 @@
   // esp[0 * kPointerSize]: return address
   // Move double input into registers.
   {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(&masm, SSE2);
     __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
     __ sqrtsd(xmm0, xmm0);
     __ movdbl(Operand(esp, 1 * kPointerSize), xmm0);
@@ -214,7 +214,7 @@
     __ bind(&ok);
   }
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope enable(SSE2);
+    CpuFeatureScope enable(&masm, SSE2);
     __ push(edi);
     __ push(esi);
     stack_offset += 2 * kPointerSize;
@@ -479,7 +479,7 @@
       ExternalReference::address_of_the_hole_nan();
   XMMRegister the_hole_nan = xmm1;
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(masm, SSE2);
     __ movdbl(the_hole_nan,
               Operand::StaticVariable(canonical_the_hole_nan_reference));
   }
@@ -504,7 +504,7 @@
   // Normal smi, convert it to double and store.
   __ SmiUntag(ebx);
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope fscope(SSE2);
+    CpuFeatureScope fscope(masm, SSE2);
     __ cvtsi2sd(xmm0, ebx);
     __ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
               xmm0);
@@ -525,7 +525,7 @@
   }
 
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(masm, SSE2);
     __ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
               the_hole_nan);
   } else {
@@ -635,7 +635,7 @@
   __ AllocateHeapNumber(edx, esi, no_reg, &gc_required);
   // edx: new heap number
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope fscope(SSE2);
+    CpuFeatureScope fscope(masm, SSE2);
     __ movdbl(xmm0,
               FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize));
     __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0);
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc
index e27ea4c..667f131 100644
--- a/src/ia32/deoptimizer-ia32.cc
+++ b/src/ia32/deoptimizer-ia32.cc
@@ -643,119 +643,6 @@
 }
 
 
-void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
-                                              int frame_index) {
-  Builtins* builtins = isolate_->builtins();
-  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
-  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
-  unsigned height = iterator->Next();
-  unsigned height_in_bytes = height * kPointerSize;
-  if (trace_) {
-    PrintF("  translating construct stub => height=%d\n", height_in_bytes);
-  }
-
-  unsigned fixed_frame_size = 7 * kPointerSize;
-  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
-
-  // Allocate and store the output frame description.
-  FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, function);
-  output_frame->SetFrameType(StackFrame::CONSTRUCT);
-
-  // Construct stub can not be topmost or bottommost.
-  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
-  ASSERT(output_[frame_index] == NULL);
-  output_[frame_index] = output_frame;
-
-  // The top address of the frame is computed from the previous
-  // frame's top and this frame's size.
-  uint32_t top_address;
-  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
-  output_frame->SetTop(top_address);
-
-  // Compute the incoming parameter translation.
-  int parameter_count = height;
-  unsigned output_offset = output_frame_size;
-  for (int i = 0; i < parameter_count; ++i) {
-    output_offset -= kPointerSize;
-    DoTranslateCommand(iterator, frame_index, output_offset);
-  }
-
-  // Read caller's PC from the previous frame.
-  output_offset -= kPointerSize;
-  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
-  output_frame->SetFrameSlot(output_offset, callers_pc);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
-           top_address + output_offset, output_offset, callers_pc);
-  }
-
-  // Read caller's FP from the previous frame, and set this frame's FP.
-  output_offset -= kPointerSize;
-  intptr_t value = output_[frame_index - 1]->GetFp();
-  output_frame->SetFrameSlot(output_offset, value);
-  intptr_t fp_value = top_address + output_offset;
-  output_frame->SetFp(fp_value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
-           fp_value, output_offset, value);
-  }
-
-  // The context can be gotten from the previous frame.
-  output_offset -= kPointerSize;
-  value = output_[frame_index - 1]->GetContext();
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; context\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // A marker value is used in place of the function.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // The output frame reflects a JSConstructStubGeneric frame.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(construct_stub);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; code object\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // Number of incoming arguments.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
-           top_address + output_offset, output_offset, value, height - 1);
-  }
-
-  // The newly allocated object was passed as receiver in the artificial
-  // constructor stub environment created by HEnvironment::CopyForInlining().
-  output_offset -= kPointerSize;
-  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  ASSERT(0 == output_offset);
-
-  uint32_t pc = reinterpret_cast<uint32_t>(
-      construct_stub->instruction_start() +
-      isolate_->heap()->construct_stub_deopt_pc_offset()->value());
-  output_frame->SetPc(pc);
-}
-
-
 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
                                    int frame_index) {
   BailoutId node_id = BailoutId(iterator->Next());
@@ -977,7 +864,7 @@
                               XMMRegister::kNumAllocatableRegisters;
   __ sub(esp, Immediate(kDoubleRegsSize));
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
       XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
       int offset = i * kDoubleSize;
@@ -1032,7 +919,7 @@
 
   int double_regs_offset = FrameDescription::double_registers_offset();
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     // Fill in the double input registers.
     for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
       int dst_offset = i * kDoubleSize + double_regs_offset;
@@ -1133,7 +1020,7 @@
 
   // In case of OSR or a failed STUB, we have to restore the XMM registers.
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
       XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
       int src_offset = i * kDoubleSize + double_regs_offset;
diff --git a/src/ia32/frames-ia32.h b/src/ia32/frames-ia32.h
index 5bd102a..c59b166 100644
--- a/src/ia32/frames-ia32.h
+++ b/src/ia32/frames-ia32.h
@@ -114,14 +114,30 @@
 
 class ArgumentsAdaptorFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+
   static const int kFrameSize =
       StandardFrameConstants::kFixedFrameSize + kPointerSize;
 };
 
 
+class ConstructFrameConstants : public AllStatic {
+ public:
+  // FP-relative.
+  static const int kImplicitReceiverOffset = -5 * kPointerSize;
+  static const int kConstructorOffset      = kMinInt;
+  static const int kLengthOffset           = -4 * kPointerSize;
+  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+
+  static const int kFrameSize =
+      StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
+};
+
+
 class InternalFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
 };
 
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 1428dfe..25c5e65 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1601,8 +1601,6 @@
           }
           break;
         }
-        // Fall through.
-      case ObjectLiteral::Property::PROTOTYPE:
         __ push(Operand(esp, 0));  // Duplicate receiver.
         VisitForStackValue(key);
         VisitForStackValue(value);
@@ -1613,6 +1611,15 @@
           __ Drop(3);
         }
         break;
+      case ObjectLiteral::Property::PROTOTYPE:
+        __ push(Operand(esp, 0));  // Duplicate receiver.
+        VisitForStackValue(value);
+        if (property->emit_store()) {
+          __ CallRuntime(Runtime::kSetPrototype, 2);
+        } else {
+          __ Drop(2);
+        }
+        break;
       case ObjectLiteral::Property::GETTER:
         accessor_table.lookup(key)->second->getter = value;
         break;
@@ -2987,7 +2994,7 @@
   // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
   // This is implemented on both SSE2 and FPU.
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope fscope(SSE2);
+    CpuFeatureScope fscope(masm(), SSE2);
     __ mov(ebx, Immediate(0x49800000));  // 1.0 x 2^20 as single.
     __ movd(xmm1, ebx);
     __ movd(xmm0, eax);
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 428d830..964db0e 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -60,11 +60,11 @@
 
 // Generated code falls through if the receiver is a regular non-global
 // JS object with slow properties and no interceptors.
-static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
-                                                  Register receiver,
-                                                  Register r0,
-                                                  Register r1,
-                                                  Label* miss) {
+static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm,
+                                                Register receiver,
+                                                Register r0,
+                                                Register r1,
+                                                Label* miss) {
   // Register usage:
   //   receiver: holds the receiver on entry and is unchanged.
   //   r0: used to hold receiver instance type.
@@ -127,21 +127,21 @@
   Label done;
 
   // Probe the dictionary.
-  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
-                                                     miss_label,
-                                                     &done,
-                                                     elements,
-                                                     name,
-                                                     r0,
-                                                     r1);
+  NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                   miss_label,
+                                                   &done,
+                                                   elements,
+                                                   name,
+                                                   r0,
+                                                   r1);
 
   // If probing finds an entry in the dictionary, r0 contains the
   // index into the dictionary. Check that the value is a normal
   // property.
   __ bind(&done);
   const int kElementsStartOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
   const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
   __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag),
           Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize));
@@ -182,21 +182,21 @@
 
 
   // Probe the dictionary.
-  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
-                                                     miss_label,
-                                                     &done,
-                                                     elements,
-                                                     name,
-                                                     r0,
-                                                     r1);
+  NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                   miss_label,
+                                                   &done,
+                                                   elements,
+                                                   name,
+                                                   r0,
+                                                   r1);
 
   // If probing finds an entry in the dictionary, r0 contains the
   // index into the dictionary. Check that the value is a normal
   // property that is not read only.
   __ bind(&done);
   const int kElementsStartOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
   const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
   const int kTypeAndReadOnlyMask =
       (PropertyDetails::TypeField::kMask |
@@ -292,31 +292,36 @@
 }
 
 
-// Checks whether a key is an array index string or an internalized string.
-// Falls through if the key is an internalized string.
-static void GenerateKeyStringCheck(MacroAssembler* masm,
-                                   Register key,
-                                   Register map,
-                                   Register hash,
-                                   Label* index_string,
-                                   Label* not_internalized) {
+// Checks whether a key is an array index string or a unique name.
+// Falls through if the key is a unique name.
+static void GenerateKeyNameCheck(MacroAssembler* masm,
+                                 Register key,
+                                 Register map,
+                                 Register hash,
+                                 Label* index_string,
+                                 Label* not_unique) {
   // Register use:
   //   key - holds the key and is unchanged. Assumed to be non-smi.
   // Scratch registers:
   //   map - used to hold the map of the key.
   //   hash - used to hold the hash of the key.
-  __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
-  __ j(above_equal, not_internalized);
+  Label unique;
+  __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
+  __ j(above, not_unique);
+  STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
+  __ j(equal, &unique);
 
   // Is the string an array index, with cached numeric value?
-  __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
-  __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
+  __ mov(hash, FieldOperand(key, Name::kHashFieldOffset));
+  __ test(hash, Immediate(Name::kContainsCachedArrayIndexMask));
   __ j(zero, index_string);
 
   // Is the string internalized?
   STATIC_ASSERT(kInternalizedTag != 0);
   __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsInternalizedMask);
-  __ j(zero, not_internalized);
+  __ j(zero, not_unique);
+
+  __ bind(&unique);
 }
 
 
@@ -403,11 +408,11 @@
   //  -- edx    : receiver
   //  -- esp[0] : return address
   // -----------------------------------
-  Label slow, check_string, index_smi, index_string, property_array_property;
+  Label slow, check_name, index_smi, index_name, property_array_property;
   Label probe_dictionary, check_number_dictionary;
 
   // Check that the key is a smi.
-  __ JumpIfNotSmi(ecx, &check_string);
+  __ JumpIfNotSmi(ecx, &check_name);
   __ bind(&index_smi);
   // Now the key is known to be a smi. This place is also jumped to from
   // where a numeric string is converted to a smi.
@@ -458,8 +463,8 @@
   __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
   GenerateRuntimeGetProperty(masm);
 
-  __ bind(&check_string);
-  GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow);
+  __ bind(&check_name);
+  GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow);
 
   GenerateKeyedLoadReceiverCheck(
       masm, edx, eax, Map::kHasNamedInterceptor, &slow);
@@ -568,7 +573,7 @@
   __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
   __ ret(0);
 
-  __ bind(&index_string);
+  __ bind(&index_name);
   __ IndexFromHash(ebx, ecx);
   // Now jump to the place where smi keys are handled.
   __ jmp(&index_smi);
@@ -1016,7 +1021,7 @@
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
 
-  GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
 
   // eax: elements
   // Search the dictionary placing the result in edi.
@@ -1132,11 +1137,11 @@
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
 
   Label do_call, slow_call, slow_load, slow_reload_receiver;
-  Label check_number_dictionary, check_string, lookup_monomorphic_cache;
-  Label index_smi, index_string;
+  Label check_number_dictionary, check_name, lookup_monomorphic_cache;
+  Label index_smi, index_name;
 
   // Check that the key is a smi.
-  __ JumpIfNotSmi(ecx, &check_string);
+  __ JumpIfNotSmi(ecx, &check_name);
 
   __ bind(&index_smi);
   // Now the key is known to be a smi. This place is also jumped to from
@@ -1195,10 +1200,10 @@
   __ mov(edi, eax);
   __ jmp(&do_call);
 
-  __ bind(&check_string);
-  GenerateKeyStringCheck(masm, ecx, eax, ebx, &index_string, &slow_call);
+  __ bind(&check_name);
+  GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow_call);
 
-  // The key is known to be an internalized string.
+  // The key is known to be a unique name.
   // If the receiver is a regular JS object with slow properties then do
   // a quick inline probe of the receiver's dictionary.
   // Otherwise do the monomorphic cache probe.
@@ -1224,14 +1229,14 @@
   __ bind(&slow_call);
   // This branch is taken if:
   // - the receiver requires boxing or access check,
-  // - the key is neither smi nor an internalized string,
+  // - the key is neither smi nor a unique name,
   // - the value loaded is not a function,
   // - there is hope that the runtime will create a monomorphic call stub
   //   that will get fetched next time.
   __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
   GenerateMiss(masm, argc);
 
-  __ bind(&index_string);
+  __ bind(&index_name);
   __ IndexFromHash(ebx, ecx);
   // Now jump to the place where smi keys are handled.
   __ jmp(&index_smi);
@@ -1276,10 +1281,10 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
 
-  // Check if the name is a string.
+  // Check if the name is really a name.
   Label miss;
   __ JumpIfSmi(ecx, &miss);
-  Condition cond = masm->IsObjectStringType(ecx, eax, eax);
+  Condition cond = masm->IsObjectNameType(ecx, eax, eax);
   __ j(NegateCondition(cond), &miss);
   CallICBase::GenerateNormal(masm, argc);
   __ bind(&miss);
@@ -1296,7 +1301,8 @@
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(
-      Code::LOAD_IC, MONOMORPHIC, Code::HANDLER_FRAGMENT);
+      Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
+      Code::NORMAL, Code::LOAD_IC);
   Isolate::Current()->stub_cache()->GenerateProbe(
       masm, flags, edx, ecx, ebx, eax);
 
@@ -1313,7 +1319,7 @@
   // -----------------------------------
   Label miss;
 
-  GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
 
   // eax: elements
   // Search the dictionary placing the result in eax.
@@ -1437,7 +1443,7 @@
 
   Label miss, restore_miss;
 
-  GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, edx, ebx, edi, &miss);
 
   // A lot of registers are needed for storing to slow case
   // objects. Push and restore receiver but rely on
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 0f2d32b..7ce2f2d 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -40,6 +40,12 @@
 namespace internal {
 
 
+static SaveFPRegsMode GetSaveFPRegsMode() {
+  // We don't need to save floating point regs when generating the snapshot
+  return CpuFeatures::IsSafeForSnapshot(SSE2) ? kSaveFPRegs : kDontSaveFPRegs;
+}
+
+
 // When invoking builtins, we need to record the safepoint in the middle of
 // the invoke instruction sequence generated by the macro assembler.
 class SafepointGenerator : public CallWrapper {
@@ -260,7 +266,7 @@
 
     if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
       Comment(";;; Save clobbered callee double registers");
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       int count = 0;
       BitVector* doubles = chunk()->allocated_double_registers();
       BitVector::Iterator save_iterator(doubles);
@@ -1695,8 +1701,8 @@
     int32_t lower = static_cast<int32_t>(int_val);
     int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
     if (CpuFeatures::IsSupported(SSE4_1)) {
-      CpuFeatures::Scope scope1(SSE2);
-      CpuFeatures::Scope scope2(SSE4_1);
+      CpuFeatureScope scope1(masm(), SSE2);
+      CpuFeatureScope scope2(masm(), SSE4_1);
       if (lower != 0) {
         __ Set(temp, Immediate(lower));
         __ movd(res, Operand(temp));
@@ -1708,7 +1714,7 @@
         __ pinsrd(res, Operand(temp), 1);
       }
     } else {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       __ Set(temp, Immediate(upper));
       __ movd(res, Operand(temp));
       __ psllq(res, 32);
@@ -1871,7 +1877,7 @@
 
 
 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   ASSERT(left->Equals(instr->result()));
@@ -1933,7 +1939,7 @@
 
 
 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   XMMRegister left = ToDoubleRegister(instr->left());
   XMMRegister right = ToDoubleRegister(instr->right());
   XMMRegister result = ToDoubleRegister(instr->result());
@@ -2018,7 +2024,7 @@
 void LCodeGen::DoBranch(LBranch* instr) {
   int true_block = chunk_->LookupDestination(instr->true_block_id());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
 
   Representation r = instr->hydrogen()->value()->representation();
   if (r.IsInteger32()) {
@@ -2188,7 +2194,7 @@
     EmitGoto(next_block);
   } else {
     if (instr->is_double()) {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       // Don't base result on EFLAGS when a NaN is involved. Instead
       // jump to the false block.
       __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
@@ -2706,7 +2712,7 @@
   }
   if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
     ASSERT(NeedsEagerFrame());
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     BitVector* doubles = chunk()->allocated_double_registers();
     BitVector::Iterator save_iterator(doubles);
     int count = 0;
@@ -2847,7 +2853,7 @@
                               offset,
                               value,
                               temp,
-                              kSaveFPRegs,
+                              GetSaveFPRegsMode(),
                               EMIT_REMEMBERED_SET,
                               check_needed);
   }
@@ -3119,7 +3125,7 @@
       instr->additional_index()));
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
     if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       XMMRegister result(ToDoubleRegister(instr->result()));
       __ movss(result, operand);
       __ cvtss2sd(result, result);
@@ -3129,7 +3135,7 @@
     }
   } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
     if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       __ movdbl(ToDoubleRegister(instr->result()), operand);
     } else {
       __ fld_d(operand);
@@ -3223,7 +3229,7 @@
       FixedDoubleArray::kHeaderSize - kHeapObjectTag,
       instr->additional_index());
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     XMMRegister result = ToDoubleRegister(instr->result());
     __ movdbl(result, double_load_operand);
   } else {
@@ -3647,7 +3653,7 @@
   ASSERT(instr->value()->Equals(instr->result()));
   Representation r = instr->hydrogen()->value()->representation();
 
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   if (r.IsDouble()) {
     XMMRegister  scratch = xmm0;
     XMMRegister input_reg = ToDoubleRegister(instr->value());
@@ -3669,13 +3675,13 @@
 
 
 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   XMMRegister xmm_scratch = xmm0;
   Register output_reg = ToRegister(instr->result());
   XMMRegister input_reg = ToDoubleRegister(instr->value());
 
   if (CpuFeatures::IsSupported(SSE4_1)) {
-    CpuFeatures::Scope scope(SSE4_1);
+    CpuFeatureScope scope(masm(), SSE4_1);
     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
       // Deoptimize on negative zero.
       Label non_zero;
@@ -3734,7 +3740,7 @@
 }
 
 void LCodeGen::DoMathRound(LMathRound* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   Register output_reg = ToRegister(instr->result());
   XMMRegister input_reg = ToDoubleRegister(instr->value());
   XMMRegister xmm_scratch = xmm0;
@@ -3795,7 +3801,7 @@
 
 
 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   XMMRegister input_reg = ToDoubleRegister(instr->value());
   ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
   __ sqrtsd(input_reg, input_reg);
@@ -3803,7 +3809,7 @@
 
 
 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   XMMRegister xmm_scratch = xmm0;
   XMMRegister input_reg = ToDoubleRegister(instr->value());
   Register scratch = ToRegister(instr->temp());
@@ -3880,7 +3886,7 @@
 
   DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr);
 
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   // Having marked this instruction as a call we can use any
   // registers.
   ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
@@ -3948,7 +3954,7 @@
 
 
 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   ASSERT(instr->value()->Equals(instr->result()));
   XMMRegister input_reg = ToDoubleRegister(instr->value());
   Label positive, done, zero;
@@ -3980,7 +3986,7 @@
 
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   XMMRegister input = ToDoubleRegister(instr->value());
   XMMRegister result = ToDoubleRegister(instr->result());
   Register temp1 = ToRegister(instr->temp1());
@@ -4179,7 +4185,7 @@
                           HeapObject::kMapOffset,
                           temp_map,
                           temp,
-                          kSaveFPRegs,
+                          GetSaveFPRegsMode(),
                           OMIT_REMEMBERED_SET,
                           OMIT_SMI_CHECK);
     }
@@ -4198,7 +4204,7 @@
                           offset,
                           value,
                           temp,
-                          kSaveFPRegs,
+                          GetSaveFPRegsMode(),
                           EMIT_REMEMBERED_SET,
                           check_needed);
     }
@@ -4213,7 +4219,7 @@
                           offset,
                           value,
                           object,
-                          kSaveFPRegs,
+                          GetSaveFPRegsMode(),
                           EMIT_REMEMBERED_SET,
                           check_needed);
     }
@@ -4270,11 +4276,11 @@
       0,
       instr->additional_index()));
   if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
     __ movss(operand, xmm0);
   } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     __ movdbl(operand, ToDoubleRegister(instr->value()));
   } else {
     Register value = ToRegister(instr->value());
@@ -4310,7 +4316,7 @@
 
 
 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   XMMRegister value = ToDoubleRegister(instr->value());
 
   if (instr->NeedsCanonicalization()) {
@@ -4360,7 +4366,7 @@
     __ RecordWrite(elements,
                    key,
                    value,
-                   kSaveFPRegs,
+                   GetSaveFPRegsMode(),
                    EMIT_REMEMBERED_SET,
                    check_needed);
   }
@@ -4585,7 +4591,7 @@
 
 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     LOperand* input = instr->value();
     ASSERT(input->IsRegister() || input->IsStackSlot());
     LOperand* output = instr->result();
@@ -4598,7 +4604,7 @@
 
 
 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   LOperand* input = instr->value();
   LOperand* output = instr->result();
   LOperand* temp = instr->temp();
@@ -4677,7 +4683,7 @@
     __ SmiUntag(reg);
     __ xor_(reg, 0x80000000);
     if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope feature_scope(SSE2);
+      CpuFeatureScope feature_scope(masm(), SSE2);
       __ cvtsi2sd(xmm0, Operand(reg));
     } else {
       __ push(reg);
@@ -4686,7 +4692,7 @@
     }
   } else {
     if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope feature_scope(SSE2);
+      CpuFeatureScope feature_scope(masm(), SSE2);
       __ LoadUint32(xmm0, reg, xmm1);
     } else {
       // There's no fild variant for unsigned values, so zero-extend to a 64-bit
@@ -4726,7 +4732,7 @@
   // number.
   __ bind(&done);
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope feature_scope(SSE2);
+    CpuFeatureScope feature_scope(masm(), SSE2);
     __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0);
   } else {
     __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
@@ -4760,7 +4766,7 @@
   if (convert_hole) {
     bool use_sse2 = CpuFeatures::IsSupported(SSE2);
     if (use_sse2) {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       XMMRegister input_reg = ToDoubleRegister(instr->value());
       __ ucomisd(input_reg, input_reg);
     } else {
@@ -4775,7 +4781,7 @@
     __ j(parity_odd, &no_special_nan_handling);
     __ sub(esp, Immediate(kDoubleSize));
     if (use_sse2) {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       XMMRegister input_reg = ToDoubleRegister(instr->value());
       __ movdbl(MemOperand(esp, 0), input_reg);
     } else {
@@ -4794,7 +4800,7 @@
     ExternalReference nan =
         ExternalReference::address_of_canonical_non_hole_nan();
     if (use_sse2) {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       XMMRegister input_reg = ToDoubleRegister(instr->value());
       __ movdbl(input_reg, Operand::StaticVariable(nan));
     } else {
@@ -4813,7 +4819,7 @@
   }
   __ bind(deferred->exit());
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     XMMRegister input_reg = ToDoubleRegister(instr->value());
     __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
   } else {
@@ -4956,7 +4962,7 @@
 
     __ bind(&heap_number);
     if (CpuFeatures::IsSupported(SSE3)) {
-      CpuFeatures::Scope scope(SSE3);
+      CpuFeatureScope scope(masm(), SSE3);
       Label convert;
       // Use more powerful conversion when sse3 is available.
       // Load x87 register with heap number.
@@ -4981,7 +4987,7 @@
       __ mov(input_reg, Operand(esp, 0));  // Low word of answer is the result.
       __ add(Operand(esp), Immediate(kDoubleSize));
     } else {
-      CpuFeatures::Scope scope(SSE2);
+      CpuFeatureScope scope(masm(), SSE2);
       XMMRegister xmm_temp = ToDoubleRegister(instr->temp());
       __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
       __ cvttsd2si(input_reg, Operand(xmm0));
@@ -4996,7 +5002,7 @@
       DeoptimizeIf(parity_even, instr->environment());  // NaN.
     }
   } else if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     // Deoptimize if we don't have a heap number.
     __ RecordComment("Deferred TaggedToI: not a heap number");
     DeoptimizeIf(not_equal, instr->environment());
@@ -5063,7 +5069,7 @@
   ASSERT(result->IsDoubleRegister());
 
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(masm(), SSE2);
     Register input_reg = ToRegister(input);
     XMMRegister result_reg = ToDoubleRegister(result);
 
@@ -5106,7 +5112,7 @@
   ASSERT(input->IsDoubleRegister());
   LOperand* result = instr->result();
   ASSERT(result->IsRegister());
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
 
   XMMRegister input_reg = ToDoubleRegister(input);
   Register result_reg = ToRegister(result);
@@ -5118,7 +5124,7 @@
     __ cmp(result_reg, 0x80000000u);
     if (CpuFeatures::IsSupported(SSE3)) {
       // This will deoptimize if the exponent of the input in out of range.
-      CpuFeatures::Scope scope(SSE3);
+      CpuFeatureScope scope(masm(), SSE3);
       Label convert, done;
       __ j(not_equal, &done, Label::kNear);
       __ sub(Operand(esp), Immediate(kDoubleSize));
@@ -5323,7 +5329,7 @@
 
 
 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
   XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
   Register result_reg = ToRegister(instr->result());
   __ ClampDoubleToUint8(value_reg, xmm0, result_reg);
@@ -5338,7 +5344,7 @@
 
 
 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
-  CpuFeatures::Scope scope(SSE2);
+  CpuFeatureScope scope(masm(), SSE2);
 
   ASSERT(instr->unclamped()->Equals(instr->result()));
   Register input_reg = ToRegister(instr->unclamped());
diff --git a/src/ia32/lithium-gap-resolver-ia32.cc b/src/ia32/lithium-gap-resolver-ia32.cc
index 6fee7fe..b062ba5 100644
--- a/src/ia32/lithium-gap-resolver-ia32.cc
+++ b/src/ia32/lithium-gap-resolver-ia32.cc
@@ -324,7 +324,7 @@
     }
 
   } else if (source->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(cgen_->masm(), SSE2);
     XMMRegister src = cgen_->ToDoubleRegister(source);
     if (destination->IsDoubleRegister()) {
       XMMRegister dst = cgen_->ToDoubleRegister(destination);
@@ -335,7 +335,7 @@
       __ movdbl(dst, src);
     }
   } else if (source->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(cgen_->masm(), SSE2);
     ASSERT(destination->IsDoubleRegister() ||
            destination->IsDoubleStackSlot());
     Operand src = cgen_->ToOperand(source);
@@ -411,7 +411,7 @@
       __ mov(src, tmp0);
     }
   } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(cgen_->masm(), SSE2);
     // XMM register-register swap. We rely on having xmm0
     // available as a fixed scratch register.
     XMMRegister src = cgen_->ToDoubleRegister(source);
@@ -421,7 +421,7 @@
     __ movaps(dst, xmm0);
 
   } else if (source->IsDoubleRegister() || destination->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(cgen_->masm(), SSE2);
     // XMM register-memory swap.  We rely on having xmm0
     // available as a fixed scratch register.
     ASSERT(source->IsDoubleStackSlot() || destination->IsDoubleStackSlot());
@@ -435,7 +435,7 @@
     __ movdbl(reg, Operand(xmm0));
 
   } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(cgen_->masm(), SSE2);
     // Double-width memory-to-memory.  Spill on demand to use a general
     // purpose temporary register and also rely on having xmm0 available as
     // a fixed scratch register.
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 587699f..494a1bf 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -527,7 +527,7 @@
   ExternalReference canonical_nan_reference =
       ExternalReference::address_of_canonical_non_hole_nan();
   if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(this, SSE2);
     movdbl(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
     bind(&have_double_value);
     movdbl(FieldOperand(elements, key, times_4,
@@ -549,7 +549,7 @@
   j(zero, &not_nan);
   bind(&is_nan);
   if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(this, SSE2);
     movdbl(scratch2, Operand::StaticVariable(canonical_nan_reference));
   } else {
     fld_d(Operand::StaticVariable(canonical_nan_reference));
@@ -562,7 +562,7 @@
   mov(scratch1, maybe_number);
   SmiUntag(scratch1);
   if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
-    CpuFeatures::Scope fscope(SSE2);
+    CpuFeatureScope fscope(this, SSE2);
     cvtsi2sd(scratch2, scratch1);
     movdbl(FieldOperand(elements, key, times_4,
                         FixedDoubleArray::kHeaderSize - elements_offset),
@@ -643,6 +643,16 @@
 }
 
 
+Condition MacroAssembler::IsObjectNameType(Register heap_object,
+                                           Register map,
+                                           Register instance_type) {
+  mov(map, FieldOperand(heap_object, HeapObject::kMapOffset));
+  movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
+  cmpb(instance_type, static_cast<uint8_t>(LAST_NAME_TYPE));
+  return below_equal;
+}
+
+
 void MacroAssembler::IsObjectJSObjectType(Register heap_object,
                                           Register map,
                                           Register scratch,
@@ -710,6 +720,19 @@
 }
 
 
+void MacroAssembler::AssertName(Register object) {
+  if (emit_debug_code()) {
+    test(object, Immediate(kSmiTagMask));
+    Check(not_equal, "Operand is a smi and not a name");
+    push(object);
+    mov(object, FieldOperand(object, HeapObject::kMapOffset));
+    CmpInstanceType(object, LAST_NAME_TYPE);
+    pop(object);
+    Check(below_equal, "Operand is not a name");
+  }
+}
+
+
 void MacroAssembler::AssertNotSmi(Register object) {
   if (emit_debug_code()) {
     test(object, Immediate(kSmiTagMask));
@@ -767,7 +790,7 @@
 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
   // Optionally save all XMM registers.
   if (save_doubles) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(this, SSE2);
     int space = XMMRegister::kNumRegisters * kDoubleSize + argc * kPointerSize;
     sub(esp, Immediate(space));
     const int offset = -2 * kPointerSize;
@@ -813,7 +836,7 @@
 void MacroAssembler::LeaveExitFrame(bool save_doubles) {
   // Optionally restore all XMM registers.
   if (save_doubles) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(this, SSE2);
     const int offset = -2 * kPointerSize;
     for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
       XMMRegister reg = XMMRegister::from_code(i);
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 65899ce..05ad82d 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -423,6 +423,15 @@
                                Register map,
                                Register instance_type);
 
+  // Check if the object in register heap_object is a name. Afterwards the
+  // register map contains the object map and the register instance_type
+  // contains the instance_type. The registers map and instance_type can be the
+  // same in which case it contains the instance type afterwards. Either of the
+  // registers map and instance_type can be the same as heap_object.
+  Condition IsObjectNameType(Register heap_object,
+                             Register map,
+                             Register instance_type);
+
   // Check if a heap object's type is in the JSObject range, not including
   // JSFunction.  The object's map will be loaded in the map register.
   // Any or all of the three registers may be the same.
@@ -513,6 +522,9 @@
   // Abort execution if argument is not a string, enabled via --debug-code.
   void AssertString(Register object);
 
+  // Abort execution if argument is not a name, enabled via --debug-code.
+  void AssertName(Register object);
+
   // ---------------------------------------------------------------------------
   // Exception handling
 
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 34ce36d..d0b7881 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -141,14 +141,14 @@
 // the property. This function may return false negatives, so miss_label
 // must always call a backup property check that is complete.
 // This function is safe to call if the receiver has fast properties.
-// Name must be an internalized string and receiver must be a heap object.
+// Name must be unique and receiver must be a heap object.
 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
                                              Label* miss_label,
                                              Register receiver,
-                                             Handle<String> name,
+                                             Handle<Name> name,
                                              Register r0,
                                              Register r1) {
-  ASSERT(name->IsInternalizedString());
+  ASSERT(name->IsUniqueName());
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->negative_lookups(), 1);
   __ IncrementCounter(counters->negative_lookups_miss(), 1);
@@ -177,12 +177,12 @@
   __ j(not_equal, miss_label);
 
   Label done;
-  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
-                                                     miss_label,
-                                                     &done,
-                                                     properties,
-                                                     name,
-                                                     r1);
+  NameDictionaryLookupStub::GenerateNegativeLookup(masm,
+                                                   miss_label,
+                                                   &done,
+                                                   properties,
+                                                   name,
+                                                   r1);
   __ bind(&done);
   __ DecrementCounter(counters->negative_lookups_miss(), 1);
 }
@@ -227,7 +227,7 @@
   __ JumpIfSmi(receiver, &miss);
 
   // Get the map of the receiver and compute the hash.
-  __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
+  __ mov(offset, FieldOperand(name, Name::kHashFieldOffset));
   __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
   __ xor_(offset, flags);
   // We mask out the last two bits because they are not part of the hash and
@@ -241,7 +241,7 @@
   ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra);
 
   // Primary miss: Compute hash for secondary probe.
-  __ mov(offset, FieldOperand(name, String::kHashFieldOffset));
+  __ mov(offset, FieldOperand(name, Name::kHashFieldOffset));
   __ add(offset, FieldOperand(receiver, HeapObject::kMapOffset));
   __ xor_(offset, flags);
   __ and_(offset, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
@@ -547,7 +547,7 @@
   void Compile(MacroAssembler* masm,
                Handle<JSObject> object,
                Handle<JSObject> holder,
-               Handle<String> name,
+               Handle<Name> name,
                LookupResult* lookup,
                Register receiver,
                Register scratch1,
@@ -579,7 +579,7 @@
                         Register scratch3,
                         Handle<JSObject> interceptor_holder,
                         LookupResult* lookup,
-                        Handle<String> name,
+                        Handle<Name> name,
                         const CallOptimization& optimization,
                         Label* miss_label) {
     ASSERT(optimization.is_constant_call());
@@ -672,7 +672,7 @@
                       Register scratch1,
                       Register scratch2,
                       Register scratch3,
-                      Handle<String> name,
+                      Handle<Name> name,
                       Handle<JSObject> interceptor_holder,
                       Label* miss_label) {
     Register holder =
@@ -760,7 +760,7 @@
                                       Handle<JSObject> object,
                                       int index,
                                       Handle<Map> transition,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Register receiver_reg,
                                       Register name_reg,
                                       Register scratch1,
@@ -894,7 +894,7 @@
 // property.
 static void GenerateCheckPropertyCell(MacroAssembler* masm,
                                       Handle<GlobalObject> global,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Register scratch,
                                       Label* miss) {
   Handle<JSGlobalPropertyCell> cell =
@@ -917,7 +917,7 @@
 static void GenerateCheckPropertyCells(MacroAssembler* masm,
                                        Handle<JSObject> object,
                                        Handle<JSObject> holder,
-                                       Handle<String> name,
+                                       Handle<Name> name,
                                        Register scratch,
                                        Label* miss) {
   Handle<JSObject> current = object;
@@ -948,7 +948,7 @@
                                        Register holder_reg,
                                        Register scratch1,
                                        Register scratch2,
-                                       Handle<String> name,
+                                       Handle<Name> name,
                                        int save_at_depth,
                                        Label* miss,
                                        PrototypeCheckType check) {
@@ -980,11 +980,12 @@
     if (!current->HasFastProperties() &&
         !current->IsJSGlobalObject() &&
         !current->IsJSGlobalProxy()) {
-      if (!name->IsInternalizedString()) {
-        name = factory()->InternalizeString(name);
+      if (!name->IsUniqueName()) {
+        ASSERT(name->IsString());
+        name = factory()->InternalizeString(Handle<String>::cast(name));
       }
       ASSERT(current->property_dictionary()->FindEntry(*name) ==
-             StringDictionary::kNotFound);
+             NameDictionary::kNotFound);
 
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
                                        scratch1, scratch2);
@@ -1070,7 +1071,7 @@
     Handle<JSObject> object,
     Register object_reg,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     Label* success,
     Handle<ExecutableAccessorInfo> callback) {
   Label miss;
@@ -1091,13 +1092,13 @@
 
     // Probe the dictionary.
     Label probe_done, pop_and_miss;
-    StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
-                                                       &pop_and_miss,
-                                                       &probe_done,
-                                                       dictionary,
-                                                       this->name(),
-                                                       scratch2(),
-                                                       scratch3());
+    NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
+                                                     &pop_and_miss,
+                                                     &probe_done,
+                                                     dictionary,
+                                                     this->name(),
+                                                     scratch2(),
+                                                     scratch3());
     __ bind(&pop_and_miss);
     if (must_preserve_dictionary_reg) {
       __ pop(dictionary);
@@ -1109,8 +1110,8 @@
     // index into the dictionary. Check that the value is the callback.
     Register index = scratch2();
     const int kElementsStartOffset =
-        StringDictionary::kHeaderSize +
-        StringDictionary::kElementsStartIndex * kPointerSize;
+        NameDictionary::kHeaderSize +
+        NameDictionary::kElementsStartIndex * kPointerSize;
     const int kValueOffset = kElementsStartOffset + kPointerSize;
     __ mov(scratch3(),
            Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag));
@@ -1129,7 +1130,7 @@
 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
     Handle<JSObject> object,
     Handle<JSObject> last,
-    Handle<String> name,
+    Handle<Name> name,
     Label* success,
     Handle<GlobalObject> global) {
   Label miss;
@@ -1222,7 +1223,7 @@
     Handle<JSObject> object,
     Handle<JSObject> interceptor_holder,
     LookupResult* lookup,
-    Handle<String> name) {
+    Handle<Name> name) {
   ASSERT(interceptor_holder->HasNamedInterceptor());
   ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
 
@@ -1318,7 +1319,7 @@
 }
 
 
-void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
   if (kind_ == Code::KEYED_CALL_IC) {
     __ cmp(ecx, Immediate(name));
     __ j(not_equal, miss);
@@ -1328,7 +1329,7 @@
 
 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
                                                    Handle<JSObject> holder,
-                                                   Handle<String> name,
+                                                   Handle<Name> name,
                                                    Label* miss) {
   ASSERT(holder->IsGlobalObject());
 
@@ -1390,7 +1391,7 @@
 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
-                                                Handle<String> name) {
+                                                Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -2046,7 +2047,7 @@
     return Handle<Code>::null();
   }
 
-  CpuFeatures::Scope use_sse2(SSE2);
+  CpuFeatureScope use_sse2(masm(), SSE2);
 
   const int argc = arguments().immediate();
 
@@ -2324,7 +2325,7 @@
 
 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
                                               Handle<JSObject> holder,
-                                              Handle<String> name,
+                                              Handle<Name> name,
                                               CheckType check,
                                               Label* success) {
   // ----------- S t a t e -------------
@@ -2436,14 +2437,14 @@
 Handle<Code> CallStubCompiler::CompileCallConstant(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     CheckType check,
     Handle<JSFunction> function) {
 
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
                                           Handle<JSGlobalPropertyCell>::null(),
-                                          function, name);
+                                          function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2461,7 +2462,7 @@
 
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
-                                                      Handle<String> name) {
+                                                      Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -2523,7 +2524,7 @@
     Handle<GlobalObject> holder,
     Handle<JSGlobalPropertyCell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -2533,7 +2534,8 @@
   // -----------------------------------
 
   if (HasCustomCallGenerator(function)) {
-    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
+    Handle<Code> code = CompileCustomCall(
+        object, holder, cell, function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2582,7 +2584,7 @@
 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
                                                   int index,
                                                   Handle<Map> transition,
-                                                  Handle<String> name) {
+                                                  Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
@@ -2613,7 +2615,7 @@
 
 
 Handle<Code> StoreStubCompiler::CompileStoreCallback(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<ExecutableAccessorInfo> callback) {
@@ -2703,7 +2705,7 @@
 
 
 Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<JSFunction> setter) {
@@ -2735,7 +2737,7 @@
 
 Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
     Handle<JSObject> receiver,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
@@ -2782,7 +2784,7 @@
 Handle<Code> StoreStubCompiler::CompileStoreGlobal(
     Handle<GlobalObject> object,
     Handle<JSGlobalPropertyCell> cell,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
@@ -2830,7 +2832,7 @@
 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
                                                        int index,
                                                        Handle<Map> transition,
-                                                       Handle<String> name) {
+                                                       Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -2881,7 +2883,7 @@
   Handle<Code> stub =
       KeyedStoreElementStub(is_jsarray,
                             elements_kind,
-                            grow_mode_).GetCode(isolate());
+                            store_mode_).GetCode(isolate());
 
   __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK);
 
@@ -2931,7 +2933,7 @@
 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
     Handle<JSObject> object,
     Handle<JSObject> last,
-    Handle<String> name,
+    Handle<Name> name,
     Handle<GlobalObject> global) {
   Label success;
 
@@ -2944,7 +2946,7 @@
   __ ret(0);
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
+  return GetCode(kind(), Code::NONEXISTENT, name);
 }
 
 
@@ -2962,7 +2964,7 @@
 }
 
 
-void KeyedLoadStubCompiler::GenerateNameCheck(Handle<String> name,
+void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
                                               Register name_reg,
                                               Label* miss) {
   __ cmp(name_reg, Immediate(name));
@@ -3011,7 +3013,7 @@
     Handle<JSObject> object,
     Handle<GlobalObject> global,
     Handle<JSGlobalPropertyCell> cell,
-    Handle<String> name,
+    Handle<Name> name,
     bool is_dont_delete) {
   Label success, miss;
 
@@ -3044,7 +3046,7 @@
   __ ret(0);
 
   // Return the generated code.
-  return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
+  return GetICCode(kind(), Code::NORMAL, name);
 }
 
 
@@ -3072,14 +3074,14 @@
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
-  return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
+  return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
 }
 
 
 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
     MapHandleList* receiver_maps,
     CodeHandleList* handlers,
-    Handle<String> name,
+    Handle<Name> name,
     Code::StubType type,
     IcCheckType check) {
   Label miss;
@@ -3103,7 +3105,7 @@
   // Return the generated code.
   InlineCacheState state =
       receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
-  return GetCode(Code::IC_FRAGMENT, type, name, state);
+  return GetICCode(kind(), type, name, state);
 }
 
 
@@ -3196,7 +3198,7 @@
       __ mov(ebx, edi);
       __ cmp(eax, arg_number);
       if (CpuFeatures::IsSupported(CMOV)) {
-        CpuFeatures::Scope use_cmov(CMOV);
+        CpuFeatureScope use_cmov(masm(), CMOV);
         __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize));
       } else {
         Label not_passed;
@@ -3309,7 +3311,7 @@
   // Check that key is a smi and if SSE2 is available a heap number
   // containing a smi and branch if the check fails.
   if (CpuFeatures::IsSupported(SSE2)) {
-    CpuFeatures::Scope use_sse2(SSE2);
+    CpuFeatureScope use_sse2(masm, SSE2);
     Label key_ok;
     __ JumpIfSmi(key, &key_ok);
     __ cmp(FieldOperand(key, HeapObject::kMapOffset),
@@ -3446,7 +3448,7 @@
         if ((elements_kind == EXTERNAL_INT_ELEMENTS ||
              elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) &&
             CpuFeatures::IsSupported(SSE3)) {
-          CpuFeatures::Scope scope(SSE3);
+          CpuFeatureScope scope(masm, SSE3);
           // fisttp stores values as signed integers. To represent the
           // entire range of int and unsigned int arrays, store as a
           // 64-bit int and discard the high 32 bits.
@@ -3471,7 +3473,7 @@
           __ mov(Operand(edi, ecx, times_2, 0), ebx);
         } else {
           ASSERT(CpuFeatures::IsSupported(SSE2));
-          CpuFeatures::Scope scope(SSE2);
+          CpuFeatureScope scope(masm, SSE2);
           __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset));
           __ cmp(ebx, 0x80000000u);
           __ j(equal, &slow);
@@ -3536,7 +3538,7 @@
     MacroAssembler* masm,
     bool is_js_array,
     ElementsKind elements_kind,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -3561,7 +3563,7 @@
   if (is_js_array) {
     // Check that the key is within bounds.
     __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
-    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
+    if (IsGrowStoreMode(store_mode)) {
       __ j(above_equal, &grow);
     } else {
       __ j(above_equal, &miss_force_generic);
@@ -3613,7 +3615,7 @@
   Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
   __ jmp(ic_miss, RelocInfo::CODE_TARGET);
 
-  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (is_js_array && IsGrowStoreMode(store_mode)) {
     // Handle transition requiring the array to grow.
     __ bind(&grow);
 
@@ -3691,7 +3693,7 @@
 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
     MacroAssembler* masm,
     bool is_js_array,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -3714,7 +3716,7 @@
   if (is_js_array) {
     // Check that the key is within bounds.
     __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
-    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
+    if (IsGrowStoreMode(store_mode)) {
       __ j(above_equal, &grow);
     } else {
       __ j(above_equal, &miss_force_generic);
@@ -3741,7 +3743,7 @@
   Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
   __ jmp(ic_miss, RelocInfo::CODE_TARGET);
 
-  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (is_js_array && IsGrowStoreMode(store_mode)) {
     // Handle transition requiring the array to grow.
     __ bind(&grow);
 
diff --git a/src/ic.cc b/src/ic.cc
index 7fdf6be..f69d79a 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -59,6 +59,17 @@
   return 0;
 }
 
+
+const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
+  if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
+  if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
+    return ".IGNORE_OOB";
+  }
+  if (IsGrowStoreMode(mode)) return ".GROW";
+  return "";
+}
+
+
 void IC::TraceIC(const char* type,
                  Handle<Object> name,
                  State old_state,
@@ -81,13 +92,13 @@
       }
     }
     JavaScriptFrame::PrintTop(isolate, stdout, false, true);
-    bool new_can_grow =
-        Code::GetKeyedAccessGrowMode(new_target->extra_ic_state()) ==
-        ALLOW_JSARRAY_GROWTH;
+    Code::ExtraICState state = new_target->extra_ic_state();
+    const char* modifier =
+        GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(state));
     PrintF(" (%c->%c%s)",
            TransitionMarkFromState(old_state),
            TransitionMarkFromState(new_state),
-           new_can_grow ? ".GROW" : "");
+           modifier);
     name->Print();
     PrintF("]\n");
   }
@@ -959,13 +970,23 @@
       target()->type() == Code::NORMAL) {
     return false;
   }
+
   MapHandleList receiver_maps;
   CodeHandleList handlers;
-  target()->FindAllMaps(&receiver_maps);
-  int number_of_maps = receiver_maps.length();
-  if (number_of_maps == 0 || number_of_maps >= 4) return false;
 
-  target()->FindAllCode(&handlers, receiver_maps.length());
+  {
+    AssertNoAllocation no_gc;
+    target()->FindAllMaps(&receiver_maps);
+    int number_of_maps = receiver_maps.length();
+    if (number_of_maps >= 4) return false;
+
+    // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC.
+    // In that case, allow the IC to go back monomorphic.
+    if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) {
+      return false;
+    }
+    target()->FindAllCode(&handlers, receiver_maps.length());
+  }
 
   if (!AddOneReceiverMapIfMissing(&receiver_maps,
                                   Handle<Map>(receiver->map()))) {
@@ -1000,6 +1021,8 @@
 }
 
 
+// Since GC may have been invoked, by the time PatchCache is called, |state| is
+// not necessarily equal to target()->state().
 void IC::PatchCache(State state,
                     StrictModeFlag strict_mode,
                     Handle<JSObject> receiver,
@@ -1019,11 +1042,28 @@
             break;
           }
         }
-        // We are transitioning from monomorphic to megamorphic case.  Place the
-        // stub compiled for the receiver into stub cache.
-        Map* map = target()->FindFirstMap();
-        if (map != NULL) {
-          UpdateMegamorphicCache(map, *name, target());
+        if (target()->type() != Code::NORMAL) {
+          // We are transitioning from monomorphic to megamorphic case. Place
+          // the stub compiled for the receiver into stub cache.
+          Map* map;
+          Code* handler;
+          {
+            AssertNoAllocation no_gc;
+            map = target()->FindFirstMap();
+            if (map != NULL) {
+              if (target()->is_load_stub()) {
+                handler = target()->FindFirstCode();
+              } else {
+                handler = target();
+              }
+            } else {
+              // Avoid compiler warnings.
+              handler = NULL;
+            }
+          }
+          if (handler != NULL) {
+            UpdateMegamorphicCache(map, *name, handler);
+          }
         }
         UpdateMegamorphicCache(receiver->map(), *name, *code);
         set_target((strict_mode == kStrictMode)
@@ -1042,8 +1082,11 @@
         }
         MapHandleList receiver_maps;
         CodeHandleList handlers;
-        target()->FindAllMaps(&receiver_maps);
-        target()->FindAllCode(&handlers, receiver_maps.length());
+        {
+          AssertNoAllocation no_gc;
+          target()->FindAllMaps(&receiver_maps);
+          target()->FindAllCode(&handlers, receiver_maps.length());
+        }
         for (int i = 0; i < receiver_maps.length(); i++) {
           UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
         }
@@ -1602,13 +1645,8 @@
 
 
 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver,
-                                            StubKind stub_kind,
+                                            KeyedAccessStoreMode store_mode,
                                             StrictModeFlag strict_mode) {
-  State ic_state = target()->ic_state();
-  KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind)
-      ? ALLOW_JSARRAY_GROWTH
-      : DO_NOT_ALLOW_JSARRAY_GROWTH;
-
   // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
   // via megamorphic stubs, since they don't have a map in their relocation info
   // and so the stubs can't be harvested for the object needed for a map check.
@@ -1617,42 +1655,76 @@
     return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
   }
 
+  if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW ||
+       store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS)) {
+    // TODO(danno): We'll soon handle MONOMORPHIC ICs that also support
+    // copying COW arrays and silently ignoring some OOB stores into external
+    // arrays, but for now use the generic.
+    TRACE_GENERIC_IC(isolate(), "KeyedIC", "COW/OOB external array");
+    return strict_mode == kStrictMode
+        ? generic_stub_strict()
+        : generic_stub();
+  }
+
+  State ic_state = target()->ic_state();
   Handle<Map> receiver_map(receiver->map());
-  MapHandleList target_receiver_maps;
   if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
     // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
     // yet will do so and stay there.
-    Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, stub_kind);
-    stub_kind = GetNoTransitionStubKind(stub_kind);
+    Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
+    store_mode = GetNonTransitioningStoreMode(store_mode);
     return isolate()->stub_cache()->ComputeKeyedStoreElement(
-        monomorphic_map, stub_kind, strict_mode, grow_mode);
+        monomorphic_map, strict_mode, store_mode);
   }
 
-  GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
+  MapHandleList target_receiver_maps;
+  target()->FindAllMaps(&target_receiver_maps);
   if (target_receiver_maps.length() == 0) {
-    // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
-    // yet will do so and stay there.
-    stub_kind = GetNoTransitionStubKind(stub_kind);
-    return isolate()->stub_cache()->ComputeKeyedStoreElement(
-        receiver_map, stub_kind, strict_mode, grow_mode);
+    // In the case that there is a non-map-specific IC is installed (e.g. keyed
+    // stores into properties in dictionary mode), then there will be not
+    // receiver maps in the target.
+    return strict_mode == kStrictMode
+        ? generic_stub_strict()
+        : generic_stub();
   }
-  // The first time a receiver is seen that is a transitioned version of the
-  // previous monomorphic receiver type, assume the new ElementsKind is the
-  // monomorphic type. This benefits global arrays that only transition
-  // once, and all call sites accessing them are faster if they remain
-  // monomorphic. If this optimistic assumption is not true, the IC will
-  // miss again and it will become polymorphic and support both the
-  // untransitioned and transitioned maps.
-  if (ic_state == MONOMORPHIC &&
-      IsTransitionStubKind(stub_kind) &&
-      IsMoreGeneralElementsKindTransition(
-          target_receiver_maps.at(0)->elements_kind(),
-          receiver->GetElementsKind())) {
-    Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, stub_kind);
-    ASSERT(*monomorphic_map != *receiver_map);
-    stub_kind = GetNoTransitionStubKind(stub_kind);
-    return isolate()->stub_cache()->ComputeKeyedStoreElement(
-        monomorphic_map, stub_kind, strict_mode, grow_mode);
+
+  // There are several special cases where an IC that is MONOMORPHIC can still
+  // transition to a different GetNonTransitioningStoreMode IC that handles a
+  // superset of the original IC. Handle those here if the receiver map hasn't
+  // changed or it has transitioned to a more general kind.
+  KeyedAccessStoreMode old_store_mode =
+      Code::GetKeyedAccessStoreMode(target()->extra_ic_state());
+  Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
+  if (ic_state == MONOMORPHIC && old_store_mode == STANDARD_STORE) {
+      // If the "old" and "new" maps are in the same elements map family, stay
+      // MONOMORPHIC and use the map for the most generic ElementsKind.
+    Handle<Map> transitioned_receiver_map = receiver_map;
+    if (IsTransitionStoreMode(store_mode)) {
+      transitioned_receiver_map =
+          ComputeTransitionedMap(receiver, store_mode);
+    }
+    ElementsKind transitioned_kind =
+        transitioned_receiver_map->elements_kind();
+    bool more_general_transition =
+        IsMoreGeneralElementsKindTransition(
+            previous_receiver_map->elements_kind(),
+            transitioned_kind);
+    Map* transitioned_previous_map = more_general_transition
+        ? previous_receiver_map->LookupElementsTransitionMap(transitioned_kind)
+        : NULL;
+    if (transitioned_previous_map == *transitioned_receiver_map) {
+      // Element family is the same, use the "worst" case map.
+      store_mode = GetNonTransitioningStoreMode(store_mode);
+      return isolate()->stub_cache()->ComputeKeyedStoreElement(
+          transitioned_receiver_map, strict_mode, store_mode);
+    } else if (*previous_receiver_map == receiver->map()) {
+      if (IsGrowStoreMode(store_mode)) {
+        // A "normal" IC that handles stores can switch to a version that can
+        // grow at the end of the array and still stay MONOMORPHIC.
+        return isolate()->stub_cache()->ComputeKeyedStoreElement(
+            receiver_map, strict_mode, store_mode);
+      }
+    }
   }
 
   ASSERT(ic_state != GENERIC);
@@ -1660,9 +1732,11 @@
   bool map_added =
       AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
 
-  if (IsTransitionStubKind(stub_kind)) {
-    Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind);
-    map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
+  if (IsTransitionStoreMode(store_mode)) {
+    Handle<Map> transitioned_receiver_map =
+        ComputeTransitionedMap(receiver, store_mode);
+    map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
+                                            transitioned_receiver_map);
   }
 
   if (!map_added) {
@@ -1679,19 +1753,29 @@
     return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
   }
 
-  if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) ==
-       ALLOW_JSARRAY_GROWTH)) {
-    grow_mode = ALLOW_JSARRAY_GROWTH;
+  // Make sure all polymorphic handlers have the same store mode, otherwise the
+  // generic stub must be used.
+  store_mode = GetNonTransitioningStoreMode(store_mode);
+  if (old_store_mode != STANDARD_STORE) {
+    if (store_mode == STANDARD_STORE) {
+      store_mode = old_store_mode;
+    } else if (store_mode != old_store_mode) {
+      TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch");
+      return strict_mode == kStrictMode
+          ? generic_stub_strict()
+          : generic_stub();
+    }
   }
 
   return isolate()->stub_cache()->ComputeStoreElementPolymorphic(
-      &target_receiver_maps, grow_mode, strict_mode);
+      &target_receiver_maps, store_mode, strict_mode);
 }
 
 
-Handle<Map> KeyedStoreIC::ComputeTransitionedMap(Handle<JSObject> receiver,
-                                                 StubKind stub_kind) {
-  switch (stub_kind) {
+Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
+    Handle<JSObject> receiver,
+    KeyedAccessStoreMode store_mode) {
+  switch (store_mode) {
     case STORE_TRANSITION_SMI_TO_OBJECT:
     case STORE_TRANSITION_DOUBLE_TO_OBJECT:
     case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT:
@@ -1710,7 +1794,11 @@
     case STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE:
       return JSObject::GetElementsTransitionMap(receiver,
                                                 FAST_HOLEY_DOUBLE_ELEMENTS);
-    case STORE_NO_TRANSITION:
+    case STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS:
+      ASSERT(receiver->map()->has_external_array_elements());
+      // Fall through
+    case STORE_NO_TRANSITION_HANDLE_COW:
+    case STANDARD_STORE:
     case STORE_AND_GROW_NO_TRANSITION:
       return Handle<Map>(receiver->map());
   }
@@ -1718,15 +1806,23 @@
 }
 
 
-KeyedStoreIC::StubKind KeyedStoreIC::GetStubKind(Handle<JSObject> receiver,
-                                                 Handle<Object> key,
-                                                 Handle<Object> value) {
+bool IsOutOfBoundsAccess(Handle<JSObject> receiver,
+                         int index) {
+  if (receiver->IsJSArray()) {
+    return JSArray::cast(*receiver)->length()->IsSmi() &&
+        index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
+  }
+  return index >= receiver->elements()->length();
+}
+
+
+KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
+                                                Handle<Object> key,
+                                                Handle<Object> value) {
   ASSERT(key->IsSmi());
   int index = Smi::cast(*key)->value();
-  bool allow_growth = receiver->IsJSArray() &&
-      JSArray::cast(*receiver)->length()->IsSmi() &&
-      index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
-
+  bool oob_access = IsOutOfBoundsAccess(receiver, index);
+  bool allow_growth = receiver->IsJSArray() && oob_access;
   if (allow_growth) {
     // Handle growing array in stub if necessary.
     if (receiver->HasFastSmiElements()) {
@@ -1779,7 +1875,12 @@
         }
       }
     }
-    return STORE_NO_TRANSITION;
+    if (!FLAG_trace_external_array_abuse &&
+        receiver->map()->has_external_array_elements() && oob_access) {
+      return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
+    } else {
+      return STANDARD_STORE;
+    }
   }
 }
 
@@ -1819,8 +1920,8 @@
             isolate()->heap()->non_strict_arguments_elements_map()) {
           stub = non_strict_arguments_stub();
         } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
-          StubKind stub_kind = GetStubKind(receiver, key, value);
-          stub = StoreElementStub(receiver, stub_kind, strict_mode);
+          KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
+          stub = StoreElementStub(receiver, store_mode, strict_mode);
         }
       }
     } else {
diff --git a/src/ic.h b/src/ic.h
index 78c3642..f5f822b 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -584,43 +584,6 @@
 
 class KeyedStoreIC: public StoreIC {
  public:
-  enum StubKind {
-    STORE_NO_TRANSITION,
-    STORE_TRANSITION_SMI_TO_OBJECT,
-    STORE_TRANSITION_SMI_TO_DOUBLE,
-    STORE_TRANSITION_DOUBLE_TO_OBJECT,
-    STORE_TRANSITION_HOLEY_SMI_TO_OBJECT,
-    STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE,
-    STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
-    STORE_AND_GROW_NO_TRANSITION,
-    STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
-    STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
-    STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT,
-    STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT,
-    STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE,
-    STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT
-  };
-
-  static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
-      STORE_NO_TRANSITION;
-  STATIC_ASSERT(kGrowICDelta ==
-                STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT -
-                STORE_TRANSITION_SMI_TO_OBJECT);
-  STATIC_ASSERT(kGrowICDelta ==
-                STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE -
-                STORE_TRANSITION_SMI_TO_DOUBLE);
-  STATIC_ASSERT(kGrowICDelta ==
-                STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT -
-                STORE_TRANSITION_DOUBLE_TO_OBJECT);
-
-  static inline StubKind GetGrowStubKind(StubKind stub_kind) {
-    if (stub_kind < STORE_AND_GROW_NO_TRANSITION) {
-      stub_kind = static_cast<StubKind>(static_cast<int>(stub_kind) +
-                                        kGrowICDelta);
-    }
-    return stub_kind;
-  }
-
   explicit KeyedStoreIC(Isolate* isolate) : StoreIC(isolate) {
     ASSERT(target()->is_keyed_store_stub());
   }
@@ -662,7 +625,7 @@
   }
 
   Handle<Code> StoreElementStub(Handle<JSObject> receiver,
-                                StubKind stub_kind,
+                                KeyedAccessStoreMode store_mode,
                                 StrictModeFlag strict_mode);
 
  private:
@@ -692,27 +655,12 @@
 
   static void Clear(Address address, Code* target);
 
-  StubKind GetStubKind(Handle<JSObject> receiver,
-                       Handle<Object> key,
-                       Handle<Object> value);
-
-  static bool IsTransitionStubKind(StubKind stub_kind) {
-    return stub_kind > STORE_NO_TRANSITION &&
-        stub_kind != STORE_AND_GROW_NO_TRANSITION;
-  }
-
-  static bool IsGrowStubKind(StubKind stub_kind) {
-    return stub_kind >= STORE_AND_GROW_NO_TRANSITION;
-  }
-
-  static StubKind GetNoTransitionStubKind(StubKind stub_kind) {
-    if (!IsTransitionStubKind(stub_kind)) return stub_kind;
-    if (IsGrowStubKind(stub_kind)) return STORE_AND_GROW_NO_TRANSITION;
-    return STORE_NO_TRANSITION;
-  }
+  KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
+                                    Handle<Object> key,
+                                    Handle<Object> value);
 
   Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
-                                     StubKind stub_kind);
+                                     KeyedAccessStoreMode store_mode);
 
   friend class IC;
 };
@@ -836,7 +784,6 @@
 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK };
 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check);
 
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
 
 } }  // namespace v8::internal
diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc
index e2fca5b..658a34c 100644
--- a/src/incremental-marking.cc
+++ b/src/incremental-marking.cc
@@ -562,7 +562,6 @@
 
 
 void IncrementalMarking::Start() {
-  ASSERT(!heap_->mark_compact_collector()->IsConcurrentSweepingInProgress());
   if (FLAG_trace_incremental_marking) {
     PrintF("[IncrementalMarking] Start\n");
   }
@@ -901,7 +900,7 @@
   }
 
   if (state_ == SWEEPING) {
-    if (heap_->AdvanceSweepers(static_cast<int>(bytes_to_process))) {
+    if (heap_->EnsureSweepersProgressed(static_cast<int>(bytes_to_process))) {
       bytes_scanned_ = 0;
       StartMarking(PREVENT_COMPACTION);
     }
diff --git a/src/isolate.cc b/src/isolate.cc
index 4970ec7..5e61761 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -338,7 +338,7 @@
 Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
 Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
-
+Atomic32 Isolate::isolate_counter_ = 0;
 
 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
     ThreadId thread_id) {
@@ -1624,7 +1624,8 @@
 #define TRACE_ISOLATE(tag)                                              \
   do {                                                                  \
     if (FLAG_trace_isolates) {                                          \
-      PrintF("Isolate %p " #tag "\n", reinterpret_cast<void*>(this));   \
+      PrintF("Isolate %p (id %d)" #tag "\n",                            \
+             reinterpret_cast<void*>(this), id());                      \
     }                                                                   \
   } while (false)
 #else
@@ -1684,6 +1685,7 @@
       optimizing_compiler_thread_(this),
       marking_thread_(NULL),
       sweeper_thread_(NULL) {
+  id_ = NoBarrier_AtomicIncrement(&isolate_counter_, 1);
   TRACE_ISOLATE(constructor);
 
   memset(isolate_addresses_, 0,
@@ -1772,6 +1774,8 @@
   if (state_ == INITIALIZED) {
     TRACE_ISOLATE(deinit);
 
+    if (FLAG_parallel_recompilation) optimizing_compiler_thread_.Stop();
+
     if (FLAG_sweeper_threads > 0) {
       for (int i = 0; i < FLAG_sweeper_threads; i++) {
         sweeper_thread_[i]->Stop();
@@ -1788,9 +1792,7 @@
       delete[] marking_thread_;
     }
 
-    if (FLAG_parallel_recompilation) optimizing_compiler_thread_.Stop();
-
-    if (FLAG_hydrogen_stats) HStatistics::Instance()->Print();
+    if (FLAG_hydrogen_stats) GetHStatistics()->Print();
 
     // We must stop the logger before we tear down other components.
     logger_->EnsureTickerStopped();
@@ -2154,8 +2156,10 @@
   }
 
   if (!Serializer::enabled()) {
-    // Ensure that the stub failure trampoline has been generated.
+    // Ensure that all stubs which need to be generated ahead of time, but
+    // cannot be serialized into the snapshot have been generated.
     HandleScope scope(this);
+    StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this);
     CodeStub::GenerateFPStubs(this);
     StubFailureTrampolineStub::GenerateAheadOfTime(this);
   }
@@ -2198,6 +2202,11 @@
     FLAG_concurrent_sweeping = false;
     FLAG_parallel_sweeping = false;
   }
+  if (FLAG_parallel_recompilation &&
+      SystemThreadManager::NumberOfParallelSystemThreads(
+          SystemThreadManager::PARALLEL_RECOMPILATION) == 0) {
+    FLAG_parallel_recompilation = false;
+  }
   return true;
 }
 
@@ -2311,6 +2320,18 @@
 }
 
 
+HStatistics* Isolate::GetHStatistics() {
+  if (hstatistics() == NULL) set_hstatistics(new HStatistics());
+  return hstatistics();
+}
+
+
+HTracer* Isolate::GetHTracer() {
+  if (htracer() == NULL) set_htracer(new HTracer(id()));
+  return htracer();
+}
+
+
 CodeStubInterfaceDescriptor*
     Isolate::code_stub_interface_descriptor(int index) {
   return code_stub_interface_descriptors_ + index;
diff --git a/src/isolate.h b/src/isolate.h
index 33e4d3e..e6f6d16 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -68,6 +68,8 @@
 class FunctionInfoListener;
 class HandleScopeImplementer;
 class HeapProfiler;
+class HStatistics;
+class HTracer;
 class InlineRuntimeFunctionsTable;
 class NoAllocationStringAllocator;
 class InnerPointerToCodeCache;
@@ -292,7 +294,8 @@
   enum ParallelSystemComponent {
     PARALLEL_SWEEPING,
     CONCURRENT_SWEEPING,
-    PARALLEL_MARKING
+    PARALLEL_MARKING,
+    PARALLEL_RECOMPILATION
   };
 
   static int NumberOfParallelSystemThreads(ParallelSystemComponent type);
@@ -368,10 +371,11 @@
   V(unsigned, ast_node_count, 0)                                               \
   /* SafeStackFrameIterator activations count. */                              \
   V(int, safe_stack_iterator_counter, 0)                                       \
-  V(uint64_t, enabled_cpu_features, 0)                                         \
   V(CpuProfiler*, cpu_profiler, NULL)                                          \
   V(HeapProfiler*, heap_profiler, NULL)                                        \
   V(bool, observer_delivery_pending, false)                                    \
+  V(HStatistics*, hstatistics, NULL)                                           \
+  V(HTracer*, htracer, NULL)                                                   \
   ISOLATE_DEBUGGER_INIT_LIST(V)
 
 class Isolate {
@@ -1100,9 +1104,14 @@
     return sweeper_thread_;
   }
 
+  HStatistics* GetHStatistics();
+  HTracer* GetHTracer();
+
  private:
   Isolate();
 
+  int id() const { return static_cast<int>(id_); }
+
   friend struct GlobalState;
   friend struct InitializeGlobalState;
 
@@ -1170,6 +1179,9 @@
   static Isolate* default_isolate_;
   static ThreadDataTable* thread_data_table_;
 
+  // A global counter for all generated Isolates, might overflow.
+  static Atomic32 isolate_counter_;
+
   void Deinit();
 
   static void SetIsolateThreadLocals(Isolate* isolate,
@@ -1214,6 +1226,7 @@
   // the Error object.
   bool IsErrorObject(Handle<Object> obj);
 
+  Atomic32 id_;
   EntryStackItem* entry_stack_;
   int stack_trace_nesting_level_;
   StringStream* incomplete_message_;
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index e9121d4..ad9ef3d 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -577,7 +577,10 @@
       object->elements()->length() == 0) {
     Handle<Map> map(object->map());
     for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
-      Handle<String> key(map->instance_descriptors()->GetKey(i), isolate_);
+      Handle<Name> name(map->instance_descriptors()->GetKey(i), isolate_);
+      // TODO(rossberg): Should this throw?
+      if (!name->IsString()) continue;
+      Handle<String> key = Handle<String>::cast(name);
       PropertyDetails details = map->instance_descriptors()->GetDetails(i);
       if (details.IsDontEnum() || details.IsDeleted()) continue;
       Handle<Object> property;
@@ -679,7 +682,8 @@
     if (DoNotEscape(c)) {
       *(dest++) = static_cast<DestChar>(c);
     } else {
-      const char* chars = &JsonEscapeTable[c * kJsonEscapeTableEntrySize];
+      const uint8_t* chars = reinterpret_cast<const uint8_t*>(
+          &JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
       while (*chars != '\0') *(dest++) = *(chars++);
     }
   }
@@ -719,9 +723,8 @@
       if (DoNotEscape(c)) {
         Append_<is_ascii, Char>(c);
       } else {
-        Append_<is_ascii, uint8_t>(
-            reinterpret_cast<const uint8_t*>(
-                &JsonEscapeTable[c * kJsonEscapeTableEntrySize]));
+        Append_<is_ascii, uint8_t>(reinterpret_cast<const uint8_t*>(
+            &JsonEscapeTable[c * kJsonEscapeTableEntrySize]));
       }
       // If GC moved the string, we need to refresh the vector.
       if (*string != string_location) {
diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h
index 2953550..2ca8537 100644
--- a/src/lithium-allocator.h
+++ b/src/lithium-allocator.h
@@ -423,6 +423,7 @@
 
   LPlatformChunk* chunk() const { return chunk_; }
   HGraph* graph() const { return graph_; }
+  Isolate* isolate() const { return graph_->isolate(); }
   Zone* zone() const { return zone_; }
 
   int GetVirtualRegister() {
diff --git a/src/lithium.h b/src/lithium.h
index 420a262..9d5b0b9 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -663,6 +663,7 @@
   int spill_slot_count() const { return spill_slot_count_; }
   CompilationInfo* info() const { return info_; }
   HGraph* graph() const { return graph_; }
+  Isolate* isolate() const { return graph_->isolate(); }
   const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
   void AddGapMove(int index, LOperand* from, LOperand* to);
   LGap* GetGapAt(int index) const;
diff --git a/src/log.cc b/src/log.cc
index 2ed0141..30ccc6c 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -427,6 +427,14 @@
     }
   }
 
+  void AppendHex(uint32_t n) {
+    Vector<char> buffer(utf8_buffer_ + utf8_pos_, kUtf8BufferSize - utf8_pos_);
+    int size = OS::SNPrintF(buffer, "%x", n);
+    if (size > 0 && utf8_pos_ + size <= kUtf8BufferSize) {
+      utf8_pos_ += size;
+    }
+  }
+
   const char* get() { return utf8_buffer_; }
   int size() const { return utf8_pos_; }
 
@@ -635,6 +643,8 @@
     SmartArrayPointer<char> str =
         String::cast(key)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
     ApiEvent("api,check-security,\"%s\"\n", *str);
+  } else if (key->IsSymbol()) {
+    ApiEvent("api,check-security,symbol(hash %x)\n", Symbol::cast(key)->Hash());
   } else if (key->IsUndefined()) {
     ApiEvent("api,check-security,undefined\n");
   } else {
@@ -813,14 +823,19 @@
 void Logger::ApiNamedPropertyAccess(const char* tag,
                                     JSObject* holder,
                                     Object* name) {
-  ASSERT(name->IsString());
+  ASSERT(name->IsName());
   if (!log_->IsEnabled() || !FLAG_log_api) return;
   String* class_name_obj = holder->class_name();
   SmartArrayPointer<char> class_name =
       class_name_obj->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
-  SmartArrayPointer<char> property_name =
-      String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
-  ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
+  if (name->IsString()) {
+    SmartArrayPointer<char> property_name =
+        String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    ApiEvent("api,%s,\"%s\",\"%s\"\n", tag, *class_name, *property_name);
+  } else {
+    uint32_t hash = Symbol::cast(name)->Hash();
+    ApiEvent("api,%s,\"%s\",symbol(hash %x)\n", tag, *class_name, hash);
+  }
 }
 
 void Logger::ApiIndexedPropertyAccess(const char* tag,
@@ -874,7 +889,7 @@
   LOGGER->DeleteEvent(name, object);
 }
 
-void Logger::CallbackEventInternal(const char* prefix, const char* name,
+void Logger::CallbackEventInternal(const char* prefix, Name* name,
                                    Address entry_point) {
   if (!log_->IsEnabled() || !FLAG_log_code) return;
   LogMessageBuilder msg(this);
@@ -882,33 +897,33 @@
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[CALLBACK_TAG]);
   msg.AppendAddress(entry_point);
-  msg.Append(",1,\"%s%s\"", prefix, name);
+  if (name->IsString()) {
+    SmartArrayPointer<char> str =
+        String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    msg.Append(",1,\"%s%s\"", prefix, *str);
+  } else {
+    msg.Append(",1,symbol(hash %x)", prefix, Name::cast(name)->Hash());
+  }
   msg.Append('\n');
   msg.WriteToLogFile();
 }
 
 
-void Logger::CallbackEvent(String* name, Address entry_point) {
+void Logger::CallbackEvent(Name* name, Address entry_point) {
   if (!log_->IsEnabled() || !FLAG_log_code) return;
-  SmartArrayPointer<char> str =
-      name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
-  CallbackEventInternal("", *str, entry_point);
+  CallbackEventInternal("", name, entry_point);
 }
 
 
-void Logger::GetterCallbackEvent(String* name, Address entry_point) {
+void Logger::GetterCallbackEvent(Name* name, Address entry_point) {
   if (!log_->IsEnabled() || !FLAG_log_code) return;
-  SmartArrayPointer<char> str =
-      name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
-  CallbackEventInternal("get ", *str, entry_point);
+  CallbackEventInternal("get ", name, entry_point);
 }
 
 
-void Logger::SetterCallbackEvent(String* name, Address entry_point) {
+void Logger::SetterCallbackEvent(Name* name, Address entry_point) {
   if (!log_->IsEnabled() || !FLAG_log_code) return;
-  SmartArrayPointer<char> str =
-      name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
-  CallbackEventInternal("set ", *str, entry_point);
+  CallbackEventInternal("set ", name, entry_point);
 }
 
 
@@ -954,13 +969,19 @@
 
 void Logger::CodeCreateEvent(LogEventsAndTags tag,
                              Code* code,
-                             String* name) {
+                             Name* name) {
   if (!is_logging_code_events()) return;
   if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
     name_buffer_->Reset();
     name_buffer_->AppendBytes(kLogEventsNames[tag]);
     name_buffer_->AppendByte(':');
-    name_buffer_->AppendString(name);
+    if (name->IsString()) {
+      name_buffer_->AppendString(String::cast(name));
+    } else {
+      name_buffer_->AppendBytes("symbol(hash ");
+      name_buffer_->AppendHex(Name::cast(name)->Hash());
+      name_buffer_->AppendByte(')');
+    }
   }
   if (code_event_handler_ != NULL) {
     IssueCodeAddedEvent(code, NULL, name_buffer_->get(), name_buffer_->size());
@@ -979,9 +1000,14 @@
              kLogEventsNames[tag],
              code->kind());
   msg.AppendAddress(code->address());
-  msg.Append(",%d,\"", code->ExecutableSize());
-  msg.AppendDetailed(name, false);
-  msg.Append('"');
+  msg.Append(",%d,", code->ExecutableSize());
+  if (name->IsString()) {
+    msg.Append('"');
+    msg.AppendDetailed(String::cast(name), false);
+    msg.Append('"');
+  } else {
+    msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+  }
   msg.Append('\n');
   msg.WriteToLogFile();
 }
@@ -1000,14 +1026,20 @@
 void Logger::CodeCreateEvent(LogEventsAndTags tag,
                              Code* code,
                              SharedFunctionInfo* shared,
-                             String* name) {
+                             Name* name) {
   if (!is_logging_code_events()) return;
   if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
     name_buffer_->Reset();
     name_buffer_->AppendBytes(kLogEventsNames[tag]);
     name_buffer_->AppendByte(':');
     name_buffer_->AppendBytes(ComputeMarker(code));
-    name_buffer_->AppendString(name);
+    if (name->IsString()) {
+      name_buffer_->AppendString(String::cast(name));
+    } else {
+      name_buffer_->AppendBytes("symbol(hash ");
+      name_buffer_->AppendHex(Name::cast(name)->Hash());
+      name_buffer_->AppendByte(')');
+    }
   }
   if (code_event_handler_ != NULL) {
     Script* script =
@@ -1030,14 +1062,20 @@
     return;
 
   LogMessageBuilder msg(this);
-  SmartArrayPointer<char> str =
-      name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   msg.Append("%s,%s,%d,",
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[tag],
              code->kind());
   msg.AppendAddress(code->address());
-  msg.Append(",%d,\"%s\",", code->ExecutableSize(), *str);
+  msg.Append(",%d,", code->ExecutableSize());
+  if (name->IsString()) {
+    SmartArrayPointer<char> str =
+        String::cast(name)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    msg.Append("\"%s\"", *str);
+  } else {
+    msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+  }
+  msg.Append(',');
   msg.AppendAddress(shared->address());
   msg.Append(",%s", ComputeMarker(code));
   msg.Append('\n');
@@ -1051,7 +1089,7 @@
 void Logger::CodeCreateEvent(LogEventsAndTags tag,
                              Code* code,
                              SharedFunctionInfo* shared,
-                             String* source, int line) {
+                             Name* source, int line) {
   if (!is_logging_code_events()) return;
   if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
     name_buffer_->Reset();
@@ -1060,7 +1098,13 @@
     name_buffer_->AppendBytes(ComputeMarker(code));
     name_buffer_->AppendString(shared->DebugName());
     name_buffer_->AppendByte(' ');
-    name_buffer_->AppendString(source);
+    if (source->IsString()) {
+      name_buffer_->AppendString(String::cast(source));
+    } else {
+      name_buffer_->AppendBytes("symbol(hash ");
+      name_buffer_->AppendHex(Name::cast(source)->Hash());
+      name_buffer_->AppendByte(')');
+    }
     name_buffer_->AppendByte(':');
     name_buffer_->AppendInt(line);
   }
@@ -1083,18 +1127,20 @@
   LogMessageBuilder msg(this);
   SmartArrayPointer<char> name =
       shared->DebugName()->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
-  SmartArrayPointer<char> sourcestr =
-      source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
   msg.Append("%s,%s,%d,",
              kLogEventsNames[CODE_CREATION_EVENT],
              kLogEventsNames[tag],
              code->kind());
   msg.AppendAddress(code->address());
-  msg.Append(",%d,\"%s %s:%d\",",
-             code->ExecutableSize(),
-             *name,
-             *sourcestr,
-             line);
+  msg.Append(",%d,\"%s ", code->ExecutableSize(), *name);
+  if (source->IsString()) {
+    SmartArrayPointer<char> sourcestr =
+       String::cast(source)->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
+    msg.Append("%s", *sourcestr);
+  } else {
+    msg.Append("symbol(hash %x)", Name::cast(source)->Hash());
+  }
+  msg.Append(":%d\",", line);
   msg.AppendAddress(shared->address());
   msg.Append(",%s", ComputeMarker(code));
   msg.Append('\n');
@@ -1298,7 +1344,7 @@
 }
 
 
-void Logger::SuspectReadEvent(String* name, Object* obj) {
+void Logger::SuspectReadEvent(Name* name, Object* obj) {
   if (!log_->IsEnabled() || !FLAG_log_suspect) return;
   LogMessageBuilder msg(this);
   String* class_name = obj->IsJSObject()
@@ -1307,9 +1353,13 @@
   msg.Append("suspect-read,");
   msg.Append(class_name);
   msg.Append(',');
-  msg.Append('"');
-  msg.Append(name);
-  msg.Append('"');
+  if (name->IsString()) {
+    msg.Append('"');
+    msg.Append(String::cast(name));
+    msg.Append('"');
+  } else {
+    msg.Append("symbol(hash %x)", Name::cast(name)->Hash());
+  }
   msg.Append('\n');
   msg.WriteToLogFile();
 }
@@ -1735,9 +1785,9 @@
   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
     if (!obj->IsExecutableAccessorInfo()) continue;
     ExecutableAccessorInfo* ai = ExecutableAccessorInfo::cast(obj);
-    if (!ai->name()->IsString()) continue;
-    String* name = String::cast(ai->name());
+    if (!ai->name()->IsName()) continue;
     Address getter_entry = v8::ToCData<Address>(ai->getter());
+    Name* name = Name::cast(ai->name());
     if (getter_entry != 0) {
       PROFILE(ISOLATE, GetterCallbackEvent(name, getter_entry));
     }
diff --git a/src/log.h b/src/log.h
index 718dc02..27d517a 100644
--- a/src/log.h
+++ b/src/log.h
@@ -203,7 +203,7 @@
 
   // Emits an event that an undefined property was read from an
   // object.
-  void SuspectReadEvent(String* name, Object* obj);
+  void SuspectReadEvent(Name* name, Object* obj);
 
   // Emits an event when a message is put on or read from a debugging queue.
   // DebugTag lets us put a call-site specific label on the event.
@@ -224,22 +224,22 @@
 
   // ==== Events logged by --log-code. ====
   // Emits a code event for a callback function.
-  void CallbackEvent(String* name, Address entry_point);
-  void GetterCallbackEvent(String* name, Address entry_point);
-  void SetterCallbackEvent(String* name, Address entry_point);
+  void CallbackEvent(Name* name, Address entry_point);
+  void GetterCallbackEvent(Name* name, Address entry_point);
+  void SetterCallbackEvent(Name* name, Address entry_point);
   // Emits a code create event.
   void CodeCreateEvent(LogEventsAndTags tag,
                        Code* code, const char* source);
   void CodeCreateEvent(LogEventsAndTags tag,
-                       Code* code, String* name);
+                       Code* code, Name* name);
   void CodeCreateEvent(LogEventsAndTags tag,
                        Code* code,
                        SharedFunctionInfo* shared,
-                       String* name);
+                       Name* name);
   void CodeCreateEvent(LogEventsAndTags tag,
                        Code* code,
                        SharedFunctionInfo* shared,
-                       String* source, int line);
+                       Name* source, int line);
   void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
   void CodeMovingGCEvent();
   // Emits a code create event for a RegExp.
@@ -395,7 +395,7 @@
 
   // Emits callback event messages.
   void CallbackEventInternal(const char* prefix,
-                             const char* name,
+                             Name* name,
                              Address entry_point);
 
   // Internal configurable move event.
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 366594f..cbb9dfb 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -67,6 +67,7 @@
       compacting_(false),
       was_marked_incrementally_(false),
       sweeping_pending_(false),
+      sequential_sweeping_(false),
       tracer_(NULL),
       migration_slots_buffer_(NULL),
       heap_(NULL),
@@ -550,16 +551,15 @@
 
 
 void MarkCompactCollector::WaitUntilSweepingCompleted() {
-  if (sweeping_pending_) {
-    for (int i = 0; i < FLAG_sweeper_threads; i++) {
-      heap()->isolate()->sweeper_threads()[i]->WaitForSweeperThread();
-    }
-    sweeping_pending_ = false;
-    StealMemoryFromSweeperThreads(heap()->paged_space(OLD_DATA_SPACE));
-    StealMemoryFromSweeperThreads(heap()->paged_space(OLD_POINTER_SPACE));
-    heap()->paged_space(OLD_DATA_SPACE)->ResetUnsweptFreeBytes();
-    heap()->paged_space(OLD_POINTER_SPACE)->ResetUnsweptFreeBytes();
+  ASSERT(sweeping_pending_ == true);
+  for (int i = 0; i < FLAG_sweeper_threads; i++) {
+    heap()->isolate()->sweeper_threads()[i]->WaitForSweeperThread();
   }
+  sweeping_pending_ = false;
+  StealMemoryFromSweeperThreads(heap()->paged_space(OLD_DATA_SPACE));
+  StealMemoryFromSweeperThreads(heap()->paged_space(OLD_POINTER_SPACE));
+  heap()->paged_space(OLD_DATA_SPACE)->ResetUnsweptFreeBytes();
+  heap()->paged_space(OLD_POINTER_SPACE)->ResetUnsweptFreeBytes();
 }
 
 
@@ -908,7 +908,7 @@
 
   ASSERT(!FLAG_never_compact || !FLAG_always_compact);
 
-  if (AreSweeperThreadsActivated() && FLAG_concurrent_sweeping) {
+  if (IsConcurrentSweepingInProgress()) {
     // Instead of waiting we could also abort the sweeper threads here.
     WaitUntilSweepingCompleted();
     FinalizeSweeping();
@@ -1062,16 +1062,6 @@
 }
 
 
-bool CodeFlusher::ContainsCandidate(SharedFunctionInfo* shared_info) {
-  SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
-  while (candidate != NULL) {
-    if (candidate == shared_info) return true;
-    candidate = GetNextCandidate(candidate);
-  }
-  return false;
-}
-
-
 void CodeFlusher::EvictCandidate(SharedFunctionInfo* shared_info) {
   // Make sure previous flushing decisions are revisited.
   isolate_->heap()->incremental_marking()->RecordWrites(shared_info);
@@ -3771,10 +3761,10 @@
 
   PageIterator it(space);
 
-  intptr_t freed_bytes = 0;
   int pages_swept = 0;
   bool lazy_sweeping_active = false;
   bool unused_page_present = false;
+  bool parallel_sweeping_active = false;
 
   while (it.has_next()) {
     Page* p = it.next();
@@ -3810,15 +3800,6 @@
       unused_page_present = true;
     }
 
-    if (lazy_sweeping_active) {
-      if (FLAG_gc_verbose) {
-        PrintF("Sweeping 0x%" V8PRIxPTR " lazily postponed.\n",
-               reinterpret_cast<intptr_t>(p));
-      }
-      space->IncreaseUnsweptFreeBytes(p);
-      continue;
-    }
-
     switch (sweeper) {
       case CONSERVATIVE: {
         if (FLAG_gc_verbose) {
@@ -3830,24 +3811,42 @@
         break;
       }
       case LAZY_CONSERVATIVE: {
-        if (FLAG_gc_verbose) {
-          PrintF("Sweeping 0x%" V8PRIxPTR " conservatively as needed.\n",
-                 reinterpret_cast<intptr_t>(p));
+        if (lazy_sweeping_active) {
+          if (FLAG_gc_verbose) {
+            PrintF("Sweeping 0x%" V8PRIxPTR " lazily postponed.\n",
+                   reinterpret_cast<intptr_t>(p));
+          }
+          space->IncreaseUnsweptFreeBytes(p);
+        } else {
+          if (FLAG_gc_verbose) {
+            PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n",
+                   reinterpret_cast<intptr_t>(p));
+          }
+          SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+          pages_swept++;
+          space->SetPagesToSweep(p->next_page());
+          lazy_sweeping_active = true;
         }
-        freed_bytes += SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
-        pages_swept++;
-        space->SetPagesToSweep(p->next_page());
-        lazy_sweeping_active = true;
         break;
       }
       case CONCURRENT_CONSERVATIVE:
       case PARALLEL_CONSERVATIVE: {
-        if (FLAG_gc_verbose) {
-          PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n",
-                 reinterpret_cast<intptr_t>(p));
+        if (!parallel_sweeping_active) {
+          if (FLAG_gc_verbose) {
+            PrintF("Sweeping 0x%" V8PRIxPTR " conservatively.\n",
+                   reinterpret_cast<intptr_t>(p));
+          }
+          SweepConservatively<SWEEP_SEQUENTIALLY>(space, NULL, p);
+          pages_swept++;
+          parallel_sweeping_active = true;
+        } else {
+          if (FLAG_gc_verbose) {
+            PrintF("Sweeping 0x%" V8PRIxPTR " conservatively in parallel.\n",
+                   reinterpret_cast<intptr_t>(p));
+          }
+          p->set_parallel_sweeping(1);
+          space->IncreaseUnsweptFreeBytes(p);
         }
-        p->set_parallel_sweeping(1);
-        space->IncreaseUnsweptFreeBytes(p);
         break;
       }
       case PRECISE: {
@@ -3896,7 +3895,7 @@
   // the map space last because freeing non-live maps overwrites them and
   // the other spaces rely on possibly non-live maps to get the sizes for
   // non-live objects.
-
+  SequentialSweepingScope scope(this);
   SweepSpace(heap()->old_pointer_space(), how_to_sweep);
   SweepSpace(heap()->old_data_space(), how_to_sweep);
 
diff --git a/src/mark-compact.h b/src/mark-compact.h
index b5d60fd..65d39d2 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -423,10 +423,6 @@
     if (GetNextCandidate(shared_info) == NULL) {
       SetNextCandidate(shared_info, shared_function_info_candidates_head_);
       shared_function_info_candidates_head_ = shared_info;
-    } else {
-      // TODO(mstarzinger): Active in release mode to flush out problems.
-      // Should be turned back into an ASSERT or removed completely.
-      CHECK(ContainsCandidate(shared_info));
     }
   }
 
@@ -438,8 +434,6 @@
     }
   }
 
-  bool ContainsCandidate(SharedFunctionInfo* shared_info);
-
   void EvictCandidate(SharedFunctionInfo* shared_info);
   void EvictCandidate(JSFunction* function);
 
@@ -698,6 +692,14 @@
 
   void FinalizeSweeping();
 
+  void set_sequential_sweeping(bool sequential_sweeping) {
+    sequential_sweeping_ = sequential_sweeping;
+  }
+
+  bool sequential_sweeping() const {
+    return sequential_sweeping_;
+  }
+
   // Parallel marking support.
   void MarkInParallel();
 
@@ -749,6 +751,8 @@
   // True if concurrent or parallel sweeping is currently in progress.
   bool sweeping_pending_;
 
+  bool sequential_sweeping_;
+
   // A pointer to the current stack-allocated GC tracer object during a full
   // collection (NULL before and after).
   GCTracer* tracer_;
@@ -904,6 +908,22 @@
 };
 
 
+class SequentialSweepingScope BASE_EMBEDDED {
+ public:
+  explicit SequentialSweepingScope(MarkCompactCollector *collector) :
+    collector_(collector) {
+    collector_->set_sequential_sweeping(true);
+  }
+
+  ~SequentialSweepingScope() {
+    collector_->set_sequential_sweeping(false);
+  }
+
+ private:
+  MarkCompactCollector* collector_;
+};
+
+
 const char* AllocationSpaceName(AllocationSpace space);
 
 } }  // namespace v8::internal
diff --git a/src/math.js b/src/math.js
index 4686328..0e02541 100644
--- a/src/math.js
+++ b/src/math.js
@@ -37,7 +37,7 @@
 function MathConstructor() {}
 %FunctionSetInstanceClassName(MathConstructor, 'Math');
 var $Math = new MathConstructor();
-$Math.__proto__ = $Object.prototype;
+%SetPrototype($Math, $Object.prototype);
 %SetProperty(global, "Math", $Math, DONT_ENUM);
 
 // ECMA 262 - 15.8.2.1
diff --git a/src/messages.js b/src/messages.js
index 14ba73f..7353444 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -1208,7 +1208,7 @@
 function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
   // Climb the prototype chain until we find the holder.
   while (error && !%HasLocalProperty(error, name)) {
-    error = error.__proto__;
+    error = %GetPrototype(error);
   }
   if (error === null) return void 0;
   if (!IS_OBJECT(error)) return error[name];
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index 962255d..4c11c7f 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -47,7 +47,7 @@
 bool CpuFeatures::initialized_ = false;
 #endif
 unsigned CpuFeatures::supported_ = 0;
-unsigned CpuFeatures::found_by_runtime_probing_ = 0;
+unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
 
 
 ExternalReference ExternalReference::cpu_features() {
@@ -63,7 +63,7 @@
 static uint64_t CpuFeaturesImpliedByCompiler() {
   uint64_t answer = 0;
 #ifdef CAN_USE_FPU_INSTRUCTIONS
-  answer |= 1u << FPU;
+  answer |= static_cast<uint64_t>(1) << FPU;
 #endif  // def CAN_USE_FPU_INSTRUCTIONS
 
 #ifdef __mips__
@@ -71,7 +71,7 @@
   // generation even when generating snapshots.  This won't work for cross
   // compilation.
 #if(defined(__mips_hard_float) && __mips_hard_float != 0)
-  answer |= 1u << FPU;
+  answer |= static_cast<uint64_t>(1) << FPU;
 #endif  // defined(__mips_hard_float) && __mips_hard_float != 0
 #endif  // def __mips__
 
@@ -129,15 +129,15 @@
 #if !defined(__mips__)
   // For the simulator=mips build, use FPU when FLAG_enable_fpu is enabled.
   if (FLAG_enable_fpu) {
-      supported_ |= 1u << FPU;
+      supported_ |= static_cast<uint64_t>(1) << FPU;
   }
 #else
   // Probe for additional features not already known to be available.
   if (OS::MipsCpuHasFeature(FPU)) {
     // This implementation also sets the FPU flags if
     // runtime detection of FPU returns true.
-    supported_ |= 1u << FPU;
-    found_by_runtime_probing_ |= 1u << FPU;
+    supported_ |= static_cast<uint64_t>(1) << FPU;
+    found_by_runtime_probing_only_ |= static_cast<uint64_t>(1) << FPU;
   }
 #endif
 }
@@ -874,7 +874,7 @@
                                  FPURegister fd,
                                  SecondaryField func) {
   ASSERT(fd.is_valid() && fs.is_valid() && ft.is_valid());
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   Instr instr = opcode | fmt | (ft.code() << kFtShift) | (fs.code() << kFsShift)
       | (fd.code() << kFdShift) | func;
   emit(instr);
@@ -888,7 +888,7 @@
                                  FPURegister fd,
                                  SecondaryField func) {
   ASSERT(fd.is_valid() && fr.is_valid() && fs.is_valid() && ft.is_valid());
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   Instr instr = opcode | (fr.code() << kFrShift) | (ft.code() << kFtShift)
       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
   emit(instr);
@@ -902,7 +902,7 @@
                                  FPURegister fd,
                                  SecondaryField func) {
   ASSERT(fd.is_valid() && fs.is_valid() && rt.is_valid());
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   Instr instr = opcode | fmt | (rt.code() << kRtShift)
       | (fs.code() << kFsShift) | (fd.code() << kFdShift) | func;
   emit(instr);
@@ -915,7 +915,7 @@
                                  FPUControlRegister fs,
                                  SecondaryField func) {
   ASSERT(fs.is_valid() && rt.is_valid());
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   Instr instr =
       opcode | fmt | (rt.code() << kRtShift) | (fs.code() << kFsShift) | func;
   emit(instr);
@@ -950,7 +950,7 @@
                                   FPURegister ft,
                                   int32_t j) {
   ASSERT(rs.is_valid() && ft.is_valid() && (is_int16(j) || is_uint16(j)));
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   Instr instr = opcode | (rs.code() << kRsShift) | (ft.code() << kFtShift)
       | (j & kImm16Mask);
   emit(instr);
@@ -1872,7 +1872,7 @@
 // Conditions.
 void Assembler::c(FPUCondition cond, SecondaryField fmt,
     FPURegister fs, FPURegister ft, uint16_t cc) {
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   ASSERT(is_uint3(cc));
   ASSERT((fmt & ~(31 << kRsShift)) == 0);
   Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift
@@ -1883,7 +1883,7 @@
 
 void Assembler::fcmp(FPURegister src1, const double src2,
       FPUCondition cond) {
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   ASSERT(src2 == 0.0);
   mtc1(zero_reg, f14);
   cvt_d_w(f14, f14);
@@ -1892,7 +1892,7 @@
 
 
 void Assembler::bc1f(int16_t offset, uint16_t cc) {
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   ASSERT(is_uint3(cc));
   Instr instr = COP1 | BC1 | cc << 18 | 0 << 16 | (offset & kImm16Mask);
   emit(instr);
@@ -1900,7 +1900,7 @@
 
 
 void Assembler::bc1t(int16_t offset, uint16_t cc) {
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   ASSERT(is_uint3(cc));
   Instr instr = COP1 | BC1 | cc << 18 | 1 << 16 | (offset & kImm16Mask);
   emit(instr);
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index d108edc..1177181 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -393,7 +393,7 @@
 
 
 // CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
 class CpuFeatures : public AllStatic {
  public:
   // Detect features of the target CPU. Set safe defaults if the serializer
@@ -407,88 +407,18 @@
     return (supported_ & (1u << f)) != 0;
   }
 
-
-#ifdef DEBUG
-  // Check whether a feature is currently enabled.
-  static bool IsEnabled(CpuFeature f) {
+  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
     ASSERT(initialized_);
-    Isolate* isolate = Isolate::UncheckedCurrent();
-    if (isolate == NULL) {
-      // When no isolate is available, work as if we're running in
-      // release mode.
-      return IsSupported(f);
-    }
-    unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
-    return (enabled & (1u << f)) != 0;
+    return (found_by_runtime_probing_only_ &
+            (static_cast<uint64_t>(1) << f)) != 0;
   }
-#endif
-
-  // Enable a specified feature within a scope.
-  class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
-   public:
-    explicit Scope(CpuFeature f) {
-      unsigned mask = 1u << f;
-      ASSERT(CpuFeatures::IsSupported(f));
-      ASSERT(!Serializer::enabled() ||
-             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
-      isolate_ = Isolate::UncheckedCurrent();
-      old_enabled_ = 0;
-      if (isolate_ != NULL) {
-        old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
-        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
-      }
-    }
-    ~Scope() {
-      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
-      if (isolate_ != NULL) {
-        isolate_->set_enabled_cpu_features(old_enabled_);
-      }
-    }
-
- private:
-    Isolate* isolate_;
-    unsigned old_enabled_;
-#else
-
- public:
-    explicit Scope(CpuFeature f) {}
-#endif
-  };
-
-  class TryForceFeatureScope BASE_EMBEDDED {
-   public:
-    explicit TryForceFeatureScope(CpuFeature f)
-        : old_supported_(CpuFeatures::supported_) {
-      if (CanForce()) {
-        CpuFeatures::supported_ |= (1u << f);
-      }
-    }
-
-    ~TryForceFeatureScope() {
-      if (CanForce()) {
-        CpuFeatures::supported_ = old_supported_;
-      }
-    }
-
-   private:
-    static bool CanForce() {
-      // It's only safe to temporarily force support of CPU features
-      // when there's only a single isolate, which is guaranteed when
-      // the serializer is enabled.
-      return Serializer::enabled();
-    }
-
-    const unsigned old_supported_;
-  };
 
  private:
 #ifdef DEBUG
   static bool initialized_;
 #endif
   static unsigned supported_;
-  static unsigned found_by_runtime_probing_;
+  static unsigned found_by_runtime_probing_only_;
 
   friend class ExternalReference;
   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 65081b9..8edfe71 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -555,34 +555,64 @@
   // ----------- S t a t e -------------
   //  -- a0     : number of arguments
   //  -- a1     : constructor function
+  //  -- a2     : type info cell
   //  -- ra     : return address
   //  -- sp[...]: constructor arguments
   // -----------------------------------
-  Label generic_constructor;
 
   if (FLAG_debug_code) {
     // The array construct code is only set for the builtin and internal
     // Array functions which always have a map.
     // Initial map for the builtin Array function should be a map.
-    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
-    __ And(t0, a2, Operand(kSmiTagMask));
+    __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
+    __ And(t0, a3, Operand(kSmiTagMask));
     __ Assert(ne, "Unexpected initial map for Array function (3)",
               t0, Operand(zero_reg));
-    __ GetObjectType(a2, a3, t0);
+    __ GetObjectType(a3, a3, t0);
     __ Assert(eq, "Unexpected initial map for Array function (4)",
               t0, Operand(MAP_TYPE));
+
+    if (FLAG_optimize_constructed_arrays) {
+      // We should either have undefined in a2 or a valid jsglobalpropertycell
+      Label okay_here;
+      Handle<Object> undefined_sentinel(
+          masm->isolate()->heap()->undefined_value(), masm->isolate());
+      Handle<Map> global_property_cell_map(
+          masm->isolate()->heap()->global_property_cell_map());
+      __ Branch(&okay_here, eq, a2, Operand(undefined_sentinel));
+      __ lw(a3, FieldMemOperand(a2, 0));
+      __ Assert(eq, "Expected property cell in register a3",
+                a3, Operand(global_property_cell_map));
+      __ bind(&okay_here);
+    }
   }
 
-  // Run the native code for the Array function called as a constructor.
-  ArrayNativeCode(masm, &generic_constructor);
+  if (FLAG_optimize_constructed_arrays) {
+    Label not_zero_case, not_one_case;
+    __ Branch(&not_zero_case, ne, a0, Operand(zero_reg));
+    ArrayNoArgumentConstructorStub no_argument_stub;
+    __ TailCallStub(&no_argument_stub);
 
-  // Jump to the generic construct code in case the specialized code cannot
-  // handle the construction.
-  __ bind(&generic_constructor);
+    __ bind(&not_zero_case);
+    __ Branch(&not_one_case, gt, a0, Operand(1));
+    ArraySingleArgumentConstructorStub single_argument_stub;
+    __ TailCallStub(&single_argument_stub);
 
-  Handle<Code> generic_construct_stub =
-      masm->isolate()->builtins()->JSConstructStubGeneric();
-  __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
+    __ bind(&not_one_case);
+    ArrayNArgumentsConstructorStub n_argument_stub;
+    __ TailCallStub(&n_argument_stub);
+  } else {
+    Label generic_constructor;
+    // Run the native code for the Array function called as a constructor.
+    ArrayNativeCode(masm, &generic_constructor);
+
+    // Jump to the generic construct code in case the specialized code cannot
+    // handle the construction.
+    __ bind(&generic_constructor);
+    Handle<Code> generic_construct_stub =
+        masm->isolate()->builtins()->JSConstructStubGeneric();
+    __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
+  }
 }
 
 
@@ -698,7 +728,7 @@
   // Load the empty string into a2, remove the receiver from the
   // stack, and jump back to the case where the argument is a string.
   __ bind(&no_arguments);
-  __ LoadRoot(argument, Heap::kEmptyStringRootIndex);
+  __ LoadRoot(argument, Heap::kempty_stringRootIndex);
   __ Drop(1);
   __ Branch(&argument_is_string);
 
@@ -1171,6 +1201,10 @@
     // Invoke the code and pass argc as a0.
     __ mov(a0, a3);
     if (is_construct) {
+      // No type feedback cell is available
+      Handle<Object> undefined_sentinel(
+          masm->isolate()->heap()->undefined_value(), masm->isolate());
+      __ li(a2, Operand(undefined_sentinel));
       CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
       __ CallStub(&stub);
     } else {
@@ -1375,12 +1409,6 @@
 
 
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
-  CpuFeatures::TryForceFeatureScope scope(VFP3);
-  if (!CpuFeatures::IsSupported(FPU)) {
-    __ Abort("Unreachable code: Cannot optimize without FPU support.");
-    return;
-  }
-
   // Lookup the function in the JavaScript frame and push it as an
   // argument to the on-stack replacement function.
   __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 4eba0fa..81ad1ef 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -74,6 +74,44 @@
 }
 
 
+static void InitializeArrayConstructorDescriptor(Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  // register state
+  // a1 -- constructor function
+  // a2 -- type info cell with elements kind
+  // a0 -- number of arguments to the constructor function
+  static Register registers[] = { a1, a2 };
+  descriptor->register_param_count_ = 2;
+  // stack param count needs (constructor pointer, and single argument)
+  descriptor->stack_parameter_count_ = &a0;
+  descriptor->register_params_ = registers;
+  descriptor->extra_expression_stack_count_ = 1;
+  descriptor->deoptimization_handler_ =
+      FUNCTION_ADDR(ArrayConstructor_StubFailure);
+}
+
+
+void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  InitializeArrayConstructorDescriptor(isolate, descriptor);
+}
+
+
+void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  InitializeArrayConstructorDescriptor(isolate, descriptor);
+}
+
+
+void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  InitializeArrayConstructorDescriptor(isolate, descriptor);
+}
+
+
 #define __ ACCESS_MASM(masm)
 
 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
@@ -614,7 +652,7 @@
                                    Register scratch1,
                                    Register scratch2) {
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ sra(scratch1, a0, kSmiTagSize);
     __ mtc1(scratch1, f14);
     __ cvt_d_w(f14, f14);
@@ -665,7 +703,7 @@
   // Handle loading a double from a heap number.
   if (CpuFeatures::IsSupported(FPU) &&
       destination == kFPURegisters) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Load the double from tagged HeapNumber to double register.
 
     // ARM uses a workaround here because of the unaligned HeapNumber
@@ -684,7 +722,7 @@
   // Handle loading a double from a smi.
   __ bind(&is_smi);
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Convert smi to double using FPU instructions.
     __ mtc1(scratch1, dst);
     __ cvt_d_w(dst, dst);
@@ -760,7 +798,7 @@
   Label done;
 
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ mtc1(int_scratch, single_scratch);
     __ cvt_d_w(double_dst, single_scratch);
     if (destination == kCoreRegisters) {
@@ -862,7 +900,7 @@
 
   // Load the number.
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Load the double value.
     __ ldc1(double_dst, FieldMemOperand(object, HeapNumber::kValueOffset));
 
@@ -959,7 +997,7 @@
   // Object is a heap number.
   // Convert the floating point value to a 32-bit integer.
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Load the double value.
     __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset));
 
@@ -1097,7 +1135,7 @@
   __ push(ra);
   __ PrepareCallCFunction(4, scratch);  // Two doubles are 4 arguments.
   if (!IsMipsSoftFloatABI) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // We are not using MIPS FPU instructions, and parameters for the runtime
     // function call are prepaired in a0-a3 registers, but function we are
     // calling is compiled with hard-float flag and expecting hard float ABI
@@ -1113,7 +1151,7 @@
   }
   // Store answer in the overwritable heap number.
   if (!IsMipsSoftFloatABI) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Double returned in register f0.
     __ sdc1(f0, FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
   } else {
@@ -1337,7 +1375,7 @@
   // Rhs is a smi, lhs is a number.
   // Convert smi rhs to double.
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ sra(at, rhs, kSmiTagSize);
     __ mtc1(at, f14);
     __ cvt_d_w(f14, f14);
@@ -1376,7 +1414,7 @@
   // Lhs is a smi, rhs is a number.
   // Convert smi lhs to double.
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ sra(at, lhs, kSmiTagSize);
     __ mtc1(at, f12);
     __ cvt_d_w(f12, f12);
@@ -1404,7 +1442,7 @@
 void EmitNanCheck(MacroAssembler* masm, Condition cc) {
   bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Lhs and rhs are already loaded to f12 and f14 register pairs.
     __ Move(t0, t1, f14);
     __ Move(t2, t3, f12);
@@ -1471,7 +1509,7 @@
     // Exception: 0 and -0.
     bool exp_first = (HeapNumber::kExponentOffset == HeapNumber::kValueOffset);
     if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm, FPU);
       // Lhs and rhs are already loaded to f12 and f14 register pairs.
       __ Move(t0, t1, f14);
       __ Move(t2, t3, f12);
@@ -1527,7 +1565,7 @@
     __ pop(ra);  // Because this function returns int, result is in v0.
     __ Ret();
   } else {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     Label equal, less_than;
     __ BranchF(&equal, NULL, eq, f12, f14);
     __ BranchF(&less_than, NULL, lt, f12, f14);
@@ -1577,12 +1615,13 @@
     // Check for oddballs: true, false, null, undefined.
     __ Branch(&return_not_equal, eq, a3, Operand(ODDBALL_TYPE));
 
-    // Now that we have the types we might as well check for symbol-symbol.
-    // Ensure that no non-strings have the symbol bit set.
-    STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsSymbolMask);
-    STATIC_ASSERT(kSymbolTag != 0);
+    // Now that we have the types we might as well check for
+    // internalized-internalized.
+    // Ensure that no non-strings have the internalized bit set.
+    STATIC_ASSERT(LAST_TYPE < kNotStringTag + kIsInternalizedMask);
+    STATIC_ASSERT(kInternalizedTag != 0);
     __ And(t2, a2, Operand(a3));
-    __ And(t0, t2, Operand(kIsSymbolMask));
+    __ And(t0, t2, Operand(kIsInternalizedMask));
     __ Branch(&return_not_equal, ne, t0, Operand(zero_reg));
 }
 
@@ -1602,7 +1641,7 @@
   // Both are heap numbers. Load them up then jump to the code we have
   // for that.
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ ldc1(f12, FieldMemOperand(lhs, HeapNumber::kValueOffset));
     __ ldc1(f14, FieldMemOperand(rhs, HeapNumber::kValueOffset));
   } else {
@@ -1620,30 +1659,30 @@
 }
 
 
-// Fast negative check for symbol-to-symbol equality.
-static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
-                                         Register lhs,
-                                         Register rhs,
-                                         Label* possible_strings,
-                                         Label* not_both_strings) {
+// Fast negative check for internalized-to-internalized equality.
+static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
+                                                     Register lhs,
+                                                     Register rhs,
+                                                     Label* possible_strings,
+                                                     Label* not_both_strings) {
   ASSERT((lhs.is(a0) && rhs.is(a1)) ||
          (lhs.is(a1) && rhs.is(a0)));
 
   // a2 is object type of lhs.
-  // Ensure that no non-strings have the symbol bit set.
+  // Ensure that no non-strings have the internalized bit set.
   Label object_test;
-  STATIC_ASSERT(kSymbolTag != 0);
+  STATIC_ASSERT(kInternalizedTag != 0);
   __ And(at, a2, Operand(kIsNotStringMask));
   __ Branch(&object_test, ne, at, Operand(zero_reg));
-  __ And(at, a2, Operand(kIsSymbolMask));
+  __ And(at, a2, Operand(kIsInternalizedMask));
   __ Branch(possible_strings, eq, at, Operand(zero_reg));
   __ GetObjectType(rhs, a3, a3);
   __ Branch(not_both_strings, ge, a3, Operand(FIRST_NONSTRING_TYPE));
-  __ And(at, a3, Operand(kIsSymbolMask));
+  __ And(at, a3, Operand(kIsInternalizedMask));
   __ Branch(possible_strings, eq, at, Operand(zero_reg));
 
-  // Both are symbols. We already checked they weren't the same pointer
-  // so they are not equal.
+  // Both are internalized strings. We already checked they weren't the same
+  // pointer so they are not equal.
   __ Ret(USE_DELAY_SLOT);
   __ li(v0, Operand(1));   // Non-zero indicates not equal.
 
@@ -1697,7 +1736,7 @@
   if (!object_is_smi) {
     __ JumpIfSmi(object, &is_smi);
     if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm, FPU);
       __ CheckMap(object,
                   scratch1,
                   Heap::kHeapNumberMapRootIndex,
@@ -1789,7 +1828,7 @@
     __ CheckMap(input, scratch, Heap::kHeapNumberMapRootIndex, fail,
                 DONT_DO_SMI_CHECK);
   }
-  // We could be strict about symbol/string here, but as long as
+  // We could be strict about internalized/string here, but as long as
   // hydrogen doesn't care, the stub doesn't have to care either.
   __ bind(&ok);
 }
@@ -1850,7 +1889,7 @@
 
   Isolate* isolate = masm->isolate();
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     Label nan;
     __ li(t0, Operand(LESS));
     __ li(t1, Operand(GREATER));
@@ -1902,25 +1941,28 @@
     EmitStrictTwoHeapObjectCompare(masm, lhs, rhs);
   }
 
-  Label check_for_symbols;
+  Label check_for_internalized_strings;
   Label flat_string_check;
   // Check for heap-number-heap-number comparison. Can jump to slow case,
   // or load both doubles and jump to the code that handles
-  // that case. If the inputs are not doubles then jumps to check_for_symbols.
+  // that case. If the inputs are not doubles then jumps to
+  // check_for_internalized_strings.
   // In this case a2 will contain the type of lhs_.
   EmitCheckForTwoHeapNumbers(masm,
                              lhs,
                              rhs,
                              &both_loaded_as_doubles,
-                             &check_for_symbols,
+                             &check_for_internalized_strings,
                              &flat_string_check);
 
-  __ bind(&check_for_symbols);
+  __ bind(&check_for_internalized_strings);
   if (cc == eq && !strict()) {
-    // Returns an answer for two symbols or two detectable objects.
+    // Returns an answer for two internalized strings or two
+    // detectable objects.
     // Otherwise jumps to string case or not both strings case.
     // Assumes that a2 is the type of lhs_ on entry.
-    EmitCheckForSymbolsOrObjects(masm, lhs, rhs, &flat_string_check, &slow);
+    EmitCheckForInternalizedStringsOrObjects(
+        masm, lhs, rhs, &flat_string_check, &slow);
   }
 
   // Check for both being sequential ASCII strings, and inline if that is the
@@ -1982,7 +2024,7 @@
 // it, too: zero for false, and a non-zero value for true.
 void ToBooleanStub::Generate(MacroAssembler* masm) {
   // This stub uses FPU instructions.
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm, FPU);
 
   Label patch;
   const Register map = t5.is(tos_) ? t3 : t5;
@@ -2097,7 +2139,7 @@
   // restore them.
   __ MultiPush(kJSCallerSaved | ra.bit());
   if (save_doubles_ == kSaveFPRegs) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ MultiPushFPU(kCallerSavedFPU);
   }
   const int argument_count = 1;
@@ -2111,7 +2153,7 @@
       ExternalReference::store_buffer_overflow_function(masm->isolate()),
       argument_count);
   if (save_doubles_ == kSaveFPRegs) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ MultiPopFPU(kCallerSavedFPU);
   }
 
@@ -2344,7 +2386,7 @@
 
   if (CpuFeatures::IsSupported(FPU)) {
     // Convert the int32 in a1 to the heap number in v0. a2 is corrupted.
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ mtc1(a1, f0);
     __ cvt_d_w(f0, f0);
     __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset));
@@ -2689,7 +2731,7 @@
         // Using FPU registers:
         // f12: Left value.
         // f14: Right value.
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm, FPU);
         switch (op) {
         case Token::ADD:
           __ add_d(f10, f12, f14);
@@ -2821,7 +2863,7 @@
       if (CpuFeatures::IsSupported(FPU)) {
         // Convert the int32 in a2 to the heap number in a0. As
         // mentioned above SHR needs to always produce a positive result.
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm, FPU);
         __ mtc1(a2, f0);
         if (op == Token::SHR) {
           __ Cvt_d_uw(f0, f0, f22);
@@ -3016,7 +3058,7 @@
                                                    &transition);
 
       if (destination == FloatingPointHelper::kFPURegisters) {
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm, FPU);
         Label return_heap_number;
         switch (op_) {
           case Token::ADD:
@@ -3230,7 +3272,7 @@
                                                 mode_);
 
       if (CpuFeatures::IsSupported(FPU)) {
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm, FPU);
 
         if (op_ != Token::SHR) {
           // Convert the result to a floating point value.
@@ -3434,7 +3476,7 @@
   const bool tagged = (argument_type_ == TAGGED);
 
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
 
     if (tagged) {
       // Argument is a number and is on stack and in a0.
@@ -3544,7 +3586,7 @@
                                  1);
   } else {
     ASSERT(CpuFeatures::IsSupported(FPU));
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
 
     Label no_update;
     Label skip_cache;
@@ -3672,7 +3714,7 @@
 
 
 void MathPowStub::Generate(MacroAssembler* masm) {
-  CpuFeatures::Scope fpu_scope(FPU);
+  CpuFeatureScope fpu_scope(masm, FPU);
   const Register base = a1;
   const Register exponent = a2;
   const Register heapnumbermap = t1;
@@ -3915,21 +3957,15 @@
   // These stubs might already be in the snapshot, detect that and don't
   // regenerate, which would lead to code stub initialization state being messed
   // up.
-  Code* save_doubles_code = NULL;
-  Code* store_buffer_overflow_code = NULL;
-  if (!save_doubles.FindCodeInCache(&save_doubles_code, ISOLATE)) {
-    if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope2(FPU);
-      save_doubles_code = *save_doubles.GetCode(isolate);
-      store_buffer_overflow_code = *stub.GetCode(isolate);
-    } else {
-      save_doubles_code = *save_doubles.GetCode(isolate);
-      store_buffer_overflow_code = *stub.GetCode(isolate);
-    }
+  Code* save_doubles_code;
+  if (!save_doubles.FindCodeInCache(&save_doubles_code, isolate)) {
+    save_doubles_code = *save_doubles.GetCode(isolate);
     save_doubles_code->set_is_pregenerated(true);
+
+    Code* store_buffer_overflow_code = *stub.GetCode(isolate);
     store_buffer_overflow_code->set_is_pregenerated(true);
   }
-  ISOLATE->set_fp_stubs_generated(true);
+  isolate->set_fp_stubs_generated(true);
 }
 
 
@@ -4185,7 +4221,7 @@
   __ MultiPush(kCalleeSaved | ra.bit());
 
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Save callee-saved FPU registers.
     __ MultiPushFPU(kCalleeSavedFPU);
     // Set up the reserved register for 0.0.
@@ -4334,7 +4370,7 @@
   __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset);
 
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     // Restore callee-saved fpu registers.
     __ MultiPopFPU(kCalleeSavedFPU);
   }
@@ -4534,7 +4570,7 @@
     //  -- a1    : receiver
     // -----------------------------------
     __ Branch(&miss, ne, a0,
-        Operand(masm->isolate()->factory()->length_symbol()));
+        Operand(masm->isolate()->factory()->length_string()));
     receiver = a1;
   } else {
     ASSERT(kind() == Code::LOAD_IC);
@@ -4563,7 +4599,7 @@
     //  -- a1    : receiver
     // -----------------------------------
     __ Branch(&miss, ne, a0,
-        Operand(masm->isolate()->factory()->prototype_symbol()));
+        Operand(masm->isolate()->factory()->prototype_string()));
     receiver = a1;
   } else {
     ASSERT(kind() == Code::LOAD_IC);
@@ -4592,7 +4628,7 @@
     //  -- a1    : receiver
     // -----------------------------------
     __ Branch(&miss, ne, a0,
-        Operand(masm->isolate()->factory()->length_symbol()));
+        Operand(masm->isolate()->factory()->length_string()));
     receiver = a1;
   } else {
     ASSERT(kind() == Code::LOAD_IC);
@@ -4630,7 +4666,7 @@
     //  -- a2    : receiver
     // -----------------------------------
     __ Branch(&miss, ne, a1,
-        Operand(masm->isolate()->factory()->length_symbol()));
+        Operand(masm->isolate()->factory()->length_string()));
     receiver = a2;
     value = a0;
   } else {
@@ -5224,7 +5260,7 @@
   // (3) Cons string.  Check that it's flat.
   // Replace subject with first string and reload instance type.
   __ lw(a0, FieldMemOperand(subject, ConsString::kSecondOffset));
-  __ LoadRoot(a1, Heap::kEmptyStringRootIndex);
+  __ LoadRoot(a1, Heap::kempty_stringRootIndex);
   __ Branch(&runtime, ne, a0, Operand(a1));
   __ lw(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
 
@@ -5620,12 +5656,13 @@
 }
 
 
-static void GenerateRecordCallTarget(MacroAssembler* masm) {
+static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) {
   // Cache the called function in a global property cell.  Cache states
   // are uninitialized, monomorphic (indicated by a JSFunction), and
   // megamorphic.
   // a1 : the function to call
   // a2 : cache cell for call target
+  ASSERT(!FLAG_optimize_constructed_arrays);
   Label done;
 
   ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
@@ -5662,6 +5699,78 @@
 }
 
 
+static void GenerateRecordCallTarget(MacroAssembler* masm) {
+  // Cache the called function in a global property cell.  Cache states
+  // are uninitialized, monomorphic (indicated by a JSFunction), and
+  // megamorphic.
+  // a1 : the function to call
+  // a2 : cache cell for call target
+  ASSERT(FLAG_optimize_constructed_arrays);
+  Label initialize, done, miss, megamorphic, not_array_function;
+
+  ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
+            masm->isolate()->heap()->undefined_value());
+  ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
+            masm->isolate()->heap()->the_hole_value());
+
+  // Load the cache state into a3.
+  __ lw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
+
+  // A monomorphic cache hit or an already megamorphic state: invoke the
+  // function without changing the state.
+  __ Branch(&done, eq, a3, Operand(a1));
+  __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
+  __ Branch(&done, eq, a3, Operand(at));
+
+  // Special handling of the Array() function, which caches not only the
+  // monomorphic Array function but the initial ElementsKind with special
+  // sentinels
+  Handle<Object> terminal_kind_sentinel =
+      TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
+                                                  LAST_FAST_ELEMENTS_KIND);
+  __ Branch(&miss, ne, a3, Operand(terminal_kind_sentinel));
+  // Make sure the function is the Array() function
+  __ LoadArrayFunction(a3);
+  __ Branch(&megamorphic, ne, a1, Operand(a3));
+  __ jmp(&done);
+
+  __ bind(&miss);
+
+  // A monomorphic miss (i.e, here the cache is not uninitialized) goes
+  // megamorphic.
+  __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
+  __ Branch(&initialize, eq, a3, Operand(at));
+  // MegamorphicSentinel is an immortal immovable object (undefined) so no
+  // write-barrier is needed.
+  __ bind(&megamorphic);
+  __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
+  __ sw(at, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
+
+  // An uninitialized cache is patched with the function or sentinel to
+  // indicate the ElementsKind if function is the Array constructor.
+  __ bind(&initialize);
+  // Make sure the function is the Array() function
+  __ LoadArrayFunction(a3);
+  __ Branch(&not_array_function, ne, a1, Operand(a3));
+
+  // The target function is the Array constructor, install a sentinel value in
+  // the constructor's type info cell that will track the initial ElementsKind
+  // that should be used for the array when its constructed.
+  Handle<Object> initial_kind_sentinel =
+      TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
+          GetInitialFastElementsKind());
+  __ li(a3, Operand(initial_kind_sentinel));
+  __ sw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
+  __ Branch(&done);
+
+  __ bind(&not_array_function);
+  __ sw(a1, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
+  // No need for a write barrier here - cells are rescanned.
+
+  __ bind(&done);
+}
+
+
 void CallFunctionStub::Generate(MacroAssembler* masm) {
   // a1 : the function to call
   // a2 : cache cell for call target
@@ -5694,7 +5803,11 @@
   __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
 
   if (RecordCallTarget()) {
-    GenerateRecordCallTarget(masm);
+    if (FLAG_optimize_constructed_arrays) {
+      GenerateRecordCallTarget(masm);
+    } else {
+      GenerateRecordCallTargetNoArray(masm);
+    }
   }
 
   // Fast-case: Invoke the function now.
@@ -5768,13 +5881,19 @@
   __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
 
   if (RecordCallTarget()) {
-    GenerateRecordCallTarget(masm);
+    if (FLAG_optimize_constructed_arrays) {
+      GenerateRecordCallTarget(masm);
+    } else {
+      GenerateRecordCallTargetNoArray(masm);
+    }
   }
 
   // Jump to the function-specific construct stub.
-  __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
-  __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kConstructStubOffset));
-  __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
+  Register jmp_reg = FLAG_optimize_constructed_arrays ? a3 : a2;
+  __ lw(jmp_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
+  __ lw(jmp_reg, FieldMemOperand(jmp_reg,
+                                 SharedFunctionInfo::kConstructStubOffset));
+  __ Addu(at, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(at);
 
   // a0: number of arguments
@@ -6102,7 +6221,7 @@
   Register scratch = scratch3;
 
   // Make sure that both characters are not digits as such strings has a
-  // different hash algorithm. Don't try to look for these in the symbol table.
+  // different hash algorithm. Don't try to look for these in the string table.
   Label not_array_index;
   __ Subu(scratch, c1, Operand(static_cast<int>('0')));
   __ Branch(&not_array_index,
@@ -6137,21 +6256,21 @@
   // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
   // hash:  hash of two character string.
 
-  // Load symbol table.
-  // Load address of first element of the symbol table.
+  // Load string table.
+  // Load address of first element of the string table.
   Register string_table = c2;
   __ LoadRoot(string_table, Heap::kStringTableRootIndex);
 
   Register undefined = scratch4;
   __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
 
-  // Calculate capacity mask from the symbol table capacity.
+  // Calculate capacity mask from the string table capacity.
   Register mask = scratch2;
   __ lw(mask, FieldMemOperand(string_table, StringTable::kCapacityOffset));
   __ sra(mask, mask, 1);
   __ Addu(mask, mask, -1);
 
-  // Calculate untagged address of the first element of the symbol table.
+  // Calculate untagged address of the first element of the string table.
   Register first_string_table_element = string_table;
   __ Addu(first_string_table_element, string_table,
          Operand(StringTable::kElementsStartOffset - kHeapObjectTag));
@@ -6161,17 +6280,17 @@
   // hash:  hash of two character string
   // mask:  capacity mask
   // first_string_table_element: address of the first element of
-  //                             the symbol table
+  //                             the string table
   // undefined: the undefined object
   // scratch: -
 
-  // Perform a number of probes in the symbol table.
+  // Perform a number of probes in the string table.
   const int kProbes = 4;
   Label found_in_string_table;
   Label next_probe[kProbes];
   Register candidate = scratch5;  // Scratch register contains candidate.
   for (int i = 0; i < kProbes; i++) {
-    // Calculate entry in symbol table.
+    // Calculate entry in string table.
     if (i > 0) {
       __ Addu(candidate, hash, Operand(StringTable::GetProbeOffset(i)));
     } else {
@@ -6195,7 +6314,7 @@
     // Must be the hole (deleted entry).
     if (FLAG_debug_code) {
       __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
-      __ Assert(eq, "oddball in symbol table is not undefined or the hole",
+      __ Assert(eq, "oddball in string table is not undefined or the hole",
           scratch, Operand(candidate));
     }
     __ jmp(&next_probe[i]);
@@ -6356,7 +6475,7 @@
   __ Branch(&sliced_string, ne, t0, Operand(zero_reg));
   // Cons string.  Check whether it is flat, then fetch first part.
   __ lw(t1, FieldMemOperand(v0, ConsString::kSecondOffset));
-  __ LoadRoot(t0, Heap::kEmptyStringRootIndex);
+  __ LoadRoot(t0, Heap::kempty_stringRootIndex);
   __ Branch(&runtime, ne, t1, Operand(t0));
   __ lw(t1, FieldMemOperand(v0, ConsString::kFirstOffset));
   // Update instance type.
@@ -6739,8 +6858,8 @@
   // Adding two lengths can't overflow.
   STATIC_ASSERT(String::kMaxLength < String::kMaxLength * 2);
   __ Addu(t2, a2, Operand(a3));
-  // Use the symbol table when adding two one character strings, as it
-  // helps later optimizations to return a symbol here.
+  // Use the string table when adding two one character strings, as it
+  // helps later optimizations to return a string here.
   __ Branch(&longer_than_two, ne, t2, Operand(2));
 
   // Check that both strings are non-external ASCII strings.
@@ -6757,7 +6876,7 @@
   __ lbu(a2, FieldMemOperand(a0, SeqOneByteString::kHeaderSize));
   __ lbu(a3, FieldMemOperand(a1, SeqOneByteString::kHeaderSize));
 
-  // Try to lookup two character string in symbol table. If it is not found
+  // Try to lookup two character string in string table. If it is not found
   // just allocate a new one.
   Label make_two_character_string;
   StringHelper::GenerateTwoCharacterStringTableProbe(
@@ -7023,7 +7142,7 @@
   // Inlining the double comparison and falling back to the general compare
   // stub if NaN is involved or FPU is unsupported.
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
 
     // Load left and right operand.
     Label done, left, left_smi, right_smi;
@@ -7102,7 +7221,7 @@
 }
 
 
-void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
+void ICCompareStub::GenerateInternalizedStrings(MacroAssembler* masm) {
   ASSERT(state_ == CompareIC::SYMBOL);
   Label miss;
 
@@ -7115,14 +7234,14 @@
   // Check that both operands are heap objects.
   __ JumpIfEitherSmi(left, right, &miss);
 
-  // Check that both operands are symbols.
+  // Check that both operands are internalized strings.
   __ lw(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
   __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
   __ lbu(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
   __ lbu(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
-  STATIC_ASSERT(kSymbolTag != 0);
+  STATIC_ASSERT(kInternalizedTag != 0);
   __ And(tmp1, tmp1, Operand(tmp2));
-  __ And(tmp1, tmp1, kIsSymbolMask);
+  __ And(tmp1, tmp1, kIsInternalizedMask);
   __ Branch(&miss, eq, tmp1, Operand(zero_reg));
   // Make sure a0 is non-zero. At this point input operands are
   // guaranteed to be non-zero.
@@ -7130,7 +7249,7 @@
   STATIC_ASSERT(EQUAL == 0);
   STATIC_ASSERT(kSmiTag == 0);
   __ mov(v0, right);
-  // Symbols are compared by identity.
+  // Internalized strings are compared by identity.
   __ Ret(ne, left, Operand(right));
   __ li(v0, Operand(Smi::FromInt(EQUAL)));
   __ Ret();
@@ -7180,13 +7299,13 @@
 
   // Handle not identical strings.
 
-  // Check that both strings are symbols. If they are, we're done
+  // Check that both strings are internalized strings. If they are, we're done
   // because we already know they are not identical.
   if (equality) {
     ASSERT(GetCondition() == eq);
-    STATIC_ASSERT(kSymbolTag != 0);
+    STATIC_ASSERT(kInternalizedTag != 0);
     __ And(tmp3, tmp1, Operand(tmp2));
-    __ And(tmp5, tmp3, Operand(kIsSymbolMask));
+    __ And(tmp5, tmp3, Operand(kIsInternalizedMask));
     Label is_symbol;
     __ Branch(&is_symbol, eq, tmp5, Operand(zero_reg));
     // Make sure a0 is non-zero. At this point input operands are
@@ -7389,11 +7508,11 @@
       Label the_hole;
       __ Branch(&the_hole, eq, entity_name, Operand(tmp));
 
-      // Check if the entry name is not a symbol.
+      // Check if the entry name is not a internalized string.
       __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
       __ lbu(entity_name,
              FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
-      __ And(scratch0, entity_name, Operand(kIsSymbolMask));
+      __ And(scratch0, entity_name, Operand(kIsInternalizedMask));
       __ Branch(miss, eq, scratch0, Operand(zero_reg));
 
       __ bind(&the_hole);
@@ -7569,11 +7688,11 @@
     __ Branch(&in_dictionary, eq, entry_key, Operand(key));
 
     if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
-      // Check if the entry name is not a symbol.
+      // Check if the entry name is not a internalized string.
       __ lw(entry_key, FieldMemOperand(entry_key, HeapObject::kMapOffset));
       __ lbu(entry_key,
              FieldMemOperand(entry_key, Map::kInstanceTypeOffset));
-      __ And(result, entry_key, Operand(kIsSymbolMask));
+      __ And(result, entry_key, Operand(kIsInternalizedMask));
       __ Branch(&maybe_in_dictionary, eq, result, Operand(zero_reg));
     }
   }
diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h
index 7647916..37db215 100644
--- a/src/mips/code-stubs-mips.h
+++ b/src/mips/code-stubs-mips.h
@@ -173,9 +173,9 @@
                                          int flags);
 
 
-  // Probe the symbol table for a two character string. If the string is
+  // Probe the string table for a two character string. If the string is
   // not found by probing a jump to the label not_found is performed. This jump
-  // does not guarantee that the string is not in the symbol table. If the
+  // does not guarantee that the string is not in the string table. If the
   // string is found the code falls through with the string in register r0.
   // Contents of both c1 and c2 registers are modified. At the exit c1 is
   // guaranteed to contain halfword with low and high bytes equal to
@@ -484,7 +484,7 @@
     void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
       masm->MultiPush((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
       if (mode == kSaveFPRegs) {
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm, FPU);
         masm->MultiPushFPU(kCallerSavedFPU);
       }
     }
@@ -492,7 +492,7 @@
     inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
                                            SaveFPRegsMode mode) {
       if (mode == kSaveFPRegs) {
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm, FPU);
         masm->MultiPopFPU(kCallerSavedFPU);
       }
       masm->MultiPop((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index d5ab329..f5cb5e4 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -72,7 +72,7 @@
   MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
 
   {
-    CpuFeatures::Scope use_fpu(FPU);
+    CpuFeatureScope use_fpu(&masm, FPU);
     DoubleRegister input = f12;
     DoubleRegister result = f0;
     DoubleRegister double_scratch1 = f4;
@@ -278,7 +278,7 @@
 
   // Normal smi, convert to double and store.
   if (fpu_supported) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ mtc1(t5, f0);
     __ cvt_d_w(f0, f0);
     __ sdc1(f0, MemOperand(t3));
@@ -475,7 +475,7 @@
   // the string.
   __ bind(&cons_string);
   __ lw(result, FieldMemOperand(string, ConsString::kSecondOffset));
-  __ LoadRoot(at, Heap::kEmptyStringRootIndex);
+  __ LoadRoot(at, Heap::kempty_stringRootIndex);
   __ Branch(call_runtime, ne, result, Operand(at));
   // Get the first of the two strings and load its instance type.
   __ lw(string, FieldMemOperand(string, ConsString::kFirstOffset));
diff --git a/src/mips/constants-mips.h b/src/mips/constants-mips.h
index e7c55f5..139e7db 100644
--- a/src/mips/constants-mips.h
+++ b/src/mips/constants-mips.h
@@ -429,7 +429,9 @@
 
 // ----- Emulated conditions.
 // On MIPS we use this enum to abstract from conditionnal branch instructions.
-// the 'U' prefix is used to specify unsigned comparisons.
+// The 'U' prefix is used to specify unsigned comparisons.
+// Oppposite conditions must be paired as odd/even numbers
+// because 'NegateCondition' function flips LSB to negate condition.
 enum Condition {
   // Any value < 0 is considered no_condition.
   kNoCondition  = -1,
@@ -450,8 +452,10 @@
   greater_equal = 13,
   less_equal    = 14,
   greater       = 15,
+  ueq           = 16,  // Unordered or Equal.
+  nue           = 17,  // Not (Unordered or Equal).
 
-  cc_always     = 16,
+  cc_always     = 18,
 
   // Aliases.
   carry         = Uless,
diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc
index 8e96cd5..c315670 100644
--- a/src/mips/deoptimizer-mips.cc
+++ b/src/mips/deoptimizer-mips.cc
@@ -531,128 +531,6 @@
 }
 
 
-void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
-                                              int frame_index) {
-  Builtins* builtins = isolate_->builtins();
-  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
-  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
-  unsigned height = iterator->Next();
-  unsigned height_in_bytes = height * kPointerSize;
-  if (FLAG_trace_deopt) {
-    PrintF("  translating construct stub => height=%d\n", height_in_bytes);
-  }
-
-  unsigned fixed_frame_size = 8 * kPointerSize;
-  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
-
-  // Allocate and store the output frame description.
-  FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, function);
-  output_frame->SetFrameType(StackFrame::CONSTRUCT);
-
-  // Construct stub can not be topmost or bottommost.
-  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
-  ASSERT(output_[frame_index] == NULL);
-  output_[frame_index] = output_frame;
-
-  // The top address of the frame is computed from the previous
-  // frame's top and this frame's size.
-  uint32_t top_address;
-  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
-  output_frame->SetTop(top_address);
-
-  // Compute the incoming parameter translation.
-  int parameter_count = height;
-  unsigned output_offset = output_frame_size;
-  for (int i = 0; i < parameter_count; ++i) {
-    output_offset -= kPointerSize;
-    DoTranslateCommand(iterator, frame_index, output_offset);
-  }
-
-  // Read caller's PC from the previous frame.
-  output_offset -= kPointerSize;
-  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
-  output_frame->SetFrameSlot(output_offset, callers_pc);
-  if (FLAG_trace_deopt) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
-           top_address + output_offset, output_offset, callers_pc);
-  }
-
-  // Read caller's FP from the previous frame, and set this frame's FP.
-  output_offset -= kPointerSize;
-  intptr_t value = output_[frame_index - 1]->GetFp();
-  output_frame->SetFrameSlot(output_offset, value);
-  intptr_t fp_value = top_address + output_offset;
-  output_frame->SetFp(fp_value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
-           fp_value, output_offset, value);
-  }
-
-  // The context can be gotten from the previous frame.
-  output_offset -= kPointerSize;
-  value = output_[frame_index - 1]->GetContext();
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; context\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // A marker value is used in place of the function.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // The output frame reflects a JSConstructStubGeneric frame.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(construct_stub);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; code object\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // Number of incoming arguments.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
-           top_address + output_offset, output_offset, value, height - 1);
-  }
-
-  // Constructor function being invoked by the stub.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(function);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; constructor function\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // The newly allocated object was passed as receiver in the artificial
-  // constructor stub environment created by HEnvironment::CopyForInlining().
-  output_offset -= kPointerSize;
-  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  ASSERT(0 == output_offset);
-
-  uint32_t pc = reinterpret_cast<uint32_t>(
-      construct_stub->instruction_start() +
-      isolate_->heap()->construct_stub_deopt_pc_offset()->value());
-  output_frame->SetPc(pc);
-}
-
-
 // This code is very similar to ia32/arm code, but relies on register names
 // (fp, sp) and how the frame is laid out.
 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
@@ -868,7 +746,7 @@
       kDoubleSize * FPURegister::kMaxNumAllocatableRegisters;
 
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     // Save all FPU registers before messing with them.
     __ Subu(sp, sp, Operand(kDoubleRegsSize));
     for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
@@ -951,7 +829,7 @@
 
   int double_regs_offset = FrameDescription::double_registers_offset();
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     // Copy FPU registers to
     // double_registers_[DoubleRegister::kNumAllocatableRegisters]
     for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
@@ -1029,7 +907,7 @@
   __ Branch(&outer_push_loop, lt, t0, Operand(a1));
 
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
 
     __ lw(a1, MemOperand(a0, Deoptimizer::input_offset()));
     for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
diff --git a/src/mips/frames-mips.h b/src/mips/frames-mips.h
index 188e7d1..1568ce6 100644
--- a/src/mips/frames-mips.h
+++ b/src/mips/frames-mips.h
@@ -208,14 +208,30 @@
 
 class ArgumentsAdaptorFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+
   static const int kFrameSize =
       StandardFrameConstants::kFixedFrameSize + kPointerSize;
 };
 
 
+class ConstructFrameConstants : public AllStatic {
+ public:
+  // FP-relative.
+  static const int kImplicitReceiverOffset = -6 * kPointerSize;
+  static const int kConstructorOffset      = -5 * kPointerSize;
+  static const int kLengthOffset           = -4 * kPointerSize;
+  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+
+  static const int kFrameSize =
+      StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize;
+};
+
+
 class InternalFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
 };
 
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 5f44e539..7f2cf65 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1638,7 +1638,7 @@
         ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
         // Fall through.
       case ObjectLiteral::Property::COMPUTED:
-        if (key->handle()->IsSymbol()) {
+        if (key->handle()->IsInternalizedString()) {
           if (property->emit_store()) {
             VisitForAccumulatorValue(value);
             __ mov(a0, result_register());
@@ -1654,8 +1654,6 @@
           }
           break;
         }
-        // Fall through.
-      case ObjectLiteral::Property::PROTOTYPE:
         // Duplicate receiver on stack.
         __ lw(a0, MemOperand(sp));
         __ push(a0);
@@ -1669,6 +1667,17 @@
           __ Drop(3);
         }
         break;
+      case ObjectLiteral::Property::PROTOTYPE:
+        // Duplicate receiver on stack.
+        __ lw(a0, MemOperand(sp));
+        __ push(a0);
+        VisitForStackValue(value);
+        if (property->emit_store()) {
+          __ CallRuntime(Runtime::kSetPrototype, 2);
+        } else {
+          __ Drop(2);
+        }
+        break;
       case ObjectLiteral::Property::GETTER:
         accessor_table.lookup(key)->second->getter = value;
         break;
@@ -2711,7 +2720,7 @@
   __ LoadRoot(t0, Heap::kHashTableMapRootIndex);
   __ Branch(if_false, eq, a2, Operand(t0));
 
-  // Look for valueOf symbol in the descriptor array, and indicate false if
+  // Look for valueOf name in the descriptor array, and indicate false if
   // found. Since we omit an enumeration index check, if it is added via a
   // transition that shares its descriptor array, this is a false positive.
   Label entry, loop, done;
@@ -2736,10 +2745,10 @@
   __ Addu(a2, a2, t1);
 
   // Loop through all the keys in the descriptor array. If one of these is the
-  // symbol valueOf the result is false.
-  // The use of t2 to store the valueOf symbol asumes that it is not otherwise
+  // string "valueOf" the result is false.
+  // The use of t2 to store the valueOf string assumes that it is not otherwise
   // used in the loop below.
-  __ LoadRoot(t2, Heap::kvalue_of_symbolRootIndex);
+  __ li(t2, Operand(FACTORY->value_of_string()));
   __ jmp(&entry);
   __ bind(&loop);
   __ lw(a3, MemOperand(t0, 0));
@@ -2970,12 +2979,12 @@
 
   // Functions have class 'Function'.
   __ bind(&function);
-  __ LoadRoot(v0, Heap::kfunction_class_symbolRootIndex);
+  __ LoadRoot(v0, Heap::kfunction_class_stringRootIndex);
   __ jmp(&done);
 
   // Objects with a non-function constructor have class 'Object'.
   __ bind(&non_function_constructor);
-  __ LoadRoot(v0, Heap::kObject_symbolRootIndex);
+  __ LoadRoot(v0, Heap::kObject_stringRootIndex);
   __ jmp(&done);
 
   // Non-JS objects have class null.
@@ -3039,7 +3048,7 @@
     __ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset));
     __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
 
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     // 0x41300000 is the top half of 1.0 x 2^20 as a double.
     __ li(a1, Operand(0x41300000));
     // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU.
@@ -3345,7 +3354,7 @@
   __ bind(&index_out_of_range);
   // When the index is out of range, the spec requires us to return
   // the empty string.
-  __ LoadRoot(result, Heap::kEmptyStringRootIndex);
+  __ LoadRoot(result, Heap::kempty_stringRootIndex);
   __ jmp(&done);
 
   __ bind(&need_conversion);
@@ -3660,7 +3669,7 @@
   __ lw(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
   __ SmiUntag(array_length);
   __ Branch(&non_trivial_array, ne, array_length, Operand(zero_reg));
-  __ LoadRoot(v0, Heap::kEmptyStringRootIndex);
+  __ LoadRoot(v0, Heap::kempty_stringRootIndex);
   __ Branch(&done);
 
   __ bind(&non_trivial_array);
@@ -4275,12 +4284,12 @@
   }
   PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
 
-  if (check->Equals(isolate()->heap()->number_symbol())) {
+  if (check->Equals(isolate()->heap()->number_string())) {
     __ JumpIfSmi(v0, if_true);
     __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
     Split(eq, v0, Operand(at), if_true, if_false, fall_through);
-  } else if (check->Equals(isolate()->heap()->string_symbol())) {
+  } else if (check->Equals(isolate()->heap()->string_string())) {
     __ JumpIfSmi(v0, if_false);
     // Check for undetectable objects => false.
     __ GetObjectType(v0, v0, a1);
@@ -4289,16 +4298,16 @@
     __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
     Split(eq, a1, Operand(zero_reg),
           if_true, if_false, fall_through);
-  } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
+  } else if (check->Equals(isolate()->heap()->boolean_string())) {
     __ LoadRoot(at, Heap::kTrueValueRootIndex);
     __ Branch(if_true, eq, v0, Operand(at));
     __ LoadRoot(at, Heap::kFalseValueRootIndex);
     Split(eq, v0, Operand(at), if_true, if_false, fall_through);
   } else if (FLAG_harmony_typeof &&
-             check->Equals(isolate()->heap()->null_symbol())) {
+             check->Equals(isolate()->heap()->null_string())) {
     __ LoadRoot(at, Heap::kNullValueRootIndex);
     Split(eq, v0, Operand(at), if_true, if_false, fall_through);
-  } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
+  } else if (check->Equals(isolate()->heap()->undefined_string())) {
     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
     __ Branch(if_true, eq, v0, Operand(at));
     __ JumpIfSmi(v0, if_false);
@@ -4307,14 +4316,14 @@
     __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
     __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
     Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
-  } else if (check->Equals(isolate()->heap()->function_symbol())) {
+  } else if (check->Equals(isolate()->heap()->function_string())) {
     __ JumpIfSmi(v0, if_false);
     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
     __ GetObjectType(v0, v0, a1);
     __ Branch(if_true, eq, a1, Operand(JS_FUNCTION_TYPE));
     Split(eq, a1, Operand(JS_FUNCTION_PROXY_TYPE),
           if_true, if_false, fall_through);
-  } else if (check->Equals(isolate()->heap()->object_symbol())) {
+  } else if (check->Equals(isolate()->heap()->object_string())) {
     __ JumpIfSmi(v0, if_false);
     if (!FLAG_harmony_typeof) {
       __ LoadRoot(at, Heap::kNullValueRootIndex);
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index fe020c3..11c8034 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -305,30 +305,30 @@
 }
 
 
-// Checks whether a key is an array index string or a symbol string.
-// Falls through if a key is a symbol.
+// Checks whether a key is an array index string or an internalized string.
+// Falls through if a key is an internalized string.
 static void GenerateKeyStringCheck(MacroAssembler* masm,
                                    Register key,
                                    Register map,
                                    Register hash,
                                    Label* index_string,
-                                   Label* not_symbol) {
+                                   Label* not_internalized) {
   // The key is not a smi.
   // Is it a string?
   __ GetObjectType(key, map, hash);
-  __ Branch(not_symbol, ge, hash, Operand(FIRST_NONSTRING_TYPE));
+  __ Branch(not_internalized, ge, hash, Operand(FIRST_NONSTRING_TYPE));
 
   // Is the string an array index, with cached numeric value?
   __ lw(hash, FieldMemOperand(key, String::kHashFieldOffset));
   __ And(at, hash, Operand(String::kContainsCachedArrayIndexMask));
   __ Branch(index_string, eq, at, Operand(zero_reg));
 
-  // Is the string a symbol?
+  // Is the string internalized?
   // map: key map
   __ lbu(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
-  STATIC_ASSERT(kSymbolTag != 0);
-  __ And(at, hash, Operand(kIsSymbolMask));
-  __ Branch(not_symbol, eq, at, Operand(zero_reg));
+  STATIC_ASSERT(kInternalizedTag != 0);
+  __ And(at, hash, Operand(kIsInternalizedMask));
+  __ Branch(not_internalized, eq, at, Operand(zero_reg));
 }
 
 
@@ -583,7 +583,7 @@
   __ bind(&check_string);
   GenerateKeyStringCheck(masm, a2, a0, a3, &index_string, &slow_call);
 
-  // The key is known to be a symbol.
+  // The key is known to be internalized.
   // If the receiver is a regular JS object with slow properties then do
   // a quick inline probe of the receiver's dictionary.
   // Otherwise do the monomorphic cache probe.
@@ -610,7 +610,7 @@
   __ bind(&slow_call);
   // This branch is taken if:
   // - the receiver requires boxing or access check,
-  // - the key is neither smi nor symbol,
+  // - the key is neither smi nor an internalized string,
   // - the value loaded is not a function,
   // - there is hope that the runtime will create a monomorphic call stub,
   //   that will get fetched next time.
@@ -991,7 +991,7 @@
   int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
   __ And(a3, a3, Operand(mask));
 
-  // Load the key (consisting of map and symbol) from the cache and
+  // Load the key (consisting of map and internalized string) from the cache and
   // check for match.
   Label load_in_object_property;
   static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index a44c943..dfc3d5f 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -65,7 +65,7 @@
   HPhase phase("Z_Code generation", chunk());
   ASSERT(is_unused());
   status_ = GENERATING;
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
 
   // Open a frame scope to indicate that there is a frame on the stack.  The
   // NONE indicates that the scope shouldn't actually generate code to set up
@@ -194,7 +194,7 @@
   }
 
   if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     Comment(";;; Save clobbered callee double registers");
     int count = 0;
     BitVector* doubles = chunk()->allocated_double_registers();
@@ -1474,7 +1474,7 @@
 void LCodeGen::DoConstantD(LConstantD* instr) {
   ASSERT(instr->result()->IsDoubleRegister());
   DoubleRegister result = ToDoubleRegister(instr->result());
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   double v = instr->value();
   __ Move(result, v);
 }
@@ -1672,7 +1672,7 @@
     __ bind(&done);
   } else {
     ASSERT(instr->hydrogen()->representation().IsDouble());
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     FPURegister left_reg = ToDoubleRegister(left);
     FPURegister right_reg = ToDoubleRegister(right);
     FPURegister result_reg = ToDoubleRegister(instr->result());
@@ -1713,7 +1713,7 @@
 
 
 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   DoubleRegister left = ToDoubleRegister(instr->left());
   DoubleRegister right = ToDoubleRegister(instr->right());
   DoubleRegister result = ToDoubleRegister(instr->result());
@@ -1823,10 +1823,10 @@
     Register reg = ToRegister(instr->value());
     EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
   } else if (r.IsDouble()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     DoubleRegister reg = ToDoubleRegister(instr->value());
     // Test the double value. Zero and NaN are false.
-    EmitBranchF(true_block, false_block, ne, reg, kDoubleRegZero);
+    EmitBranchF(true_block, false_block, nue, reg, kDoubleRegZero);
   } else {
     ASSERT(r.IsTagged());
     Register reg = ToRegister(instr->value());
@@ -1901,7 +1901,7 @@
       }
 
       if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm(), FPU);
         // heap number -> false iff +0, -0, or NaN.
         DoubleRegister dbl_scratch = double_scratch0();
         Label not_heap_number;
@@ -1981,7 +1981,7 @@
     EmitGoto(next_block);
   } else {
     if (instr->is_double()) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm(), FPU);
       // Compare left and right as doubles and load the
       // resulting flags into the normal status register.
       FPURegister left_reg = ToDoubleRegister(left);
@@ -2327,12 +2327,12 @@
   __ lw(temp, FieldMemOperand(temp, JSFunction::kSharedFunctionInfoOffset));
   __ lw(temp, FieldMemOperand(temp,
                                SharedFunctionInfo::kInstanceClassNameOffset));
-  // The class name we are testing against is a symbol because it's a literal.
-  // The name in the constructor is a symbol because of the way the context is
-  // booted.  This routine isn't expected to work for random API-created
+  // The class name we are testing against is internalized since it's a literal.
+  // The name in the constructor is internalized because of the way the context
+  // is booted.  This routine isn't expected to work for random API-created
   // classes and it doesn't have to because you can't access it with natives
-  // syntax.  Since both sides are symbols it is sufficient to use an identity
-  // comparison.
+  // syntax.  Since both sides are internalized it is sufficient to use an
+  // identity comparison.
 
   // End with the address of this class_name instance in temp register.
   // On MIPS, the caller must do the comparison with Handle<String>class_name.
@@ -2527,11 +2527,12 @@
   // A minor optimization that relies on LoadRoot always emitting one
   // instruction.
   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm());
-  Label done;
+  Label done, check;
   __ Branch(USE_DELAY_SLOT, &done, condition, v0, Operand(zero_reg));
+  __ bind(&check);
   __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
+  ASSERT_EQ(1, masm()->InstructionsGeneratedSince(&check));
   __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
-  ASSERT_EQ(3, masm()->InstructionsGeneratedSince(&done));
   __ bind(&done);
 }
 
@@ -2544,7 +2545,7 @@
     __ CallRuntime(Runtime::kTraceExit, 1);
   }
   if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     ASSERT(NeedsEagerFrame());
     BitVector* doubles = chunk()->allocated_double_registers();
     BitVector::Iterator save_iterator(doubles);
@@ -2923,7 +2924,7 @@
       __ Addu(scratch0(), scratch0(), external_pointer);
     }
     if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm(), FPU);
       if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
         __ lwc1(result, MemOperand(scratch0(), additional_offset));
         __ cvt_d_s(result, result);
@@ -3052,7 +3053,7 @@
     __ Addu(elements, elements, scratch);
   }
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     __ Addu(elements, elements, Operand(base_offset));
     __ ldc1(result, MemOperand(elements));
     if (instr->hydrogen()->RequiresHoleCheck()) {
@@ -3506,8 +3507,6 @@
   Label done;
   __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
   __ mov(result, input);
-  ASSERT_EQ(2, masm()->InstructionsGeneratedSince(&done));
-  __ subu(result, zero_reg, input);
   // Overflow if result is still negative, i.e. 0x80000000.
   DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg));
   __ bind(&done);
@@ -3515,7 +3514,7 @@
 
 
 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   // Class for deferred case.
   class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
    public:
@@ -3552,7 +3551,7 @@
 
 
 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   DoubleRegister input = ToDoubleRegister(instr->value());
   Register result = ToRegister(instr->result());
   Register scratch1 = scratch0();
@@ -3581,7 +3580,7 @@
 
 
 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   DoubleRegister input = ToDoubleRegister(instr->value());
   Register result = ToRegister(instr->result());
   DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
@@ -3658,7 +3657,7 @@
 
 
 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   DoubleRegister input = ToDoubleRegister(instr->value());
   DoubleRegister result = ToDoubleRegister(instr->result());
   __ sqrt_d(result, input);
@@ -3666,7 +3665,7 @@
 
 
 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   DoubleRegister input = ToDoubleRegister(instr->value());
   DoubleRegister result = ToDoubleRegister(instr->result());
   DoubleRegister temp = ToDoubleRegister(instr->temp());
@@ -3691,7 +3690,7 @@
 
 
 void LCodeGen::DoPower(LPower* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   Representation exponent_type = instr->hydrogen()->right()->representation();
   // Having marked this as a call, we can use any registers.
   // Just make sure that the input/output registers are the expected ones.
@@ -3722,7 +3721,7 @@
 
 
 void LCodeGen::DoRandom(LRandom* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   class DeferredDoRandom: public LDeferredCode {
    public:
     DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
@@ -3799,7 +3798,7 @@
 
 
 void LCodeGen::DoMathExp(LMathExp* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   DoubleRegister input = ToDoubleRegister(instr->value());
   DoubleRegister result = ToDoubleRegister(instr->result());
   DoubleRegister double_scratch1 = ToDoubleRegister(instr->double_temp());
@@ -3965,12 +3964,32 @@
   ASSERT(ToRegister(instr->constructor()).is(a1));
   ASSERT(ToRegister(instr->result()).is(v0));
 
-  CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
   __ li(a0, Operand(instr->arity()));
+  if (FLAG_optimize_constructed_arrays) {
+    // No cell in a2 for construct type feedback in optimized code
+    Handle<Object> undefined_value(isolate()->heap()->undefined_value(),
+                                   isolate());
+    __ li(a2, Operand(undefined_value));
+  }
+  CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
   CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
 }
 
 
+void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
+  ASSERT(ToRegister(instr->constructor()).is(a1));
+  ASSERT(ToRegister(instr->result()).is(v0));
+  ASSERT(FLAG_optimize_constructed_arrays);
+
+  __ li(a0, Operand(instr->arity()));
+  __ li(a2, Operand(instr->hydrogen()->property_cell()));
+  Handle<Code> array_construct_code =
+      isolate()->builtins()->ArrayConstructCode();
+
+  CallCode(array_construct_code, RelocInfo::CONSTRUCT_CALL, instr);
+}
+
+
 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
   CallRuntime(instr->function(), instr->arity(), instr);
 }
@@ -4075,7 +4094,7 @@
 
 
 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   Register external_pointer = ToRegister(instr->elements());
   Register key = no_reg;
   ElementsKind elements_kind = instr->elements_kind();
@@ -4149,7 +4168,7 @@
 
 
 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   DoubleRegister value = ToDoubleRegister(instr->value());
   Register elements = ToRegister(instr->elements());
   Register key = no_reg;
@@ -4453,7 +4472,7 @@
 
 
 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   LOperand* input = instr->value();
   ASSERT(input->IsRegister() || input->IsStackSlot());
   LOperand* output = instr->result();
@@ -4471,7 +4490,7 @@
 
 
 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
   LOperand* input = instr->value();
   LOperand* output = instr->result();
 
@@ -4592,7 +4611,7 @@
       __ Xor(src, src, Operand(0x80000000));
     }
     if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm(), FPU);
       __ mtc1(src, dbl_scratch);
       __ cvt_d_w(dbl_scratch, dbl_scratch);
     } else {
@@ -4604,7 +4623,7 @@
     }
   } else {
     if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm(), FPU);
       __ mtc1(src, dbl_scratch);
       __ Cvt_d_uw(dbl_scratch, dbl_scratch, f22);
     } else {
@@ -4644,7 +4663,7 @@
   // number.
   __ bind(&done);
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset));
   } else {
     __ sw(sfpd_lo, MemOperand(dst, HeapNumber::kMantissaOffset));
@@ -4683,7 +4702,7 @@
   Label done;
   if (convert_hole) {
     if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm(), FPU);
       DoubleRegister input_reg = ToDoubleRegister(instr->value());
       __ BranchF(&no_special_nan_handling, NULL, eq, input_reg, input_reg);
       __ Move(reg, scratch0(), input_reg);
@@ -4729,7 +4748,7 @@
   }
   __ bind(deferred->exit());
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     __ sdc1(input_reg, MemOperand(reg, HeapNumber::kValueOffset));
   } else {
     __ sw(sfpd_lo, MemOperand(reg, HeapNumber::kValueOffset));
@@ -4784,7 +4803,7 @@
                                 LEnvironment* env,
                                 NumberUntagDMode mode) {
   Register scratch = scratch0();
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(masm(), FPU);
 
   Label load_smi, heap_number, done;
 
@@ -4862,7 +4881,7 @@
   // of the if.
 
   if (instr->truncating()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm(), FPU);
     Register scratch3 = ToRegister(instr->temp2());
     FPURegister single_scratch = double_scratch.low();
     ASSERT(!scratch3.is(input_reg) &&
@@ -5117,7 +5136,7 @@
 
 
 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
-  CpuFeatures::Scope vfp_scope(FPU);
+  CpuFeatureScope vfp_scope(masm(), FPU);
   DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
   Register result_reg = ToRegister(instr->result());
   DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
@@ -5126,7 +5145,7 @@
 
 
 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
-  CpuFeatures::Scope vfp_scope(FPU);
+  CpuFeatureScope vfp_scope(masm(), FPU);
   Register unclamped_reg = ToRegister(instr->unclamped());
   Register result_reg = ToRegister(instr->result());
   __ ClampUint8(result_reg, unclamped_reg);
@@ -5134,7 +5153,7 @@
 
 
 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
-  CpuFeatures::Scope vfp_scope(FPU);
+  CpuFeatureScope vfp_scope(masm(), FPU);
   Register scratch = scratch0();
   Register input_reg = ToRegister(instr->unclamped());
   Register result_reg = ToRegister(instr->result());
@@ -5720,7 +5739,7 @@
   // register.
   Condition final_branch_condition = kNoCondition;
   Register scratch = scratch0();
-  if (type_name->Equals(heap()->number_symbol())) {
+  if (type_name->Equals(heap()->number_string())) {
     __ JumpIfSmi(input, true_label);
     __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
     __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
@@ -5728,7 +5747,7 @@
     cmp2 = Operand(at);
     final_branch_condition = eq;
 
-  } else if (type_name->Equals(heap()->string_symbol())) {
+  } else if (type_name->Equals(heap()->string_string())) {
     __ JumpIfSmi(input, false_label);
     __ GetObjectType(input, input, scratch);
     __ Branch(USE_DELAY_SLOT, false_label,
@@ -5741,7 +5760,7 @@
     cmp2 = Operand(zero_reg);
     final_branch_condition = eq;
 
-  } else if (type_name->Equals(heap()->boolean_symbol())) {
+  } else if (type_name->Equals(heap()->boolean_string())) {
     __ LoadRoot(at, Heap::kTrueValueRootIndex);
     __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
     __ LoadRoot(at, Heap::kFalseValueRootIndex);
@@ -5749,13 +5768,13 @@
     cmp2 = Operand(input);
     final_branch_condition = eq;
 
-  } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_symbol())) {
+  } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
     __ LoadRoot(at, Heap::kNullValueRootIndex);
     cmp1 = at;
     cmp2 = Operand(input);
     final_branch_condition = eq;
 
-  } else if (type_name->Equals(heap()->undefined_symbol())) {
+  } else if (type_name->Equals(heap()->undefined_string())) {
     __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
     __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
     // The first instruction of JumpIfSmi is an And - it is safe in the delay
@@ -5769,7 +5788,7 @@
     cmp2 = Operand(zero_reg);
     final_branch_condition = ne;
 
-  } else if (type_name->Equals(heap()->function_symbol())) {
+  } else if (type_name->Equals(heap()->function_string())) {
     STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
     __ JumpIfSmi(input, false_label);
     __ GetObjectType(input, scratch, input);
@@ -5778,7 +5797,7 @@
     cmp2 = Operand(JS_FUNCTION_PROXY_TYPE);
     final_branch_condition = eq;
 
-  } else if (type_name->Equals(heap()->object_symbol())) {
+  } else if (type_name->Equals(heap()->object_string())) {
     __ JumpIfSmi(input, false_label);
     if (!FLAG_harmony_typeof) {
       __ LoadRoot(at, Heap::kNullValueRootIndex);
diff --git a/src/mips/lithium-gap-resolver-mips.cc b/src/mips/lithium-gap-resolver-mips.cc
index a4a4411..b415156 100644
--- a/src/mips/lithium-gap-resolver-mips.cc
+++ b/src/mips/lithium-gap-resolver-mips.cc
@@ -172,10 +172,10 @@
   } else if (source->IsStackSlot()) {
     __ lw(kLithiumScratchReg, cgen_->ToMemOperand(source));
   } else if (source->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(cgen_->masm(), FPU);
     __ mov_d(kLithiumScratchDouble, cgen_->ToDoubleRegister(source));
   } else if (source->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(cgen_->masm(), FPU);
     __ ldc1(kLithiumScratchDouble, cgen_->ToMemOperand(source));
   } else {
     UNREACHABLE();
@@ -195,11 +195,11 @@
   } else if (saved_destination_->IsStackSlot()) {
     __ sw(kLithiumScratchReg, cgen_->ToMemOperand(saved_destination_));
   } else if (saved_destination_->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(cgen_->masm(), FPU);
     __ mov_d(cgen_->ToDoubleRegister(saved_destination_),
             kLithiumScratchDouble);
   } else if (saved_destination_->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(cgen_->masm(), FPU);
     __ sdc1(kLithiumScratchDouble,
             cgen_->ToMemOperand(saved_destination_));
   } else {
@@ -236,7 +236,7 @@
       MemOperand destination_operand = cgen_->ToMemOperand(destination);
       if (in_cycle_) {
         if (!destination_operand.OffsetIsInt16Encodable()) {
-          CpuFeatures::Scope scope(FPU);
+          CpuFeatureScope scope(cgen_->masm(), FPU);
           // 'at' is overwritten while saving the value to the destination.
           // Therefore we can't use 'at'.  It is OK if the read from the source
           // destroys 'at', since that happens before the value is read.
@@ -276,7 +276,7 @@
     }
 
   } else if (source->IsDoubleRegister()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(cgen_->masm(), FPU);
     DoubleRegister source_register = cgen_->ToDoubleRegister(source);
     if (destination->IsDoubleRegister()) {
       __ mov_d(cgen_->ToDoubleRegister(destination), source_register);
@@ -287,7 +287,7 @@
     }
 
   } else if (source->IsDoubleStackSlot()) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(cgen_->masm(), FPU);
     MemOperand source_operand = cgen_->ToMemOperand(source);
     if (destination->IsDoubleRegister()) {
       __ ldc1(cgen_->ToDoubleRegister(destination), source_operand);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index cc5c10d..533207c 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -355,6 +355,17 @@
 }
 
 
+void LCallNewArray::PrintDataTo(StringStream* stream) {
+  stream->Add("= ");
+  constructor()->PrintTo(stream);
+  stream->Add(" #%d / ", arity());
+  ASSERT(hydrogen()->property_cell()->value()->IsSmi());
+  ElementsKind kind = static_cast<ElementsKind>(
+      Smi::cast(hydrogen()->property_cell()->value())->value());
+  stream->Add(" (%s) ", ElementsKindToString(kind));
+}
+
+
 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
   arguments()->PrintTo(stream);
   stream->Add(" length ");
@@ -1141,6 +1152,14 @@
 }
 
 
+LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
+  LOperand* constructor = UseFixed(instr->constructor(), a1);
+  argument_count_ -= instr->argument_count();
+  LCallNewArray* result = new(zone()) LCallNewArray(constructor);
+  return MarkAsCall(DefineFixed(result, v0), instr);
+}
+
+
 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
   LOperand* function = UseFixed(instr->function(), a1);
   argument_count_ -= instr->argument_count();
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index db235e4..c5a00d7 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -68,6 +68,7 @@
   V(CallKnownGlobal)                            \
   V(CallNamed)                                  \
   V(CallNew)                                    \
+  V(CallNewArray)                               \
   V(CallRuntime)                                \
   V(CallStub)                                   \
   V(CheckFunction)                              \
@@ -1762,6 +1763,23 @@
 };
 
 
+class LCallNewArray: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCallNewArray(LOperand* constructor) {
+    inputs_[0] = constructor;
+  }
+
+  LOperand* constructor() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CallNewArray, "call-new-array")
+  DECLARE_HYDROGEN_ACCESSOR(CallNewArray)
+
+  virtual void PrintDataTo(StringStream* stream);
+
+  int arity() const { return hydrogen()->argument_count() - 1; }
+};
+
+
 class LCallRuntime: public LTemplateInstruction<1, 0, 0> {
  public:
   DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 1829522..49bcf0c 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -853,7 +853,7 @@
 
 
 void MacroAssembler::MultiPushFPU(RegList regs) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   int16_t num_to_push = NumberOfBitsSet(regs);
   int16_t stack_offset = num_to_push * kDoubleSize;
 
@@ -868,7 +868,7 @@
 
 
 void MacroAssembler::MultiPushReversedFPU(RegList regs) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   int16_t num_to_push = NumberOfBitsSet(regs);
   int16_t stack_offset = num_to_push * kDoubleSize;
 
@@ -883,7 +883,7 @@
 
 
 void MacroAssembler::MultiPopFPU(RegList regs) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   int16_t stack_offset = 0;
 
   for (int16_t i = 0; i < kNumRegisters; i++) {
@@ -897,7 +897,7 @@
 
 
 void MacroAssembler::MultiPopReversedFPU(RegList regs) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   int16_t stack_offset = 0;
 
   for (int16_t i = kNumRegisters - 1; i >= 0; i--) {
@@ -1125,23 +1125,19 @@
     // have been handled by the caller.
     // Unsigned conditions are treated as their signed counterpart.
     switch (cc) {
-      case Uless:
-      case less:
+      case lt:
         c(OLT, D, cmp1, cmp2);
         bc1t(target);
         break;
-      case Ugreater:
-      case greater:
+      case gt:
         c(ULE, D, cmp1, cmp2);
         bc1f(target);
         break;
-      case Ugreater_equal:
-      case greater_equal:
+      case ge:
         c(ULT, D, cmp1, cmp2);
         bc1f(target);
         break;
-      case Uless_equal:
-      case less_equal:
+      case le:
         c(OLE, D, cmp1, cmp2);
         bc1t(target);
         break;
@@ -1149,10 +1145,18 @@
         c(EQ, D, cmp1, cmp2);
         bc1t(target);
         break;
+      case ueq:
+        c(UEQ, D, cmp1, cmp2);
+        bc1t(target);
+        break;
       case ne:
         c(EQ, D, cmp1, cmp2);
         bc1f(target);
         break;
+      case nue:
+        c(UEQ, D, cmp1, cmp2);
+        bc1f(target);
+        break;
       default:
         CHECK(0);
     };
@@ -1165,7 +1169,7 @@
 
 
 void MacroAssembler::Move(FPURegister dst, double imm) {
-  ASSERT(CpuFeatures::IsEnabled(FPU));
+  ASSERT(IsEnabled(FPU));
   static const DoubleRepresentation minus_zero(-0.0);
   static const DoubleRepresentation zero(0.0);
   DoubleRepresentation value(imm);
@@ -1345,7 +1349,7 @@
   }
   bind(&right_exponent);
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(this, FPU);
     // MIPS FPU instructions implementing double precision to integer
     // conversion using round to zero. Since the FP value was qualified
     // above, the resulting integer should be a legal int32.
@@ -1406,7 +1410,7 @@
   ASSERT(!except_flag.is(scratch));
 
   ASSERT(CpuFeatures::IsSupported(FPU));
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   Label done;
 
   // Clear the except flag (0 = no exception)
@@ -1548,7 +1552,7 @@
                                       Register scratch,
                                       Register scratch2,
                                       Register scratch3) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   ASSERT(!scratch2.is(result));
   ASSERT(!scratch3.is(result));
   ASSERT(!scratch3.is(scratch2));
@@ -3484,7 +3488,7 @@
                                           scratch4,
                                           f2);
   if (destination == FloatingPointHelper::kFPURegisters) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(this, FPU);
     sdc1(f0, MemOperand(scratch1, 0));
   } else {
     sw(mantissa_reg, MemOperand(scratch1, 0));
@@ -3577,7 +3581,7 @@
 
 
 void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   if (IsMipsSoftFloatABI) {
     Move(dst, v0, v1);
   } else {
@@ -3587,7 +3591,7 @@
 
 
 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   if (!IsMipsSoftFloatABI) {
     Move(f12, dreg);
   } else {
@@ -3598,7 +3602,7 @@
 
 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
                                              DoubleRegister dreg2) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   if (!IsMipsSoftFloatABI) {
     if (dreg2.is(f12)) {
       ASSERT(!dreg1.is(f14));
@@ -3617,7 +3621,7 @@
 
 void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
                                              Register reg) {
-  CpuFeatures::Scope scope(FPU);
+  CpuFeatureScope scope(this, FPU);
   if (!IsMipsSoftFloatABI) {
     Move(f12, dreg);
     Move(a2, reg);
@@ -4557,6 +4561,19 @@
 }
 
 
+void MacroAssembler::LoadArrayFunction(Register function) {
+  // Load the global or builtins object from the current context.
+  lw(function,
+     MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+  // Load the global context from the global or builtins object.
+  lw(function,
+     FieldMemOperand(function, GlobalObject::kGlobalContextOffset));
+  // Load the array function from the native context.
+  lw(function,
+     MemOperand(function, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
+}
+
+
 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
                                                   Register map,
                                                   Register scratch) {
@@ -4632,7 +4649,7 @@
 
   const int frame_alignment = MacroAssembler::ActivationFrameAlignment();
   if (save_doubles) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(this, FPU);
     // The stack  must be allign to 0 modulo 8 for stores with sdc1.
     ASSERT(kDoubleSize == frame_alignment);
     if (frame_alignment > 0) {
@@ -4670,7 +4687,7 @@
                                     bool do_return) {
   // Optionally restore all double registers.
   if (save_doubles) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(this, FPU);
     // Remember: we only need to restore every 2nd double FPU value.
     lw(t8, MemOperand(fp, ExitFrameConstants::kSPOffset));
     for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) {
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index d994405..fdcb9a5 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -835,6 +835,7 @@
                            bool can_have_holes);
 
   void LoadGlobalFunction(int index, Register function);
+  void LoadArrayFunction(Register function);
 
   // Load the initial map from the global function. The registers
   // function and map can be the same, function is then overwritten.
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index dd5681b..192c7bf 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -121,14 +121,14 @@
 // the property. This function may return false negatives, so miss_label
 // must always call a backup property check that is complete.
 // This function is safe to call if the receiver has fast properties.
-// Name must be a symbol and receiver must be a heap object.
+// Name must be internalized and receiver must be a heap object.
 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
                                              Label* miss_label,
                                              Register receiver,
                                              Handle<String> name,
                                              Register scratch0,
                                              Register scratch1) {
-  ASSERT(name->IsSymbol());
+  ASSERT(name->IsInternalizedString());
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
   __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
@@ -998,7 +998,7 @@
                             Register scratch1,
                             Register scratch2) {
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     __ mtc1(ival, f0);
     __ cvt_s_w(f0, f0);
     __ sll(scratch1, wordoffset, 2);
@@ -1103,7 +1103,7 @@
     if (!current->HasFastProperties() &&
         !current->IsJSGlobalObject() &&
         !current->IsJSGlobalProxy()) {
-      if (!name->IsSymbol()) {
+      if (!name->IsInternalizedString()) {
         name = factory()->InternalizeString(name);
       }
       ASSERT(current->property_dictionary()->FindEntry(*name) ==
@@ -2001,7 +2001,7 @@
 
   if (index_out_of_range.is_linked()) {
     __ bind(&index_out_of_range);
-    __ LoadRoot(v0, Heap::kEmptyStringRootIndex);
+    __ LoadRoot(v0, Heap::kempty_stringRootIndex);
     __ Drop(argc + 1);
     __ Ret();
   }
@@ -2108,7 +2108,7 @@
     return Handle<Code>::null();
   }
 
-  CpuFeatures::Scope scope_fpu(FPU);
+  CpuFeatureScope scope_fpu(masm(), FPU);
   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.
@@ -2420,7 +2420,7 @@
       break;
 
     case STRING_CHECK:
-      // Check that the object is a two-byte string or a symbol.
+      // Check that the object is a string.
       __ GetObjectType(a1, a3, a3);
       __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE));
       // Check that the maps starting from the prototype haven't changed.
@@ -3353,7 +3353,7 @@
                                 FPURegister double_scratch1,
                                 Label* fail) {
   if (CpuFeatures::IsSupported(FPU)) {
-    CpuFeatures::Scope scope(FPU);
+    CpuFeatureScope scope(masm, FPU);
     Label key_ok;
     // Check for smi or a smi inside a heap number.  We convert the heap
     // number and check if the conversion is exact and fits into the smi
@@ -3489,7 +3489,7 @@
           f0, t2, t3,  // These are: double_dst, dst_mantissa, dst_exponent.
           t0, f2);  // These are: scratch2, single_scratch.
       if (destination == FloatingPointHelper::kFPURegisters) {
-        CpuFeatures::Scope scope(FPU);
+        CpuFeatureScope scope(masm(), FPU);
         __ sdc1(f0, MemOperand(a3, 0));
       } else {
         __ sw(t2, MemOperand(a3, 0));
@@ -3527,7 +3527,7 @@
     // reproducible behavior, convert these to zero.
 
     if (CpuFeatures::IsSupported(FPU)) {
-      CpuFeatures::Scope scope(FPU);
+      CpuFeatureScope scope(masm, FPU);
 
       __ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset));
 
@@ -3788,7 +3788,7 @@
     MacroAssembler* masm,
     bool is_js_array,
     ElementsKind elements_kind,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- a0    : value
   //  -- a1    : key
@@ -3950,7 +3950,7 @@
 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
     MacroAssembler* masm,
     bool is_js_array,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- a0    : value
   //  -- a1    : key
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index e583016..3cb3d24 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -744,7 +744,7 @@
 
 void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorVerify() {
   CHECK(IsDeclaredAccessorDescriptor());
-  VerifySmiField(kInternalFieldOffset);
+  VerifyPointer(serialized_data());
 }
 
 
@@ -922,7 +922,7 @@
     info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
     info->number_of_fast_unused_fields_ += map()->unused_property_fields();
   } else {
-    StringDictionary* dict = property_dictionary();
+    NameDictionary* dict = property_dictionary();
     info->number_of_slow_used_properties_ += dict->NumberOfElements();
     info->number_of_slow_unused_properties_ +=
         dict->Capacity() - dict->NumberOfElements();
@@ -1013,10 +1013,10 @@
 
 bool DescriptorArray::IsSortedNoDuplicates(int valid_entries) {
   if (valid_entries == -1) valid_entries = number_of_descriptors();
-  String* current_key = NULL;
+  Name* current_key = NULL;
   uint32_t current = 0;
   for (int i = 0; i < number_of_descriptors(); i++) {
-    String* key = GetSortedKey(i);
+    Name* key = GetSortedKey(i);
     if (key == current_key) {
       PrintDescriptors();
       return false;
@@ -1035,10 +1035,10 @@
 
 bool TransitionArray::IsSortedNoDuplicates(int valid_entries) {
   ASSERT(valid_entries == -1);
-  String* current_key = NULL;
+  Name* current_key = NULL;
   uint32_t current = 0;
   for (int i = 0; i < number_of_transitions(); i++) {
-    String* key = GetSortedKey(i);
+    Name* key = GetSortedKey(i);
     if (key == current_key) {
       PrintTransitions();
       return false;
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 374bcbd..f2cdde9 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -902,13 +902,13 @@
 }
 
 
-MaybeObject* Object::GetProperty(String* key) {
+MaybeObject* Object::GetProperty(Name* key) {
   PropertyAttributes attributes;
   return GetPropertyWithReceiver(this, key, &attributes);
 }
 
 
-MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
+MaybeObject* Object::GetProperty(Name* key, PropertyAttributes* attributes) {
   return GetPropertyWithReceiver(this, key, attributes);
 }
 
@@ -1493,7 +1493,7 @@
 
 
 bool JSObject::TryTransitionToField(Handle<JSObject> object,
-                                    Handle<String> key) {
+                                    Handle<Name> key) {
   if (!object->map()->HasTransitionArray()) return false;
   Handle<TransitionArray> transitions(object->map()->transitions());
   int transition = transitions->Search(*key);
@@ -2021,7 +2021,7 @@
 // there are three entries in this array it should be called with low=0 and
 // high=2.
 template<SearchMode search_mode, typename T>
-int BinarySearch(T* array, String* name, int low, int high, int valid_entries) {
+int BinarySearch(T* array, Name* name, int low, int high, int valid_entries) {
   uint32_t hash = name->Hash();
   int limit = high;
 
@@ -2029,7 +2029,7 @@
 
   while (low != high) {
     int mid = (low + high) / 2;
-    String* mid_name = array->GetSortedKey(mid);
+    Name* mid_name = array->GetSortedKey(mid);
     uint32_t mid_hash = mid_name->Hash();
 
     if (mid_hash >= hash) {
@@ -2041,7 +2041,7 @@
 
   for (; low <= limit; ++low) {
     int sort_index = array->GetSortedKeyIndex(low);
-    String* entry = array->GetKey(sort_index);
+    Name* entry = array->GetKey(sort_index);
     if (entry->Hash() != hash) break;
     if (entry->Equals(name)) {
       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
@@ -2058,12 +2058,12 @@
 // Perform a linear search in this fixed array. len is the number of entry
 // indices that are valid.
 template<SearchMode search_mode, typename T>
-int LinearSearch(T* array, String* name, int len, int valid_entries) {
+int LinearSearch(T* array, Name* name, int len, int valid_entries) {
   uint32_t hash = name->Hash();
   if (search_mode == ALL_ENTRIES) {
     for (int number = 0; number < len; number++) {
       int sorted_index = array->GetSortedKeyIndex(number);
-      String* entry = array->GetKey(sorted_index);
+      Name* entry = array->GetKey(sorted_index);
       uint32_t current_hash = entry->Hash();
       if (current_hash > hash) break;
       if (current_hash == hash && entry->Equals(name)) return sorted_index;
@@ -2071,7 +2071,7 @@
   } else {
     ASSERT(len >= valid_entries);
     for (int number = 0; number < valid_entries; number++) {
-      String* entry = array->GetKey(number);
+      Name* entry = array->GetKey(number);
       uint32_t current_hash = entry->Hash();
       if (current_hash == hash && entry->Equals(name)) return number;
     }
@@ -2081,7 +2081,7 @@
 
 
 template<SearchMode search_mode, typename T>
-int Search(T* array, String* name, int valid_entries) {
+int Search(T* array, Name* name, int valid_entries) {
   if (search_mode == VALID_ENTRIES) {
     SLOW_ASSERT(array->IsSortedNoDuplicates(valid_entries));
   } else {
@@ -2105,12 +2105,12 @@
 }
 
 
-int DescriptorArray::Search(String* name, int valid_descriptors) {
+int DescriptorArray::Search(Name* name, int valid_descriptors) {
   return internal::Search<VALID_ENTRIES>(this, name, valid_descriptors);
 }
 
 
-int DescriptorArray::SearchWithCache(String* name, Map* map) {
+int DescriptorArray::SearchWithCache(Name* name, Map* map) {
   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   if (number_of_own_descriptors == 0) return kNotFound;
 
@@ -2127,7 +2127,7 @@
 
 
 void Map::LookupDescriptor(JSObject* holder,
-                           String* name,
+                           Name* name,
                            LookupResult* result) {
   DescriptorArray* descriptors = this->instance_descriptors();
   int number = descriptors->SearchWithCache(name, this);
@@ -2137,7 +2137,7 @@
 
 
 void Map::LookupTransition(JSObject* holder,
-                           String* name,
+                           Name* name,
                            LookupResult* result) {
   if (HasTransitionArray()) {
     TransitionArray* transition_array = transitions();
@@ -2168,9 +2168,9 @@
 }
 
 
-String* DescriptorArray::GetKey(int descriptor_number) {
+Name* DescriptorArray::GetKey(int descriptor_number) {
   ASSERT(descriptor_number < number_of_descriptors());
-  return String::cast(get(ToKeyIndex(descriptor_number)));
+  return Name::cast(get(ToKeyIndex(descriptor_number)));
 }
 
 
@@ -2179,7 +2179,7 @@
 }
 
 
-String* DescriptorArray::GetSortedKey(int descriptor_number) {
+Name* DescriptorArray::GetSortedKey(int descriptor_number) {
   return GetKey(GetSortedKeyIndex(descriptor_number));
 }
 
@@ -2293,7 +2293,7 @@
   int insertion;
 
   for (insertion = descriptor_number; insertion > 0; --insertion) {
-    String* key = GetSortedKey(insertion - 1);
+    Name* key = GetSortedKey(insertion - 1);
     if (key->Hash() <= hash) break;
     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
   }
@@ -2314,7 +2314,7 @@
   int insertion;
 
   for (insertion = descriptor_number; insertion > 0; --insertion) {
-    String* key = GetSortedKey(insertion - 1);
+    Name* key = GetSortedKey(insertion - 1);
     if (key->Hash() <= hash) break;
     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
   }
@@ -2428,12 +2428,12 @@
 CAST_ACCESSOR(ExternalAsciiString)
 CAST_ACCESSOR(ExternalTwoByteString)
 CAST_ACCESSOR(Symbol)
+CAST_ACCESSOR(Name)
 CAST_ACCESSOR(JSReceiver)
 CAST_ACCESSOR(JSObject)
 CAST_ACCESSOR(Smi)
 CAST_ACCESSOR(HeapObject)
 CAST_ACCESSOR(HeapNumber)
-CAST_ACCESSOR(Name)
 CAST_ACCESSOR(Oddball)
 CAST_ACCESSOR(JSGlobalPropertyCell)
 CAST_ACCESSOR(SharedFunctionInfo)
@@ -2499,10 +2499,16 @@
 }
 
 
+bool Name::Equals(Name* other) {
+  if (other == this) return true;
+  if (this->IsUniqueName() && other->IsUniqueName()) return false;
+  return String::cast(this)->SlowEquals(String::cast(other));
+}
+
+
 bool String::Equals(String* other) {
   if (other == this) return true;
-  if (StringShape(this).IsInternalized() &&
-      StringShape(other).IsInternalized()) {
+  if (this->IsInternalizedString() && other->IsInternalizedString()) {
     return false;
   }
   return SlowEquals(other);
@@ -2642,6 +2648,32 @@
 }
 
 
+// TODO(dcarney): Remove this class after conversion to VisitFlat.
+class ConsStringCaptureOp {
+ public:
+  inline ConsStringCaptureOp() : cons_string_(NULL) {}
+  inline String* Operate(String* string, unsigned*, int32_t*, unsigned*) {
+    cons_string_ = ConsString::cast(string);
+    return NULL;
+  }
+  ConsString* cons_string_;
+};
+
+
+template<class Visitor>
+ConsString* String::VisitFlat(Visitor* visitor,
+                              String* string,
+                              int offset,
+                              int length,
+                              int32_t type) {
+  ASSERT(length >= 0 && length == string->length());
+  ASSERT(offset >= 0 && offset <= length);
+  ConsStringCaptureOp op;
+  Visit(string, offset, *visitor, op, type, static_cast<unsigned>(length));
+  return op.cons_string_;
+}
+
+
 uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
   ASSERT(index >= 0 && index < length());
   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
@@ -3231,7 +3263,7 @@
 int HeapObject::SizeFromMap(Map* map) {
   int instance_size = map->instance_size();
   if (instance_size != kVariableSizeSentinel) return instance_size;
-  // We can ignore the "internalized" bit becase it is only set for strings
+  // We can ignore the "internalized" bit because it is only set for strings
   // and thus implies a string type.
   int instance_type =
       static_cast<int>(map->instance_type()) & ~kIsInternalizedMask;
@@ -4013,7 +4045,7 @@
 }
 
 
-MaybeObject* Map::AddTransition(String* key,
+MaybeObject* Map::AddTransition(Name* key,
                                 Map* target,
                                 SimpleTransitionFlag flag) {
   if (HasTransitionArray()) return transitions()->CopyInsert(key, target);
@@ -4146,7 +4178,8 @@
 ACCESSORS(AccessorInfo, expected_receiver_type, Object,
           kExpectedReceiverTypeOffset)
 
-ACCESSORS(DeclaredAccessorDescriptor, internal_field, Smi, kInternalFieldOffset)
+ACCESSORS(DeclaredAccessorDescriptor, serialized_data, ByteArray,
+          kSerializedDataOffset)
 
 ACCESSORS(DeclaredAccessorInfo, descriptor, DeclaredAccessorDescriptor,
           kDescriptorOffset)
@@ -4983,6 +5016,7 @@
 void Code::set_stub_info(int value) {
   ASSERT(kind() == COMPARE_IC ||
          kind() == BINARY_OP_IC ||
+         kind() == STUB ||
          kind() == LOAD_IC ||
          kind() == KEYED_LOAD_IC ||
          kind() == STORE_IC ||
@@ -5262,9 +5296,9 @@
 }
 
 
-StringDictionary* JSObject::property_dictionary() {
+NameDictionary* JSObject::property_dictionary() {
   ASSERT(!HasFastProperties());
-  return StringDictionary::cast(properties());
+  return NameDictionary::cast(properties());
 }
 
 
@@ -5387,6 +5421,11 @@
 }
 
 
+bool Name::AsArrayIndex(uint32_t* index) {
+  return IsString() && String::cast(this)->AsArrayIndex(index);
+}
+
+
 bool String::AsArrayIndex(uint32_t* index) {
   uint32_t field = hash_field();
   if (IsHashFieldComputed(field) && (field & kIsNotArrayIndexMask)) {
@@ -5406,7 +5445,7 @@
 }
 
 
-bool JSReceiver::HasProperty(String* name) {
+bool JSReceiver::HasProperty(Name* name) {
   if (IsJSProxy()) {
     return JSProxy::cast(this)->HasPropertyWithHandler(name);
   }
@@ -5414,7 +5453,7 @@
 }
 
 
-bool JSReceiver::HasLocalProperty(String* name) {
+bool JSReceiver::HasLocalProperty(Name* name) {
   if (IsJSProxy()) {
     return JSProxy::cast(this)->HasPropertyWithHandler(name);
   }
@@ -5422,7 +5461,7 @@
 }
 
 
-PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
+PropertyAttributes JSReceiver::GetPropertyAttribute(Name* key) {
   uint32_t index;
   if (IsJSObject() && key->AsArrayIndex(&index)) {
     return GetElementAttribute(index);
@@ -5547,7 +5586,7 @@
                                       Object* key,
                                       Object* value,
                                       PropertyDetails details) {
-  ASSERT(!key->IsString() ||
+  ASSERT(!key->IsName() ||
          details.IsDeleted() ||
          details.dictionary_index() > 0);
   int index = HashTable<Shape, Key>::EntryToIndex(entry);
@@ -5592,25 +5631,25 @@
 }
 
 
-bool StringDictionaryShape::IsMatch(String* key, Object* other) {
+bool NameDictionaryShape::IsMatch(Name* key, Object* other) {
   // We know that all entries in a hash table had their hash keys created.
   // Use that knowledge to have fast failure.
-  if (key->Hash() != String::cast(other)->Hash()) return false;
-  return key->Equals(String::cast(other));
+  if (key->Hash() != Name::cast(other)->Hash()) return false;
+  return key->Equals(Name::cast(other));
 }
 
 
-uint32_t StringDictionaryShape::Hash(String* key) {
+uint32_t NameDictionaryShape::Hash(Name* key) {
   return key->Hash();
 }
 
 
-uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
-  return String::cast(other)->Hash();
+uint32_t NameDictionaryShape::HashForObject(Name* key, Object* other) {
+  return Name::cast(other)->Hash();
 }
 
 
-MaybeObject* StringDictionaryShape::AsObject(String* key) {
+MaybeObject* NameDictionaryShape::AsObject(Name* key) {
   return key;
 }
 
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 32940c4..4522ee4 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -259,7 +259,7 @@
     DescriptorArray* descs = map()->instance_descriptors();
     for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
       PrintF(out, "   ");
-      descs->GetKey(i)->StringPrint(out);
+      descs->GetKey(i)->NamePrint(out);
       PrintF(out, ": ");
       switch (descs->GetType(i)) {
         case FIELD: {
@@ -417,7 +417,7 @@
   TransitionArray* transitions = map()->transitions();
   for (int i = 0; i < transitions->number_of_transitions(); i++) {
     PrintF(out, "   ");
-    transitions->GetKey(i)->StringPrint(out);
+    transitions->GetKey(i)->NamePrint(out);
     PrintF(out, ": ");
     switch (transitions->GetTargetDetails(i).type()) {
       case FIELD: {
@@ -599,6 +599,8 @@
   constructor()->ShortPrint(out);
   PrintF(out, "\n - code cache: ");
   code_cache()->ShortPrint(out);
+  PrintF(out, "\n - dependent code: ");
+  dependent_code()->ShortPrint(out);
   PrintF(out, "\n");
 }
 
@@ -710,6 +712,14 @@
 }
 
 
+void Name::NamePrint(FILE* out) {
+  if (IsString())
+    String::cast(this)->StringPrint(out);
+  else
+    ShortPrint();
+}
+
+
 // This method is only meant to be called from gdb for debugging purposes.
 // Since the string can also be in two-byte encoding, non-ASCII characters
 // will be ignored in the output.
@@ -919,7 +929,7 @@
 void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorPrint(FILE* out) {
   HeapObject::PrintHeader(out, "DeclaredAccessorDescriptor");
   PrintF(out, "\n - internal field: ");
-  internal_field()->ShortPrint(out);
+  serialized_data()->ShortPrint(out);
 }
 
 
@@ -1136,7 +1146,7 @@
   PrintF(out, "Transition array  %d\n", number_of_transitions());
   for (int i = 0; i < number_of_transitions(); i++) {
     PrintF(out, " %d: ", i);
-    GetKey(i)->StringPrint(out);
+    GetKey(i)->NamePrint(out);
     PrintF(out, ": ");
     switch (GetTargetDetails(i).type()) {
       case FIELD: {
diff --git a/src/objects.cc b/src/objects.cc
index e05ba05..a33f6e5 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -130,7 +130,7 @@
 }
 
 
-void Object::Lookup(String* name, LookupResult* result) {
+void Object::Lookup(Name* name, LookupResult* result) {
   Object* holder = NULL;
   if (IsJSReceiver()) {
     holder = this;
@@ -155,7 +155,7 @@
 
 
 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
-                                             String* name,
+                                             Name* name,
                                              PropertyAttributes* attributes) {
   LookupResult result(name->GetIsolate());
   Lookup(name, &result);
@@ -165,9 +165,149 @@
 }
 
 
+template<typename To>
+static inline To* CheckedCast(void *from) {
+  uintptr_t temp = reinterpret_cast<uintptr_t>(from);
+  ASSERT(temp % sizeof(To) == 0);
+  return reinterpret_cast<To*>(temp);
+}
+
+
+static MaybeObject* PerformCompare(const BitmaskCompareDescriptor& descriptor,
+                                   char* ptr,
+                                   Heap* heap) {
+  uint32_t bitmask = descriptor.bitmask;
+  uint32_t compare_value = descriptor.compare_value;
+  uint32_t value;
+  switch (descriptor.size) {
+    case 1:
+      value = static_cast<uint32_t>(*CheckedCast<uint8_t>(ptr));
+      compare_value &= 0xff;
+      bitmask &= 0xff;
+      break;
+    case 2:
+      value = static_cast<uint32_t>(*CheckedCast<uint16_t>(ptr));
+      compare_value &= 0xffff;
+      bitmask &= 0xffff;
+      break;
+    case 4:
+      value = *CheckedCast<uint32_t>(ptr);
+      break;
+    default:
+      UNREACHABLE();
+      return NULL;
+  }
+  return heap->ToBoolean((bitmask & value) == (bitmask & compare_value));
+}
+
+
+static MaybeObject* PerformCompare(const PointerCompareDescriptor& descriptor,
+                                   char* ptr,
+                                   Heap* heap) {
+  uintptr_t compare_value =
+      reinterpret_cast<uintptr_t>(descriptor.compare_value);
+  uintptr_t value = *CheckedCast<uintptr_t>(ptr);
+  return heap->ToBoolean(compare_value == value);
+}
+
+
+static MaybeObject* GetPrimitiveValue(
+    const PrimitiveValueDescriptor& descriptor,
+    char* ptr,
+    Heap* heap) {
+  int32_t int32_value = 0;
+  switch (descriptor.data_type) {
+    case kDescriptorInt8Type:
+      int32_value = *CheckedCast<int8_t>(ptr);
+      break;
+    case kDescriptorUint8Type:
+      int32_value = *CheckedCast<uint8_t>(ptr);
+      break;
+    case kDescriptorInt16Type:
+      int32_value = *CheckedCast<int16_t>(ptr);
+      break;
+    case kDescriptorUint16Type:
+      int32_value = *CheckedCast<uint16_t>(ptr);
+      break;
+    case kDescriptorInt32Type:
+      int32_value = *CheckedCast<int32_t>(ptr);
+      break;
+    case kDescriptorUint32Type: {
+      uint32_t value = *CheckedCast<uint32_t>(ptr);
+      return heap->NumberFromUint32(value);
+    }
+    case kDescriptorBoolType: {
+      uint8_t byte = *CheckedCast<uint8_t>(ptr);
+      return heap->ToBoolean(byte & (0x1 << descriptor.bool_offset));
+    }
+    case kDescriptorFloatType: {
+      float value = *CheckedCast<float>(ptr);
+      return heap->NumberFromDouble(value);
+    }
+    case kDescriptorDoubleType: {
+      double value = *CheckedCast<double>(ptr);
+      return heap->NumberFromDouble(value);
+    }
+  }
+  return heap->NumberFromInt32(int32_value);
+}
+
+
+static MaybeObject* GetDeclaredAccessorProperty(Object* receiver,
+                                                DeclaredAccessorInfo* info,
+                                                Isolate* isolate) {
+  char* current = reinterpret_cast<char*>(receiver);
+  DeclaredAccessorDescriptorIterator iterator(info->descriptor());
+  while (true) {
+    const DeclaredAccessorDescriptorData* data = iterator.Next();
+    switch (data->type) {
+      case kDescriptorReturnObject: {
+        ASSERT(iterator.Complete());
+        current = *CheckedCast<char*>(current);
+        return *CheckedCast<Object*>(current);
+      }
+      case kDescriptorPointerDereference:
+        ASSERT(!iterator.Complete());
+        current = *reinterpret_cast<char**>(current);
+        break;
+      case kDescriptorPointerShift:
+        ASSERT(!iterator.Complete());
+        current += data->pointer_shift_descriptor.byte_offset;
+        break;
+      case kDescriptorObjectDereference: {
+        ASSERT(!iterator.Complete());
+        Object* object = CheckedCast<Object>(current);
+        int field = data->object_dereference_descriptor.internal_field;
+        Object* smi = JSObject::cast(object)->GetInternalField(field);
+        ASSERT(smi->IsSmi());
+        current = reinterpret_cast<char*>(smi);
+        break;
+      }
+      case kDescriptorBitmaskCompare:
+        ASSERT(iterator.Complete());
+        return PerformCompare(data->bitmask_compare_descriptor,
+                              current,
+                              isolate->heap());
+      case kDescriptorPointerCompare:
+        ASSERT(iterator.Complete());
+        return PerformCompare(data->pointer_compare_descriptor,
+                              current,
+                              isolate->heap());
+      case kDescriptorPrimitiveValue:
+        ASSERT(iterator.Complete());
+        return GetPrimitiveValue(data->primitive_value_descriptor,
+                                 current,
+                                 isolate->heap());
+    }
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
                                                Object* structure,
-                                               String* name) {
+                                               Name* name) {
   Isolate* isolate = name->GetIsolate();
   // To accommodate both the old and the new api we switch on the
   // data structure used to store the callbacks.  Eventually foreign
@@ -182,9 +322,8 @@
   }
 
   // api style callbacks.
-  if (structure->IsExecutableAccessorInfo()) {
-    ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure);
-    if (!data->IsCompatibleReceiver(receiver)) {
+  if (structure->IsAccessorInfo()) {
+    if (!AccessorInfo::cast(structure)->IsCompatibleReceiver(receiver)) {
       Handle<Object> name_handle(name, isolate);
       Handle<Object> receiver_handle(receiver, isolate);
       Handle<Object> args[2] = { name_handle, receiver_handle };
@@ -194,12 +333,21 @@
                                                         ARRAY_SIZE(args)));
       return isolate->Throw(*error);
     }
+    // TODO(rossberg): Handling symbols in the API requires changing the API,
+    // so we do not support it for now.
+    if (name->IsSymbol()) return isolate->heap()->undefined_value();
+    if (structure->IsDeclaredAccessorInfo()) {
+      return GetDeclaredAccessorProperty(receiver,
+                                         DeclaredAccessorInfo::cast(structure),
+                                         isolate);
+    }
+    ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure);
     Object* fun_obj = data->getter();
     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
     if (call_fun == NULL) return isolate->heap()->undefined_value();
     HandleScope scope(isolate);
     JSObject* self = JSObject::cast(receiver);
-    Handle<String> key(name);
+    Handle<String> key(String::cast(name));
     LOG(isolate, ApiNamedPropertyAccess("load", self, name));
     CustomArguments args(isolate, data->data(), self, this);
     v8::AccessorInfo info(args.end());
@@ -229,18 +377,13 @@
     return isolate->heap()->undefined_value();
   }
 
-  // TODO(dcarney): Handle correctly.
-  if (structure->IsDeclaredAccessorInfo()) {
-    return isolate->heap()->undefined_value();
-  }
-
   UNREACHABLE();
   return NULL;
 }
 
 
 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
-                                             String* name_raw) {
+                                             Name* name_raw) {
   Isolate* isolate = GetIsolate();
   HandleScope scope(isolate);
   Handle<Object> receiver(receiver_raw, isolate);
@@ -255,11 +398,12 @@
 }
 
 
-Handle<Object> Object::GetProperty(Handle<Object> object, Handle<String> name) {
+Handle<Object> Object::GetProperty(Handle<Object> object, Handle<Name> name) {
   // TODO(rossberg): The index test should not be here but in the GetProperty
   // method (or somewhere else entirely). Needs more global clean-up.
   uint32_t index;
-  if (name->AsArrayIndex(&index)) return GetElement(object, index);
+  if (name->AsArrayIndex(&index))
+    return GetElement(object, index);
   Isolate* isolate = object->IsHeapObject()
       ? Handle<HeapObject>::cast(object)->GetIsolate()
       : Isolate::Current();
@@ -332,7 +476,7 @@
 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
     Object* receiver,
     LookupResult* result,
-    String* name,
+    Name* name,
     PropertyAttributes* attributes) {
   if (result->IsProperty()) {
     switch (result->type()) {
@@ -392,7 +536,7 @@
 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
     Object* receiver,
     LookupResult* result,
-    String* name,
+    Name* name,
     bool continue_search) {
   if (result->IsProperty()) {
     switch (result->type()) {
@@ -478,7 +622,7 @@
 
 
 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
-                                               Handle<String> key,
+                                               Handle<Name> key,
                                                Handle<Object> value,
                                                PropertyDetails details) {
   CALL_HEAP_FUNCTION(object->GetIsolate(),
@@ -487,12 +631,12 @@
 }
 
 
-MaybeObject* JSObject::SetNormalizedProperty(String* name,
+MaybeObject* JSObject::SetNormalizedProperty(Name* name,
                                              Object* value,
                                              PropertyDetails details) {
   ASSERT(!HasFastProperties());
   int entry = property_dictionary()->FindEntry(name);
-  if (entry == StringDictionary::kNotFound) {
+  if (entry == NameDictionary::kNotFound) {
     Object* store_value = value;
     if (IsGlobalObject()) {
       Heap* heap = name->GetHeap();
@@ -505,7 +649,7 @@
           property_dictionary()->Add(name, store_value, details);
       if (!maybe_dict->ToObject(&dict)) return maybe_dict;
     }
-    set_properties(StringDictionary::cast(dict));
+    set_properties(NameDictionary::cast(dict));
     return value;
   }
 
@@ -536,11 +680,11 @@
 }
 
 
-MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
+MaybeObject* JSObject::DeleteNormalizedProperty(Name* name, DeleteMode mode) {
   ASSERT(!HasFastProperties());
-  StringDictionary* dictionary = property_dictionary();
+  NameDictionary* dictionary = property_dictionary();
   int entry = dictionary->FindEntry(name);
-  if (entry != StringDictionary::kNotFound) {
+  if (entry != NameDictionary::kNotFound) {
     // If we have a global object set the cell to the hole.
     if (IsGlobalObject()) {
       PropertyDetails details = dictionary->DetailsAt(entry);
@@ -596,7 +740,7 @@
 Handle<Object> Object::GetProperty(Handle<Object> object,
                                    Handle<Object> receiver,
                                    LookupResult* result,
-                                   Handle<String> key,
+                                   Handle<Name> key,
                                    PropertyAttributes* attributes) {
   Isolate* isolate = object->IsHeapObject()
       ? Handle<HeapObject>::cast(object)->GetIsolate()
@@ -610,7 +754,7 @@
 
 MaybeObject* Object::GetProperty(Object* receiver,
                                  LookupResult* result,
-                                 String* name,
+                                 Name* name,
                                  PropertyAttributes* attributes) {
   // Make sure that the top context does not change when doing
   // callbacks or interceptor calls.
@@ -791,7 +935,7 @@
 
 
 MaybeObject* Object::GetHash(CreationFlag flag) {
-  // The object is either a number, a string, an odd-ball,
+  // The object is either a number, a name, an odd-ball,
   // a real JS object, or a Harmony proxy.
   if (IsNumber()) {
     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
@@ -817,7 +961,7 @@
 bool Object::SameValue(Object* other) {
   if (other == this) return true;
 
-  // The object is either a number, a string, an odd-ball,
+  // The object is either a number, a name, an odd-ball,
   // a real JS object, or a Harmony proxy.
   if (IsNumber() && other->IsNumber()) {
     double this_value = Number();
@@ -1553,7 +1697,7 @@
 
 
 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
-                                               String* name,
+                                               Name* name,
                                                Object* value,
                                                int field_index) {
   if (map()->unused_property_fields() == 0) {
@@ -1570,8 +1714,10 @@
 }
 
 
-static bool IsIdentifier(UnicodeCache* cache, String* string) {
+static bool IsIdentifier(UnicodeCache* cache, Name* name) {
   // Checks whether the buffer contains an identifier (no escape).
+  if (!name->IsString()) return false;
+  String* string = String::cast(name);
   if (string->length() == 0) return false;
   ConsStringIteratorOp op;
   StringCharacterStream stream(string, &op);
@@ -1587,7 +1733,7 @@
 }
 
 
-MaybeObject* JSObject::AddFastProperty(String* name,
+MaybeObject* JSObject::AddFastProperty(Name* name,
                                        Object* value,
                                        PropertyAttributes attributes,
                                        StoreFromKeyed store_mode) {
@@ -1596,7 +1742,7 @@
          map()->instance_descriptors()->Search(
              name, map()->NumberOfOwnDescriptors()));
 
-  // Normalize the object if the name is an actual string (not the
+  // Normalize the object if the name is an actual name (not the
   // hidden strings) and is not a real identifier.
   // Normalize the object if it will have too many fast properties.
   Isolate* isolate = GetHeap()->isolate();
@@ -1651,7 +1797,7 @@
 
 
 MaybeObject* JSObject::AddConstantFunctionProperty(
-    String* name,
+    Name* name,
     JSFunction* function,
     PropertyAttributes attributes) {
   // Allocate new instance descriptors with (name, function) added
@@ -1676,16 +1822,16 @@
 
 
 // Add property in slow mode
-MaybeObject* JSObject::AddSlowProperty(String* name,
+MaybeObject* JSObject::AddSlowProperty(Name* name,
                                        Object* value,
                                        PropertyAttributes attributes) {
   ASSERT(!HasFastProperties());
-  StringDictionary* dict = property_dictionary();
+  NameDictionary* dict = property_dictionary();
   Object* store_value = value;
   if (IsGlobalObject()) {
     // In case name is an orphaned property reuse the cell.
     int entry = dict->FindEntry(name);
-    if (entry != StringDictionary::kNotFound) {
+    if (entry != NameDictionary::kNotFound) {
       store_value = dict->ValueAt(entry);
       JSGlobalPropertyCell::cast(store_value)->set_value(value);
       // Assign an enumeration index to the property and update
@@ -1708,12 +1854,12 @@
   { MaybeObject* maybe_result = dict->Add(name, store_value, details);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
-  if (dict != result) set_properties(StringDictionary::cast(result));
+  if (dict != result) set_properties(NameDictionary::cast(result));
   return value;
 }
 
 
-MaybeObject* JSObject::AddProperty(String* name,
+MaybeObject* JSObject::AddProperty(Name* name,
                                    Object* value,
                                    PropertyAttributes attributes,
                                    StrictModeFlag strict_mode,
@@ -1729,7 +1875,7 @@
     if (strict_mode == kNonStrictMode) {
       return value;
     } else {
-      Handle<Object> args[1] = {Handle<String>(name)};
+      Handle<Object> args[1] = {Handle<Name>(name)};
       return isolate->Throw(
           *FACTORY->NewTypeError("object_not_extensible",
                                  HandleVector(args, 1)));
@@ -1775,7 +1921,7 @@
 
 void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
                                    const char* type_str,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    Handle<Object> old_value) {
   Isolate* isolate = object->GetIsolate();
   HandleScope scope(isolate);
@@ -1808,7 +1954,7 @@
 
 
 MaybeObject* JSObject::SetPropertyPostInterceptor(
-    String* name,
+    Name* name,
     Object* value,
     PropertyAttributes attributes,
     StrictModeFlag strict_mode,
@@ -1833,10 +1979,10 @@
 }
 
 
-MaybeObject* JSObject::ReplaceSlowProperty(String* name,
+MaybeObject* JSObject::ReplaceSlowProperty(Name* name,
                                            Object* value,
                                            PropertyAttributes attributes) {
-  StringDictionary* dictionary = property_dictionary();
+  NameDictionary* dictionary = property_dictionary();
   int old_index = dictionary->FindEntry(name);
   int new_enumeration_index = 0;  // 0 means "Use the next available index."
   if (old_index != -1) {
@@ -1851,7 +1997,7 @@
 
 MaybeObject* JSObject::ConvertTransitionToMapTransition(
     int transition_index,
-    String* name,
+    Name* name,
     Object* new_value,
     PropertyAttributes attributes) {
   Map* old_map = map();
@@ -1897,7 +2043,7 @@
 }
 
 
-MaybeObject* JSObject::ConvertDescriptorToField(String* name,
+MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
                                                 Object* new_value,
                                                 PropertyAttributes attributes) {
   if (map()->unused_property_fields() == 0 &&
@@ -1940,14 +2086,16 @@
 
 
 MaybeObject* JSObject::SetPropertyWithInterceptor(
-    String* name,
+    Name* name,
     Object* value,
     PropertyAttributes attributes,
     StrictModeFlag strict_mode) {
+  // TODO(rossberg): Support symbols in the API.
+  if (name->IsSymbol()) return value;
   Isolate* isolate = GetIsolate();
   HandleScope scope(isolate);
   Handle<JSObject> this_handle(this);
-  Handle<String> name_handle(name);
+  Handle<String> name_handle(String::cast(name));
   Handle<Object> value_handle(value, isolate);
   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   if (!interceptor->setter()->IsUndefined()) {
@@ -1983,7 +2131,7 @@
 
 
 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
-                                       Handle<String> key,
+                                       Handle<Name> key,
                                        Handle<Object> value,
                                        PropertyAttributes attributes,
                                        StrictModeFlag strict_mode) {
@@ -1993,7 +2141,7 @@
 }
 
 
-MaybeObject* JSReceiver::SetProperty(String* name,
+MaybeObject* JSReceiver::SetProperty(Name* name,
                                      Object* value,
                                      PropertyAttributes attributes,
                                      StrictModeFlag strict_mode,
@@ -2008,7 +2156,7 @@
 
 
 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
-                                               String* name,
+                                               Name* name,
                                                Object* value,
                                                JSObject* holder,
                                                StrictModeFlag strict_mode) {
@@ -2046,10 +2194,12 @@
                                                         ARRAY_SIZE(args)));
       return isolate->Throw(*error);
     }
+    // TODO(rossberg): Support symbols in the API.
+    if (name->IsSymbol()) return value;
     Object* call_obj = data->setter();
     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
     if (call_fun == NULL) return value;
-    Handle<String> key(name);
+    Handle<String> key(String::cast(name));
     LOG(isolate, ApiNamedPropertyAccess("store", this, name));
     CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
     v8::AccessorInfo info(args.end());
@@ -2073,7 +2223,7 @@
       if (strict_mode == kNonStrictMode) {
         return value;
       }
-      Handle<String> key(name);
+      Handle<Name> key(name);
       Handle<Object> holder_handle(holder, isolate);
       Handle<Object> args[2] = { key, holder_handle };
       return isolate->Throw(
@@ -2158,7 +2308,7 @@
 }
 
 MaybeObject* JSObject::SetPropertyViaPrototypes(
-    String* name,
+    Name* name,
     Object* value,
     PropertyAttributes attributes,
     StrictModeFlag strict_mode,
@@ -2291,15 +2441,17 @@
 
   ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
 
-  // Ensure the keys are internalized strings before writing them into the
+  // Ensure the keys are unique names before writing them into the
   // instance descriptor. Since it may cause a GC, it has to be done before we
   // temporarily put the heap in an invalid state while appending descriptors.
   for (int i = 0; i < nof_callbacks; ++i) {
     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
-    Handle<String> key =
-        isolate->factory()->InternalizedStringFromString(
-            Handle<String>(String::cast(entry->name())));
-    entry->set_name(*key);
+    if (!entry->name()->IsUniqueName()) {
+      Handle<String> key =
+          isolate->factory()->InternalizedStringFromString(
+              Handle<String>(String::cast(entry->name())));
+      entry->set_name(*key);
+    }
   }
 
   int nof = map->NumberOfOwnDescriptors();
@@ -2309,7 +2461,7 @@
   // precedence over previously added callbacks with that name.
   for (int i = nof_callbacks - 1; i >= 0; i--) {
     AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
-    String* key = String::cast(entry->name());
+    Name* key = Name::cast(entry->name());
     // Check if a descriptor with this name already exists before writing.
     if (array->Search(key, nof) == DescriptorArray::kNotFound) {
       CallbacksDescriptor desc(key, entry, entry->property_attributes());
@@ -2468,8 +2620,7 @@
 }
 
 
-void JSObject::LocalLookupRealNamedProperty(String* name,
-                                            LookupResult* result) {
+void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) {
   if (IsJSGlobalProxy()) {
     Object* proto = GetPrototype();
     if (proto->IsNull()) return result->NotFound();
@@ -2496,7 +2647,7 @@
   }
 
   int entry = property_dictionary()->FindEntry(name);
-  if (entry != StringDictionary::kNotFound) {
+  if (entry != NameDictionary::kNotFound) {
     Object* value = property_dictionary()->ValueAt(entry);
     if (IsGlobalObject()) {
       PropertyDetails d = property_dictionary()->DetailsAt(entry);
@@ -2517,7 +2668,7 @@
 }
 
 
-void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
+void JSObject::LookupRealNamedProperty(Name* name, LookupResult* result) {
   LocalLookupRealNamedProperty(name, result);
   if (result->IsFound()) return;
 
@@ -2525,7 +2676,7 @@
 }
 
 
-void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
+void JSObject::LookupRealNamedPropertyInPrototypes(Name* name,
                                                    LookupResult* result) {
   Isolate* isolate = GetIsolate();
   Heap* heap = isolate->heap();
@@ -2546,7 +2697,7 @@
 // We only need to deal with CALLBACKS and INTERCEPTORS
 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
     LookupResult* result,
-    String* name,
+    Name* name,
     Object* value,
     bool check_prototype,
     StrictModeFlag strict_mode) {
@@ -2601,7 +2752,7 @@
 
 
 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
-                                     String* key,
+                                     Name* key,
                                      Object* value,
                                      PropertyAttributes attributes,
                                      StrictModeFlag strict_mode,
@@ -2616,7 +2767,7 @@
 }
 
 
-bool JSProxy::HasPropertyWithHandler(String* name_raw) {
+bool JSProxy::HasPropertyWithHandler(Name* name_raw) {
   Isolate* isolate = GetIsolate();
   HandleScope scope(isolate);
   Handle<Object> receiver(this, isolate);
@@ -2633,7 +2784,7 @@
 
 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
     JSReceiver* receiver_raw,
-    String* name_raw,
+    Name* name_raw,
     Object* value_raw,
     PropertyAttributes attributes,
     StrictModeFlag strict_mode) {
@@ -2653,7 +2804,7 @@
 
 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
     JSReceiver* receiver_raw,
-    String* name_raw,
+    Name* name_raw,
     Object* value_raw,
     PropertyAttributes attributes,
     StrictModeFlag strict_mode,
@@ -2661,7 +2812,7 @@
   Isolate* isolate = GetIsolate();
   Handle<JSProxy> proxy(this);
   Handle<JSReceiver> receiver(receiver_raw);
-  Handle<String> name(name_raw);
+  Handle<Name> name(name_raw);
   Handle<Object> value(value_raw, isolate);
   Handle<Object> handler(this->handler(), isolate);  // Trap might morph proxy.
 
@@ -2748,7 +2899,7 @@
 
 
 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
-    String* name_raw, DeleteMode mode) {
+    Name* name_raw, DeleteMode mode) {
   Isolate* isolate = GetIsolate();
   HandleScope scope(isolate);
   Handle<JSProxy> receiver(this);
@@ -2786,7 +2937,7 @@
 
 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
     JSReceiver* receiver_raw,
-    String* name_raw) {
+    Name* name_raw) {
   Isolate* isolate = GetIsolate();
   HandleScope scope(isolate);
   Handle<JSProxy> proxy(this);
@@ -2913,7 +3064,7 @@
 
 
 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
-                                            String* name_raw,
+                                            Name* name_raw,
                                             Object* value_raw,
                                             PropertyAttributes attributes,
                                             StrictModeFlag strict_mode,
@@ -2927,9 +3078,11 @@
   // Optimization for 2-byte strings often used as keys in a decompression
   // dictionary.  We internalize these short keys to avoid constantly
   // reallocating them.
-  if (!name_raw->IsInternalizedString() && name_raw->length() <= 2) {
+  if (name_raw->IsString() && !name_raw->IsInternalizedString() &&
+      String::cast(name_raw)->length() <= 2) {
     Object* internalized_version;
-    { MaybeObject* maybe_string_version = heap->InternalizeString(name_raw);
+    { MaybeObject* maybe_string_version =
+        heap->InternalizeString(String::cast(name_raw));
       if (maybe_string_version->ToObject(&internalized_version)) {
         name_raw = String::cast(internalized_version);
       }
@@ -2959,7 +3112,7 @@
   // SetPropertyViaPrototypes might call back into JavaScript.
   HandleScope scope(isolate);
   Handle<JSObject> self(this);
-  Handle<String> name(name_raw);
+  Handle<Name> name(name_raw);
   Handle<Object> value(value_raw, isolate);
 
   if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) {
@@ -3092,7 +3245,7 @@
 // doesn't handle function prototypes correctly.
 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
     Handle<JSObject> object,
-    Handle<String> key,
+    Handle<Name> key,
     Handle<Object> value,
     PropertyAttributes attributes) {
   CALL_HEAP_FUNCTION(
@@ -3103,7 +3256,7 @@
 
 
 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
-    String* name_raw,
+    Name* name_raw,
     Object* value_raw,
     PropertyAttributes attributes) {
   // Make sure that the top context does not change when doing callbacks or
@@ -3143,7 +3296,7 @@
   // From this point on everything needs to be handlified.
   HandleScope scope(isolate);
   Handle<JSObject> self(this);
-  Handle<String> name(name_raw);
+  Handle<Name> name(name_raw);
   Handle<Object> value(value_raw, isolate);
 
   Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate);
@@ -3239,7 +3392,7 @@
 
 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
       JSObject* receiver,
-      String* name,
+      Name* name,
       bool continue_search) {
   // Check local property, ignore interceptor.
   LookupResult result(GetIsolate());
@@ -3260,8 +3413,11 @@
 
 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
       JSObject* receiver,
-      String* name,
+      Name* name,
       bool continue_search) {
+  // TODO(rossberg): Support symbols in the API.
+  if (name->IsSymbol()) return ABSENT;
+
   Isolate* isolate = GetIsolate();
 
   // Make sure that the top context does not change when doing
@@ -3272,7 +3428,7 @@
   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   Handle<JSObject> receiver_handle(receiver);
   Handle<JSObject> holder_handle(this);
-  Handle<String> name_handle(name);
+  Handle<String> name_handle(String::cast(name));
   CustomArguments args(isolate, interceptor->data(), receiver, this);
   v8::AccessorInfo info(args.end());
   if (!interceptor->query()->IsUndefined()) {
@@ -3311,7 +3467,7 @@
 
 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
       JSReceiver* receiver,
-      String* key) {
+      Name* key) {
   uint32_t index = 0;
   if (IsJSObject() && key->AsArrayIndex(&index)) {
     return JSObject::cast(this)->GetElementAttributeWithReceiver(
@@ -3327,7 +3483,7 @@
 PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
     JSReceiver* receiver,
     LookupResult* lookup,
-    String* name,
+    Name* name,
     bool continue_search) {
   // Check access rights if needed.
   if (IsAccessCheckNeeded()) {
@@ -3361,7 +3517,7 @@
 }
 
 
-PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
+PropertyAttributes JSReceiver::GetLocalPropertyAttribute(Name* name) {
   // Check whether the name is an array index.
   uint32_t index = 0;
   if (IsJSObject() && name->AsArrayIndex(&index)) {
@@ -3497,7 +3653,9 @@
         ASSERT(memcmp(Map::cast(fresh)->address(),
                       Map::cast(result)->address(),
                       Map::kCodeCacheOffset) == 0);
-        int offset = Map::kCodeCacheOffset + kPointerSize;
+        STATIC_ASSERT(Map::kDependentCodeOffset ==
+                      Map::kCodeCacheOffset + kPointerSize);
+        int offset = Map::kDependentCodeOffset + kPointerSize;
         ASSERT(memcmp(Map::cast(fresh)->address() + offset,
                       Map::cast(result)->address() + offset,
                       Map::kSize - offset) == 0);
@@ -3528,7 +3686,7 @@
 
 
 void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
-                                  Handle<String> name,
+                                  Handle<Name> name,
                                   Handle<Code> code) {
   Isolate* isolate = object->GetIsolate();
   CALL_HEAP_FUNCTION_VOID(isolate,
@@ -3536,7 +3694,7 @@
 }
 
 
-MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
+MaybeObject* JSObject::UpdateMapCodeCache(Name* name, Code* code) {
   if (map()->is_shared()) {
     // Fast case maps are never marked as shared.
     ASSERT(!HasFastProperties());
@@ -3582,8 +3740,8 @@
   } else {
     property_count += 2;  // Make space for two more properties.
   }
-  StringDictionary* dictionary;
-  MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
+  NameDictionary* dictionary;
+  MaybeObject* maybe_dictionary = NameDictionary::Allocate(property_count);
   if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
 
   DescriptorArray* descs = map_of_this->instance_descriptors();
@@ -3848,8 +4006,8 @@
 }
 
 
-Object* JSObject::GetHiddenProperty(String* key) {
-  ASSERT(key->IsInternalizedString());
+Object* JSObject::GetHiddenProperty(Name* key) {
+  ASSERT(key->IsUniqueName());
   if (IsJSGlobalProxy()) {
     // For a proxy, use the prototype as target object.
     Object* proxy_parent = GetPrototype();
@@ -3882,7 +4040,7 @@
 
 
 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj,
-                                           Handle<String> key,
+                                           Handle<Name> key,
                                            Handle<Object> value) {
   CALL_HEAP_FUNCTION(obj->GetIsolate(),
                      obj->SetHiddenProperty(*key, *value),
@@ -3890,8 +4048,8 @@
 }
 
 
-MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
-  ASSERT(key->IsInternalizedString());
+MaybeObject* JSObject::SetHiddenProperty(Name* key, Object* value) {
+  ASSERT(key->IsUniqueName());
   if (IsJSGlobalProxy()) {
     // For a proxy, use the prototype as target object.
     Object* proxy_parent = GetPrototype();
@@ -3931,8 +4089,8 @@
 }
 
 
-void JSObject::DeleteHiddenProperty(String* key) {
-  ASSERT(key->IsInternalizedString());
+void JSObject::DeleteHiddenProperty(Name* key) {
+  ASSERT(key->IsUniqueName());
   if (IsJSGlobalProxy()) {
     // For a proxy, use the prototype as target object.
     Object* proxy_parent = GetPrototype();
@@ -3972,7 +4130,7 @@
   if (HasFastProperties()) {
     // If the object has fast properties, check whether the first slot
     // in the descriptor array matches the hidden string. Since the
-    // hidden strings hash code is zero (and no other string has hash
+    // hidden strings hash code is zero (and no other name has hash
     // code zero) it will always occupy the first entry if present.
     DescriptorArray* descriptors = this->map()->instance_descriptors();
     if (descriptors->number_of_descriptors() > 0) {
@@ -4041,7 +4199,7 @@
   if (HasFastProperties()) {
     // If the object has fast properties, check whether the first slot
     // in the descriptor array matches the hidden string. Since the
-    // hidden strings hash code is zero (and no other string has hash
+    // hidden strings hash code is zero (and no other name has hash
     // code zero) it will always occupy the first entry if present.
     DescriptorArray* descriptors = this->map()->instance_descriptors();
     if (descriptors->number_of_descriptors() > 0) {
@@ -4066,7 +4224,7 @@
 }
 
 
-MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
+MaybeObject* JSObject::DeletePropertyPostInterceptor(Name* name,
                                                      DeleteMode mode) {
   // Check local property, ignore interceptor.
   LookupResult result(GetIsolate());
@@ -4083,11 +4241,14 @@
 }
 
 
-MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
+MaybeObject* JSObject::DeletePropertyWithInterceptor(Name* name) {
+  // TODO(rossberg): Support symbols in the API.
+  if (name->IsSymbol()) return GetHeap()->false_value();
+
   Isolate* isolate = GetIsolate();
   HandleScope scope(isolate);
   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
-  Handle<String> name_handle(name);
+  Handle<String> name_handle(String::cast(name));
   Handle<JSObject> this_handle(this);
   if (!interceptor->deleter()->IsUndefined()) {
     v8::NamedPropertyDeleter deleter =
@@ -4230,17 +4391,17 @@
 
 
 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj,
-                              Handle<String> prop) {
+                                        Handle<Name> prop) {
   CALL_HEAP_FUNCTION(obj->GetIsolate(),
                      obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
                      Object);
 }
 
 
-MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
+MaybeObject* JSObject::DeleteProperty(Name* name, DeleteMode mode) {
   Isolate* isolate = GetIsolate();
   // ECMA-262, 3rd, 8.6.2.5
-  ASSERT(name->IsString());
+  ASSERT(name->IsName());
 
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
@@ -4280,7 +4441,7 @@
   // From this point on everything needs to be handlified.
   HandleScope scope(isolate);
   Handle<JSObject> self(this);
-  Handle<String> hname(name);
+  Handle<Name> hname(name);
 
   Handle<Object> old_value = isolate->factory()->the_hole_value();
   bool is_observed = FLAG_harmony_observation && self->map()->is_observed();
@@ -4325,7 +4486,7 @@
 }
 
 
-MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
+MaybeObject* JSReceiver::DeleteProperty(Name* name, DeleteMode mode) {
   if (IsJSProxy()) {
     return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
   }
@@ -4551,13 +4712,16 @@
       ? descs->number_of_descriptors()
       : NumberOfOwnDescriptors();
   for (int i = 0; i < limit; i++) {
-    if ((descs->GetDetails(i).attributes() & filter) == 0) result++;
+    if ((descs->GetDetails(i).attributes() & filter) == 0 &&
+        ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
+      result++;
+    }
   }
   return result;
 }
 
 
-int Map::PropertyIndexFor(String* name) {
+int Map::PropertyIndexFor(Name* name) {
   DescriptorArray* descs = instance_descriptors();
   int limit = NumberOfOwnDescriptors();
   for (int i = 0; i < limit; i++) {
@@ -4581,7 +4745,7 @@
 }
 
 
-AccessorDescriptor* Map::FindAccessor(String* name) {
+AccessorDescriptor* Map::FindAccessor(Name* name) {
   DescriptorArray* descs = instance_descriptors();
   int number_of_own_descriptors = NumberOfOwnDescriptors();
   for (int i = 0; i < number_of_own_descriptors; i++) {
@@ -4594,8 +4758,8 @@
 
 
 void JSReceiver::LocalLookup(
-    String* name, LookupResult* result, bool search_hidden_prototypes) {
-  ASSERT(name->IsString());
+    Name* name, LookupResult* result, bool search_hidden_prototypes) {
+  ASSERT(name->IsName());
 
   Heap* heap = GetHeap();
 
@@ -4639,7 +4803,7 @@
 }
 
 
-void JSReceiver::Lookup(String* name, LookupResult* result) {
+void JSReceiver::Lookup(Name* name, LookupResult* result) {
   // Ecma-262 3rd 8.6.2.4
   Heap* heap = GetHeap();
   for (Object* current = this;
@@ -4653,7 +4817,7 @@
 
 
 // Search object and its prototype chain for callback properties.
-void JSObject::LookupCallbackProperty(String* name, LookupResult* result) {
+void JSObject::LookupCallbackProperty(Name* name, LookupResult* result) {
   Heap* heap = GetHeap();
   for (Object* current = this;
        current != heap->null_value() && current->IsJSObject();
@@ -4759,7 +4923,7 @@
 }
 
 
-MaybeObject* JSObject::CreateAccessorPairFor(String* name) {
+MaybeObject* JSObject::CreateAccessorPairFor(Name* name) {
   LookupResult result(GetHeap()->isolate());
   LocalLookupRealNamedProperty(name, &result);
   if (result.IsPropertyCallbacks()) {
@@ -4778,7 +4942,7 @@
 }
 
 
-MaybeObject* JSObject::DefinePropertyAccessor(String* name,
+MaybeObject* JSObject::DefinePropertyAccessor(Name* name,
                                               Object* getter,
                                               Object* setter,
                                               PropertyAttributes attributes) {
@@ -4815,7 +4979,7 @@
 }
 
 
-bool JSObject::CanSetCallback(String* name) {
+bool JSObject::CanSetCallback(Name* name) {
   ASSERT(!IsAccessCheckNeeded() ||
          GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
 
@@ -4877,7 +5041,7 @@
 }
 
 
-MaybeObject* JSObject::SetPropertyCallback(String* name,
+MaybeObject* JSObject::SetPropertyCallback(Name* name,
                                            Object* structure,
                                            PropertyAttributes attributes) {
   // Normalize object to make this operation simple.
@@ -4909,7 +5073,7 @@
 
 
 void JSObject::DefineAccessor(Handle<JSObject> object,
-                              Handle<String> name,
+                              Handle<Name> name,
                               Handle<Object> getter,
                               Handle<Object> setter,
                               PropertyAttributes attributes) {
@@ -4918,7 +5082,7 @@
       object->DefineAccessor(*name, *getter, *setter, attributes));
 }
 
-MaybeObject* JSObject::DefineAccessor(String* name_raw,
+MaybeObject* JSObject::DefineAccessor(Name* name_raw,
                                       Object* getter_raw,
                                       Object* setter_raw,
                                       PropertyAttributes attributes) {
@@ -4943,14 +5107,14 @@
   AssertNoContextChange ncc;
 
   // Try to flatten before operating on the string.
-  name_raw->TryFlatten();
+  if (name_raw->IsString()) String::cast(name_raw)->TryFlatten();
 
   if (!CanSetCallback(name_raw)) return isolate->heap()->undefined_value();
 
   // From this point on everything needs to be handlified.
   HandleScope scope(isolate);
   Handle<JSObject> self(this);
-  Handle<String> name(name_raw);
+  Handle<Name> name(name_raw);
   Handle<Object> getter(getter_raw, isolate);
   Handle<Object> setter(setter_raw, isolate);
 
@@ -5021,7 +5185,7 @@
 }
 
 
-MaybeObject* JSObject::DefineFastAccessor(String* name,
+MaybeObject* JSObject::DefineFastAccessor(Name* name,
                                           AccessorComponent component,
                                           Object* accessor,
                                           PropertyAttributes attributes) {
@@ -5104,7 +5268,7 @@
 
 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
   Isolate* isolate = GetIsolate();
-  String* name = String::cast(info->name());
+  Name* name = Name::cast(info->name());
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
@@ -5124,7 +5288,7 @@
   AssertNoContextChange ncc;
 
   // Try to flatten before operating on the string.
-  name->TryFlatten();
+  if (name->IsString()) String::cast(name)->TryFlatten();
 
   if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
 
@@ -5184,7 +5348,7 @@
 }
 
 
-Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
+Object* JSObject::LookupAccessor(Name* name, AccessorComponent component) {
   Heap* heap = GetHeap();
 
   // Make sure that the top context does not change when doing callbacks or
@@ -5335,7 +5499,7 @@
   MaybeObject* maybe_result = CopyDropDescriptors();
   if (!maybe_result->To(&result)) return maybe_result;
 
-  String* name = descriptor->GetKey();
+  Name* name = descriptor->GetKey();
 
   TransitionArray* transitions;
   MaybeObject* maybe_transitions =
@@ -5400,7 +5564,7 @@
 
 
 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
-                                         String* name,
+                                         Name* name,
                                          TransitionFlag flag,
                                          int descriptor_index) {
   ASSERT(descriptors->IsSortedNoDuplicates());
@@ -5516,8 +5680,8 @@
                                     TransitionFlag flag) {
   DescriptorArray* descriptors = instance_descriptors();
 
-  // Ensure the key is an internalized string.
-  MaybeObject* maybe_failure = descriptor->KeyToInternalizedString();
+  // Ensure the key is unique.
+  MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
   if (maybe_failure->IsFailure()) return maybe_failure;
 
   int old_size = NumberOfOwnDescriptors();
@@ -5549,7 +5713,7 @@
     new_descriptors->Append(descriptor, witness);
   }
 
-  String* key = descriptor->GetKey();
+  Name* key = descriptor->GetKey();
   int insertion_index = new_descriptors->number_of_descriptors() - 1;
 
   return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
@@ -5560,8 +5724,8 @@
                                        TransitionFlag flag) {
   DescriptorArray* old_descriptors = instance_descriptors();
 
-  // Ensure the key is an internalized string.
-  MaybeObject* maybe_result = descriptor->KeyToInternalizedString();
+  // Ensure the key is unique.
+  MaybeObject* maybe_result = descriptor->KeyToUniqueName();
   if (maybe_result->IsFailure()) return maybe_result;
 
   // We replace the key if it is already present.
@@ -5597,11 +5761,11 @@
                                         Descriptor* descriptor,
                                         int insertion_index,
                                         TransitionFlag flag) {
-  // Ensure the key is an internalized string.
-  MaybeObject* maybe_failure = descriptor->KeyToInternalizedString();
+  // Ensure the key is unique.
+  MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
   if (maybe_failure->IsFailure()) return maybe_failure;
 
-  String* key = descriptor->GetKey();
+  Name* key = descriptor->GetKey();
   ASSERT(key == descriptors->GetKey(insertion_index));
 
   int new_size = NumberOfOwnDescriptors();
@@ -5632,7 +5796,7 @@
 
 
 void Map::UpdateCodeCache(Handle<Map> map,
-                          Handle<String> name,
+                          Handle<Name> name,
                           Handle<Code> code) {
   Isolate* isolate = map->GetIsolate();
   CALL_HEAP_FUNCTION_VOID(isolate,
@@ -5640,7 +5804,7 @@
 }
 
 
-MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
+MaybeObject* Map::UpdateCodeCache(Name* name, Code* code) {
   ASSERT(!is_shared() || code->allowed_in_shared_map_code_cache());
 
   // Allocate the code cache if not present.
@@ -5657,7 +5821,7 @@
 }
 
 
-Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
+Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
   // Do a lookup if a code cache exists.
   if (!code_cache()->IsFixedArray()) {
     return CodeCache::cast(code_cache())->Lookup(name, flags);
@@ -5676,7 +5840,7 @@
 }
 
 
-void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
+void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
   // No GC is supposed to happen between a call to IndexInCodeCache and
   // RemoveFromCodeCache so the code cache must be there.
   ASSERT(!code_cache()->IsFixedArray());
@@ -5879,7 +6043,7 @@
 }
 
 
-MaybeObject* CodeCache::Update(String* name, Code* code) {
+MaybeObject* CodeCache::Update(Name* name, Code* code) {
   // The number of monomorphic stubs for normal load/store/call IC's can grow to
   // a large number and therefore they need to go into a hash table. They are
   // used to load global properties from cells.
@@ -5901,7 +6065,7 @@
 }
 
 
-MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
+MaybeObject* CodeCache::UpdateDefaultCache(Name* name, Code* code) {
   // When updating the default code cache we disregard the type encoded in the
   // flags. This allows call constant stubs to overwrite call field
   // stubs, etc.
@@ -5924,7 +6088,7 @@
       cache->set(i + kCodeCacheEntryCodeOffset, code);
       return this;
     }
-    if (name->Equals(String::cast(key))) {
+    if (name->Equals(Name::cast(key))) {
       Code::Flags found =
           Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
       if (Code::RemoveTypeFromFlags(found) == flags) {
@@ -5961,7 +6125,7 @@
 }
 
 
-MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
+MaybeObject* CodeCache::UpdateNormalTypeCache(Name* name, Code* code) {
   // Adding a new entry can cause a new cache to be allocated.
   CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   Object* new_cache;
@@ -5973,7 +6137,7 @@
 }
 
 
-Object* CodeCache::Lookup(String* name, Code::Flags flags) {
+Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
   if (Code::ExtractTypeFromFlags(flags) == Code::NORMAL) {
     return LookupNormalTypeCache(name, flags);
   } else {
@@ -5982,7 +6146,7 @@
 }
 
 
-Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
+Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
   FixedArray* cache = default_cache();
   int length = cache->length();
   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
@@ -5990,7 +6154,7 @@
     // Skip deleted elements.
     if (key->IsNull()) continue;
     if (key->IsUndefined()) return key;
-    if (name->Equals(String::cast(key))) {
+    if (name->Equals(Name::cast(key))) {
       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
       if (code->flags() == flags) {
         return code;
@@ -6001,7 +6165,7 @@
 }
 
 
-Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
+Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
   if (!normal_type_cache()->IsUndefined()) {
     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
     return cache->Lookup(name, flags);
@@ -6015,7 +6179,7 @@
   if (code->type() == Code::NORMAL) {
     if (normal_type_cache()->IsUndefined()) return -1;
     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
-    return cache->GetIndex(String::cast(name), code->flags());
+    return cache->GetIndex(Name::cast(name), code->flags());
   }
 
   FixedArray* array = default_cache();
@@ -6031,7 +6195,7 @@
   if (code->type() == Code::NORMAL) {
     ASSERT(!normal_type_cache()->IsUndefined());
     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
-    ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
+    ASSERT(cache->GetIndex(Name::cast(name), code->flags()) == index);
     cache->RemoveByIndex(index);
   } else {
     FixedArray* array = default_cache();
@@ -6052,10 +6216,10 @@
 // lookup not to create a new entry.
 class CodeCacheHashTableKey : public HashTableKey {
  public:
-  CodeCacheHashTableKey(String* name, Code::Flags flags)
+  CodeCacheHashTableKey(Name* name, Code::Flags flags)
       : name_(name), flags_(flags), code_(NULL) { }
 
-  CodeCacheHashTableKey(String* name, Code* code)
+  CodeCacheHashTableKey(Name* name, Code* code)
       : name_(name),
         flags_(code->flags()),
         code_(code) { }
@@ -6064,7 +6228,7 @@
   bool IsMatch(Object* other) {
     if (!other->IsFixedArray()) return false;
     FixedArray* pair = FixedArray::cast(other);
-    String* name = String::cast(pair->get(0));
+    Name* name = Name::cast(pair->get(0));
     Code::Flags flags = Code::cast(pair->get(1))->flags();
     if (flags != flags_) {
       return false;
@@ -6072,7 +6236,7 @@
     return name_->Equals(name);
   }
 
-  static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
+  static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
     return name->Hash() ^ flags;
   }
 
@@ -6080,7 +6244,7 @@
 
   uint32_t HashForObject(Object* obj) {
     FixedArray* pair = FixedArray::cast(obj);
-    String* name = String::cast(pair->get(0));
+    Name* name = Name::cast(pair->get(0));
     Code* code = Code::cast(pair->get(1));
     return NameFlagsHashHelper(name, code->flags());
   }
@@ -6098,14 +6262,14 @@
   }
 
  private:
-  String* name_;
+  Name* name_;
   Code::Flags flags_;
   // TODO(jkummerow): We should be able to get by without this.
   Code* code_;
 };
 
 
-Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
+Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
   CodeCacheHashTableKey key(name, flags);
   int entry = FindEntry(&key);
   if (entry == kNotFound) return GetHeap()->undefined_value();
@@ -6113,7 +6277,7 @@
 }
 
 
-MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
+MaybeObject* CodeCacheHashTable::Put(Name* name, Code* code) {
   CodeCacheHashTableKey key(name, code);
   Object* obj;
   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
@@ -6136,7 +6300,7 @@
 }
 
 
-int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) {
+int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
   CodeCacheHashTableKey key(name, flags);
   int entry = FindEntry(&key);
   return (entry == kNotFound) ? -1 : entry;
@@ -6333,7 +6497,7 @@
   if (FLAG_enable_slow_asserts) {
     for (int i = 0; i < result->length(); i++) {
       Object* current = result->get(i);
-      ASSERT(current->IsNumber() || current->IsString());
+      ASSERT(current->IsNumber() || current->IsName());
     }
   }
 #endif
@@ -6351,7 +6515,7 @@
   if (FLAG_enable_slow_asserts) {
     for (int i = 0; i < result->length(); i++) {
       Object* current = result->get(i);
-      ASSERT(current->IsNumber() || current->IsString());
+      ASSERT(current->IsNumber() || current->IsName());
     }
   }
 #endif
@@ -7737,7 +7901,7 @@
       }
     } else {
       if (i != transition_index) {
-        String* key = t->GetKey(i);
+        Name* key = t->GetKey(i);
         t->SetKey(transition_index, key);
         Object** key_slot = t->GetKeySlot(transition_index);
         collector->RecordSlot(key_slot, key_slot, key);
@@ -8785,7 +8949,7 @@
     if (i++ == length) return;
     RelocInfo* info = it.rinfo();
     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
-    ASSERT(code->is_load_stub());
+    ASSERT(code->kind() == Code::STUB);
     code_list->Add(Handle<Code>(code));
   }
   UNREACHABLE();
@@ -9780,7 +9944,7 @@
 }
 
 
-PropertyType JSObject::GetLocalPropertyType(String* name) {
+PropertyType JSObject::GetLocalPropertyType(Name* name) {
   uint32_t index = 0;
   if (name->AsArrayIndex(&index)) {
     return GetLocalElementType(index);
@@ -9796,7 +9960,7 @@
 }
 
 
-AccessorPair* JSObject::GetLocalPropertyAccessorPair(String* name) {
+AccessorPair* JSObject::GetLocalPropertyAccessorPair(Name* name) {
   uint32_t index = 0;
   if (name->AsArrayIndex(&index)) {
     return GetLocalElementAccessorPair(index);
@@ -9917,8 +10081,9 @@
   }
 
   if (structure->IsDeclaredAccessorInfo()) {
-    // TODO(dcarney): Handle correctly.
-    return isolate->heap()->undefined_value();
+    return GetDeclaredAccessorProperty(receiver,
+                                       DeclaredAccessorInfo::cast(structure),
+                                       isolate);
   }
 
   UNREACHABLE();
@@ -11096,7 +11261,7 @@
 
 MaybeObject* JSObject::GetPropertyPostInterceptor(
     Object* receiver,
-    String* name,
+    Name* name,
     PropertyAttributes* attributes) {
   // Check local property in holder, ignore interceptor.
   LookupResult result(GetIsolate());
@@ -11114,7 +11279,7 @@
 
 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
     Object* receiver,
-    String* name,
+    Name* name,
     PropertyAttributes* attributes) {
   // Check local property in holder, ignore interceptor.
   LookupResult result(GetIsolate());
@@ -11128,14 +11293,17 @@
 
 MaybeObject* JSObject::GetPropertyWithInterceptor(
     Object* receiver,
-    String* name,
+    Name* name,
     PropertyAttributes* attributes) {
+  // TODO(rossberg): Support symbols in the API.
+  if (name->IsSymbol()) return GetHeap()->undefined_value();
+
   Isolate* isolate = GetIsolate();
   InterceptorInfo* interceptor = GetNamedInterceptor();
   HandleScope scope(isolate);
   Handle<Object> receiver_handle(receiver, isolate);
   Handle<JSObject> holder_handle(this);
-  Handle<String> name_handle(name);
+  Handle<String> name_handle(String::cast(name));
 
   if (!interceptor->getter()->IsUndefined()) {
     v8::NamedPropertyGetter getter =
@@ -11168,7 +11336,7 @@
 }
 
 
-bool JSObject::HasRealNamedProperty(String* key) {
+bool JSObject::HasRealNamedProperty(Name* key) {
   // Check access rights if needed.
   Isolate* isolate = GetIsolate();
   if (IsAccessCheckNeeded()) {
@@ -11248,7 +11416,7 @@
 }
 
 
-bool JSObject::HasRealNamedCallbackProperty(String* key) {
+bool JSObject::HasRealNamedCallbackProperty(Name* key) {
   // Check access rights if needed.
   Isolate* isolate = GetIsolate();
   if (IsAccessCheckNeeded()) {
@@ -11268,7 +11436,7 @@
   if (HasFastProperties()) {
     Map* map = this->map();
     if (filter == NONE) return map->NumberOfOwnDescriptors();
-    if (filter == DONT_ENUM) {
+    if (filter & DONT_ENUM) {
       int result = map->EnumLength();
       if (result != Map::kInvalidEnumCache) return result;
     }
@@ -11406,7 +11574,7 @@
   } else {
     property_dictionary()->CopyKeysTo(storage,
                                       index,
-                                      StringDictionary::UNSORTED);
+                                      NameDictionary::UNSORTED);
   }
 }
 
@@ -11945,15 +12113,15 @@
 
 
 // Find entry for key otherwise return kNotFound.
-int StringDictionary::FindEntry(String* key) {
-  if (!key->IsInternalizedString()) {
-    return HashTable<StringDictionaryShape, String*>::FindEntry(key);
+int NameDictionary::FindEntry(Name* key) {
+  if (!key->IsUniqueName()) {
+    return HashTable<NameDictionaryShape, Name*>::FindEntry(key);
   }
 
-  // Optimized for internalized string key. Knowledge of the key type allows:
-  // 1. Move the check if the key is internalized out of the loop.
-  // 2. Avoid comparing hash codes in internalized-to-internalized comparison.
-  // 3. Detect a case when a dictionary key is not internalized but the key is.
+  // Optimized for unique names. Knowledge of the key type allows:
+  // 1. Move the check if the key is unique out of the loop.
+  // 2. Avoid comparing hash codes in unique-to-unique comparison.
+  // 3. Detect a case when a dictionary key is not unique but the key is.
   //    In case of positive result the dictionary key may be replaced by the
   //    internalized string with minimal performance penalty. It gives a chance
   //    to perform further lookups in code stubs (and significant performance
@@ -11969,15 +12137,15 @@
     Object* element = get(index);
     if (element->IsUndefined()) break;  // Empty entry.
     if (key == element) return entry;
-    if (!element->IsInternalizedString() &&
+    if (!element->IsUniqueName() &&
         !element->IsTheHole() &&
-        String::cast(element)->Equals(key)) {
-      // Replace a key that is not an internalized string by the equivalent
+        Name::cast(element)->Equals(key)) {
+      // Replace a key that is a non-internalized string by the equivalent
       // internalized string for faster further lookups.
       set(index, key);
       return entry;
     }
-    ASSERT(element->IsTheHole() || !String::cast(element)->Equals(key));
+    ASSERT(element->IsTheHole() || !Name::cast(element)->Equals(key));
     entry = NextProbe(entry, count++, capacity);
   }
   return kNotFound;
@@ -12104,7 +12272,7 @@
 
 template class HashTable<ObjectHashTableShape<2>, Object*>;
 
-template class Dictionary<StringDictionaryShape, String*>;
+template class Dictionary<NameDictionaryShape, Name*>;
 
 template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
 
@@ -12116,8 +12284,7 @@
 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
     Allocate(int at_least_space_for);
 
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate(
-    int);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Allocate(int n);
 
 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
     uint32_t, Object*);
@@ -12131,7 +12298,7 @@
 template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
     SlowReverseLookup(Object* value);
 
-template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
+template Object* Dictionary<NameDictionaryShape, Name*>::SlowReverseLookup(
     Object*);
 
 template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo(
@@ -12139,32 +12306,31 @@
     PropertyAttributes,
     Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode);
 
-template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
+template Object* Dictionary<NameDictionaryShape, Name*>::DeleteProperty(
     int, JSObject::DeleteMode);
 
 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
     DeleteProperty(int, JSObject::DeleteMode);
 
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
-    String*);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Shrink(Name* n);
 
 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
     uint32_t);
 
-template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
+template void Dictionary<NameDictionaryShape, Name*>::CopyKeysTo(
     FixedArray*,
     int,
-    Dictionary<StringDictionaryShape, String*>::SortMode);
+    Dictionary<NameDictionaryShape, Name*>::SortMode);
 
 template int
-Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
+Dictionary<NameDictionaryShape, Name*>::NumberOfElementsFilterAttributes(
     PropertyAttributes);
 
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
-    String*, Object*, PropertyDetails);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Add(
+    Name*, Object*, PropertyDetails);
 
 template MaybeObject*
-Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
+Dictionary<NameDictionaryShape, Name*>::GenerateNewEnumerationIndices();
 
 template int
 Dictionary<SeededNumberDictionaryShape, uint32_t>::
@@ -12182,8 +12348,8 @@
 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
     EnsureCapacity(int, uint32_t);
 
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::
-    EnsureCapacity(int, String*);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
+    EnsureCapacity(int, Name*);
 
 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
@@ -12191,14 +12357,14 @@
 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
 
-template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry(
-    String*, Object*, PropertyDetails, uint32_t);
+template MaybeObject* Dictionary<NameDictionaryShape, Name*>::AddEntry(
+    Name*, Object*, PropertyDetails, uint32_t);
 
 template
 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements();
 
 template
-int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
+int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements();
 
 template
 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
@@ -12616,7 +12782,7 @@
 
 Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell(
     Handle<GlobalObject> global,
-    Handle<String> name) {
+    Handle<Name> name) {
   Isolate* isolate = global->GetIsolate();
   CALL_HEAP_FUNCTION(isolate,
                      global->EnsurePropertyCell(*name),
@@ -12624,10 +12790,10 @@
 }
 
 
-MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
+MaybeObject* GlobalObject::EnsurePropertyCell(Name* name) {
   ASSERT(!HasFastProperties());
   int entry = property_dictionary()->FindEntry(name);
-  if (entry == StringDictionary::kNotFound) {
+  if (entry == NameDictionary::kNotFound) {
     Heap* heap = GetHeap();
     Object* cell;
     { MaybeObject* maybe_cell =
@@ -12641,7 +12807,7 @@
           property_dictionary()->Add(name, cell, details);
       if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
     }
-    set_properties(StringDictionary::cast(dictionary));
+    set_properties(NameDictionary::cast(dictionary));
     return cell;
   } else {
     Object* value = property_dictionary()->ValueAt(entry);
@@ -12949,7 +13115,7 @@
 }
 
 
-// StringsKey used for HashTable where key is array of internalzied strings.
+// StringsKey used for HashTable where key is array of internalized strings.
 class StringsKey : public HashTableKey {
  public:
   explicit StringsKey(FixedArray* strings) : strings_(strings) { }
@@ -13021,8 +13187,8 @@
 }
 
 
-void StringDictionary::DoGenerateNewEnumerationIndices(
-    Handle<StringDictionary> dictionary) {
+void NameDictionary::DoGenerateNewEnumerationIndices(
+    Handle<NameDictionary> dictionary) {
   CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(),
                           dictionary->GenerateNewEnumerationIndices());
 }
@@ -13192,8 +13358,8 @@
     SetNextEnumerationIndex(index + 1);
   }
   SetEntry(entry, k, value, details);
-  ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
-          || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
+  ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() ||
+          Dictionary<Shape, Key>::KeyAt(entry)->IsName()));
   HashTable<Shape, Key>::ElementAdded();
   return this;
 }
@@ -13304,7 +13470,8 @@
   int result = 0;
   for (int i = 0; i < capacity; i++) {
     Object* k = HashTable<Shape, Key>::KeyAt(i);
-    if (HashTable<Shape, Key>::IsKey(k)) {
+    if (HashTable<Shape, Key>::IsKey(k) &&
+        ((filter & SYMBOLIC) == 0 || !k->IsSymbol())) {
       PropertyDetails details = DetailsAt(i);
       if (details.IsDeleted()) continue;
       PropertyAttributes attr = details.attributes();
@@ -13346,7 +13513,7 @@
 }
 
 
-FixedArray* StringDictionary::CopyEnumKeysTo(FixedArray* storage) {
+FixedArray* NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
   int length = storage->length();
   ASSERT(length >= NumberOfEnumElements());
   Heap* heap = GetHeap();
@@ -13359,7 +13526,7 @@
   // that are deleted or not enumerable.
   for (int i = 0; i < capacity; i++) {
      Object* k = KeyAt(i);
-     if (IsKey(k)) {
+     if (IsKey(k) && !k->IsSymbol()) {
        PropertyDetails details = DetailsAt(i);
        if (details.IsDeleted() || details.IsDontEnum()) continue;
        properties++;
@@ -13430,7 +13597,7 @@
 }
 
 
-MaybeObject* StringDictionary::TransformPropertiesToFastFor(
+MaybeObject* NameDictionary::TransformPropertiesToFastFor(
     JSObject* obj, int unused_property_fields) {
   // Make sure we preserve dictionary representation if there are too many
   // descriptors.
@@ -13511,11 +13678,15 @@
     Object* k = KeyAt(i);
     if (IsKey(k)) {
       Object* value = ValueAt(i);
-      // Ensure the key is an internalized string before writing into the
-      // instance descriptor.
-      String* key;
-      MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
-      if (!maybe_key->To(&key)) return maybe_key;
+      Name* key;
+      if (k->IsSymbol()) {
+        key = Symbol::cast(k);
+      } else {
+        // Ensure the key is a unique name before writing into the
+        // instance descriptor.
+        MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
+        if (!maybe_key->To(&key)) return maybe_key;
+      }
 
       PropertyDetails details = DetailsAt(i);
       ASSERT(details.descriptor_index() == details.dictionary_index());
@@ -13694,6 +13865,58 @@
 }
 
 
+DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
+    DeclaredAccessorDescriptor* descriptor)
+    : array_(descriptor->serialized_data()->GetDataStartAddress()),
+      length_(descriptor->serialized_data()->length()),
+      offset_(0) {
+}
+
+
+const DeclaredAccessorDescriptorData*
+  DeclaredAccessorDescriptorIterator::Next() {
+  ASSERT(offset_ < length_);
+  uint8_t* ptr = &array_[offset_];
+  ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0);
+  const DeclaredAccessorDescriptorData* data =
+      reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr);
+  offset_ += sizeof(*data);
+  ASSERT(offset_ <= length_);
+  return data;
+}
+
+
+Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create(
+    Isolate* isolate,
+    const DeclaredAccessorDescriptorData& descriptor,
+    Handle<DeclaredAccessorDescriptor> previous) {
+  int previous_length =
+      previous.is_null() ? 0 : previous->serialized_data()->length();
+  int length = sizeof(descriptor) + previous_length;
+  Handle<ByteArray> serialized_descriptor =
+      isolate->factory()->NewByteArray(length);
+  Handle<DeclaredAccessorDescriptor> value =
+      isolate->factory()->NewDeclaredAccessorDescriptor();
+  value->set_serialized_data(*serialized_descriptor);
+  // Copy in the data.
+  {
+    AssertNoAllocation no_allocation;
+    uint8_t* array = serialized_descriptor->GetDataStartAddress();
+    if (previous_length != 0) {
+      uint8_t* previous_array =
+          previous->serialized_data()->GetDataStartAddress();
+      memcpy(array, previous_array, previous_length);
+      array += previous_length;
+    }
+    ASSERT(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0);
+    DeclaredAccessorDescriptorData* data =
+        reinterpret_cast<DeclaredAccessorDescriptorData*>(array);
+    *data = descriptor;
+  }
+  return value;
+}
+
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
 // Check if there is a break point at this code position.
 bool DebugInfo::HasBreakPoint(int code_position) {
diff --git a/src/objects.h b/src/objects.h
index bf8c1e8..59cddc2 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -152,11 +152,75 @@
   ALLOW_ELEMENT_TRANSITION_MAPS
 };
 
-enum KeyedAccessGrowMode {
-  DO_NOT_ALLOW_JSARRAY_GROWTH,
-  ALLOW_JSARRAY_GROWTH
+enum KeyedAccessStoreMode {
+  STANDARD_STORE,
+  STORE_TRANSITION_SMI_TO_OBJECT,
+  STORE_TRANSITION_SMI_TO_DOUBLE,
+  STORE_TRANSITION_DOUBLE_TO_OBJECT,
+  STORE_TRANSITION_HOLEY_SMI_TO_OBJECT,
+  STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE,
+  STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
+  STORE_AND_GROW_NO_TRANSITION,
+  STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT,
+  STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE,
+  STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT,
+  STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT,
+  STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE,
+  STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT,
+  STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS,
+  STORE_NO_TRANSITION_HANDLE_COW
 };
 
+
+static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
+    STANDARD_STORE;
+STATIC_ASSERT(STANDARD_STORE == 0);
+STATIC_ASSERT(kGrowICDelta ==
+              STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT -
+              STORE_TRANSITION_SMI_TO_OBJECT);
+STATIC_ASSERT(kGrowICDelta ==
+              STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE -
+              STORE_TRANSITION_SMI_TO_DOUBLE);
+STATIC_ASSERT(kGrowICDelta ==
+              STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT -
+              STORE_TRANSITION_DOUBLE_TO_OBJECT);
+
+
+static inline KeyedAccessStoreMode GetGrowStoreMode(
+    KeyedAccessStoreMode store_mode) {
+  if (store_mode < STORE_AND_GROW_NO_TRANSITION) {
+    store_mode = static_cast<KeyedAccessStoreMode>(
+        static_cast<int>(store_mode) + kGrowICDelta);
+  }
+  return store_mode;
+}
+
+
+static inline bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode) {
+  return store_mode > STANDARD_STORE &&
+      store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT &&
+      store_mode != STORE_AND_GROW_NO_TRANSITION;
+}
+
+
+static inline KeyedAccessStoreMode GetNonTransitioningStoreMode(
+    KeyedAccessStoreMode store_mode) {
+  if (store_mode >= STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
+    return store_mode;
+  }
+  if (store_mode >= STORE_AND_GROW_NO_TRANSITION) {
+    return STORE_AND_GROW_NO_TRANSITION;
+  }
+  return STANDARD_STORE;
+}
+
+
+static inline bool IsGrowStoreMode(KeyedAccessStoreMode store_mode) {
+  return store_mode >= STORE_AND_GROW_NO_TRANSITION &&
+      store_mode <= STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
+}
+
+
 // Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
 enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
 
@@ -936,8 +1000,6 @@
   V(ObjectHashTable)                           \
 
 
-class JSReceiver;
-
 // Object is the abstract superclass for all classes in the
 // object hierarchy.
 // Object does not use any virtual functions to avoid the
@@ -1003,28 +1065,28 @@
   // Failure is returned otherwise.
   MUST_USE_RESULT inline MaybeObject* ToSmi();
 
-  void Lookup(String* name, LookupResult* result);
+  void Lookup(Name* name, LookupResult* result);
 
   // Property access.
-  MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
+  MUST_USE_RESULT inline MaybeObject* GetProperty(Name* key);
   MUST_USE_RESULT inline MaybeObject* GetProperty(
-      String* key,
+      Name* key,
       PropertyAttributes* attributes);
   MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
       Object* receiver,
-      String* key,
+      Name* key,
       PropertyAttributes* attributes);
 
-  static Handle<Object> GetProperty(Handle<Object> object, Handle<String> key);
+  static Handle<Object> GetProperty(Handle<Object> object, Handle<Name> key);
   static Handle<Object> GetProperty(Handle<Object> object,
                                     Handle<Object> receiver,
                                     LookupResult* result,
-                                    Handle<String> key,
+                                    Handle<Name> key,
                                     PropertyAttributes* attributes);
 
   MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
                                            LookupResult* result,
-                                           String* key,
+                                           Name* key,
                                            PropertyAttributes* attributes);
 
   MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
@@ -1491,20 +1553,20 @@
   static inline JSReceiver* cast(Object* obj);
 
   static Handle<Object> SetProperty(Handle<JSReceiver> object,
-                                    Handle<String> key,
+                                    Handle<Name> key,
                                     Handle<Object> value,
                                     PropertyAttributes attributes,
                                     StrictModeFlag strict_mode);
   // Can cause GC.
   MUST_USE_RESULT MaybeObject* SetProperty(
-      String* key,
+      Name* key,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
       StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED);
   MUST_USE_RESULT MaybeObject* SetProperty(
       LookupResult* result,
-      String* key,
+      Name* key,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
@@ -1512,7 +1574,7 @@
   MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter,
                                                             Object* value);
 
-  MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
+  MUST_USE_RESULT MaybeObject* DeleteProperty(Name* name, DeleteMode mode);
   MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
 
   // Set the index'th array element.
@@ -1533,17 +1595,17 @@
   // function that was used to instantiate the object).
   String* constructor_name();
 
-  inline PropertyAttributes GetPropertyAttribute(String* name);
+  inline PropertyAttributes GetPropertyAttribute(Name* name);
   PropertyAttributes GetPropertyAttributeWithReceiver(JSReceiver* receiver,
-                                                      String* name);
-  PropertyAttributes GetLocalPropertyAttribute(String* name);
+                                                      Name* name);
+  PropertyAttributes GetLocalPropertyAttribute(Name* name);
 
   inline PropertyAttributes GetElementAttribute(uint32_t index);
   inline PropertyAttributes GetLocalElementAttribute(uint32_t index);
 
   // Can cause a GC.
-  inline bool HasProperty(String* name);
-  inline bool HasLocalProperty(String* name);
+  inline bool HasProperty(Name* name);
+  inline bool HasLocalProperty(Name* name);
   inline bool HasElement(uint32_t index);
   inline bool HasLocalElement(uint32_t index);
 
@@ -1563,9 +1625,9 @@
 
   // Lookup a property.  If found, the result is valid and has
   // detailed information.
-  void LocalLookup(String* name, LookupResult* result,
+  void LocalLookup(Name* name, LookupResult* result,
                    bool search_hidden_prototypes = false);
-  void Lookup(String* name, LookupResult* result);
+  void Lookup(Name* name, LookupResult* result);
 
  protected:
   Smi* GenerateIdentityHash();
@@ -1573,7 +1635,7 @@
  private:
   PropertyAttributes GetPropertyAttributeForResult(JSReceiver* receiver,
                                                    LookupResult* result,
-                                                   String* name,
+                                                   Name* name,
                                                    bool continue_search);
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
@@ -1591,7 +1653,7 @@
   DECL_ACCESSORS(properties, FixedArray)  // Get and set fast properties.
   inline void initialize_properties();
   inline bool HasFastProperties();
-  inline StringDictionary* property_dictionary();  // Gets slow properties.
+  inline NameDictionary* property_dictionary();  // Gets slow properties.
 
   // [elements]: The elements (properties with names that are integers).
   //
@@ -1665,34 +1727,34 @@
 
   MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
                                                        Object* structure,
-                                                       String* name);
+                                                       Name* name);
 
   // Can cause GC.
   MUST_USE_RESULT MaybeObject* SetPropertyForResult(LookupResult* result,
-                                           String* key,
+                                           Name* key,
                                            Object* value,
                                            PropertyAttributes attributes,
                                            StrictModeFlag strict_mode,
                                            StoreFromKeyed store_mode);
   MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
       LookupResult* result,
-      String* name,
+      Name* name,
       Object* value,
       bool check_prototype,
       StrictModeFlag strict_mode);
   MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(
       Object* structure,
-      String* name,
+      Name* name,
       Object* value,
       JSObject* holder,
       StrictModeFlag strict_mode);
   MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode);
   MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
@@ -1700,14 +1762,14 @@
 
   static Handle<Object> SetLocalPropertyIgnoreAttributes(
       Handle<JSObject> object,
-      Handle<String> key,
+      Handle<Name> key,
       Handle<Object> value,
       PropertyAttributes attributes);
 
   // Try to follow an existing transition to a field with attributes NONE. The
   // return value indicates whether the transition was successful.
   static inline bool TryTransitionToField(Handle<JSObject> object,
-                                          Handle<String> key);
+                                          Handle<Name> key);
 
   inline int LastAddedFieldIndex();
 
@@ -1718,7 +1780,7 @@
 
   // Can cause GC.
   MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
-      String* key,
+      Name* key,
       Object* value,
       PropertyAttributes attributes);
 
@@ -1733,16 +1795,16 @@
   // Sets the property value in a normalized object given (key, value, details).
   // Handles the special representation of JS global objects.
   static Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
-                                              Handle<String> key,
+                                              Handle<Name> key,
                                               Handle<Object> value,
                                               PropertyDetails details);
 
-  MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
+  MUST_USE_RESULT MaybeObject* SetNormalizedProperty(Name* name,
                                                      Object* value,
                                                      PropertyDetails details);
 
   // Deletes the named property in a normalized object.
-  MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
+  MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(Name* name,
                                                         DeleteMode mode);
 
   MUST_USE_RESULT MaybeObject* OptimizeAsPrototype();
@@ -1753,27 +1815,27 @@
 
   // Used from JSReceiver.
   PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
-                                                         String* name,
+                                                         Name* name,
                                                          bool continue_search);
   PropertyAttributes GetPropertyAttributeWithInterceptor(JSObject* receiver,
-                                                         String* name,
+                                                         Name* name,
                                                          bool continue_search);
   PropertyAttributes GetPropertyAttributeWithFailedAccessCheck(
       Object* receiver,
       LookupResult* result,
-      String* name,
+      Name* name,
       bool continue_search);
   PropertyAttributes GetElementAttributeWithReceiver(JSReceiver* receiver,
                                                      uint32_t index,
                                                      bool continue_search);
 
   static void DefineAccessor(Handle<JSObject> object,
-                             Handle<String> name,
+                             Handle<Name> name,
                              Handle<Object> getter,
                              Handle<Object> setter,
                              PropertyAttributes attributes);
   // Can cause GC.
-  MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
+  MUST_USE_RESULT MaybeObject* DefineAccessor(Name* name,
                                               Object* getter,
                                               Object* setter,
                                               PropertyAttributes attributes);
@@ -1781,11 +1843,11 @@
   // Returns a JavaScript null if this was not possible and we have to use the
   // slow case. Note that we can fail due to allocations, too.
   MUST_USE_RESULT MaybeObject* DefineFastAccessor(
-      String* name,
+      Name* name,
       AccessorComponent component,
       Object* accessor,
       PropertyAttributes attributes);
-  Object* LookupAccessor(String* name, AccessorComponent component);
+  Object* LookupAccessor(Name* name, AccessorComponent component);
 
   MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
 
@@ -1793,19 +1855,19 @@
   MUST_USE_RESULT MaybeObject* GetPropertyWithFailedAccessCheck(
       Object* receiver,
       LookupResult* result,
-      String* name,
+      Name* name,
       PropertyAttributes* attributes);
   MUST_USE_RESULT MaybeObject* GetPropertyWithInterceptor(
       Object* receiver,
-      String* name,
+      Name* name,
       PropertyAttributes* attributes);
   MUST_USE_RESULT MaybeObject* GetPropertyPostInterceptor(
       Object* receiver,
-      String* name,
+      Name* name,
       PropertyAttributes* attributes);
   MUST_USE_RESULT MaybeObject* GetLocalPropertyPostInterceptor(
       Object* receiver,
-      String* name,
+      Name* name,
       PropertyAttributes* attributes);
 
   // Returns true if this is an instance of an api function and has
@@ -1828,17 +1890,17 @@
   // Sets a hidden property on this object. Returns this object if successful,
   // undefined if called on a detached proxy.
   static Handle<Object> SetHiddenProperty(Handle<JSObject> obj,
-                                          Handle<String> key,
+                                          Handle<Name> key,
                                           Handle<Object> value);
   // Returns a failure if a GC is required.
-  MUST_USE_RESULT MaybeObject* SetHiddenProperty(String* key, Object* value);
+  MUST_USE_RESULT MaybeObject* SetHiddenProperty(Name* key, Object* value);
   // Gets the value of a hidden property with the given key. Returns undefined
   // if the property doesn't exist (or if called on a detached proxy),
   // otherwise returns the value set for the key.
-  Object* GetHiddenProperty(String* key);
+  Object* GetHiddenProperty(Name* key);
   // Deletes a hidden property. Deleting a non-existing property is
   // considered successful.
-  void DeleteHiddenProperty(String* key);
+  void DeleteHiddenProperty(Name* key);
   // Returns true if the object has a property with the hidden string as name.
   bool HasHiddenProperties();
 
@@ -1847,9 +1909,9 @@
   MUST_USE_RESULT MaybeObject* SetIdentityHash(Smi* hash, CreationFlag flag);
 
   static Handle<Object> DeleteProperty(Handle<JSObject> obj,
-                                       Handle<String> name);
+                                       Handle<Name> name);
   // Can cause GC.
-  MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
+  MUST_USE_RESULT MaybeObject* DeleteProperty(Name* name, DeleteMode mode);
 
   static Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
   MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
@@ -1893,11 +1955,11 @@
     return old_capacity + (old_capacity >> 1) + 16;
   }
 
-  PropertyType GetLocalPropertyType(String* name);
+  PropertyType GetLocalPropertyType(Name* name);
   PropertyType GetLocalElementType(uint32_t index);
 
   // These methods do not perform access checks!
-  AccessorPair* GetLocalPropertyAccessorPair(String* name);
+  AccessorPair* GetLocalPropertyAccessorPair(Name* name);
   AccessorPair* GetLocalElementAccessorPair(uint32_t index);
 
   MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index,
@@ -1970,9 +2032,9 @@
   inline bool HasIndexedInterceptor();
 
   // Support functions for v8 api (needed for correct interceptor behavior).
-  bool HasRealNamedProperty(String* key);
+  bool HasRealNamedProperty(Name* key);
   bool HasRealElementProperty(uint32_t index);
-  bool HasRealNamedCallbackProperty(String* key);
+  bool HasRealNamedCallbackProperty(Name* key);
 
   // Get the header size for a JSObject.  Used to compute the index of
   // internal fields as well as the number of internal fields.
@@ -1985,12 +2047,12 @@
   inline void SetInternalField(int index, Smi* value);
 
   // The following lookup functions skip interceptors.
-  void LocalLookupRealNamedProperty(String* name, LookupResult* result);
-  void LookupRealNamedProperty(String* name, LookupResult* result);
-  void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
+  void LocalLookupRealNamedProperty(Name* name, LookupResult* result);
+  void LookupRealNamedProperty(Name* name, LookupResult* result);
+  void LookupRealNamedPropertyInPrototypes(Name* name, LookupResult* result);
   MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
       uint32_t index, Object* value, bool* found, StrictModeFlag strict_mode);
-  void LookupCallbackProperty(String* name, LookupResult* result);
+  void LookupCallbackProperty(Name* name, LookupResult* result);
 
   // Returns the number of properties on this object filtering out properties
   // with the specified attributes (ignoring interceptors).
@@ -2017,7 +2079,7 @@
   // Add a property to a fast-case object using a map transition to
   // new_map.
   MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
-                                                       String* name,
+                                                       Name* name,
                                                        Object* value,
                                                        int field_index);
 
@@ -2028,12 +2090,12 @@
   // This avoids the creation of many maps with the same constant
   // function, all orphaned.
   MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
-      String* name,
+      Name* name,
       JSFunction* function,
       PropertyAttributes attributes);
 
   MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes);
 
@@ -2057,32 +2119,32 @@
   // Replaces an existing transition with a transition to a map with a FIELD.
   MUST_USE_RESULT MaybeObject* ConvertTransitionToMapTransition(
       int transition_index,
-      String* name,
+      Name* name,
       Object* new_value,
       PropertyAttributes attributes);
 
   // Converts a descriptor of any other type to a real field, backed by the
   // properties array.
   MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
-      String* name,
+      Name* name,
       Object* new_value,
       PropertyAttributes attributes);
 
   // Add a property to a fast-case object.
   MUST_USE_RESULT MaybeObject* AddFastProperty(
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes,
       StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
 
   // Add a property to a slow-case object.
-  MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
+  MUST_USE_RESULT MaybeObject* AddSlowProperty(Name* name,
                                                Object* value,
                                                PropertyAttributes attributes);
 
   // Add a property to an object. May cause GC.
   MUST_USE_RESULT MaybeObject* AddProperty(
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
@@ -2109,10 +2171,10 @@
   MUST_USE_RESULT MaybeObject* NormalizeElements();
 
   static void UpdateMapCodeCache(Handle<JSObject> object,
-                                 Handle<String> name,
+                                 Handle<Name> name,
                                  Handle<Code> code);
 
-  MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
+  MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(Name* name, Code* code);
 
   // Transform slow named properties to fast variants.
   // Returns failure if allocation failed.
@@ -2249,7 +2311,7 @@
   // Enqueue change record for Object.observe. May cause GC.
   static void EnqueueChangeRecord(Handle<JSObject> object,
                                   const char* type,
-                                  Handle<String> name,
+                                  Handle<Name> name,
                                   Handle<Object> old_value);
 
   // Deliver change records to observers. May cause GC.
@@ -2296,15 +2358,15 @@
   // read-only, reject and set '*done' to true. Otherwise, set '*done' to
   // false. Can cause GC and can return a failure result with '*done==true'.
   MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypes(
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
       bool* done);
 
-  MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
+  MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(Name* name,
                                                              DeleteMode mode);
-  MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
+  MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(Name* name);
 
   MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
 
@@ -2322,13 +2384,13 @@
   // Gets the current elements capacity and the number of used elements.
   void GetElementsCapacityAndUsage(int* capacity, int* used);
 
-  bool CanSetCallback(String* name);
+  bool CanSetCallback(Name* name);
   MUST_USE_RESULT MaybeObject* SetElementCallback(
       uint32_t index,
       Object* structure,
       PropertyAttributes attributes);
   MUST_USE_RESULT MaybeObject* SetPropertyCallback(
-      String* name,
+      Name* name,
       Object* structure,
       PropertyAttributes attributes);
   MUST_USE_RESULT MaybeObject* DefineElementAccessor(
@@ -2336,9 +2398,9 @@
       Object* getter,
       Object* setter,
       PropertyAttributes attributes);
-  MUST_USE_RESULT MaybeObject* CreateAccessorPairFor(String* name);
+  MUST_USE_RESULT MaybeObject* CreateAccessorPairFor(Name* name);
   MUST_USE_RESULT MaybeObject* DefinePropertyAccessor(
-      String* name,
+      Name* name,
       Object* getter,
       Object* setter,
       PropertyAttributes attributes);
@@ -2639,7 +2701,7 @@
                     Object* new_index_cache);
 
   // Accessors for fetching instance descriptor at descriptor number.
-  inline String* GetKey(int descriptor_number);
+  inline Name* GetKey(int descriptor_number);
   inline Object** GetKeySlot(int descriptor_number);
   inline Object* GetValue(int descriptor_number);
   inline Object** GetValueSlot(int descriptor_number);
@@ -2652,7 +2714,7 @@
   inline Object* GetCallbacksObject(int descriptor_number);
   inline AccessorDescriptor* GetCallbacks(int descriptor_number);
 
-  inline String* GetSortedKey(int descriptor_number);
+  inline Name* GetSortedKey(int descriptor_number);
   inline int GetSortedKeyIndex(int descriptor_number);
   inline void SetSortedKey(int pointer, int descriptor_number);
 
@@ -2682,11 +2744,11 @@
   void Sort();
 
   // Search the instance descriptors for given name.
-  INLINE(int Search(String* name, int number_of_own_descriptors));
+  INLINE(int Search(Name* name, int number_of_own_descriptors));
 
   // As the above, but uses DescriptorLookupCache and updates it when
   // necessary.
-  INLINE(int SearchWithCache(String* name, Map* map));
+  INLINE(int SearchWithCache(Name* name, Map* map));
 
   // Allocates a DescriptorArray, but returns the singleton
   // empty descriptor array object if number_of_descriptors is 0.
@@ -2795,11 +2857,11 @@
 enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
 
 template<SearchMode search_mode, typename T>
-inline int LinearSearch(T* array, String* name, int len, int valid_entries);
+inline int LinearSearch(T* array, Name* name, int len, int valid_entries);
 
 
 template<SearchMode search_mode, typename T>
-inline int Search(T* array, String* name, int valid_entries = 0);
+inline int Search(T* array, Name* name, int valid_entries = 0);
 
 
 // HashTable is a subclass of FixedArray that implements a hash table
@@ -3127,11 +3189,11 @@
 
 // MapCache.
 //
-// Maps keys that are a fixed array of internalized strings to a map.
+// Maps keys that are a fixed array of unique names to a map.
 // Used for canonicalize maps for object literals.
 class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
  public:
-  // Find cached value for a string key, otherwise return null.
+  // Find cached value for a name key, otherwise return null.
   Object* Lookup(FixedArray* key);
   MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
   static inline MapCache* cast(Object* obj);
@@ -3250,29 +3312,29 @@
 };
 
 
-class StringDictionaryShape : public BaseShape<String*> {
+class NameDictionaryShape : public BaseShape<Name*> {
  public:
-  static inline bool IsMatch(String* key, Object* other);
-  static inline uint32_t Hash(String* key);
-  static inline uint32_t HashForObject(String* key, Object* object);
-  MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
+  static inline bool IsMatch(Name* key, Object* other);
+  static inline uint32_t Hash(Name* key);
+  static inline uint32_t HashForObject(Name* key, Object* object);
+  MUST_USE_RESULT static inline MaybeObject* AsObject(Name* key);
   static const int kPrefixSize = 2;
   static const int kEntrySize = 3;
   static const bool kIsEnumerable = true;
 };
 
 
-class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
+class NameDictionary: public Dictionary<NameDictionaryShape, Name*> {
  public:
-  static inline StringDictionary* cast(Object* obj) {
+  static inline NameDictionary* cast(Object* obj) {
     ASSERT(obj->IsDictionary());
-    return reinterpret_cast<StringDictionary*>(obj);
+    return reinterpret_cast<NameDictionary*>(obj);
   }
 
   // Copies enumerable keys to preallocated fixed array.
   FixedArray* CopyEnumKeysTo(FixedArray* storage);
   static void DoGenerateNewEnumerationIndices(
-      Handle<StringDictionary> dictionary);
+      Handle<NameDictionary> dictionary);
 
   // For transforming properties of a JSObject.
   MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
@@ -3281,7 +3343,7 @@
 
   // Find entry for key, otherwise return kNotFound. Optimized version of
   // HashTable::FindEntry.
-  int FindEntry(String* key);
+  int FindEntry(Name* key);
 };
 
 
@@ -4282,11 +4344,6 @@
     NONEXISTENT
   };
 
-  enum IcFragment {
-    IC_FRAGMENT,
-    HANDLER_FRAGMENT
-  };
-
   enum {
     NUMBER_OF_KINDS = LAST_IC_KIND + 1
   };
@@ -4476,24 +4533,22 @@
   void FindAllCode(CodeHandleList* code_list, int length);
 
   class ExtraICStateStrictMode: public BitField<StrictModeFlag, 0, 1> {};
-  class ExtraICStateKeyedAccessGrowMode:
-      public BitField<KeyedAccessGrowMode, 1, 1> {};  // NOLINT
-
-  static const int kExtraICStateGrowModeShift = 1;
+  class ExtraICStateKeyedAccessStoreMode:
+      public BitField<KeyedAccessStoreMode, 1, 4> {};  // NOLINT
 
   static inline StrictModeFlag GetStrictMode(ExtraICState extra_ic_state) {
     return ExtraICStateStrictMode::decode(extra_ic_state);
   }
 
-  static inline KeyedAccessGrowMode GetKeyedAccessGrowMode(
+  static inline KeyedAccessStoreMode GetKeyedAccessStoreMode(
       ExtraICState extra_ic_state) {
-    return ExtraICStateKeyedAccessGrowMode::decode(extra_ic_state);
+    return ExtraICStateKeyedAccessStoreMode::decode(extra_ic_state);
   }
 
   static inline ExtraICState ComputeExtraICState(
-      KeyedAccessGrowMode grow_mode,
+      KeyedAccessStoreMode store_mode,
       StrictModeFlag strict_mode) {
-    return ExtraICStateKeyedAccessGrowMode::encode(grow_mode) |
+    return ExtraICStateKeyedAccessStoreMode::encode(store_mode) |
         ExtraICStateStrictMode::encode(strict_mode);
   }
 
@@ -4657,8 +4712,8 @@
   class TypeField: public BitField<StubType, 3, 3> {};
   class CacheHolderField: public BitField<InlineCacheHolderFlag, 6, 1> {};
   class KindField: public BitField<Kind, 7, 4> {};
-  class ExtraICStateField: public BitField<ExtraICState, 11, 2> {};
-  class IsPregeneratedField: public BitField<bool, 13, 1> {};
+  class ExtraICStateField: public BitField<ExtraICState, 11, 5> {};
+  class IsPregeneratedField: public BitField<bool, 16, 1> {};
 
   // KindSpecificFlags1 layout (STUB and OPTIMIZED_FUNCTION)
   static const int kStackSlotsFirstBit = 0;
@@ -4715,7 +4770,7 @@
   class StackCheckTableOffsetField: public BitField<int, 0, 31> {};
 
   // Signed field cannot be encoded using the BitField class.
-  static const int kArgumentsCountShift = 14;
+  static const int kArgumentsCountShift = 17;
   static const int kArgumentsCountMask = ~((1 << kArgumentsCountShift) - 1);
 
   // This constant should be encodable in an ARM instruction.
@@ -4874,7 +4929,7 @@
   inline bool function_with_prototype();
 
   // Tells whether the instance with this map should be ignored by the
-  // __proto__ accessor.
+  // Object.getPrototypeOf() function and the __proto__ accessor.
   inline void set_is_hidden_prototype() {
     set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
   }
@@ -4993,7 +5048,7 @@
       Map* transitioned_map);
   inline void SetTransition(int transition_index, Map* target);
   inline Map* GetTransition(int transition_index);
-  MUST_USE_RESULT inline MaybeObject* AddTransition(String* key,
+  MUST_USE_RESULT inline MaybeObject* AddTransition(Name* key,
                                                     Map* target,
                                                     SimpleTransitionFlag flag);
   DECL_ACCESSORS(transitions, TransitionArray)
@@ -5091,11 +5146,11 @@
   // with the given holder if the name is found. The holder may be
   // NULL when this function is used from the compiler.
   inline void LookupDescriptor(JSObject* holder,
-                               String* name,
+                               Name* name,
                                LookupResult* result);
 
   inline void LookupTransition(JSObject* holder,
-                               String* name,
+                               Name* name,
                                LookupResult* result);
 
   // The size of transition arrays are limited so they do not end up in large
@@ -5144,7 +5199,7 @@
   MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
   MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
       DescriptorArray* descriptors,
-      String* name,
+      Name* name,
       TransitionFlag flag,
       int descriptor_index);
   MUST_USE_RESULT MaybeObject* ShareDescriptor(DescriptorArray* descriptors,
@@ -5172,7 +5227,7 @@
   MUST_USE_RESULT MaybeObject* Copy();
 
   // Returns the property index for name (only valid for FAST MODE).
-  int PropertyIndexFor(String* name);
+  int PropertyIndexFor(Name* name);
 
   // Returns the next free property index (only valid for FAST MODE).
   int NextFreePropertyIndex();
@@ -5186,7 +5241,7 @@
   static inline Map* cast(Object* obj);
 
   // Locate an accessor in the instance descriptor.
-  AccessorDescriptor* FindAccessor(String* name);
+  AccessorDescriptor* FindAccessor(Name* name);
 
   // Code cache operations.
 
@@ -5195,9 +5250,9 @@
 
   // Update code cache.
   static void UpdateCodeCache(Handle<Map> map,
-                              Handle<String> name,
+                              Handle<Name> name,
                               Handle<Code> code);
-  MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
+  MUST_USE_RESULT MaybeObject* UpdateCodeCache(Name* name, Code* code);
 
   // Extend the descriptor array of the map with the list of descriptors.
   // In case of duplicates, the latest descriptor is used.
@@ -5207,14 +5262,14 @@
   static void EnsureDescriptorSlack(Handle<Map> map, int slack);
 
   // Returns the found code or undefined if absent.
-  Object* FindInCodeCache(String* name, Code::Flags flags);
+  Object* FindInCodeCache(Name* name, Code::Flags flags);
 
   // Returns the non-negative index of the code object if it is in the
   // cache and -1 otherwise.
   int IndexInCodeCache(Object* name, Code* code);
 
   // Removes a code object from the code cache at the given index.
-  void RemoveFromCodeCache(String* name, Code* code, int index);
+  void RemoveFromCodeCache(Name* name, Code* code, int index);
 
   // Set all map transitions from this map to dead maps to null.  Also clear
   // back pointers in transition targets so that we do not process this map
@@ -6434,7 +6489,7 @@
   // by throwing an exception.  This is for the debug and builtins global
   // objects, where it is known which properties can be expected to be present
   // on the object.
-  Object* GetPropertyNoExceptionThrown(String* key) {
+  Object* GetPropertyNoExceptionThrown(Name* key) {
     Object* answer = GetProperty(key)->ToObjectUnchecked();
     return answer;
   }
@@ -6442,10 +6497,10 @@
   // Ensure that the global object has a cell for the given property name.
   static Handle<JSGlobalPropertyCell> EnsurePropertyCell(
       Handle<GlobalObject> global,
-      Handle<String> name);
+      Handle<Name> name);
   // TODO(kmillikin): This function can be eliminated once the stub cache is
   // fully handlified (and the static helper can be written directly).
-  MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
+  MUST_USE_RESULT MaybeObject* EnsurePropertyCell(Name* name);
 
   // Casting.
   static inline GlobalObject* cast(Object* obj);
@@ -6896,11 +6951,11 @@
   DECL_ACCESSORS(normal_type_cache, Object)
 
   // Add the code object to the cache.
-  MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
+  MUST_USE_RESULT MaybeObject* Update(Name* name, Code* code);
 
   // Lookup code object in the cache. Returns code object if found and undefined
   // if not.
-  Object* Lookup(String* name, Code::Flags flags);
+  Object* Lookup(Name* name, Code::Flags flags);
 
   // Get the internal index of a code object in the cache. Returns -1 if the
   // code object is not in that cache. This index can be used to later call
@@ -6923,10 +6978,10 @@
   static const int kSize = kNormalTypeCacheOffset + kPointerSize;
 
  private:
-  MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
-  MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
-  Object* LookupDefaultCache(String* name, Code::Flags flags);
-  Object* LookupNormalTypeCache(String* name, Code::Flags flags);
+  MUST_USE_RESULT MaybeObject* UpdateDefaultCache(Name* name, Code* code);
+  MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(Name* name, Code* code);
+  Object* LookupDefaultCache(Name* name, Code::Flags flags);
+  Object* LookupNormalTypeCache(Name* name, Code::Flags flags);
 
   // Code cache layout of the default cache. Elements are alternating name and
   // code objects for non normal load/store/call IC's.
@@ -6964,10 +7019,10 @@
 class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
                                            HashTableKey*> {
  public:
-  Object* Lookup(String* name, Code::Flags flags);
-  MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
+  Object* Lookup(Name* name, Code::Flags flags);
+  MUST_USE_RESULT MaybeObject* Put(Name* name, Code* code);
 
-  int GetIndex(String* name, Code::Flags flags);
+  int GetIndex(Name* name, Code::Flags flags);
   void RemoveByIndex(int index);
 
   static inline CodeCacheHashTable* cast(Object* obj);
@@ -7254,9 +7309,17 @@
   // Returns a hash value used for the property table
   inline uint32_t Hash();
 
+  // Equality operations.
+  inline bool Equals(Name* other);
+
+  // Conversion.
+  inline bool AsArrayIndex(uint32_t* index);
+
   // Casting.
   static inline Name* cast(Object* obj);
 
+  DECLARE_PRINTER(Name)
+
   // Layout description.
   static const int kHashFieldOffset = HeapObject::kHeaderSize;
   static const int kSize = kHashFieldOffset + kPointerSize;
@@ -7336,6 +7399,8 @@
 };
 
 
+class ConsString;
+
 // The String abstract class captures JavaScript string values:
 //
 // Ecma-262:
@@ -7614,6 +7679,7 @@
     return NonOneByteStart(chars, length) >= length;
   }
 
+  // TODO(dcarney): Replace all instances of this with VisitFlat.
   template<class Visitor, class ConsOp>
   static inline void Visit(String* string,
                            unsigned offset,
@@ -7622,6 +7688,21 @@
                            int32_t type,
                            unsigned length);
 
+  template<class Visitor>
+  static inline ConsString* VisitFlat(Visitor* visitor,
+                                      String* string,
+                                      int offset,
+                                      int length,
+                                      int32_t type);
+
+  template<class Visitor>
+  static inline ConsString* VisitFlat(Visitor* visitor,
+                                      String* string,
+                                      int offset = 0) {
+    int32_t type = string->map()->instance_type();
+    return VisitFlat(visitor, string, offset, string->length(), type);
+  }
+
  private:
   friend class Name;
 
@@ -8180,19 +8261,19 @@
   // Casting.
   static inline JSProxy* cast(Object* obj);
 
-  bool HasPropertyWithHandler(String* name);
+  bool HasPropertyWithHandler(Name* name);
   bool HasElementWithHandler(uint32_t index);
 
   MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(
       Object* receiver,
-      String* name);
+      Name* name);
   MUST_USE_RESULT MaybeObject* GetElementWithHandler(
       Object* receiver,
       uint32_t index);
 
   MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
       JSReceiver* receiver,
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode);
@@ -8208,14 +8289,14 @@
   // otherwise set it to false.
   MUST_USE_RESULT MaybeObject* SetPropertyViaPrototypesWithHandler(
       JSReceiver* receiver,
-      String* name,
+      Name* name,
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
       bool* done);
 
   MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
-      String* name,
+      Name* name,
       DeleteMode mode);
   MUST_USE_RESULT MaybeObject* DeleteElementWithHandler(
       uint32_t index,
@@ -8223,7 +8304,7 @@
 
   MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
       JSReceiver* receiver,
-      String* name);
+      Name* name);
   MUST_USE_RESULT PropertyAttributes GetElementAttributeWithHandler(
       JSReceiver* receiver,
       uint32_t index);
@@ -8522,19 +8603,91 @@
 };
 
 
+enum AccessorDescriptorType {
+  kDescriptorBitmaskCompare,
+  kDescriptorPointerCompare,
+  kDescriptorPrimitiveValue,
+  kDescriptorObjectDereference,
+  kDescriptorPointerDereference,
+  kDescriptorPointerShift,
+  kDescriptorReturnObject
+};
+
+
+struct BitmaskCompareDescriptor {
+  uint32_t bitmask;
+  uint32_t compare_value;
+  uint8_t size;  // Must be in {1,2,4}.
+};
+
+
+struct PointerCompareDescriptor {
+  void* compare_value;
+};
+
+
+struct PrimitiveValueDescriptor {
+  v8::DeclaredAccessorDescriptorDataType data_type;
+  uint8_t bool_offset;  // Must be in [0,7], used for kDescriptorBoolType.
+};
+
+
+struct ObjectDerefenceDescriptor {
+  uint8_t internal_field;
+};
+
+
+struct PointerShiftDescriptor {
+  int16_t byte_offset;
+};
+
+
+struct DeclaredAccessorDescriptorData {
+  AccessorDescriptorType type;
+  union {
+    struct BitmaskCompareDescriptor bitmask_compare_descriptor;
+    struct PointerCompareDescriptor pointer_compare_descriptor;
+    struct PrimitiveValueDescriptor primitive_value_descriptor;
+    struct ObjectDerefenceDescriptor object_dereference_descriptor;
+    struct PointerShiftDescriptor pointer_shift_descriptor;
+  };
+};
+
+
+class DeclaredAccessorDescriptor;
+
+
+class DeclaredAccessorDescriptorIterator {
+ public:
+  explicit DeclaredAccessorDescriptorIterator(
+      DeclaredAccessorDescriptor* descriptor);
+  const DeclaredAccessorDescriptorData* Next();
+  bool Complete() const { return length_ == offset_; }
+ private:
+  uint8_t* array_;
+  const int length_;
+  int offset_;
+  DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorDescriptorIterator);
+};
+
+
 class DeclaredAccessorDescriptor: public Struct {
  public:
-  // TODO(dcarney): Fill out this class.
-  DECL_ACCESSORS(internal_field, Smi)
+  DECL_ACCESSORS(serialized_data, ByteArray)
 
   static inline DeclaredAccessorDescriptor* cast(Object* obj);
 
+  static Handle<DeclaredAccessorDescriptor> Create(
+      Isolate* isolate,
+      const DeclaredAccessorDescriptorData& data,
+      Handle<DeclaredAccessorDescriptor> previous);
+
   // Dispatched behavior.
   DECLARE_PRINTER(DeclaredAccessorDescriptor)
   DECLARE_VERIFIER(DeclaredAccessorDescriptor)
 
-  static const int kInternalFieldOffset = HeapObject::kHeaderSize;
-  static const int kSize = kInternalFieldOffset + kPointerSize;
+  static const int kSerializedDataOffset = HeapObject::kHeaderSize;
+  static const int kSize = kSerializedDataOffset + kPointerSize;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(DeclaredAccessorDescriptor);
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index 1cf0434..bc26442 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -50,6 +50,11 @@
     input_queue_semaphore_->Wait();
     Logger::TimerEventScope timer(
         isolate_, Logger::TimerEventScope::v8_recompile_parallel);
+
+    if (FLAG_parallel_recompilation_delay != 0) {
+      OS::Sleep(FLAG_parallel_recompilation_delay);
+    }
+
     if (Acquire_Load(&stop_thread_)) {
       stop_semaphore_->Signal();
       if (FLAG_trace_parallel_recompilation) {
@@ -61,19 +66,8 @@
     int64_t compiling_start = 0;
     if (FLAG_trace_parallel_recompilation) compiling_start = OS::Ticks();
 
-    Heap::RelocationLock relocation_lock(isolate_->heap());
-    OptimizingCompiler* optimizing_compiler = NULL;
-    input_queue_.Dequeue(&optimizing_compiler);
-    Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(-1));
+    CompileNext();
 
-    ASSERT(!optimizing_compiler->info()->closure()->IsOptimized());
-
-    OptimizingCompiler::Status status = optimizing_compiler->OptimizeGraph();
-    ASSERT(status != OptimizingCompiler::FAILED);
-    // Prevent an unused-variable error in release mode.
-    USE(status);
-
-    output_queue_.Enqueue(optimizing_compiler);
     if (!FLAG_manual_parallel_recompilation) {
       isolate_->stack_guard()->RequestCodeReadyEvent();
     } else {
@@ -89,11 +83,46 @@
 }
 
 
+void OptimizingCompilerThread::CompileNext() {
+  Heap::RelocationLock relocation_lock(isolate_->heap());
+  OptimizingCompiler* optimizing_compiler = NULL;
+  input_queue_.Dequeue(&optimizing_compiler);
+  Barrier_AtomicIncrement(&queue_length_, static_cast<Atomic32>(-1));
+
+  // Function may have been optimized meanwhile by OSR.
+  if (FLAG_use_osr &&
+      optimizing_compiler->info()->closure()->IsOptimized()) {
+    return;
+  }
+
+  OptimizingCompiler::Status status = optimizing_compiler->OptimizeGraph();
+  ASSERT(status != OptimizingCompiler::FAILED);
+  // Prevent an unused-variable error in release mode.
+  USE(status);
+
+  output_queue_.Enqueue(optimizing_compiler);
+}
+
+
 void OptimizingCompilerThread::Stop() {
   Release_Store(&stop_thread_, static_cast<AtomicWord>(true));
   input_queue_semaphore_->Signal();
   stop_semaphore_->Wait();
 
+  if (FLAG_parallel_recompilation_delay != 0) {
+    // Execution ended before we managed to compile and install the remaining
+    // functions in the queue.  We still want to do that for debugging though.
+    // At this point the optimizing thread already stopped, so we finish
+    // processing the queue in the main thread.
+    InstallOptimizedFunctions();
+    // Barrier when loading queue length is not necessary since the write
+    // happens in CompileNext on the same thread.
+    while (NoBarrier_Load(&queue_length_) > 0) {
+      CompileNext();
+      InstallOptimizedFunctions();
+    }
+  }
+
   if (FLAG_trace_parallel_recompilation) {
     double compile_time = static_cast<double>(time_spent_compiling_);
     double total_time = static_cast<double>(time_spent_total_);
@@ -123,11 +152,13 @@
 
 Handle<SharedFunctionInfo>
     OptimizingCompilerThread::InstallNextOptimizedFunction() {
-  ASSERT(FLAG_manual_parallel_recompilation);
+  ASSERT(FLAG_manual_parallel_recompilation ||
+         FLAG_parallel_recompilation_delay != 0);
   output_queue_semaphore_->Wait();
   OptimizingCompiler* compiler = NULL;
   output_queue_.Dequeue(&compiler);
-  Handle<SharedFunctionInfo> shared = compiler->info()->shared_info();
+  // Copy a handle from deferred handle scope to the normal handle scope.
+  Handle<SharedFunctionInfo> shared(*compiler->info()->shared_info());
   Compiler::InstallOptimizedCode(compiler);
   return shared;
 }
diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h
index 7aad78c..990005b 100644
--- a/src/optimizing-compiler-thread.h
+++ b/src/optimizing-compiler-thread.h
@@ -59,6 +59,7 @@
 
   void Run();
   void Stop();
+  void CompileNext();
   void QueueForOptimization(OptimizingCompiler* optimizing_compiler);
   void InstallOptimizedFunctions();
 
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index f7e7d5e..8914d63 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -776,21 +776,4 @@
 }
 
 
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  return false;
-}
-
-
-void Sampler::DoSample() {
-}
-
-
-void Sampler::StartProfiling() {
-}
-
-
-void Sampler::StopProfiling() {
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 1af928e..986c5af 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -898,21 +898,4 @@
 }
 
 
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  return false;
-}
-
-
-void Sampler::DoSample() {
-}
-
-
-void Sampler::StartProfiling() {
-}
-
-
-void Sampler::StopProfiling() {
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index f571b99..0359b2d 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -1127,27 +1127,29 @@
 }
 
 
-class CpuProfilerSignalHandler {
+class Sampler::PlatformData : public Malloced {
  public:
+  PlatformData() : vm_tid_(GetThreadID()) {}
+
+  int vm_tid() const { return vm_tid_; }
+
+ private:
+  const int vm_tid_;
+};
+
+
+class SignalSender : public Thread {
+ public:
+  static const int kSignalSenderStackSize = 64 * KB;
+
+  explicit SignalSender(int interval)
+      : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
+        vm_tgid_(getpid()),
+        interval_(interval) {}
+
   static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
   static void TearDown() { delete mutex_; }
 
-  static bool RegisterProfilingSampler() {
-    ScopedLock lock(mutex_);
-    if (!profiling_samplers_count_) InstallSignalHandler();
-    ++profiling_samplers_count_;
-    return signal_handler_installed_;
-  }
-
-  static void UnregisterProfilingSampler() {
-    ScopedLock lock(mutex_);
-    ASSERT(profiling_samplers_count_ > 0);
-    if (!profiling_samplers_count_) return;
-    if (profiling_samplers_count_ == 1) RestoreSignalHandler();
-    --profiling_samplers_count_;
-  }
-
- private:
   static void InstallSignalHandler() {
     struct sigaction sa;
     sa.sa_sigaction = ProfilerSignalHandler;
@@ -1164,61 +1166,6 @@
     }
   }
 
-  // Protects the process wide state below.
-  static Mutex* mutex_;
-  static int profiling_samplers_count_;
-  static bool signal_handler_installed_;
-  static struct sigaction old_signal_handler_;
-};
-
-
-Mutex* CpuProfilerSignalHandler::mutex_ = NULL;
-int CpuProfilerSignalHandler::profiling_samplers_count_ = 0;
-bool CpuProfilerSignalHandler::signal_handler_installed_ = false;
-struct sigaction CpuProfilerSignalHandler::old_signal_handler_;
-
-
-class Sampler::PlatformData : public Malloced {
- public:
-  PlatformData()
-      : vm_tgid_(getpid()),
-        vm_tid_(GetThreadID()),
-        signal_handler_installed_(false) {}
-
-  void set_signal_handler_installed(bool value) {
-    signal_handler_installed_ = value;
-  }
-
-  void SendProfilingSignal() {
-    if (!signal_handler_installed_) return;
-    // Glibc doesn't provide a wrapper for tgkill(2).
-#if defined(ANDROID)
-    syscall(__NR_tgkill, vm_tgid_, vm_tid_, SIGPROF);
-#else
-    int result = syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
-    USE(result);
-    ASSERT(result == 0);
-#endif
-  }
-
- private:
-  const int vm_tgid_;
-  const int vm_tid_;
-  bool signal_handler_installed_;
-};
-
-
-class SignalSender : public Thread {
- public:
-  static const int kSignalSenderStackSize = 64 * KB;
-
-  explicit SignalSender(int interval)
-      : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
-        interval_(interval) {}
-
-  static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
-  static void TearDown() { delete mutex_; }
-
   static void AddActiveSampler(Sampler* sampler) {
     ScopedLock lock(mutex_);
     SamplerRegistry::AddActiveSampler(sampler);
@@ -1239,6 +1186,7 @@
       RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
       delete instance_;
       instance_ = NULL;
+      RestoreSignalHandler();
     }
   }
 
@@ -1250,8 +1198,10 @@
       // When CPU profiling is enabled both JavaScript and C++ code is
       // profiled. We must not suspend.
       if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
+        if (!signal_handler_installed_) InstallSignalHandler();
         SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
       } else {
+        if (signal_handler_installed_) RestoreSignalHandler();
         if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
       }
       Sleep();  // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
@@ -1260,7 +1210,20 @@
 
   static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
     if (!sampler->IsProfiling()) return;
-    sampler->DoSample();
+    SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
+    sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
+  }
+
+  void SendProfilingSignal(int tid) {
+    if (!signal_handler_installed_) return;
+    // Glibc doesn't provide a wrapper for tgkill(2).
+#if defined(ANDROID)
+    syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF);
+#else
+    int result = syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
+    USE(result);
+    ASSERT(result == 0);
+#endif
   }
 
   void Sleep() {
@@ -1284,11 +1247,13 @@
 #endif  // ANDROID
   }
 
+  const int vm_tgid_;
   const int interval_;
 
   // Protects the process wide state below.
   static Mutex* mutex_;
   static SignalSender* instance_;
+  static bool signal_handler_installed_;
   static struct sigaction old_signal_handler_;
 
  private:
@@ -1299,6 +1264,7 @@
 Mutex* SignalSender::mutex_ = NULL;
 SignalSender* SignalSender::instance_ = NULL;
 struct sigaction SignalSender::old_signal_handler_;
+bool SignalSender::signal_handler_installed_ = false;
 
 
 void OS::SetUp() {
@@ -1326,12 +1292,10 @@
   }
 #endif
   SignalSender::SetUp();
-  CpuProfilerSignalHandler::SetUp();
 }
 
 
 void OS::TearDown() {
-  CpuProfilerSignalHandler::TearDown();
   SignalSender::TearDown();
   delete limit_mutex;
 }
@@ -1341,7 +1305,6 @@
     : isolate_(isolate),
       interval_(interval),
       profiling_(false),
-      has_processing_thread_(false),
       active_(false),
       samples_taken_(0) {
   data_ = new PlatformData;
@@ -1368,26 +1331,4 @@
 }
 
 
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  return true;
-}
-
-
-void Sampler::DoSample() {
-  platform_data()->SendProfilingSignal();
-}
-
-
-void Sampler::StartProfiling() {
-  platform_data()->set_signal_handler_installed(
-      CpuProfilerSignalHandler::RegisterProfilingSampler());
-}
-
-
-void Sampler::StopProfiling() {
-  CpuProfilerSignalHandler::UnregisterProfilingSampler();
-  platform_data()->set_signal_handler_installed(false);
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index 7913981..fde5217 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -922,21 +922,4 @@
 }
 
 
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  return false;
-}
-
-
-void Sampler::DoSample() {
-}
-
-
-void Sampler::StartProfiling() {
-}
-
-
-void Sampler::StopProfiling() {
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
index 20d8801..0fef063 100644
--- a/src/platform-nullos.cc
+++ b/src/platform-nullos.cc
@@ -525,25 +525,4 @@
 }
 
 
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  UNIMPLEMENTED();
-  return false;
-}
-
-
-void Sampler::DoSample() {
-  UNIMPLEMENTED();
-}
-
-
-void Sampler::StartProfiling() {
-  UNIMPLEMENTED();
-}
-
-
-void Sampler::StopProfiling() {
-  UNIMPLEMENTED();
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index ccccedc..66eac22 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -955,21 +955,4 @@
 }
 
 
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  return false;
-}
-
-
-void Sampler::DoSample() {
-}
-
-
-void Sampler::StartProfiling() {
-}
-
-
-void Sampler::StopProfiling() {
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 88d197f..85ba95f 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -872,22 +872,4 @@
   SetActive(false);
 }
 
-
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  return false;
-}
-
-
-void Sampler::DoSample() {
-}
-
-
-void Sampler::StartProfiling() {
-}
-
-
-void Sampler::StopProfiling() {
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index b91f2a6..66dbade 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -2153,21 +2153,4 @@
 }
 
 
-bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
-  return false;
-}
-
-
-void Sampler::DoSample() {
-}
-
-
-void Sampler::StartProfiling() {
-}
-
-
-void Sampler::StopProfiling() {
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/platform.h b/src/platform.h
index 5fde6a0..56ac61d 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -766,17 +766,10 @@
   void Start();
   void Stop();
 
-  // 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() {
-    if (NoBarrier_AtomicIncrement(&profiling_, 1) == 1) StartProfiling();
-  }
-  void DecreaseProfilingDepth() {
-    if (!NoBarrier_AtomicIncrement(&profiling_, -1)) StopProfiling();
-  }
+  // Is the sampler used for profiling?
+  bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
+  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_); }
@@ -792,14 +785,6 @@
 
   PlatformData* platform_data() { return data_; }
 
-  // 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);
-  }
-
  protected:
   virtual void DoSampleStack(TickSample* sample) = 0;
 
@@ -807,15 +792,9 @@
   void SetActive(bool value) { NoBarrier_Store(&active_, value); }
   void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
 
-  // Perform platform-specific initialization before DoSample() may be invoked.
-  void StartProfiling();
-  // Perform platform-specific cleanup after profiling.
-  void StopProfiling();
-
   Isolate* isolate_;
   const int interval_;
   Atomic32 profiling_;
-  Atomic32 has_processing_thread_;
   Atomic32 active_;
   PlatformData* data_;  // Platform specific data.
   int samples_taken_;  // Counts stack samples taken.
diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h
index cbdb6dd..6e7f499 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -33,7 +33,7 @@
 namespace v8 {
 namespace internal {
 
-const char* StringsStorage::GetFunctionName(String* name) {
+const char* StringsStorage::GetFunctionName(Name* name) {
   return GetFunctionName(GetName(name));
 }
 
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index e5b5194..a51de78 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -153,14 +153,17 @@
 }
 
 
-const char* StringsStorage::GetName(String* name) {
+const char* StringsStorage::GetName(Name* name) {
   if (name->IsString()) {
-    int length = Min(kMaxNameSize, name->length());
+    String* str = String::cast(name);
+    int length = Min(kMaxNameSize, str->length());
     SmartArrayPointer<char> data =
-        name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length);
+        str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length);
     uint32_t hash = StringHasher::HashSequentialString(
         *data, length, name->GetHeap()->HashSeed());
     return AddOrDisposeString(data.Detach(), hash);
+  } else if (name->IsSymbol()) {
+    return "<symbol>";
   }
   return "";
 }
@@ -782,7 +785,7 @@
 
 
 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
-                                               String* name,
+                                               Name* name,
                                                String* resource_name,
                                                int line_number) {
   CodeEntry* entry = new CodeEntry(tag,
@@ -811,7 +814,7 @@
 
 CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
                                                const char* name_prefix,
-                                               String* name) {
+                                               Name* name) {
   CodeEntry* entry = new CodeEntry(tag,
                                    name_prefix,
                                    GetName(name),
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 8c6c71a..8315f79 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -69,9 +69,9 @@
   const char* GetCopy(const char* src);
   const char* GetFormatted(const char* format, ...);
   const char* GetVFormatted(const char* format, va_list args);
-  const char* GetName(String* name);
+  const char* GetName(Name* name);
   const char* GetName(int index);
-  inline const char* GetFunctionName(String* name);
+  inline const char* GetFunctionName(Name* name);
   inline const char* GetFunctionName(const char* name);
   size_t GetUsedMemorySize() const;
 
@@ -296,7 +296,7 @@
                             const char* title,
                             double actual_sampling_rate);
   List<CpuProfile*>* Profiles(int security_token_id);
-  const char* GetName(String* name) {
+  const char* GetName(Name* name) {
     return function_and_resource_names_.GetName(name);
   }
   const char* GetName(int args_count) {
@@ -308,10 +308,10 @@
   bool HasDetachedProfiles() { return detached_profiles_.length() > 0; }
 
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
-                          String* name, String* resource_name, int line_number);
+                          Name* name, String* resource_name, int line_number);
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name);
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
-                          const char* name_prefix, String* name);
+                          const char* name_prefix, Name* name);
   CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count);
   CodeEntry* NewCodeEntry(int security_token_id);
 
@@ -322,7 +322,7 @@
   static const int kMaxSimultaneousProfiles = 100;
 
  private:
-  const char* GetFunctionName(String* name) {
+  const char* GetFunctionName(Name* name) {
     return function_and_resource_names_.GetFunctionName(name);
   }
   const char* GetFunctionName(const char* name) {
@@ -395,7 +395,7 @@
   explicit ProfileGenerator(CpuProfilesCollection* profiles);
 
   INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
-                                 String* name,
+                                 Name* name,
                                  String* resource_name,
                                  int line_number)) {
     return profiles_->NewCodeEntry(tag, name, resource_name, line_number);
@@ -408,7 +408,7 @@
 
   INLINE(CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
                                  const char* name_prefix,
-                                 String* name)) {
+                                 Name* name)) {
     return profiles_->NewCodeEntry(tag, name_prefix, name);
   }
 
diff --git a/src/property-details.h b/src/property-details.h
index 510e985..2aa6dcf 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -42,6 +42,8 @@
   SEALED            = DONT_ENUM | DONT_DELETE,
   FROZEN            = SEALED | READ_ONLY,
 
+  SYMBOLIC          = 8,  // Used to filter symbol names
+  DONT_SHOW         = DONT_ENUM | SYMBOLIC,
   ABSENT            = 16  // Used in runtime to indicate a property is absent.
   // ABSENT can never be stored in or returned from a descriptor's attributes
   // bitfield.  It is only used as a return value meaning the attributes of
diff --git a/src/property.h b/src/property.h
index 941b51d..546967a 100644
--- a/src/property.h
+++ b/src/property.h
@@ -48,15 +48,15 @@
     return Smi::cast(value)->value();
   }
 
-  MUST_USE_RESULT MaybeObject* KeyToInternalizedString() {
-    if (!StringShape(key_).IsInternalized()) {
-      MaybeObject* maybe_result = HEAP->InternalizeString(key_);
+  MUST_USE_RESULT MaybeObject* KeyToUniqueName() {
+    if (!key_->IsUniqueName()) {
+      MaybeObject* maybe_result = HEAP->InternalizeString(String::cast(key_));
       if (!maybe_result->To(&key_)) return maybe_result;
     }
     return key_;
   }
 
-  String* GetKey() { return key_; }
+  Name* GetKey() { return key_; }
   Object* GetValue() { return value_; }
   PropertyDetails GetDetails() { return details_; }
 
@@ -71,25 +71,25 @@
   void SetSortedKeyIndex(int index) { details_ = details_.set_pointer(index); }
 
  private:
-  String* key_;
+  Name* key_;
   Object* value_;
   PropertyDetails details_;
 
  protected:
   Descriptor() : details_(Smi::FromInt(0)) {}
 
-  void Init(String* key, Object* value, PropertyDetails details) {
+  void Init(Name* key, Object* value, PropertyDetails details) {
     key_ = key;
     value_ = value;
     details_ = details;
   }
 
-  Descriptor(String* key, Object* value, PropertyDetails details)
+  Descriptor(Name* key, Object* value, PropertyDetails details)
       : key_(key),
         value_(value),
         details_(details) { }
 
-  Descriptor(String* key,
+  Descriptor(Name* key,
              Object* value,
              PropertyAttributes attributes,
              PropertyType type,
@@ -104,7 +104,7 @@
 
 class FieldDescriptor: public Descriptor {
  public:
-  FieldDescriptor(String* key,
+  FieldDescriptor(Name* key,
                   int field_index,
                   PropertyAttributes attributes,
                   int index = 0)
@@ -114,7 +114,7 @@
 
 class ConstantFunctionDescriptor: public Descriptor {
  public:
-  ConstantFunctionDescriptor(String* key,
+  ConstantFunctionDescriptor(Name* key,
                              JSFunction* function,
                              PropertyAttributes attributes,
                              int index)
@@ -124,7 +124,7 @@
 
 class CallbacksDescriptor:  public Descriptor {
  public:
-  CallbacksDescriptor(String* key,
+  CallbacksDescriptor(Name* key,
                       Object* foreign,
                       PropertyAttributes attributes,
                       int index = 0)
diff --git a/src/proxy.js b/src/proxy.js
index 53a3572..b16de01 100644
--- a/src/proxy.js
+++ b/src/proxy.js
@@ -77,8 +77,7 @@
   return function() {
     var proto = this.prototype
     if (!IS_SPEC_OBJECT(proto)) proto = $Object.prototype
-    var obj = new $Object()
-    obj.__proto__ = proto
+    var obj = { __proto__: proto };
     var result = %Apply(callTrap, obj, arguments, 0, %_ArgumentsLength());
     return IS_SPEC_OBJECT(result) ? result : obj
   }
@@ -163,6 +162,7 @@
   var enumerableNames = []
   for (var i = 0, count = 0; i < names.length; ++i) {
     var name = names[i]
+    if (IS_SYMBOL(name)) continue
     var desc = this.getOwnPropertyDescriptor(TO_STRING_INLINE(name))
     if (!IS_UNDEFINED(desc) && desc.enumerable) {
       enumerableNames[count++] = names[i]
@@ -176,6 +176,7 @@
   var enumerableNames = []
   for (var i = 0, count = 0; i < names.length; ++i) {
     var name = names[i]
+    if (IS_SYMBOL(name)) continue
     var desc = this.getPropertyDescriptor(TO_STRING_INLINE(name))
     if (!IS_UNDEFINED(desc) && desc.enumerable) {
       enumerableNames[count++] = names[i]
@@ -189,6 +190,6 @@
   if (IS_UNDEFINED(handler.enumerate)) {
     return %Apply(DerivedEnumerateTrap, handler, [], 0, 0)
   } else {
-    return ToStringArray(handler.enumerate(), "enumerate")
+    return ToNameArray(handler.enumerate(), "enumerate", false)
   }
 }
diff --git a/src/runtime.cc b/src/runtime.cc
index 2215ead..5bbca4d 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -899,7 +899,7 @@
   HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
   Handle<Object> lookup(table->Lookup(*key), isolate);
   return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
@@ -910,7 +910,7 @@
   HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
   Handle<Object> lookup(table->Lookup(*key), isolate);
   return isolate->heap()->ToBoolean(!lookup->IsTheHole());
@@ -921,7 +921,7 @@
   HandleScope scope(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
   Handle<Object> lookup(table->Lookup(*key), isolate);
   Handle<ObjectHashTable> new_table =
@@ -935,7 +935,7 @@
   HandleScope scope(isolate);
   ASSERT(args.length() == 3);
   CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
-  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
   Handle<Object> value(args[2], isolate);
   Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
   Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
@@ -975,6 +975,15 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
+  NoHandleAllocation ha(isolate);
+  ASSERT(args.length() == 2);
+  CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
+  CONVERT_ARG_CHECKED(Object, prototype, 1);
+  return input_obj->SetPrototype(prototype, true);
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
   NoHandleAllocation ha(isolate);
   ASSERT(args.length() == 2);
@@ -1049,7 +1058,7 @@
 
 static AccessCheckResult CheckPropertyAccess(
     JSObject* obj,
-    String* name,
+    Name* name,
     v8::AccessType access_type) {
   uint32_t index;
   if (name->AsArrayIndex(&index)) {
@@ -1109,7 +1118,7 @@
 
 static MaybeObject* GetOwnProperty(Isolate* isolate,
                                    Handle<JSObject> obj,
-                                   Handle<String> name) {
+                                   Handle<Name> name) {
   Heap* heap = isolate->heap();
   // Due to some WebKit tests, we want to make sure that we do not log
   // more than one access failure here.
@@ -1163,7 +1172,7 @@
   ASSERT(args.length() == 2);
   HandleScope scope(isolate);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
   return GetOwnProperty(isolate, obj, name);
 }
 
@@ -2119,7 +2128,7 @@
   } else {  // Dictionary properties.
     // Directly manipulate the property details.
     int entry = function->property_dictionary()->FindEntry(name);
-    ASSERT(entry != StringDictionary::kNotFound);
+    ASSERT(entry != NameDictionary::kNotFound);
     PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
     PropertyDetails new_details(
         static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
@@ -3898,16 +3907,16 @@
     return GetElementOrCharAt(isolate, object, index);
   }
 
-  // Convert the key to a string - possibly by calling back into JavaScript.
-  Handle<String> name;
-  if (key->IsString()) {
-    name = Handle<String>::cast(key);
+  // Convert the key to a name - possibly by calling back into JavaScript.
+  Handle<Name> name;
+  if (key->IsName()) {
+    name = Handle<Name>::cast(key);
   } else {
     bool has_pending_exception = false;
     Handle<Object> converted =
         Execution::ToString(key, &has_pending_exception);
     if (has_pending_exception) return Failure::Exception();
-    name = Handle<String>::cast(converted);
+    name = Handle<Name>::cast(converted);
   }
 
   // Check if the name is trivially convertible to an index and get
@@ -3931,7 +3940,7 @@
 }
 
 
-// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
+// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
   NoHandleAllocation ha(isolate);
   ASSERT(args.length() == 2);
@@ -3950,9 +3959,9 @@
   if (args[0]->IsJSObject()) {
     if (!args[0]->IsJSGlobalProxy() &&
         !args[0]->IsAccessCheckNeeded() &&
-        args[1]->IsString()) {
+        args[1]->IsName()) {
       JSObject* receiver = JSObject::cast(args[0]);
-      String* key = String::cast(args[1]);
+      Name* key = Name::cast(args[1]);
       if (receiver->HasFastProperties()) {
         // Attempt to use lookup cache.
         Map* receiver_map = receiver->map();
@@ -3975,9 +3984,9 @@
         }
       } else {
         // Attempt dictionary lookup.
-        StringDictionary* dictionary = receiver->property_dictionary();
+        NameDictionary* dictionary = receiver->property_dictionary();
         int entry = dictionary->FindEntry(key);
-        if ((entry != StringDictionary::kNotFound) &&
+        if ((entry != NameDictionary::kNotFound) &&
             (dictionary->DetailsAt(entry).type() == NORMAL)) {
           Object* value = dictionary->ValueAt(entry);
           if (!receiver->IsGlobalObject()) return value;
@@ -3987,7 +3996,7 @@
         }
       }
     } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
-      // JSObject without a string key. If the key is a Smi, check for a
+      // JSObject without a name key. If the key is a Smi, check for a
       // definite out-of-bounds access to elements, which is a strong indicator
       // that subsequent accesses will also call the runtime. Proactively
       // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
@@ -4047,7 +4056,7 @@
   HandleScope scope(isolate);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
   RUNTIME_ASSERT(!obj->IsNull());
-  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
   RUNTIME_ASSERT(IsValidAccessor(getter));
   CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
@@ -4072,7 +4081,7 @@
   ASSERT(args.length() == 4);
   HandleScope scope(isolate);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
   CONVERT_SMI_ARG_CHECKED(unchecked, 3);
   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
@@ -4090,6 +4099,14 @@
     if (callback->IsAccessorInfo()) {
       return isolate->heap()->undefined_value();
     }
+    // TODO(mstarzinger): The __proto__ property should actually be a real
+    // JavaScript accessor instead of a foreign callback. But for now we just
+    // avoid changing the writability and configurability attribute of this
+    // property.
+    Handle<Name> proto_string = isolate->factory()->proto_string();
+    if (callback->IsForeign() && proto_string->Equals(*name)) {
+      attr = static_cast<PropertyAttributes>(attr & ~(READ_ONLY | DONT_DELETE));
+    }
     // Avoid redefining foreign callback as data property, just use the stored
     // setter to update the value instead.
     // TODO(mstarzinger): So far this only works if property attributes don't
@@ -4137,7 +4154,7 @@
 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
   ASSERT(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
-  CONVERT_ARG_HANDLE_CHECKED(String, key, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
   LookupResult lookup(isolate);
   object->LookupRealNamedProperty(*key, &lookup);
   if (!lookup.IsFound()) return isolate->heap()->undefined_value();
@@ -4180,10 +4197,11 @@
 
   if (object->IsJSProxy()) {
     bool has_pending_exception = false;
-    Handle<Object> name = Execution::ToString(key, &has_pending_exception);
+    Handle<Object> name = key->IsSymbol()
+        ? key : Execution::ToString(key, &has_pending_exception);
     if (has_pending_exception) return Failure::Exception();
     return JSProxy::cast(*object)->SetProperty(
-        String::cast(*name), *value, attr, strict_mode);
+        Name::cast(*name), *value, attr, strict_mode);
   }
 
   // If the object isn't a JavaScript object, we ignore the store.
@@ -4213,16 +4231,16 @@
     return *value;
   }
 
-  if (key->IsString()) {
+  if (key->IsName()) {
     Handle<Object> result;
-    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
+    Handle<Name> name = Handle<Name>::cast(key);
+    if (name->AsArrayIndex(&index)) {
       result = JSObject::SetElement(
           js_object, index, value, attr, strict_mode, set_mode);
     } else {
-      Handle<String> key_string = Handle<String>::cast(key);
-      key_string->TryFlatten();
+      if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
       result = JSReceiver::SetProperty(
-          js_object, key_string, value, attr, strict_mode);
+          js_object, name, value, attr, strict_mode);
     }
     if (result.is_null()) return Failure::Exception();
     return *value;
@@ -4268,16 +4286,14 @@
         index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
   }
 
-  if (key->IsString()) {
-    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
+  if (key->IsName()) {
+    Handle<Name> name = Handle<Name>::cast(key);
+    if (name->AsArrayIndex(&index)) {
       return js_object->SetElement(
           index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
     } else {
-      Handle<String> key_string = Handle<String>::cast(key);
-      key_string->TryFlatten();
-      return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
-                                                         *value,
-                                                         attr);
+      if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
+      return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
     }
   }
 
@@ -4317,19 +4333,19 @@
     return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
   }
 
-  Handle<String> key_string;
-  if (key->IsString()) {
-    key_string = Handle<String>::cast(key);
+  Handle<Name> name;
+  if (key->IsName()) {
+    name = Handle<Name>::cast(key);
   } else {
     // Call-back into JavaScript to convert the key to a string.
     bool has_pending_exception = false;
     Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
     if (has_pending_exception) return Failure::Exception();
-    key_string = Handle<String>::cast(converted);
+    name = Handle<String>::cast(converted);
   }
 
-  key_string->TryFlatten();
-  return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
+  if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
+  return receiver->DeleteProperty(*name, JSReceiver::FORCE_DELETION);
 }
 
 
@@ -4516,7 +4532,7 @@
   NoHandleAllocation ha(isolate);
   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
   CONVERT_ARG_CHECKED(JSObject, object, 0);
-  CONVERT_ARG_CHECKED(String, name, 1);
+  CONVERT_ARG_CHECKED(Name, name, 1);
   // Compute attributes.
   PropertyAttributes attributes = NONE;
   if (args.length() == 4) {
@@ -4537,7 +4553,7 @@
   ASSERT(args.length() == 3);
 
   CONVERT_ARG_CHECKED(JSReceiver, object, 0);
-  CONVERT_ARG_CHECKED(String, key, 1);
+  CONVERT_ARG_CHECKED(Name, key, 1);
   CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
   return object->DeleteProperty(key, (strict_mode == kStrictMode)
                                       ? JSReceiver::STRICT_DELETION
@@ -4547,7 +4563,7 @@
 
 static Object* HasLocalPropertyImplementation(Isolate* isolate,
                                               Handle<JSObject> object,
-                                              Handle<String> key) {
+                                              Handle<Name> key) {
   if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
   // Handle hidden prototypes.  If there's a hidden prototype above this thing
   // then we have to check it for properties, because they are supposed to
@@ -4566,7 +4582,7 @@
 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
   NoHandleAllocation ha(isolate);
   ASSERT(args.length() == 2);
-  CONVERT_ARG_CHECKED(String, key, 1);
+  CONVERT_ARG_CHECKED(Name, key, 1);
 
   uint32_t index;
   const bool key_is_array_index = key->AsArrayIndex(&index);
@@ -4589,7 +4605,7 @@
     HandleScope scope(isolate);
     return HasLocalPropertyImplementation(isolate,
                                           Handle<JSObject>(object),
-                                          Handle<String>(key));
+                                          Handle<Name>(key));
   } else if (obj->IsString() && key_is_array_index) {
     // Well, there is one exception:  Handle [] on strings.
     String* string = String::cast(obj);
@@ -4605,7 +4621,7 @@
   NoHandleAllocation na(isolate);
   ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
-  CONVERT_ARG_CHECKED(String, key, 1);
+  CONVERT_ARG_CHECKED(Name, key, 1);
 
   bool result = receiver->HasProperty(key);
   if (isolate->has_pending_exception()) return Failure::Exception();
@@ -4630,7 +4646,7 @@
   ASSERT(args.length() == 2);
 
   CONVERT_ARG_CHECKED(JSObject, object, 0);
-  CONVERT_ARG_CHECKED(String, key, 1);
+  CONVERT_ARG_CHECKED(Name, key, 1);
 
   PropertyAttributes att = object->GetLocalPropertyAttribute(key);
   return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
@@ -4908,6 +4924,12 @@
     return frame->GetParameter(index);
   }
 
+  if (args[0]->IsSymbol()) {
+    // Lookup in the initial Object.prototype object.
+    return isolate->initial_object_prototype()->GetProperty(
+        Symbol::cast(args[0]));
+  }
+
   // Convert the key to a string.
   HandleScope scope(isolate);
   bool exception = false;
@@ -7660,31 +7682,36 @@
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
-  HandleScope scope(isolate);
-  ASSERT(args.length() == 1);
-  Handle<JSFunction> function = args.at<JSFunction>(0);
-
+bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
   // If the function is not compiled ignore the lazy
   // recompilation. This can happen if the debugger is activated and
   // the function is returned to the not compiled state.
-  if (!function->shared()->is_compiled()) {
-    function->ReplaceCode(function->shared()->code());
-    return function->code();
-  }
+  if (!function->shared()->is_compiled()) return false;
 
   // If the function is not optimizable or debugger is active continue using the
   // code from the full compiler.
   if (!FLAG_crankshaft ||
-      !function->shared()->code()->optimizable() ||
+      function->shared()->optimization_disabled() ||
       isolate->DebuggerHasBreakPoints()) {
     if (FLAG_trace_opt) {
       PrintF("[failed to optimize ");
       function->PrintName();
       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
-          function->shared()->code()->optimizable() ? "T" : "F",
+          function->shared()->optimization_disabled() ? "F" : "T",
           isolate->DebuggerHasBreakPoints() ? "T" : "F");
     }
+    return false;
+  }
+  return true;
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  Handle<JSFunction> function = args.at<JSFunction>(0);
+
+  if (!AllowOptimization(isolate, function)) {
     function->ReplaceCode(function->shared()->code());
     return function->code();
   }
@@ -7706,8 +7733,14 @@
 
 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) {
   HandleScope handle_scope(isolate);
+  Handle<JSFunction> function = args.at<JSFunction>(0);
+  if (!AllowOptimization(isolate, function)) {
+    function->ReplaceCode(function->shared()->code());
+    return function->code();
+  }
+  function->shared()->code()->set_profiler_ticks(0);
   ASSERT(FLAG_parallel_recompilation);
-  Compiler::RecompileParallel(args.at<JSFunction>(0));
+  Compiler::RecompileParallel(function);
   return isolate->heap()->undefined_value();
 }
 
@@ -7891,10 +7924,13 @@
   if (args.length() == 2 &&
       unoptimized->kind() == Code::FUNCTION) {
     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
-    CHECK(type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr")));
-    isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
-    unoptimized->set_allow_osr_at_loop_nesting_level(
-        Code::kMaxLoopNestingMarker);
+    if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
+      isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
+      unoptimized->set_allow_osr_at_loop_nesting_level(
+          Code::kMaxLoopNestingMarker);
+    } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("parallel"))) {
+      function->MarkForParallelRecompilation();
+    }
   }
 
   return isolate->heap()->undefined_value();
@@ -9874,7 +9910,7 @@
 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
   ASSERT(args.length() == 3);
   CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
-  CONVERT_ARG_CHECKED(String, name, 1);
+  CONVERT_ARG_CHECKED(Name, name, 1);
   CONVERT_SMI_ARG_CHECKED(flag, 2);
   AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
   if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
@@ -9927,7 +9963,7 @@
 
 static MaybeObject* DebugLookupResultValue(Heap* heap,
                                            Object* receiver,
-                                           String* name,
+                                           Name* name,
                                            LookupResult* result,
                                            bool* caught_exception) {
   Object* value;
@@ -9999,7 +10035,7 @@
   ASSERT(args.length() == 2);
 
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
 
   // Make sure to set the current context to the context before the debugger was
   // entered (if the debugger is entered). The reason for switching context here
@@ -10097,7 +10133,7 @@
   ASSERT(args.length() == 2);
 
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
-  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
 
   LookupResult result(isolate);
   obj->Lookup(*name, &result);
@@ -10144,7 +10180,7 @@
   ASSERT(args.length() == 2);
   CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
   RUNTIME_ASSERT(obj->HasNamedInterceptor());
-  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
+  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
 
   PropertyAttributes attributes;
   return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
@@ -13253,15 +13289,15 @@
                                                        Object* dictionary) {
   ASSERT(Isolate::Current()->heap() == heap);
   ASSERT(dictionary != NULL);
-  ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
+  ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
   for (int i = 0; i < kNumFunctions; ++i) {
     Object* name_string;
     { MaybeObject* maybe_name_string =
           heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
       if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
     }
-    StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
-    { MaybeObject* maybe_dictionary = string_dictionary->Add(
+    NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
+    { MaybeObject* maybe_dictionary = name_dictionary->Add(
           String::cast(name_string),
           Smi::FromInt(i),
           PropertyDetails(NONE, NORMAL));
diff --git a/src/runtime.h b/src/runtime.h
index a0f4fe7..cd6805c 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -67,6 +67,7 @@
   F(GetDefaultReceiver, 1, 1) \
   \
   F(GetPrototype, 1, 1) \
+  F(SetPrototype, 2, 1) \
   F(IsInPrototypeChain, 2, 1) \
   \
   F(GetOwnProperty, 2, 1) \
diff --git a/src/runtime.js b/src/runtime.js
index 6b48734..09b39ff 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -346,7 +346,7 @@
 
 // ECMA-262, section 11.4.1, page 46.
 function DELETE(key, strict) {
-  return %DeleteProperty(%ToObject(this), %ToString(key), strict);
+  return %DeleteProperty(%ToObject(this), %ToName(key), strict);
 }
 
 
@@ -356,7 +356,7 @@
     throw %MakeTypeError('invalid_in_operator_use', [this, x]);
   }
   return %_IsNonNegativeSmi(this) ?
-    %HasElement(x, this) : %HasProperty(x, %ToString(this));
+    %HasElement(x, this) : %HasProperty(x, %ToName(this));
 }
 
 
@@ -396,7 +396,7 @@
 // has a property with the given key; return the key as a string if
 // it has. Otherwise returns 0 (smi). Used in for-in statements.
 function FILTER_KEY(key) {
-  var string = %ToString(key);
+  var string = %ToName(key);
   if (%HasProperty(this, string)) return string;
   return 0;
 }
@@ -563,6 +563,12 @@
 }
 
 
+// ES6 symbols
+function ToName(x) {
+  return IS_SYMBOL(x) ? x : %ToString(x);
+}
+
+
 // ECMA-262, section 9.9, page 36.
 function ToObject(x) {
   if (IS_STRING(x)) return new $String(x);
diff --git a/src/smart-pointers.h b/src/smart-pointers.h
index 02025bb..7c35b2a 100644
--- a/src/smart-pointers.h
+++ b/src/smart-pointers.h
@@ -129,11 +129,12 @@
 
 template<typename T>
 struct ObjectDeallocator {
-  static void Delete(T* array) {
-    Malloced::Delete(array);
+  static void Delete(T* object) {
+    delete object;
   }
 };
 
+
 template<typename T>
 class SmartPointer: public SmartPointerBase<ObjectDeallocator<T>, T> {
  public:
diff --git a/src/spaces.cc b/src/spaces.cc
index 3adb2e3..1861c53 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -2476,6 +2476,12 @@
 }
 
 
+intptr_t PagedSpace::SizeOfObjects() {
+  ASSERT(!heap()->IsSweepingComplete() || (unswept_free_bytes_ == 0));
+  return Size() - unswept_free_bytes_ - (limit() - top());
+}
+
+
 // After we have booted, we have created a map which represents free space
 // on the heap.  If there was already a free list then the elements on it
 // were created with the wrong FreeSpaceMap (normally NULL), so we need to
@@ -2545,11 +2551,13 @@
 bool PagedSpace::EnsureSweeperProgress(intptr_t size_in_bytes) {
   MarkCompactCollector* collector = heap()->mark_compact_collector();
   if (collector->AreSweeperThreadsActivated()) {
-    if (FLAG_concurrent_sweeping) {
+    if (collector->IsConcurrentSweepingInProgress()) {
       if (collector->StealMemoryFromSweeperThreads(this) < size_in_bytes) {
-        collector->WaitUntilSweepingCompleted();
-        collector->FinalizeSweeping();
-        return true;
+        if (!collector->sequential_sweeping()) {
+          collector->WaitUntilSweepingCompleted();
+          collector->FinalizeSweeping();
+          return true;
+        }
       }
       return false;
     }
diff --git a/src/spaces.h b/src/spaces.h
index e7e11db..6ff3ee3 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -1648,11 +1648,7 @@
 
   // As size, but the bytes in lazily swept pages are estimated and the bytes
   // in the current linear allocation area are not included.
-  virtual intptr_t SizeOfObjects() {
-    // TODO(hpayer): broken when concurrent sweeping turned on
-    ASSERT(!IsLazySweepingComplete() || (unswept_free_bytes_ == 0));
-    return Size() - unswept_free_bytes_ - (limit() - top());
-  }
+  virtual intptr_t SizeOfObjects();
 
   // Wasted bytes in this space.  These are just the bytes that were thrown away
   // due to being too small to use for allocation.  They do not include the
@@ -1769,9 +1765,9 @@
 
   bool AdvanceSweeper(intptr_t bytes_to_sweep);
 
-  // When parallel sweeper threads are active this function waits
-  // for them to complete, otherwise AdvanceSweeper with size_in_bytes
-  // is called.
+  // When parallel sweeper threads are active and the main thread finished
+  // its sweeping phase, this function waits for them to complete, otherwise
+  // AdvanceSweeper with size_in_bytes is called.
   bool EnsureSweeperProgress(intptr_t size_in_bytes);
 
   bool IsLazySweepingComplete() {
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 2bc7355..ac94fff 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -56,14 +56,14 @@
 }
 
 
-Code* StubCache::Set(String* name, Map* map, Code* code) {
+Code* StubCache::Set(Name* name, Map* map, Code* code) {
   // Get the flags from the code.
   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
 
   // Validate that the name does not move on scavenge, and that we
-  // can use identity checks instead of string equality checks.
+  // can use identity checks instead of structural equality checks.
   ASSERT(!heap()->InNewSpace(name));
-  ASSERT(name->IsInternalizedString());
+  ASSERT(name->IsUniqueName());
 
   // The state bits are not important to the hash function because
   // the stub cache only contains monomorphic stubs. Make sure that
@@ -109,12 +109,12 @@
 }
 
 
-Handle<Code> StubCache::FindStub(Handle<String> name,
-                                 Handle<JSObject> stub_holder,
-                                 Code::Kind kind,
-                                 Code::StubType type,
-                                 Code::IcFragment fragment) {
-  Code::Flags flags = Code::ComputeMonomorphicFlags(kind, fragment, type);
+Handle<Code> StubCache::FindIC(Handle<Name> name,
+                               Handle<JSObject> stub_holder,
+                               Code::Kind kind,
+                               Code::StubType type) {
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      kind, Code::kNoExtraICState, type);
   Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
                        isolate_);
   if (probe->IsCode()) return Handle<Code>::cast(probe);
@@ -122,19 +122,29 @@
 }
 
 
-Handle<Code> StubCache::FindHandler(Handle<String> name,
-                                    Handle<JSObject> handler_holder,
-                                    Code::Kind kind,
-                                    Code::StubType type) {
-  return FindStub(name, handler_holder, kind, type, Code::HANDLER_FRAGMENT);
+Handle<Code> StubCache::FindStub(Handle<Name> name,
+                                 Handle<JSObject> stub_holder,
+                                 Code::Kind kind,
+                                 Code::StubType type) {
+  ASSERT(type != Code::NORMAL);
+  int extra_flags = -1;
+  if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
+    extra_flags = kind;
+    kind = Code::STUB;
+  }
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      kind, Code::kNoExtraICState, type, extra_flags);
+  Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
+                       isolate_);
+  if (probe->IsCode()) return Handle<Code>::cast(probe);
+  return Handle<Code>::null();
 }
 
 
 Handle<Code> StubCache::ComputeMonomorphicIC(Handle<JSObject> receiver,
                                              Handle<Code> handler,
-                                             Handle<String> name) {
-  Handle<Code> ic = FindStub(name, receiver, Code::LOAD_IC,
-                             handler->type(), Code::IC_FRAGMENT);
+                                             Handle<Name> name) {
+  Handle<Code> ic = FindIC(name, receiver, Code::LOAD_IC, handler->type());
   if (!ic.is_null()) return ic;
 
   LoadStubCompiler ic_compiler(isolate());
@@ -148,9 +158,9 @@
 
 Handle<Code> StubCache::ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
                                                   Handle<Code> handler,
-                                                  Handle<String> name) {
-  Handle<Code> ic = FindStub(name, receiver, Code::KEYED_LOAD_IC,
-                             handler->type(), Code::IC_FRAGMENT);
+                                                  Handle<Name> name) {
+  Handle<Code> ic = FindIC(
+      name, receiver, Code::KEYED_LOAD_IC, handler->type());
   if (!ic.is_null()) return ic;
 
   KeyedLoadStubCompiler ic_compiler(isolate());
@@ -162,7 +172,7 @@
 }
 
 
-Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
                                                Handle<JSObject> receiver) {
   // If no global objects are present in the prototype chain, the load
   // nonexistent IC stub can be shared for all names for a given map
@@ -170,7 +180,7 @@
   // there are global objects involved, we need to check global
   // property cells in the stub and therefore the stub will be
   // specific to the name.
-  Handle<String> cache_name = factory()->empty_string();
+  Handle<Name> cache_name = factory()->empty_string();
   Handle<JSObject> current;
   Handle<Object> next = receiver;
   Handle<GlobalObject> global;
@@ -187,7 +197,7 @@
 
   // Compile the stub that is either shared for all names or
   // name specific if there are global objects involved.
-  Handle<Code> handler = FindHandler(
+  Handle<Code> handler = FindStub(
       cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT);
   if (!handler.is_null()) return handler;
 
@@ -199,7 +209,7 @@
 }
 
 
-Handle<Code> StubCache::ComputeLoadField(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
                                          Handle<JSObject> receiver,
                                          Handle<JSObject> holder,
                                          PropertyIndex field) {
@@ -211,7 +221,7 @@
   }
 
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindHandler(
+  Handle<Code> stub = FindStub(
       name, stub_holder, Code::LOAD_IC, Code::FIELD);
   if (!stub.is_null()) return stub;
 
@@ -224,13 +234,13 @@
 
 
 Handle<Code> StubCache::ComputeLoadCallback(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<ExecutableAccessorInfo> callback) {
   ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindHandler(
+  Handle<Code> stub = FindStub(
       name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
   if (!stub.is_null()) return stub;
 
@@ -242,12 +252,12 @@
 }
 
 
-Handle<Code> StubCache::ComputeLoadViaGetter(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
                                              Handle<JSObject> receiver,
                                              Handle<JSObject> holder,
                                              Handle<JSFunction> getter) {
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindHandler(
+  Handle<Code> stub = FindStub(
       name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
   if (!stub.is_null()) return stub;
 
@@ -259,12 +269,12 @@
 }
 
 
-Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
                                             Handle<JSObject> receiver,
                                             Handle<JSObject> holder,
                                             Handle<JSFunction> value) {
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> handler = FindHandler(
+  Handle<Code> handler = FindStub(
       name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
   if (!handler.is_null()) return handler;
 
@@ -276,11 +286,11 @@
 }
 
 
-Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
                                                Handle<JSObject> receiver,
                                                Handle<JSObject> holder) {
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindHandler(
+  Handle<Code> stub = FindStub(
       name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
   if (!stub.is_null()) return stub;
 
@@ -292,20 +302,19 @@
 }
 
 
-Handle<Code> StubCache::ComputeLoadNormal(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadNormal(Handle<Name> name,
                                           Handle<JSObject> receiver) {
   return isolate_->builtins()->LoadIC_Normal();
 }
 
 
-Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
+Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
                                           Handle<JSObject> receiver,
                                           Handle<GlobalObject> holder,
                                           Handle<JSGlobalPropertyCell> cell,
                                           bool is_dont_delete) {
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindStub(
-      name, stub_holder, Code::LOAD_IC, Code::NORMAL, Code::IC_FRAGMENT);
+  Handle<Code> stub = FindIC(name, stub_holder, Code::LOAD_IC, Code::NORMAL);
   if (!stub.is_null()) return stub;
 
   LoadStubCompiler compiler(isolate_);
@@ -316,7 +325,7 @@
 }
 
 
-Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
                                               Handle<JSObject> receiver,
                                               Handle<JSObject> holder,
                                               PropertyIndex field) {
@@ -328,7 +337,7 @@
   }
 
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindHandler(
+  Handle<Code> stub = FindStub(
       name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
   if (!stub.is_null()) return stub;
 
@@ -340,12 +349,12 @@
 }
 
 
-Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
                                                  Handle<JSObject> receiver,
                                                  Handle<JSObject> holder,
                                                  Handle<JSFunction> value) {
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> handler = FindHandler(
+  Handle<Code> handler = FindStub(
       name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION);
   if (!handler.is_null()) return handler;
 
@@ -356,11 +365,11 @@
 }
 
 
-Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
                                                     Handle<JSObject> receiver,
                                                     Handle<JSObject> holder) {
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindHandler(
+  Handle<Code> stub = FindStub(
       name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
   if (!stub.is_null()) return stub;
 
@@ -373,12 +382,12 @@
 
 
 Handle<Code> StubCache::ComputeKeyedLoadCallback(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<ExecutableAccessorInfo> callback) {
   Handle<JSObject> stub_holder = StubHolder(receiver, holder);
-  Handle<Code> stub = FindHandler(
+  Handle<Code> stub = FindStub(
       name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
   if (!stub.is_null()) return stub;
 
@@ -390,7 +399,7 @@
 }
 
 
-Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
                                           Handle<JSObject> receiver,
                                           int field_index,
                                           Handle<Map> transition,
@@ -413,7 +422,7 @@
 
 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
-  Handle<String> name =
+  Handle<Name> name =
       isolate()->factory()->KeyedLoadElementMonomorphic_string();
 
   Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
@@ -429,28 +438,26 @@
 
 Handle<Code> StubCache::ComputeKeyedStoreElement(
     Handle<Map> receiver_map,
-    KeyedStoreIC::StubKind stub_kind,
     StrictModeFlag strict_mode,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   Code::ExtraICState extra_state =
-      Code::ComputeExtraICState(grow_mode, strict_mode);
+      Code::ComputeExtraICState(store_mode, strict_mode);
   Code::Flags flags = Code::ComputeMonomorphicFlags(
       Code::KEYED_STORE_IC, extra_state);
 
-  ASSERT(stub_kind == KeyedStoreIC::STORE_NO_TRANSITION ||
-         stub_kind == KeyedStoreIC::STORE_AND_GROW_NO_TRANSITION);
+  ASSERT(store_mode == STANDARD_STORE ||
+         store_mode == STORE_AND_GROW_NO_TRANSITION);
 
-  Handle<String> name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION
-      ? isolate()->factory()->KeyedStoreElementMonomorphic_string()
-      : isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_string();
-
+  Handle<String> name =
+      isolate()->factory()->KeyedStoreElementMonomorphic_string();
   Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_);
   if (probe->IsCode()) return Handle<Code>::cast(probe);
 
-  KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode);
+  KeyedStoreStubCompiler compiler(isolate(), strict_mode, store_mode);
   Handle<Code> code = compiler.CompileStoreElement(receiver_map);
 
   Map::UpdateCodeCache(receiver_map, name, code);
+  ASSERT(Code::GetKeyedAccessStoreMode(code->extra_ic_state()) == store_mode);
   return code;
 }
 
@@ -462,7 +469,7 @@
 }
 
 
-Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
                                            Handle<GlobalObject> receiver,
                                            Handle<JSGlobalPropertyCell> cell,
                                            StrictModeFlag strict_mode) {
@@ -480,7 +487,7 @@
 
 
 Handle<Code> StubCache::ComputeStoreCallback(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<ExecutableAccessorInfo> callback,
@@ -500,7 +507,7 @@
 }
 
 
-Handle<Code> StubCache::ComputeStoreViaSetter(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreViaSetter(Handle<Name> name,
                                               Handle<JSObject> receiver,
                                               Handle<JSObject> holder,
                                               Handle<JSFunction> setter,
@@ -519,7 +526,7 @@
 }
 
 
-Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
+Handle<Code> StubCache::ComputeStoreInterceptor(Handle<Name> name,
                                                 Handle<JSObject> receiver,
                                                 StrictModeFlag strict_mode) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
@@ -534,7 +541,7 @@
   return code;
 }
 
-Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name,
+Handle<Code> StubCache::ComputeKeyedStoreField(Handle<Name> name,
                                                Handle<JSObject> receiver,
                                                int field_index,
                                                Handle<Map> transition,
@@ -547,8 +554,7 @@
                        isolate_);
   if (probe->IsCode()) return Handle<Code>::cast(probe);
 
-  KeyedStoreStubCompiler compiler(isolate(), strict_mode,
-                                  DO_NOT_ALLOW_JSARRAY_GROWTH);
+  KeyedStoreStubCompiler compiler(isolate(), strict_mode, STANDARD_STORE);
   Handle<Code> code =
       compiler.CompileStoreField(receiver, field_index, transition, name);
   JSObject::UpdateMapCodeCache(receiver, name, code);
@@ -562,7 +568,7 @@
 Handle<Code> StubCache::ComputeCallConstant(int argc,
                                             Code::Kind kind,
                                             Code::ExtraICState extra_state,
-                                            Handle<String> name,
+                                            Handle<Name> name,
                                             Handle<Object> object,
                                             Handle<JSObject> holder,
                                             Handle<JSFunction> function) {
@@ -614,7 +620,7 @@
 Handle<Code> StubCache::ComputeCallField(int argc,
                                          Code::Kind kind,
                                          Code::ExtraICState extra_state,
-                                         Handle<String> name,
+                                         Handle<Name> name,
                                          Handle<Object> object,
                                          Handle<JSObject> holder,
                                          PropertyIndex index) {
@@ -654,7 +660,7 @@
 Handle<Code> StubCache::ComputeCallInterceptor(int argc,
                                                Code::Kind kind,
                                                Code::ExtraICState extra_state,
-                                               Handle<String> name,
+                                               Handle<Name> name,
                                                Handle<Object> object,
                                                Handle<JSObject> holder) {
   // Compute the check type and the map.
@@ -693,7 +699,7 @@
 Handle<Code> StubCache::ComputeCallGlobal(int argc,
                                           Code::Kind kind,
                                           Code::ExtraICState extra_state,
-                                          Handle<String> name,
+                                          Handle<Name> name,
                                           Handle<JSObject> receiver,
                                           Handle<GlobalObject> holder,
                                           Handle<JSGlobalPropertyCell> cell,
@@ -893,28 +899,32 @@
 
 Handle<Code> StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps,
                                              CodeHandleList* handlers,
-                                             Handle<String> name) {
+                                             Handle<Name> name) {
   LoadStubCompiler ic_compiler(isolate_);
+  Code::StubType type = handlers->length() == 1 ? handlers->at(0)->type()
+                                                : Code::NORMAL;
   Handle<Code> ic = ic_compiler.CompilePolymorphicIC(
-      receiver_maps, handlers, name, Code::NORMAL, PROPERTY);
+      receiver_maps, handlers, name, type, PROPERTY);
   return ic;
 }
 
 
 Handle<Code> StubCache::ComputeStoreElementPolymorphic(
     MapHandleList* receiver_maps,
-    KeyedAccessGrowMode grow_mode,
+    KeyedAccessStoreMode store_mode,
     StrictModeFlag strict_mode) {
+  ASSERT(store_mode == STANDARD_STORE ||
+         store_mode == STORE_AND_GROW_NO_TRANSITION);
   Handle<PolymorphicCodeCache> cache =
       isolate_->factory()->polymorphic_code_cache();
-  Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode,
+  Code::ExtraICState extra_state = Code::ComputeExtraICState(store_mode,
                                                              strict_mode);
   Code::Flags flags =
       Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state);
   Handle<Object> probe = cache->Lookup(receiver_maps, flags);
   if (probe->IsCode()) return Handle<Code>::cast(probe);
 
-  KeyedStoreStubCompiler compiler(isolate_, strict_mode, grow_mode);
+  KeyedStoreStubCompiler compiler(isolate_, strict_mode, store_mode);
   Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps);
   PolymorphicCodeCache::Update(cache, receiver_maps, flags, code);
   return code;
@@ -975,13 +985,13 @@
 
 
 void StubCache::CollectMatchingMaps(SmallMapList* types,
-                                    String* name,
+                                    Name* name,
                                     Code::Flags flags,
                                     Handle<Context> native_context,
                                     Zone* zone) {
   for (int i = 0; i < kPrimaryTableSize; i++) {
     if (primary_[i].key == name) {
-      Map* map = primary_[i].value->FindFirstMap();
+      Map* map = primary_[i].map;
       // Map can be NULL, if the stub is constant function call
       // with a primitive receiver.
       if (map == NULL) continue;
@@ -996,7 +1006,7 @@
 
   for (int i = 0; i < kSecondaryTableSize; i++) {
     if (secondary_[i].key == name) {
-      Map* map = secondary_[i].value->FindFirstMap();
+      Map* map = secondary_[i].map;
       // Map can be NULL, if the stub is constant function call
       // with a primitive receiver.
       if (map == NULL) continue;
@@ -1005,7 +1015,7 @@
       int primary_offset = PrimaryOffset(name, flags, map);
       Entry* primary_entry = entry(primary_, primary_offset);
       if (primary_entry->key == name) {
-        Map* primary_map = primary_entry->value->FindFirstMap();
+        Map* primary_map = primary_entry->map;
         if (map == primary_map) continue;
       }
 
@@ -1031,9 +1041,14 @@
   v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
   ASSERT(fun != NULL);
   ASSERT(callback->IsCompatibleReceiver(recv));
-  Handle<String> name = args.at<String>(2);
+  Handle<Name> name = args.at<Name>(2);
   Handle<Object> value = args.at<Object>(3);
   HandleScope scope(isolate);
+
+  // TODO(rossberg): Support symbols in the API.
+  if (name->IsSymbol()) return *value;
+  Handle<String> str = Handle<String>::cast(name);
+
   LOG(isolate, ApiNamedPropertyAccess("store", recv, *name));
   CustomArguments custom_args(isolate, callback->data(), recv, recv);
   v8::AccessorInfo info(custom_args.end());
@@ -1041,7 +1056,7 @@
     // Leaving JavaScript.
     VMState state(isolate, EXTERNAL);
     ExternalCallbackScope call_scope(isolate, setter_address);
-    fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
+    fun(v8::Utils::ToLocal(str), v8::Utils::ToLocal(value), info);
   }
   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return *value;
@@ -1059,7 +1074,7 @@
  * provide any value for the given name.
  */
 RUNTIME_FUNCTION(MaybeObject*, LoadPropertyWithInterceptorOnly) {
-  Handle<String> name_handle = args.at<String>(0);
+  Handle<Name> name_handle = args.at<Name>(0);
   Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
   ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
   ASSERT(args[2]->IsJSObject());  // Receiver.
@@ -1067,6 +1082,11 @@
   ASSERT(args[5]->IsSmi());  // Isolate.
   ASSERT(args.length() == 6);
 
+  // TODO(rossberg): Support symbols in the API.
+  if (name_handle->IsSymbol())
+    return isolate->heap()->no_interceptor_result_sentinel();
+  Handle<String> name = Handle<String>::cast(name_handle);
+
   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
   v8::NamedPropertyGetter getter =
       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
@@ -1081,7 +1101,7 @@
     {
       // Leaving JavaScript.
       VMState state(isolate, EXTERNAL);
-      r = getter(v8::Utils::ToLocal(name_handle), info);
+      r = getter(v8::Utils::ToLocal(name), info);
     }
     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!r.IsEmpty()) {
@@ -1095,7 +1115,7 @@
 }
 
 
-static MaybeObject* ThrowReferenceError(Isolate* isolate, String* name) {
+static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
   // If the load is non-contextual, just return the undefined result.
   // Note that both keyed and non-keyed loads may end up here, so we
   // can't use either LoadIC or KeyedLoadIC constructors.
@@ -1105,7 +1125,7 @@
 
   // Throw a reference error.
   HandleScope scope(isolate);
-  Handle<String> name_handle(name);
+  Handle<Name> name_handle(name);
   Handle<Object> error =
       FACTORY->NewReferenceError("not_defined",
                                   HandleVector(&name_handle, 1));
@@ -1115,7 +1135,7 @@
 
 static MaybeObject* LoadWithInterceptor(Arguments* args,
                                         PropertyAttributes* attrs) {
-  Handle<String> name_handle = args->at<String>(0);
+  Handle<Name> name_handle = args->at<Name>(0);
   Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
   ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
   Handle<JSObject> receiver_handle = args->at<JSObject>(2);
@@ -1124,6 +1144,12 @@
 
   Isolate* isolate = receiver_handle->GetIsolate();
 
+  // TODO(rossberg): Support symbols in the API.
+  if (name_handle->IsSymbol())
+    return holder_handle->GetPropertyPostInterceptor(
+        *receiver_handle, *name_handle, attrs);
+  Handle<String> name = Handle<String>::cast(name_handle);
+
   Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
   v8::NamedPropertyGetter getter =
       FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
@@ -1138,7 +1164,7 @@
     {
       // Leaving JavaScript.
       VMState state(isolate, EXTERNAL);
-      r = getter(v8::Utils::ToLocal(name_handle), info);
+      r = getter(v8::Utils::ToLocal(name), info);
     }
     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
     if (!r.IsEmpty()) {
@@ -1171,7 +1197,7 @@
 
   // If the property is present, return it.
   if (attr != ABSENT) return result;
-  return ThrowReferenceError(isolate, String::cast(args[0]));
+  return ThrowReferenceError(isolate, Name::cast(args[0]));
 }
 
 
@@ -1189,7 +1215,7 @@
 RUNTIME_FUNCTION(MaybeObject*, StoreInterceptorProperty) {
   ASSERT(args.length() == 4);
   JSObject* recv = JSObject::cast(args[0]);
-  String* name = String::cast(args[1]);
+  Name* name = Name::cast(args[1]);
   Object* value = args[2];
   ASSERT(args.smi_at(3) == kStrictMode || args.smi_at(3) == kNonStrictMode);
   StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
@@ -1371,15 +1397,15 @@
 
 
 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
-                                            Handle<String> name) {
-  return (FLAG_print_code_stubs && !name.is_null())
-      ? GetCodeWithFlags(flags, *name->ToCString())
+                                            Handle<Name> name) {
+  return (FLAG_print_code_stubs && !name.is_null() && name->IsString())
+      ? GetCodeWithFlags(flags, *Handle<String>::cast(name)->ToCString())
       : GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
 }
 
 
 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
-                                         Handle<String> name,
+                                         Handle<Name> name,
                                          LookupResult* lookup) {
   holder->LocalLookupRealNamedProperty(*name, lookup);
   if (lookup->IsFound()) return;
@@ -1394,7 +1420,7 @@
 Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle<JSObject> object,
                                                      Register object_reg,
                                                      Handle<JSObject> holder,
-                                                     Handle<String> name,
+                                                     Handle<Name> name,
                                                      Label* miss) {
   // Check the prototype chain.
   return CheckPrototypes(object, object_reg, holder,
@@ -1406,7 +1432,7 @@
 Register BaseLoadStubCompiler::HandlerFrontend(Handle<JSObject> object,
                                                Register object_reg,
                                                Handle<JSObject> holder,
-                                               Handle<String> name,
+                                               Handle<Name> name,
                                                Label* success) {
   Label miss;
 
@@ -1419,7 +1445,7 @@
 
 Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object,
                                                     Handle<JSObject> holder,
-                                                    Handle<String> name,
+                                                    Handle<Name> name,
                                                     PropertyIndex field) {
   Label miss;
 
@@ -1432,14 +1458,14 @@
   GenerateLoadMiss(masm(), kind());
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::FIELD, name);
+  return GetCode(kind(), Code::FIELD, name);
 }
 
 
 Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
     Handle<JSObject> object,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSFunction> value) {
   Label success;
   HandlerFrontend(object, receiver(), holder, name, &success);
@@ -1447,14 +1473,14 @@
   GenerateLoadConstant(value);
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::CONSTANT_FUNCTION, name);
+  return GetCode(kind(), Code::CONSTANT_FUNCTION, name);
 }
 
 
 Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
     Handle<JSObject> object,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     Handle<ExecutableAccessorInfo> callback) {
   Label success;
 
@@ -1464,14 +1490,14 @@
   GenerateLoadCallback(reg, callback);
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::CALLBACKS, name);
+  return GetCode(kind(), Code::CALLBACKS, name);
 }
 
 
 Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
     Handle<JSObject> object,
     Handle<JSObject> holder,
-    Handle<String> name) {
+    Handle<Name> name) {
   Label success;
 
   LookupResult lookup(isolate());
@@ -1484,14 +1510,14 @@
   GenerateLoadInterceptor(reg, object, holder, &lookup, name);
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::INTERCEPTOR, name);
+  return GetCode(kind(), Code::INTERCEPTOR, name);
 }
 
 
 void BaseLoadStubCompiler::GenerateLoadPostInterceptor(
     Register interceptor_reg,
     Handle<JSObject> interceptor_holder,
-    Handle<String> name,
+    Handle<Name> name,
     LookupResult* lookup) {
   Label success;
   Handle<JSObject> holder(lookup->holder());
@@ -1529,7 +1555,7 @@
 Handle<Code> BaseLoadStubCompiler::CompileMonomorphicIC(
     Handle<Map> receiver_map,
     Handle<Code> handler,
-    Handle<String> name) {
+    Handle<Name> name) {
   MapHandleList receiver_maps(1);
   receiver_maps.Add(receiver_map);
   CodeHandleList handlers(1);
@@ -1542,7 +1568,7 @@
 Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
     Handle<JSObject> object,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSFunction> getter) {
   Label success;
   HandlerFrontend(object, receiver(), holder, name, &success);
@@ -1551,28 +1577,42 @@
   GenerateLoadViaGetter(masm(), getter);
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::CALLBACKS, name);
+  return GetCode(kind(), Code::CALLBACKS, name);
 }
 
 
 #undef __
 
 
-void LoadStubCompiler::JitEvent(Handle<String> name, Handle<Code> code) {
+void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
   GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
 }
 
 
-void KeyedLoadStubCompiler::JitEvent(Handle<String> name, Handle<Code> code) {
+void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
   GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
 }
 
 
-Handle<Code> BaseLoadStubCompiler::GetCode(Code::IcFragment fragment,
+Handle<Code> BaseLoadStubCompiler::GetICCode(Code::Kind kind,
+                                             Code::StubType type,
+                                             Handle<Name> name,
+                                             InlineCacheState state) {
+  Code::Flags flags = Code::ComputeFlags(
+      kind, state, Code::kNoExtraICState, type);
+  Handle<Code> code = GetCodeWithFlags(flags, name);
+  PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
+  JitEvent(name, code);
+  return code;
+}
+
+
+Handle<Code> BaseLoadStubCompiler::GetCode(Code::Kind kind,
                                            Code::StubType type,
-                                           Handle<String> name,
-                                           InlineCacheState state) {
-  Code::Flags flags = Code::ComputeFlags(kind(), state, fragment, type);
+                                           Handle<Name> name) {
+  ASSERT(type != Code::NORMAL);
+  Code::Flags flags = Code::ComputeFlags(
+      Code::STUB, MONOMORPHIC, Code::kNoExtraICState, type, kind);
   Handle<Code> code = GetCodeWithFlags(flags, name);
   PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
   JitEvent(name, code);
@@ -1609,7 +1649,7 @@
 
 
 Handle<Code> StoreStubCompiler::GetCode(Code::StubType type,
-                                        Handle<String> name) {
+                                        Handle<Name> name) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
       Code::STORE_IC, strict_mode_, type);
   Handle<Code> code = GetCodeWithFlags(flags, name);
@@ -1620,10 +1660,10 @@
 
 
 Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type,
-                                             Handle<String> name,
+                                             Handle<Name> name,
                                              InlineCacheState state) {
   Code::ExtraICState extra_state =
-      Code::ComputeExtraICState(grow_mode_, strict_mode_);
+      Code::ComputeExtraICState(store_mode_, strict_mode_);
   Code::Flags flags =
       Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type);
   Handle<Code> code = GetCodeWithFlags(flags, name);
@@ -1657,12 +1697,12 @@
           transitioned_map->elements_kind(),
           is_js_array,
           strict_mode_,
-          grow_mode_).GetCode(isolate());
+          store_mode_).GetCode(isolate());
     } else {
       cached_stub = KeyedStoreElementStub(
           is_js_array,
           elements_kind,
-          grow_mode_).GetCode(isolate());
+          store_mode_).GetCode(isolate());
     }
     ASSERT(!cached_stub.is_null());
     handlers.Add(cached_stub);
@@ -1742,7 +1782,7 @@
 
 
 Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
-                                       Handle<String> name) {
+                                       Handle<Name> name) {
   int argc = arguments_.immediate();
   Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
                                                     extra_state_,
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 5e3fbfc..56e3d4f 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -67,7 +67,7 @@
 class StubCache {
  public:
   struct Entry {
-    String* key;
+    Name* key;
     Code* value;
     Map* map;
   };
@@ -77,57 +77,56 @@
   Handle<JSObject> StubHolder(Handle<JSObject> receiver,
                               Handle<JSObject> holder);
 
-  Handle<Code> FindStub(Handle<String> name,
+  Handle<Code> FindIC(Handle<Name> name,
+                      Handle<JSObject> stub_holder,
+                      Code::Kind kind,
+                      Code::StubType type);
+
+  Handle<Code> FindStub(Handle<Name> name,
                         Handle<JSObject> stub_holder,
                         Code::Kind kind,
-                        Code::StubType type,
-                        Code::IcFragment fragment);
-
-  Handle<Code> FindHandler(Handle<String> name,
-                           Handle<JSObject> stub_holder,
-                           Code::Kind kind,
-                           Code::StubType type);
+                        Code::StubType type);
 
   Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
                                     Handle<Code> handler,
-                                    Handle<String> name);
+                                    Handle<Name> name);
   Handle<Code> ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
                                          Handle<Code> handler,
-                                         Handle<String> name);
+                                         Handle<Name> name);
 
   // Computes the right stub matching. Inserts the result in the
   // cache before returning.  This might compile a stub if needed.
-  Handle<Code> ComputeLoadNonexistent(Handle<String> name,
+  Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
                                       Handle<JSObject> object);
 
-  Handle<Code> ComputeLoadField(Handle<String> name,
+  Handle<Code> ComputeLoadField(Handle<Name> name,
                                 Handle<JSObject> object,
                                 Handle<JSObject> holder,
                                 PropertyIndex field_index);
 
-  Handle<Code> ComputeLoadCallback(Handle<String> name,
+  Handle<Code> ComputeLoadCallback(Handle<Name> name,
                                    Handle<JSObject> object,
                                    Handle<JSObject> holder,
                                    Handle<ExecutableAccessorInfo> callback);
 
-  Handle<Code> ComputeLoadViaGetter(Handle<String> name,
+  Handle<Code> ComputeLoadViaGetter(Handle<Name> name,
                                     Handle<JSObject> object,
                                     Handle<JSObject> holder,
                                     Handle<JSFunction> getter);
 
-  Handle<Code> ComputeLoadConstant(Handle<String> name,
+  Handle<Code> ComputeLoadConstant(Handle<Name> name,
                                    Handle<JSObject> object,
                                    Handle<JSObject> holder,
                                    Handle<JSFunction> value);
 
-  Handle<Code> ComputeLoadInterceptor(Handle<String> name,
+  Handle<Code> ComputeLoadInterceptor(Handle<Name> name,
                                       Handle<JSObject> object,
                                       Handle<JSObject> holder);
 
-  Handle<Code> ComputeLoadNormal(Handle<String> name,
+  Handle<Code> ComputeLoadNormal(Handle<Name> name,
                                  Handle<JSObject> object);
 
-  Handle<Code> ComputeLoadGlobal(Handle<String> name,
+  Handle<Code> ComputeLoadGlobal(Handle<Name> name,
                                  Handle<JSObject> object,
                                  Handle<GlobalObject> holder,
                                  Handle<JSGlobalPropertyCell> cell,
@@ -135,29 +134,29 @@
 
   // ---
 
-  Handle<Code> ComputeKeyedLoadField(Handle<String> name,
+  Handle<Code> ComputeKeyedLoadField(Handle<Name> name,
                                      Handle<JSObject> object,
                                      Handle<JSObject> holder,
                                      PropertyIndex field_index);
 
   Handle<Code> ComputeKeyedLoadCallback(
-      Handle<String> name,
+      Handle<Name> name,
       Handle<JSObject> object,
       Handle<JSObject> holder,
       Handle<ExecutableAccessorInfo> callback);
 
-  Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
+  Handle<Code> ComputeKeyedLoadConstant(Handle<Name> name,
                                         Handle<JSObject> object,
                                         Handle<JSObject> holder,
                                         Handle<JSFunction> value);
 
-  Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
+  Handle<Code> ComputeKeyedLoadInterceptor(Handle<Name> name,
                                            Handle<JSObject> object,
                                            Handle<JSObject> holder);
 
   // ---
 
-  Handle<Code> ComputeStoreField(Handle<String> name,
+  Handle<Code> ComputeStoreField(Handle<Name> name,
                                  Handle<JSObject> object,
                                  int field_index,
                                  Handle<Map> transition,
@@ -165,30 +164,30 @@
 
   Handle<Code> ComputeStoreNormal(StrictModeFlag strict_mode);
 
-  Handle<Code> ComputeStoreGlobal(Handle<String> name,
+  Handle<Code> ComputeStoreGlobal(Handle<Name> name,
                                   Handle<GlobalObject> object,
                                   Handle<JSGlobalPropertyCell> cell,
                                   StrictModeFlag strict_mode);
 
-  Handle<Code> ComputeStoreCallback(Handle<String> name,
+  Handle<Code> ComputeStoreCallback(Handle<Name> name,
                                     Handle<JSObject> object,
                                     Handle<JSObject> holder,
                                     Handle<ExecutableAccessorInfo> callback,
                                     StrictModeFlag strict_mode);
 
-  Handle<Code> ComputeStoreViaSetter(Handle<String> name,
+  Handle<Code> ComputeStoreViaSetter(Handle<Name> name,
                                      Handle<JSObject> object,
                                      Handle<JSObject> holder,
                                      Handle<JSFunction> setter,
                                      StrictModeFlag strict_mode);
 
-  Handle<Code> ComputeStoreInterceptor(Handle<String> name,
+  Handle<Code> ComputeStoreInterceptor(Handle<Name> name,
                                        Handle<JSObject> object,
                                        StrictModeFlag strict_mode);
 
   // ---
 
-  Handle<Code> ComputeKeyedStoreField(Handle<String> name,
+  Handle<Code> ComputeKeyedStoreField(Handle<Name> name,
                                       Handle<JSObject> object,
                                       int field_index,
                                       Handle<Map> transition,
@@ -197,16 +196,15 @@
   Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
 
   Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
-                                        KeyedStoreIC::StubKind stub_kind,
                                         StrictModeFlag strict_mode,
-                                        KeyedAccessGrowMode grow_mode);
+                                        KeyedAccessStoreMode store_mode);
 
   // ---
 
   Handle<Code> ComputeCallField(int argc,
                                 Code::Kind,
                                 Code::ExtraICState extra_state,
-                                Handle<String> name,
+                                Handle<Name> name,
                                 Handle<Object> object,
                                 Handle<JSObject> holder,
                                 PropertyIndex index);
@@ -214,7 +212,7 @@
   Handle<Code> ComputeCallConstant(int argc,
                                    Code::Kind,
                                    Code::ExtraICState extra_state,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    Handle<Object> object,
                                    Handle<JSObject> holder,
                                    Handle<JSFunction> function);
@@ -222,14 +220,14 @@
   Handle<Code> ComputeCallInterceptor(int argc,
                                       Code::Kind,
                                       Code::ExtraICState extra_state,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Handle<Object> object,
                                       Handle<JSObject> holder);
 
   Handle<Code> ComputeCallGlobal(int argc,
                                  Code::Kind,
                                  Code::ExtraICState extra_state,
-                                 Handle<String> name,
+                                 Handle<Name> name,
                                  Handle<JSObject> object,
                                  Handle<GlobalObject> holder,
                                  Handle<JSGlobalPropertyCell> cell,
@@ -263,12 +261,12 @@
 
   Handle<Code> ComputeLoadElementPolymorphic(MapHandleList* receiver_maps);
   Handle<Code> ComputeStoreElementPolymorphic(MapHandleList* receiver_maps,
-                                              KeyedAccessGrowMode grow_mode,
+                                              KeyedAccessStoreMode store_mode,
                                               StrictModeFlag strict_mode);
 
   Handle<Code> ComputePolymorphicIC(MapHandleList* receiver_maps,
                                     CodeHandleList* handlers,
-                                    Handle<String> name);
+                                    Handle<Name> name);
 
   // Finds the Code object stored in the Heap::non_monomorphic_cache().
   Code* FindCallInitialize(int argc, RelocInfo::Mode mode, Code::Kind kind);
@@ -280,14 +278,14 @@
 #endif
 
   // Update cache for entry hash(name, map).
-  Code* Set(String* name, Map* map, Code* code);
+  Code* Set(Name* name, Map* map, Code* code);
 
   // Clear the lookup table (@ mark compact collection).
   void Clear();
 
   // Collect all maps that match the name and flags.
   void CollectMatchingMaps(SmallMapList* types,
-                           String* name,
+                           Name* name,
                            Code::Flags flags,
                            Handle<Context> native_context,
                            Zone* zone);
@@ -358,12 +356,12 @@
   // Hash algorithm for the primary table.  This algorithm is replicated in
   // assembler for every architecture.  Returns an index into the table that
   // is scaled by 1 << kHeapObjectTagSize.
-  static int PrimaryOffset(String* name, Code::Flags flags, Map* map) {
+  static int PrimaryOffset(Name* name, Code::Flags flags, Map* map) {
     // This works well because the heap object tag size and the hash
     // shift are equal.  Shifting down the length field to get the
     // hash code would effectively throw away two bits of the hash
     // code.
-    STATIC_ASSERT(kHeapObjectTagSize == String::kHashShift);
+    STATIC_ASSERT(kHeapObjectTagSize == Name::kHashShift);
     // Compute the hash of the name (use entire hash field).
     ASSERT(name->HasHashCode());
     uint32_t field = name->hash_field();
@@ -384,25 +382,25 @@
   // Hash algorithm for the secondary table.  This algorithm is replicated in
   // assembler for every architecture.  Returns an index into the table that
   // is scaled by 1 << kHeapObjectTagSize.
-  static int SecondaryOffset(String* name, Code::Flags flags, int seed) {
+  static int SecondaryOffset(Name* name, Code::Flags flags, int seed) {
     // Use the seed from the primary cache in the secondary cache.
-    uint32_t string_low32bits =
+    uint32_t name_low32bits =
         static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
     // We always set the in_loop bit to zero when generating the lookup code
     // so do it here too so the hash codes match.
     uint32_t iflags =
         (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
-    uint32_t key = (seed - string_low32bits) + iflags;
+    uint32_t key = (seed - name_low32bits) + iflags;
     return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
   }
 
   // Compute the entry for a given offset in exactly the same way as
   // we do in generated code.  We generate an hash code that already
-  // ends in String::kHashShift 0s.  Then we multiply it so it is a multiple
+  // ends in Name::kHashShift 0s.  Then we multiply it so it is a multiple
   // of sizeof(Entry).  This makes it easier to avoid making mistakes
   // in the hashed offset computations.
   static Entry* entry(Entry* table, int offset) {
-    const int multiplier = sizeof(*table) >> String::kHashShift;
+    const int multiplier = sizeof(*table) >> Name::kHashShift;
     return reinterpret_cast<Entry*>(
         reinterpret_cast<Address>(table) + offset * multiplier);
   }
@@ -512,7 +510,7 @@
                           Handle<JSObject> object,
                           int index,
                           Handle<Map> transition,
-                          Handle<String> name,
+                          Handle<Name> name,
                           Register receiver_reg,
                           Register name_reg,
                           Register scratch1,
@@ -545,7 +543,7 @@
                            Register holder_reg,
                            Register scratch1,
                            Register scratch2,
-                           Handle<String> name,
+                           Handle<Name> name,
                            Label* miss,
                            PrototypeCheckType check = CHECK_ALL_MAPS) {
     return CheckPrototypes(object, object_reg, holder, holder_reg, scratch1,
@@ -558,7 +556,7 @@
                            Register holder_reg,
                            Register scratch1,
                            Register scratch2,
-                           Handle<String> name,
+                           Handle<Name> name,
                            int save_at_depth,
                            Label* miss,
                            PrototypeCheckType check = CHECK_ALL_MAPS);
@@ -566,13 +564,13 @@
 
  protected:
   Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
-  Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<String> name);
+  Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name);
 
   MacroAssembler* masm() { return &masm_; }
   void set_failure(Failure* failure) { failure_ = failure; }
 
   static void LookupPostInterceptor(Handle<JSObject> holder,
-                                    Handle<String> name,
+                                    Handle<Name> name,
                                     LookupResult* lookup);
 
   Isolate* isolate() { return isolate_; }
@@ -599,29 +597,29 @@
 
   Handle<Code> CompileLoadField(Handle<JSObject> object,
                                 Handle<JSObject> holder,
-                                Handle<String> name,
+                                Handle<Name> name,
                                 PropertyIndex index);
 
   Handle<Code> CompileLoadCallback(Handle<JSObject> object,
                                    Handle<JSObject> holder,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    Handle<ExecutableAccessorInfo> callback);
 
   Handle<Code> CompileLoadConstant(Handle<JSObject> object,
                                    Handle<JSObject> holder,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    Handle<JSFunction> value);
 
   Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
                                       Handle<JSObject> holder,
-                                      Handle<String> name);
+                                      Handle<Name> name);
 
   Handle<Code> CompileMonomorphicIC(Handle<Map> receiver_map,
                                     Handle<Code> handler,
-                                    Handle<String> name);
+                                    Handle<Name> name);
   Handle<Code> CompilePolymorphicIC(MapHandleList* receiver_maps,
                                     CodeHandleList* handlers,
-                                    Handle<String> name,
+                                    Handle<Name> name,
                                     Code::StubType type,
                                     IcCheckType check);
 
@@ -629,24 +627,24 @@
   Register HandlerFrontendHeader(Handle<JSObject> object,
                                  Register object_reg,
                                  Handle<JSObject> holder,
-                                 Handle<String> name,
+                                 Handle<Name> name,
                                  Label* success);
   void HandlerFrontendFooter(Label* success, Label* miss);
 
   Register HandlerFrontend(Handle<JSObject> object,
                            Register object_reg,
                            Handle<JSObject> holder,
-                           Handle<String> name,
+                           Handle<Name> name,
                            Label* success);
   Register CallbackHandlerFrontend(Handle<JSObject> object,
                                    Register object_reg,
                                    Handle<JSObject> holder,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    Label* success,
                                    Handle<ExecutableAccessorInfo> callback);
   void NonexistentHandlerFrontend(Handle<JSObject> object,
                                   Handle<JSObject> last,
-                                  Handle<String> name,
+                                  Handle<Name> name,
                                   Label* success,
                                   Handle<GlobalObject> global);
 
@@ -660,16 +658,20 @@
                                Handle<JSObject> object,
                                Handle<JSObject> holder,
                                LookupResult* lookup,
-                               Handle<String> name);
+                               Handle<Name> name);
   void GenerateLoadPostInterceptor(Register reg,
                                    Handle<JSObject> interceptor_holder,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    LookupResult* lookup);
 
-  Handle<Code> GetCode(Code::IcFragment fragment,
+  Handle<Code> GetICCode(Code::Kind kind,
+                         Code::StubType type,
+                         Handle<Name> name,
+                         InlineCacheState state = MONOMORPHIC);
+
+  Handle<Code> GetCode(Code::Kind kind,
                        Code::StubType type,
-                       Handle<String> name,
-                       InlineCacheState state = MONOMORPHIC);
+                       Handle<Name> name);
 
   Register receiver() { return registers_[0]; }
   Register name()     { return registers_[1]; }
@@ -681,8 +683,8 @@
  private:
   virtual Code::Kind kind() = 0;
   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
-  virtual void JitEvent(Handle<String> name, Handle<Code> code) = 0;
-  virtual void GenerateNameCheck(Handle<String> name,
+  virtual void JitEvent(Handle<Name> name, Handle<Code> code) = 0;
+  virtual void GenerateNameCheck(Handle<Name> name,
                                  Register name_reg,
                                  Label* miss) { }
   Register* registers_;
@@ -696,7 +698,7 @@
 
   Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
                                       Handle<JSObject> last,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Handle<GlobalObject> global);
 
   static void GenerateLoadViaGetter(MacroAssembler* masm,
@@ -704,13 +706,13 @@
 
   Handle<Code> CompileLoadViaGetter(Handle<JSObject> object,
                                     Handle<JSObject> holder,
-                                    Handle<String> name,
+                                    Handle<Name> name,
                                     Handle<JSFunction> getter);
 
   Handle<Code> CompileLoadGlobal(Handle<JSObject> object,
                                  Handle<GlobalObject> holder,
                                  Handle<JSGlobalPropertyCell> cell,
-                                 Handle<String> name,
+                                 Handle<Name> name,
                                  bool is_dont_delete);
 
   static Register receiver() { return registers()[0]; }
@@ -719,10 +721,11 @@
   static Register* registers();
   virtual Code::Kind kind() { return Code::LOAD_IC; }
   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
+    if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
     return code->ic_state() == MONOMORPHIC
         ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
   }
-  virtual void JitEvent(Handle<String> name, Handle<Code> code);
+  virtual void JitEvent(Handle<Name> name, Handle<Code> code);
 };
 
 
@@ -746,11 +749,12 @@
   static Register* registers();
   virtual Code::Kind kind() { return Code::KEYED_LOAD_IC; }
   virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
+    if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
     return code->ic_state() == MONOMORPHIC
         ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
   }
-  virtual void JitEvent(Handle<String> name, Handle<Code> code);
-  virtual void GenerateNameCheck(Handle<String> name,
+  virtual void JitEvent(Handle<Name> name, Handle<Code> code);
+  virtual void GenerateNameCheck(Handle<Name> name,
                                  Register name_reg,
                                  Label* miss);
 };
@@ -765,9 +769,9 @@
   Handle<Code> CompileStoreField(Handle<JSObject> object,
                                  int index,
                                  Handle<Map> transition,
-                                 Handle<String> name);
+                                 Handle<Name> name);
 
-  Handle<Code> CompileStoreCallback(Handle<String> name,
+  Handle<Code> CompileStoreCallback(Handle<Name> name,
                                     Handle<JSObject> object,
                                     Handle<JSObject> holder,
                                     Handle<ExecutableAccessorInfo> callback);
@@ -775,20 +779,20 @@
   static void GenerateStoreViaSetter(MacroAssembler* masm,
                                      Handle<JSFunction> setter);
 
-  Handle<Code> CompileStoreViaSetter(Handle<String> name,
+  Handle<Code> CompileStoreViaSetter(Handle<Name> name,
                                      Handle<JSObject> object,
                                      Handle<JSObject> holder,
                                      Handle<JSFunction> setter);
 
   Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
-                                       Handle<String> name);
+                                       Handle<Name> name);
 
   Handle<Code> CompileStoreGlobal(Handle<GlobalObject> object,
                                   Handle<JSGlobalPropertyCell> holder,
-                                  Handle<String> name);
+                                  Handle<Name> name);
 
  private:
-  Handle<Code> GetCode(Code::StubType type, Handle<String> name);
+  Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
 
   StrictModeFlag strict_mode_;
 };
@@ -798,15 +802,15 @@
  public:
   KeyedStoreStubCompiler(Isolate* isolate,
                          StrictModeFlag strict_mode,
-                         KeyedAccessGrowMode grow_mode)
+                         KeyedAccessStoreMode store_mode)
     : StubCompiler(isolate),
       strict_mode_(strict_mode),
-      grow_mode_(grow_mode) { }
+      store_mode_(store_mode) { }
 
   Handle<Code> CompileStoreField(Handle<JSObject> object,
                                  int index,
                                  Handle<Map> transition,
-                                 Handle<String> name);
+                                 Handle<Name> name);
 
   Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
 
@@ -819,11 +823,11 @@
   static void GenerateStoreFastElement(MacroAssembler* masm,
                                        bool is_js_array,
                                        ElementsKind element_kind,
-                                       KeyedAccessGrowMode grow_mode);
+                                       KeyedAccessStoreMode store_mode);
 
   static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
                                              bool is_js_array,
-                                             KeyedAccessGrowMode grow_mode);
+                                             KeyedAccessStoreMode store_mode);
 
   static void GenerateStoreExternalArray(MacroAssembler* masm,
                                          ElementsKind elements_kind);
@@ -832,11 +836,11 @@
 
  private:
   Handle<Code> GetCode(Code::StubType type,
-                       Handle<String> name,
+                       Handle<Name> name,
                        InlineCacheState state = MONOMORPHIC);
 
   StrictModeFlag strict_mode_;
-  KeyedAccessGrowMode grow_mode_;
+  KeyedAccessStoreMode store_mode_;
 };
 
 
@@ -865,11 +869,11 @@
   Handle<Code> CompileCallField(Handle<JSObject> object,
                                 Handle<JSObject> holder,
                                 PropertyIndex index,
-                                Handle<String> name);
+                                Handle<Name> name);
 
   void CompileHandlerFrontend(Handle<Object> object,
                               Handle<JSObject> holder,
-                              Handle<String> name,
+                              Handle<Name> name,
                               CheckType check,
                               Label* success);
 
@@ -877,19 +881,19 @@
 
   Handle<Code> CompileCallConstant(Handle<Object> object,
                                    Handle<JSObject> holder,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    CheckType check,
                                    Handle<JSFunction> function);
 
   Handle<Code> CompileCallInterceptor(Handle<JSObject> object,
                                       Handle<JSObject> holder,
-                                      Handle<String> name);
+                                      Handle<Name> name);
 
   Handle<Code> CompileCallGlobal(Handle<JSObject> object,
                                  Handle<GlobalObject> holder,
                                  Handle<JSGlobalPropertyCell> cell,
                                  Handle<JSFunction> function,
-                                 Handle<String> name);
+                                 Handle<Name> name);
 
   static bool HasCustomCallGenerator(Handle<JSFunction> function);
 
@@ -919,16 +923,16 @@
                                   Handle<JSFunction> function,
                                   Handle<String> name);
 
-  Handle<Code> GetCode(Code::StubType type, Handle<String> name);
+  Handle<Code> GetCode(Code::StubType type, Handle<Name> name);
   Handle<Code> GetCode(Handle<JSFunction> function);
 
   const ParameterCount& arguments() { return arguments_; }
 
-  void GenerateNameCheck(Handle<String> name, Label* miss);
+  void GenerateNameCheck(Handle<Name> name, Label* miss);
 
   void GenerateGlobalReceiverCheck(Handle<JSObject> object,
                                    Handle<JSObject> holder,
-                                   Handle<String> name,
+                                   Handle<Name> name,
                                    Label* miss);
 
   // Generates code to load the function from the cell checking that
diff --git a/src/transitions-inl.h b/src/transitions-inl.h
index cfaa99d..45b6457 100644
--- a/src/transitions-inl.h
+++ b/src/transitions-inl.h
@@ -143,19 +143,19 @@
 }
 
 
-String* TransitionArray::GetKey(int transition_number) {
+Name* TransitionArray::GetKey(int transition_number) {
   if (IsSimpleTransition()) {
     Map* target = GetTarget(kSimpleTransitionIndex);
     int descriptor = target->LastAdded();
-    String* key = target->instance_descriptors()->GetKey(descriptor);
+    Name* key = target->instance_descriptors()->GetKey(descriptor);
     return key;
   }
   ASSERT(transition_number < number_of_transitions());
-  return String::cast(get(ToKeyIndex(transition_number)));
+  return Name::cast(get(ToKeyIndex(transition_number)));
 }
 
 
-void TransitionArray::SetKey(int transition_number, String* key) {
+void TransitionArray::SetKey(int transition_number, Name* key) {
   ASSERT(!IsSimpleTransition());
   ASSERT(transition_number < number_of_transitions());
   set(ToKeyIndex(transition_number), key);
@@ -190,9 +190,9 @@
 }
 
 
-int TransitionArray::Search(String* name) {
+int TransitionArray::Search(Name* name) {
   if (IsSimpleTransition()) {
-    String* key = GetKey(kSimpleTransitionIndex);
+    Name* key = GetKey(kSimpleTransitionIndex);
     if (key->Equals(name)) return kSimpleTransitionIndex;
     return kNotFound;
   }
@@ -201,7 +201,7 @@
 
 
 void TransitionArray::NoIncrementalWriteBarrierSet(int transition_number,
-                                                   String* key,
+                                                   Name* key,
                                                    Map* target) {
   FixedArray::NoIncrementalWriteBarrierSet(
       this, ToKeyIndex(transition_number), key);
diff --git a/src/transitions.cc b/src/transitions.cc
index 56b6caf..adbe6a1 100644
--- a/src/transitions.cc
+++ b/src/transitions.cc
@@ -65,13 +65,13 @@
 }
 
 
-static bool InsertionPointFound(String* key1, String* key2) {
+static bool InsertionPointFound(Name* key1, Name* key2) {
   return key1->Hash() > key2->Hash();
 }
 
 
 MaybeObject* TransitionArray::NewWith(SimpleTransitionFlag flag,
-                                      String* key,
+                                      Name* key,
                                       Map* target,
                                       Object* back_pointer) {
   TransitionArray* result;
@@ -107,7 +107,7 @@
 }
 
 
-MaybeObject* TransitionArray::CopyInsert(String* name, Map* target) {
+MaybeObject* TransitionArray::CopyInsert(Name* name, Map* target) {
   TransitionArray* result;
 
   int number_of_transitions = this->number_of_transitions();
diff --git a/src/transitions.h b/src/transitions.h
index 0a66026..7abef47 100644
--- a/src/transitions.h
+++ b/src/transitions.h
@@ -59,12 +59,12 @@
 class TransitionArray: public FixedArray {
  public:
   // Accessors for fetching instance transition at transition number.
-  inline String* GetKey(int transition_number);
-  inline void SetKey(int transition_number, String* value);
+  inline Name* GetKey(int transition_number);
+  inline void SetKey(int transition_number, Name* value);
   inline Object** GetKeySlot(int transition_number);
   int GetSortedKeyIndex(int transition_number) { return transition_number; }
 
-  String* GetSortedKey(int transition_number) {
+  Name* GetSortedKey(int transition_number) {
     return GetKey(transition_number);
   }
 
@@ -105,7 +105,7 @@
   // Allocate a new transition array with a single entry.
   static MUST_USE_RESULT MaybeObject* NewWith(
       SimpleTransitionFlag flag,
-      String* key,
+      Name* key,
       Map* target,
       Object* back_pointer);
 
@@ -114,7 +114,7 @@
   // Copy the transition array, inserting a new transition.
   // TODO(verwaest): This should not cause an existing transition to be
   // overwritten.
-  MUST_USE_RESULT MaybeObject* CopyInsert(String* name, Map* target);
+  MUST_USE_RESULT MaybeObject* CopyInsert(Name* name, Map* target);
 
   // Copy a single transition from the origin array.
   inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
@@ -122,7 +122,7 @@
                                                 int target_transition);
 
   // Search a transition for a given property name.
-  inline int Search(String* name);
+  inline int Search(Name* name);
 
   // Allocates a TransitionArray.
   MUST_USE_RESULT static MaybeObject* Allocate(int number_of_transitions);
@@ -195,7 +195,7 @@
   }
 
   inline void NoIncrementalWriteBarrierSet(int transition_number,
-                                           String* key,
+                                           Name* key,
                                            Map* target);
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
diff --git a/src/type-info.cc b/src/type-info.cc
index 62ca324..857a55d 100644
--- a/src/type-info.cc
+++ b/src/type-info.cc
@@ -126,12 +126,12 @@
   if (map_or_code->IsMap()) return true;
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
-    bool allow_growth =
-        Code::GetKeyedAccessGrowMode(code->extra_ic_state()) ==
-        ALLOW_JSARRAY_GROWTH;
+    bool standard_store =
+        Code::GetKeyedAccessStoreMode(code->extra_ic_state()) ==
+        STANDARD_STORE;
     bool preliminary_checks =
         code->is_keyed_store_stub() &&
-        !allow_growth &&
+        standard_store &&
         code->ic_state() == MONOMORPHIC &&
         Code::ExtractTypeFromFlags(code->flags()) == Code::NORMAL;
     if (!preliminary_checks) return false;
@@ -146,10 +146,10 @@
   Handle<Object> map_or_code = GetInfo(ast_id);
   if (map_or_code->IsCode()) {
     Handle<Code> code = Handle<Code>::cast(map_or_code);
-    bool allow_growth =
-        Code::GetKeyedAccessGrowMode(code->extra_ic_state()) ==
-        ALLOW_JSARRAY_GROWTH;
-    return code->is_keyed_store_stub() && !allow_growth &&
+    bool standard_store =
+        Code::GetKeyedAccessStoreMode(code->extra_ic_state()) ==
+        STANDARD_STORE;
+    return code->is_keyed_store_stub() && standard_store  &&
         code->ic_state() == POLYMORPHIC;
   }
   return false;
@@ -218,6 +218,19 @@
 }
 
 
+KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode(
+    TypeFeedbackId ast_id) {
+  Handle<Object> map_or_code = GetInfo(ast_id);
+  if (map_or_code->IsCode()) {
+    Handle<Code> code = Handle<Code>::cast(map_or_code);
+    if (code->kind() == Code::KEYED_STORE_IC) {
+      return Code::GetKeyedAccessStoreMode(code->extra_ic_state());
+    }
+  }
+  return STANDARD_STORE;
+}
+
+
 void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
                                            Handle<String> name,
                                            SmallMapList* types) {
diff --git a/src/type-info.h b/src/type-info.h
index 2b50bf4..1e90645 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -255,6 +255,8 @@
   Handle<Map> LoadMonomorphicReceiverType(Property* expr);
   Handle<Map> StoreMonomorphicReceiverType(TypeFeedbackId ast_id);
 
+  KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id);
+
   void LoadReceiverTypes(Property* expr,
                          Handle<String> name,
                          SmallMapList* types);
diff --git a/src/v8globals.h b/src/v8globals.h
index 072c365..8874cfb 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -128,12 +128,13 @@
 class MemoryChunk;
 class SeededNumberDictionary;
 class UnseededNumberDictionary;
-class StringDictionary;
+class NameDictionary;
 template <typename T> class Handle;
 class Heap;
 class HeapObject;
 class IC;
 class InterceptorInfo;
+class JSReceiver;
 class JSArray;
 class JSFunction;
 class JSObject;
@@ -155,6 +156,7 @@
 template <typename Config, class Allocator = FreeStoreAllocationPolicy>
     class SplayTree;
 class String;
+class Name;
 class Struct;
 class Variable;
 class RelocInfo;
diff --git a/src/v8natives.js b/src/v8natives.js
index 356ce88..f295c3a 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -94,7 +94,7 @@
     %SetProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
     %SetNativeFlag(f);
   }
-  prototype.__proto__ = null;
+  %SetPrototype(prototype, null);
   %ToFastProperties(prototype);
 }
 
@@ -258,9 +258,9 @@
 function ObjectHasOwnProperty(V) {
   if (%IsJSProxy(this)) {
     var handler = %GetHandler(this);
-    return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, TO_STRING_INLINE(V));
+    return CallTrap1(handler, "hasOwn", DerivedHasOwnTrap, ToName(V));
   }
-  return %HasLocalProperty(TO_OBJECT_INLINE(this), TO_STRING_INLINE(V));
+  return %HasLocalProperty(TO_OBJECT_INLINE(this), ToName(V));
 }
 
 
@@ -277,7 +277,7 @@
 
 // ECMA-262 - 15.2.4.6
 function ObjectPropertyIsEnumerable(V) {
-  var P = ToString(V);
+  var P = ToName(V);
   if (%IsJSProxy(this)) {
     var desc = GetOwnProperty(this, P);
     return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
@@ -300,7 +300,7 @@
   desc.setGet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
+  DefineOwnProperty(ToObject(receiver), ToName(name), desc, false);
 }
 
 
@@ -309,7 +309,7 @@
   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
     receiver = %GlobalReceiver(global);
   }
-  return %LookupAccessor(ToObject(receiver), ToString(name), GETTER);
+  return %LookupAccessor(ToObject(receiver), ToName(name), GETTER);
 }
 
 
@@ -326,7 +326,7 @@
   desc.setSet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(ToObject(receiver), ToString(name), desc, false);
+  DefineOwnProperty(ToObject(receiver), ToName(name), desc, false);
 }
 
 
@@ -335,7 +335,7 @@
   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
     receiver = %GlobalReceiver(global);
   }
-  return %LookupAccessor(ToObject(receiver), ToString(name), SETTER);
+  return %LookupAccessor(ToObject(receiver), ToName(name), SETTER);
 }
 
 
@@ -346,7 +346,7 @@
   if (%IsJSProxy(obj)) {
     var handler = %GetHandler(obj);
     var names = CallTrap0(handler, "keys", DerivedKeysTrap);
-    return ToStringArray(names, "keys");
+    return ToNameArray(names, "keys", false);
   }
   return %LocalKeys(obj);
 }
@@ -644,7 +644,7 @@
 
 // ES5 section 8.12.1.
 function GetOwnProperty(obj, v) {
-  var p = ToString(v);
+  var p = ToName(v);
   if (%IsJSProxy(obj)) {
     var handler = %GetHandler(obj);
     var descriptor = CallTrap1(handler, "getOwnPropertyDescriptor", void 0, p);
@@ -660,7 +660,7 @@
   // GetOwnProperty returns an array indexed by the constants
   // defined in macros.py.
   // If p is not a property on obj undefined is returned.
-  var props = %GetOwnProperty(ToObject(obj), ToString(v));
+  var props = %GetOwnProperty(ToObject(obj), p);
 
   // A false value here means that access checks failed.
   if (props === false) return void 0;
@@ -702,7 +702,7 @@
 
 // ES5 8.12.9.
 function DefineObjectProperty(obj, p, desc, should_throw) {
-  var current_or_access = %GetOwnProperty(ToObject(obj), ToString(p));
+  var current_or_access = %GetOwnProperty(ToObject(obj), ToName(p));
   // A false value here means that access checks failed.
   if (current_or_access === false) return void 0;
 
@@ -982,7 +982,7 @@
 
 
 // For Harmony proxies
-function ToStringArray(obj, trap) {
+function ToNameArray(obj, trap, includeSymbols) {
   if (!IS_SPEC_OBJECT(obj)) {
     throw MakeTypeError("proxy_non_object_prop_names", [obj, trap]);
   }
@@ -990,7 +990,8 @@
   var array = new $Array(n);
   var names = { __proto__: null };  // TODO(rossberg): use sets once ready.
   for (var index = 0; index < n; index++) {
-    var s = ToString(obj[index]);
+    var s = ToName(obj[index]);
+    if (IS_SYMBOL(s) && !includeSymbols) continue;
     if (%HasLocalProperty(names, s)) {
       throw MakeTypeError("proxy_repeated_prop_name", [obj, trap, s]);
     }
@@ -1010,7 +1011,7 @@
   if (%IsJSProxy(obj)) {
     var handler = %GetHandler(obj);
     var names = CallTrap0(handler, "getOwnPropertyNames", void 0);
-    return ToStringArray(names, "getOwnPropertyNames");
+    return ToNameArray(names, "getOwnPropertyNames", true);
   }
 
   // Find all the indexed properties.
@@ -1045,13 +1046,13 @@
     }
   }
 
-  // Property names are expected to be unique strings,
+  // Property names are expected to be unique names,
   // but interceptors can interfere with that assumption.
   if (interceptorInfo != 0) {
     var propertySet = { __proto__: null };
     var j = 0;
     for (var i = 0; i < propertyNames.length; ++i) {
-      var name = ToString(propertyNames[i]);
+      var name = ToName(propertyNames[i]);
       // We need to check for the exact property value since for intrinsic
       // properties like toString if(propertySet["toString"]) will always
       // succeed.
@@ -1073,8 +1074,7 @@
   if (!IS_SPEC_OBJECT(proto) && proto !== null) {
     throw MakeTypeError("proto_object_or_null", [proto]);
   }
-  var obj = new $Object();
-  obj.__proto__ = proto;
+  var obj = { __proto__: proto };
   if (!IS_UNDEFINED(properties)) ObjectDefineProperties(obj, properties);
   return obj;
 }
@@ -1085,7 +1085,7 @@
   if (!IS_SPEC_OBJECT(obj)) {
     throw MakeTypeError("called_on_non_object", ["Object.defineProperty"]);
   }
-  var name = ToString(p);
+  var name = ToName(p);
   if (%IsJSProxy(obj)) {
     // Clone the attributes object for protection.
     // TODO(rossberg): not spec'ed yet, so not sure if this should involve
diff --git a/src/version.cc b/src/version.cc
index f448e3e..1f1b784 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     17
-#define BUILD_NUMBER      7
+#define BUILD_NUMBER      8
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 0ac0862..97b9075 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -43,7 +43,7 @@
 bool CpuFeatures::initialized_ = false;
 #endif
 uint64_t CpuFeatures::supported_ = CpuFeatures::kDefaultCpuFeatures;
-uint64_t CpuFeatures::found_by_runtime_probing_ = 0;
+uint64_t CpuFeatures::found_by_runtime_probing_only_ = 0;
 
 
 ExternalReference ExternalReference::cpu_features() {
@@ -108,7 +108,7 @@
   __ bind(&cpuid);
   __ movl(rax, Immediate(1));
   supported_ = kDefaultCpuFeatures | (1 << CPUID);
-  { Scope fscope(CPUID);
+  { CpuFeatureScope fscope(&assm, CPUID);
     __ cpuid();
     // Move the result from ecx:edx to rdi.
     __ movl(rdi, rdx);  // Zero-extended to 64 bits.
@@ -143,12 +143,13 @@
 
   typedef uint64_t (*F0)();
   F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
-  supported_ = probe();
-  found_by_runtime_probing_ = supported_;
-  found_by_runtime_probing_ &= ~kDefaultCpuFeatures;
-  uint64_t os_guarantees = OS::CpuFeaturesImpliedByPlatform();
-  supported_ |= os_guarantees;
-  found_by_runtime_probing_ &= ~os_guarantees;
+
+  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;
+
   // SSE2 and CMOV must be available on an X64 CPU.
   ASSERT(IsSupported(CPUID));
   ASSERT(IsSupported(SSE2));
@@ -978,7 +979,7 @@
 
 
 void Assembler::cpuid() {
-  ASSERT(CpuFeatures::IsEnabled(CPUID));
+  ASSERT(IsEnabled(CPUID));
   EnsureSpace ensure_space(this);
   emit(0x0F);
   emit(0xA2);
@@ -2218,7 +2219,7 @@
 
 
 void Assembler::fisttp_s(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   emit_optional_rex_32(adr);
   emit(0xDB);
@@ -2227,7 +2228,7 @@
 
 
 void Assembler::fisttp_d(const Operand& adr) {
-  ASSERT(CpuFeatures::IsEnabled(SSE3));
+  ASSERT(IsEnabled(SSE3));
   EnsureSpace ensure_space(this);
   emit_optional_rex_32(adr);
   emit(0xDD);
@@ -2943,7 +2944,7 @@
 
 void Assembler::roundsd(XMMRegister dst, XMMRegister src,
                         Assembler::RoundingMode mode) {
-  ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+  ASSERT(IsEnabled(SSE4_1));
   EnsureSpace ensure_space(this);
   emit(0x66);
   emit_optional_rex_32(dst, src);
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index 69eeb8e..03e742d 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -442,10 +442,10 @@
 
 
 // CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
+// Supported features must be enabled by a CpuFeatureScope before use.
 // Example:
-//   if (CpuFeatures::IsSupported(SSE3)) {
-//     CpuFeatures::Scope fscope(SSE3);
+//   if (assembler->IsSupported(SSE3)) {
+//     CpuFeatureScope fscope(assembler, SSE3);
 //     // Generate SSE3 floating point code.
 //   } else {
 //     // Generate standard x87 or SSE2 floating point code.
@@ -465,57 +465,19 @@
     if (f == CMOV && !FLAG_enable_cmov) return false;
     if (f == RDTSC && !FLAG_enable_rdtsc) return false;
     if (f == SAHF && !FLAG_enable_sahf) return false;
-    return (supported_ & (V8_UINT64_C(1) << f)) != 0;
+    return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
   }
 
-#ifdef DEBUG
-  // Check whether a feature is currently enabled.
-  static bool IsEnabled(CpuFeature f) {
+  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
     ASSERT(initialized_);
-    Isolate* isolate = Isolate::UncheckedCurrent();
-    if (isolate == NULL) {
-      // When no isolate is available, work as if we're running in
-      // release mode.
-      return IsSupported(f);
-    }
-    uint64_t enabled = isolate->enabled_cpu_features();
-    return (enabled & (V8_UINT64_C(1) << f)) != 0;
+    return (found_by_runtime_probing_only_ &
+            (static_cast<uint64_t>(1) << f)) != 0;
   }
-#endif
 
-  // Enable a specified feature within a scope.
-  class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
-   public:
-    explicit Scope(CpuFeature f) {
-      uint64_t mask = V8_UINT64_C(1) << f;
-      ASSERT(CpuFeatures::IsSupported(f));
-      ASSERT(!Serializer::enabled() ||
-             (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
-      isolate_ = Isolate::UncheckedCurrent();
-      old_enabled_ = 0;
-      if (isolate_ != NULL) {
-        old_enabled_ = isolate_->enabled_cpu_features();
-        isolate_->set_enabled_cpu_features(old_enabled_ | mask);
-      }
-    }
-    ~Scope() {
-      ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
-      if (isolate_ != NULL) {
-        isolate_->set_enabled_cpu_features(old_enabled_);
-      }
-    }
-
-   private:
-    Isolate* isolate_;
-    uint64_t old_enabled_;
-#else
-
-   public:
-    explicit Scope(CpuFeature f) {}
-#endif
-  };
+  static bool IsSafeForSnapshot(CpuFeature f) {
+    return (IsSupported(f) &&
+            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
+  }
 
  private:
   // Safe defaults include SSE2 and CMOV for X64. It is always available, if
@@ -528,7 +490,7 @@
   static bool initialized_;
 #endif
   static uint64_t supported_;
-  static uint64_t found_by_runtime_probing_;
+  static uint64_t found_by_runtime_probing_only_;
 
   friend class ExternalReference;
   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 6aa8903..7ebc103 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -2389,6 +2389,7 @@
     //  -- rsp[0] : return address
     // -----------------------------------
     __ Cmp(rax, masm->isolate()->factory()->length_string());
+    __ j(not_equal, &miss);
     receiver = rdx;
   } else {
     ASSERT(kind() == Code::LOAD_IC);
@@ -2416,6 +2417,7 @@
     //  -- rsp[0] : return address
     // -----------------------------------
     __ Cmp(rax, masm->isolate()->factory()->prototype_string());
+    __ j(not_equal, &miss);
     receiver = rdx;
   } else {
     ASSERT(kind() == Code::LOAD_IC);
@@ -2443,6 +2445,7 @@
     //  -- rsp[0] : return address
     // -----------------------------------
     __ Cmp(rax, masm->isolate()->factory()->length_string());
+    __ j(not_equal, &miss);
     receiver = rdx;
   } else {
     ASSERT(kind() == Code::LOAD_IC);
@@ -2481,6 +2484,7 @@
   Register scratch = rbx;
   if (kind() == Code::KEYED_STORE_IC) {
     __ Cmp(rcx, masm->isolate()->factory()->length_string());
+    __ j(not_equal, &miss);
   }
 
   // Check that the receiver isn't a smi.
@@ -6210,12 +6214,13 @@
 }
 
 
-void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
-                                                        Label* miss,
-                                                        Label* done,
-                                                        Register properties,
-                                                        Handle<String> name,
-                                                        Register r0) {
+void NameDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm,
+                                                      Label* miss,
+                                                      Label* done,
+                                                      Register properties,
+                                                      Handle<Name> name,
+                                                      Register r0) {
+  ASSERT(name->IsUniqueName());
   // If names of slots in range from 1 to kProbes - 1 for the hash value are
   // not equal to the name and kProbes-th slot is not used (its name is the
   // undefined value), it guarantees the hash table doesn't contain the
@@ -6229,10 +6234,10 @@
     __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset));
     __ decl(index);
     __ and_(index,
-            Immediate(name->Hash() + StringDictionary::GetProbeOffset(i)));
+            Immediate(name->Hash() + NameDictionary::GetProbeOffset(i)));
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ lea(index, Operand(index, index, times_2, 0));  // index *= 3.
 
     Register entity_name = r0;
@@ -6246,27 +6251,27 @@
     __ j(equal, done);
 
     // Stop if found the property.
-    __ Cmp(entity_name, Handle<String>(name));
+    __ Cmp(entity_name, Handle<Name>(name));
     __ j(equal, miss);
 
-    Label the_hole;
+    Label good;
     // Check for the hole and skip.
     __ CompareRoot(entity_name, Heap::kTheHoleValueRootIndex);
-    __ j(equal, &the_hole, Label::kNear);
+    __ j(equal, &good, Label::kNear);
 
-    // Check if the entry name is not an internalized string.
+    // Check if the entry name is not a unique name.
     __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
     __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
              Immediate(kIsInternalizedMask));
-    __ j(zero, miss);
+    __ j(not_zero, &good, Label::kNear);
+    __ cmpb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+            Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
+    __ j(not_equal, miss);
 
-    __ bind(&the_hole);
+    __ bind(&good);
   }
 
-  StringDictionaryLookupStub stub(properties,
-                                  r0,
-                                  r0,
-                                  StringDictionaryLookupStub::NEGATIVE_LOOKUP);
+  NameDictionaryLookupStub stub(properties, r0, r0, NEGATIVE_LOOKUP);
   __ Push(Handle<Object>(name));
   __ push(Immediate(name->Hash()));
   __ CallStub(&stub);
@@ -6276,38 +6281,38 @@
 }
 
 
-// Probe the string dictionary in the |elements| register. Jump to the
+// Probe the name dictionary in the |elements| register. Jump to the
 // |done| label if a property with the given name is found leaving the
 // index into the dictionary in |r1|. Jump to the |miss| label
 // otherwise.
-void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
-                                                        Label* miss,
-                                                        Label* done,
-                                                        Register elements,
-                                                        Register name,
-                                                        Register r0,
-                                                        Register r1) {
+void NameDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm,
+                                                      Label* miss,
+                                                      Label* done,
+                                                      Register elements,
+                                                      Register name,
+                                                      Register r0,
+                                                      Register r1) {
   ASSERT(!elements.is(r0));
   ASSERT(!elements.is(r1));
   ASSERT(!name.is(r0));
   ASSERT(!name.is(r1));
 
-  __ AssertString(name);
+  __ AssertName(name);
 
   __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset));
   __ decl(r0);
 
   for (int i = 0; i < kInlinedProbes; i++) {
     // Compute the masked index: (hash + i + i * i) & mask.
-    __ movl(r1, FieldOperand(name, String::kHashFieldOffset));
-    __ shrl(r1, Immediate(String::kHashShift));
+    __ movl(r1, FieldOperand(name, Name::kHashFieldOffset));
+    __ shrl(r1, Immediate(Name::kHashShift));
     if (i > 0) {
-      __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i)));
+      __ addl(r1, Immediate(NameDictionary::GetProbeOffset(i)));
     }
     __ and_(r1, r0);
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ lea(r1, Operand(r1, r1, times_2, 0));  // r1 = r1 * 3
 
     // Check if the key is identical to the name.
@@ -6316,13 +6321,10 @@
     __ j(equal, done);
   }
 
-  StringDictionaryLookupStub stub(elements,
-                                  r0,
-                                  r1,
-                                  POSITIVE_LOOKUP);
+  NameDictionaryLookupStub stub(elements, r0, r1, POSITIVE_LOOKUP);
   __ push(name);
-  __ movl(r0, FieldOperand(name, String::kHashFieldOffset));
-  __ shrl(r0, Immediate(String::kHashShift));
+  __ movl(r0, FieldOperand(name, Name::kHashFieldOffset));
+  __ shrl(r0, Immediate(Name::kHashShift));
   __ push(r0);
   __ CallStub(&stub);
 
@@ -6332,7 +6334,7 @@
 }
 
 
-void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
+void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
   // This stub overrides SometimesSetsUpAFrame() to return false.  That means
   // we cannot call anything that could cause a GC from this stub.
   // Stack frame on entry:
@@ -6340,7 +6342,7 @@
   //  esp[1 * kPointerSize]: key's hash.
   //  esp[2 * kPointerSize]: key.
   // Registers:
-  //  dictionary_: StringDictionary to probe.
+  //  dictionary_: NameDictionary to probe.
   //  result_: used as scratch.
   //  index_: will hold an index of entry if lookup is successful.
   //          might alias with result_.
@@ -6364,12 +6366,12 @@
     // Compute the masked index: (hash + i + i * i) & mask.
     __ movq(scratch, Operand(rsp, 2 * kPointerSize));
     if (i > 0) {
-      __ addl(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
+      __ addl(scratch, Immediate(NameDictionary::GetProbeOffset(i)));
     }
     __ and_(scratch, Operand(rsp, 0));
 
     // Scale the index by multiplying by the entry size.
-    ASSERT(StringDictionary::kEntrySize == 3);
+    ASSERT(NameDictionary::kEntrySize == 3);
     __ lea(index_, Operand(scratch, scratch, times_2, 0));  // index *= 3.
 
     // Having undefined at this place means the name is not contained.
@@ -6386,15 +6388,20 @@
     __ j(equal, &in_dictionary);
 
     if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) {
-      // If we hit a non internalized string key during negative lookup
-      // we have to bailout as this key might be equal to the
+      // If we hit a key that is not a unique name during negative
+      // lookup we have to bailout as this key might be equal to the
       // key we are looking for.
 
-      // Check if the entry name is not an internalized string.
+      // Check if the entry name is not a unique name.
+      Label cont;
       __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
       __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset),
                Immediate(kIsInternalizedMask));
-      __ j(zero, &maybe_in_dictionary);
+      __ j(not_zero, &cont);
+      __ cmpb(FieldOperand(scratch, Map::kInstanceTypeOffset),
+              Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
+      __ j(not_equal, &maybe_in_dictionary);
+      __ bind(&cont);
     }
   }
 
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index 675e95b..5dd4064 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -316,14 +316,14 @@
 };
 
 
-class StringDictionaryLookupStub: public PlatformCodeStub {
+class NameDictionaryLookupStub: public PlatformCodeStub {
  public:
   enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
 
-  StringDictionaryLookupStub(Register dictionary,
-                             Register result,
-                             Register index,
-                             LookupMode mode)
+  NameDictionaryLookupStub(Register dictionary,
+                           Register result,
+                           Register index,
+                           LookupMode mode)
       : dictionary_(dictionary), result_(result), index_(index), mode_(mode) { }
 
   void Generate(MacroAssembler* masm);
@@ -332,7 +332,7 @@
                                      Label* miss,
                                      Label* done,
                                      Register properties,
-                                     Handle<String> name,
+                                     Handle<Name> name,
                                      Register r0);
 
   static void GeneratePositiveLookup(MacroAssembler* masm,
@@ -350,14 +350,14 @@
   static const int kTotalProbes = 20;
 
   static const int kCapacityOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kCapacityIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kCapacityIndex * kPointerSize;
 
   static const int kElementsStartOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
 
-  Major MajorKey() { return StringDictionaryLookup; }
+  Major MajorKey() { return NameDictionaryLookup; }
 
   int MinorKey() {
     return DictionaryBits::encode(dictionary_.code()) |
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index 8e776f9..5aa46f3 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -535,126 +535,6 @@
 }
 
 
-void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
-                                              int frame_index) {
-  Builtins* builtins = isolate_->builtins();
-  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
-  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
-  unsigned height = iterator->Next();
-  unsigned height_in_bytes = height * kPointerSize;
-  if (trace_) {
-    PrintF("  translating construct stub => height=%d\n", height_in_bytes);
-  }
-
-  unsigned fixed_frame_size = 7 * kPointerSize;
-  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
-
-  // Allocate and store the output frame description.
-  FrameDescription* output_frame =
-      new(output_frame_size) FrameDescription(output_frame_size, function);
-  output_frame->SetFrameType(StackFrame::CONSTRUCT);
-
-  // Construct stub can not be topmost or bottommost.
-  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
-  ASSERT(output_[frame_index] == NULL);
-  output_[frame_index] = output_frame;
-
-  // The top address of the frame is computed from the previous
-  // frame's top and this frame's size.
-  intptr_t top_address;
-  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
-  output_frame->SetTop(top_address);
-
-  // Compute the incoming parameter translation.
-  int parameter_count = height;
-  unsigned output_offset = output_frame_size;
-  for (int i = 0; i < parameter_count; ++i) {
-    output_offset -= kPointerSize;
-    DoTranslateCommand(iterator, frame_index, output_offset);
-  }
-
-  // Read caller's PC from the previous frame.
-  output_offset -= kPointerSize;
-  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
-  output_frame->SetFrameSlot(output_offset, callers_pc);
-  if (trace_) {
-    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
-           V8PRIxPTR " ; caller's pc\n",
-           top_address + output_offset, output_offset, callers_pc);
-  }
-
-  // Read caller's FP from the previous frame, and set this frame's FP.
-  output_offset -= kPointerSize;
-  intptr_t value = output_[frame_index - 1]->GetFp();
-  output_frame->SetFrameSlot(output_offset, value);
-  intptr_t fp_value = top_address + output_offset;
-  output_frame->SetFp(fp_value);
-  if (trace_) {
-    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
-           V8PRIxPTR " ; caller's fp\n",
-           fp_value, output_offset, value);
-  }
-
-  // The context can be gotten from the previous frame.
-  output_offset -= kPointerSize;
-  value = output_[frame_index - 1]->GetContext();
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
-           V8PRIxPTR " ; context\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // A marker value is used in place of the function.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
-           V8PRIxPTR " ; function (construct sentinel)\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // The output frame reflects a JSConstructStubGeneric frame.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(construct_stub);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
-           V8PRIxPTR " ; code object\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  // Number of incoming arguments.
-  output_offset -= kPointerSize;
-  value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
-           V8PRIxPTR " ; argc (%d)\n",
-           top_address + output_offset, output_offset, value, height - 1);
-  }
-
-  // The newly allocated object was passed as receiver in the artificial
-  // constructor stub environment created by HEnvironment::CopyForInlining().
-  output_offset -= kPointerSize;
-  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
-  output_frame->SetFrameSlot(output_offset, value);
-  if (trace_) {
-    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
-           V8PRIxPTR " ; allocated receiver\n",
-           top_address + output_offset, output_offset, value);
-  }
-
-  ASSERT(0 == output_offset);
-
-  intptr_t pc = reinterpret_cast<intptr_t>(
-      construct_stub->instruction_start() +
-      isolate_->heap()->construct_stub_deopt_pc_offset()->value());
-  output_frame->SetPc(pc);
-}
-
-
 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
                                    int frame_index) {
   BailoutId node_id = BailoutId(iterator->Next());
diff --git a/src/x64/frames-x64.h b/src/x64/frames-x64.h
index c9092af..53c3459 100644
--- a/src/x64/frames-x64.h
+++ b/src/x64/frames-x64.h
@@ -100,14 +100,30 @@
 
 class ArgumentsAdaptorFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
+
   static const int kFrameSize =
       StandardFrameConstants::kFixedFrameSize + kPointerSize;
 };
 
 
+class ConstructFrameConstants : public AllStatic {
+ public:
+  // FP-relative.
+  static const int kImplicitReceiverOffset = -5 * kPointerSize;
+  static const int kConstructorOffset      = kMinInt;
+  static const int kLengthOffset           = -4 * kPointerSize;
+  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
+
+  static const int kFrameSize =
+      StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
+};
+
+
 class InternalFrameConstants : public AllStatic {
  public:
+  // FP-relative.
   static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
 };
 
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index fa1d948..299fc45 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1626,8 +1626,6 @@
           }
           break;
         }
-        // Fall through.
-      case ObjectLiteral::Property::PROTOTYPE:
         __ push(Operand(rsp, 0));  // Duplicate receiver.
         VisitForStackValue(key);
         VisitForStackValue(value);
@@ -1638,6 +1636,15 @@
           __ Drop(3);
         }
         break;
+      case ObjectLiteral::Property::PROTOTYPE:
+        __ push(Operand(rsp, 0));  // Duplicate receiver.
+        VisitForStackValue(value);
+        if (property->emit_store()) {
+          __ CallRuntime(Runtime::kSetPrototype, 2);
+        } else {
+          __ Drop(2);
+        }
+        break;
       case ObjectLiteral::Property::GETTER:
         accessor_table.lookup(key)->second->getter = value;
         break;
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 15423e4..b185684 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -60,11 +60,11 @@
 
 // Generated code falls through if the receiver is a regular non-global
 // JS object with slow properties and no interceptors.
-static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
-                                                  Register receiver,
-                                                  Register r0,
-                                                  Register r1,
-                                                  Label* miss) {
+static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm,
+                                                Register receiver,
+                                                Register r0,
+                                                Register r1,
+                                                Label* miss) {
   // Register usage:
   //   receiver: holds the receiver on entry and is unchanged.
   //   r0: used to hold receiver instance type.
@@ -127,21 +127,21 @@
   Label done;
 
   // Probe the dictionary.
-  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
-                                                     miss_label,
-                                                     &done,
-                                                     elements,
-                                                     name,
-                                                     r0,
-                                                     r1);
+  NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                   miss_label,
+                                                   &done,
+                                                   elements,
+                                                   name,
+                                                   r0,
+                                                   r1);
 
   // If probing finds an entry in the dictionary, r1 contains the
   // index into the dictionary. Check that the value is a normal
   // property.
   __ bind(&done);
   const int kElementsStartOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
   const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
   __ Test(Operand(elements, r1, times_pointer_size,
                   kDetailsOffset - kHeapObjectTag),
@@ -184,21 +184,21 @@
   Label done;
 
   // Probe the dictionary.
-  StringDictionaryLookupStub::GeneratePositiveLookup(masm,
-                                                     miss_label,
-                                                     &done,
-                                                     elements,
-                                                     name,
-                                                     scratch0,
-                                                     scratch1);
+  NameDictionaryLookupStub::GeneratePositiveLookup(masm,
+                                                   miss_label,
+                                                   &done,
+                                                   elements,
+                                                   name,
+                                                   scratch0,
+                                                   scratch1);
 
   // If probing finds an entry in the dictionary, scratch0 contains the
   // index into the dictionary. Check that the value is a normal
   // property that is not read only.
   __ bind(&done);
   const int kElementsStartOffset =
-      StringDictionary::kHeaderSize +
-      StringDictionary::kElementsStartIndex * kPointerSize;
+      NameDictionary::kHeaderSize +
+      NameDictionary::kElementsStartIndex * kPointerSize;
   const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
   const int kTypeAndReadOnlyMask =
       (PropertyDetails::TypeField::kMask |
@@ -313,31 +313,37 @@
 }
 
 
-// Checks whether a key is an array index string or an internalized string.
-// Falls through if the key is an internalized string.
-static void GenerateKeyStringCheck(MacroAssembler* masm,
-                                   Register key,
-                                   Register map,
-                                   Register hash,
-                                   Label* index_string,
-                                   Label* not_internalized) {
+// Checks whether a key is an array index string or a unique name.
+// Falls through if the key is a unique name.
+static void GenerateKeyNameCheck(MacroAssembler* masm,
+                                 Register key,
+                                 Register map,
+                                 Register hash,
+                                 Label* index_string,
+                                 Label* not_unique) {
   // Register use:
   //   key - holds the key and is unchanged. Assumed to be non-smi.
   // Scratch registers:
   //   map - used to hold the map of the key.
   //   hash - used to hold the hash of the key.
-  __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
-  __ j(above_equal, not_internalized);
+  Label unique;
+  __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
+  __ j(above, not_unique);
+  STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
+  __ j(equal, &unique);
+
   // Is the string an array index, with cached numeric value?
-  __ movl(hash, FieldOperand(key, String::kHashFieldOffset));
-  __ testl(hash, Immediate(String::kContainsCachedArrayIndexMask));
+  __ movl(hash, FieldOperand(key, Name::kHashFieldOffset));
+  __ testl(hash, Immediate(Name::kContainsCachedArrayIndexMask));
   __ j(zero, index_string);  // The value in hash is used at jump target.
 
   // Is the string internalized?
   STATIC_ASSERT(kInternalizedTag != 0);
   __ testb(FieldOperand(map, Map::kInstanceTypeOffset),
            Immediate(kIsInternalizedMask));
-  __ j(zero, not_internalized);
+  __ j(zero, not_unique);
+
+  __ bind(&unique);
 }
 
 
@@ -348,11 +354,11 @@
   //  -- rdx    : receiver
   //  -- rsp[0] : return address
   // -----------------------------------
-  Label slow, check_string, index_smi, index_string, property_array_property;
+  Label slow, check_name, index_smi, index_name, property_array_property;
   Label probe_dictionary, check_number_dictionary;
 
   // Check that the key is a smi.
-  __ JumpIfNotSmi(rax, &check_string);
+  __ JumpIfNotSmi(rax, &check_name);
   __ bind(&index_smi);
   // Now the key is known to be a smi. This place is also jumped to from below
   // where a numeric string is converted to a smi.
@@ -397,8 +403,8 @@
   __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
   GenerateRuntimeGetProperty(masm);
 
-  __ bind(&check_string);
-  GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow);
+  __ bind(&check_name);
+  GenerateKeyNameCheck(masm, rax, rcx, rbx, &index_name, &slow);
 
   GenerateKeyedLoadReceiverCheck(
       masm, rdx, rcx, Map::kHasNamedInterceptor, &slow);
@@ -499,7 +505,7 @@
   __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
   __ ret(0);
 
-  __ bind(&index_string);
+  __ bind(&index_name);
   __ IndexFromHash(rbx, rax);
   __ jmp(&index_smi);
 }
@@ -900,7 +906,7 @@
   // Get the receiver of the function from the stack.
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
 
-  GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
 
   // rax: elements
   // Search the dictionary placing the result in rdi.
@@ -1020,11 +1026,11 @@
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
 
   Label do_call, slow_call, slow_load;
-  Label check_number_dictionary, check_string, lookup_monomorphic_cache;
-  Label index_smi, index_string;
+  Label check_number_dictionary, check_name, lookup_monomorphic_cache;
+  Label index_smi, index_name;
 
   // Check that the key is a smi.
-  __ JumpIfNotSmi(rcx, &check_string);
+  __ JumpIfNotSmi(rcx, &check_name);
 
   __ bind(&index_smi);
   // Now the key is known to be a smi. This place is also jumped to from below
@@ -1072,10 +1078,10 @@
   __ movq(rdi, rax);
   __ jmp(&do_call);
 
-  __ bind(&check_string);
-  GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call);
+  __ bind(&check_name);
+  GenerateKeyNameCheck(masm, rcx, rax, rbx, &index_name, &slow_call);
 
-  // The key is known to be an internalized string.
+  // The key is known to be a unique name.
   // If the receiver is a regular JS object with slow properties then do
   // a quick inline probe of the receiver's dictionary.
   // Otherwise do the monomorphic cache probe.
@@ -1102,14 +1108,14 @@
   __ bind(&slow_call);
   // This branch is taken if:
   // - the receiver requires boxing or access check,
-  // - the key is neither smi nor internalized string,
+  // - the key is neither smi nor a unique name,
   // - the value loaded is not a function,
   // - there is hope that the runtime will create a monomorphic call stub
   //   that will get fetched next time.
   __ IncrementCounter(counters->keyed_call_generic_slow(), 1);
   GenerateMiss(masm, argc);
 
-  __ bind(&index_string);
+  __ bind(&index_name);
   __ IndexFromHash(rbx, rcx);
   // Now jump to the place where smi keys are handled.
   __ jmp(&index_smi);
@@ -1127,10 +1133,10 @@
   // rsp[(argc + 1) * 8]      : argument 0 = receiver
   // -----------------------------------
 
-  // Check if the name is a string.
+  // Check if the name is really a name.
   Label miss;
   __ JumpIfSmi(rcx, &miss);
-  Condition cond = masm->IsObjectStringType(rcx, rax, rax);
+  Condition cond = masm->IsObjectNameType(rcx, rax, rax);
   __ j(NegateCondition(cond), &miss);
   CallICBase::GenerateNormal(masm, argc);
   __ bind(&miss);
@@ -1322,7 +1328,8 @@
 
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(
-      Code::LOAD_IC, MONOMORPHIC, Code::HANDLER_FRAGMENT);
+      Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
+      Code::NORMAL, Code::LOAD_IC);
   Isolate::Current()->stub_cache()->GenerateProbe(
       masm, flags, rax, rcx, rbx, rdx);
 
@@ -1339,7 +1346,7 @@
   // -----------------------------------
   Label miss;
 
-  GenerateStringDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss);
 
   //  rdx: elements
   // Search the dictionary placing the result in rax.
@@ -1466,7 +1473,7 @@
 
   Label miss;
 
-  GenerateStringDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss);
 
   GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9);
   Counters* counters = masm->isolate()->counters();
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index de47f6f..5eb15b7 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -3474,7 +3474,7 @@
   XMMRegister input_reg = ToDoubleRegister(instr->value());
 
   if (CpuFeatures::IsSupported(SSE4_1)) {
-    CpuFeatures::Scope scope(SSE4_1);
+    CpuFeatureScope scope(masm(), SSE4_1);
     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
       // Deoptimize if minus zero.
       __ movq(output_reg, input_reg);
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 5f467e3..5a263ab 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -898,7 +898,7 @@
   }
   // R12 to r15 are callee save on all platforms.
   if (fp_mode == kSaveFPRegs) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(this, SSE2);
     subq(rsp, Immediate(kDoubleSize * XMMRegister::kMaxNumRegisters));
     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
       XMMRegister reg = XMMRegister::from_code(i);
@@ -913,7 +913,7 @@
                                     Register exclusion2,
                                     Register exclusion3) {
   if (fp_mode == kSaveFPRegs) {
-    CpuFeatures::Scope scope(SSE2);
+    CpuFeatureScope scope(this, SSE2);
     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
       XMMRegister reg = XMMRegister::from_code(i);
       movsd(reg, Operand(rsp, i * kDoubleSize));
@@ -3017,6 +3017,19 @@
 }
 
 
+void MacroAssembler::AssertName(Register object) {
+  if (emit_debug_code()) {
+    testb(object, Immediate(kSmiTagMask));
+    Check(not_equal, "Operand is a smi and not a name");
+    push(object);
+    movq(object, FieldOperand(object, HeapObject::kMapOffset));
+    CmpInstanceType(object, LAST_NAME_TYPE);
+    pop(object);
+    Check(below_equal, "Operand is not a name");
+  }
+}
+
+
 void MacroAssembler::AssertRootValue(Register src,
                                      Heap::RootListIndex root_value_index,
                                      const char* message) {
@@ -3041,6 +3054,16 @@
 }
 
 
+Condition MacroAssembler::IsObjectNameType(Register heap_object,
+                                           Register map,
+                                           Register instance_type) {
+  movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
+  movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
+  cmpb(instance_type, Immediate(static_cast<uint8_t>(LAST_NAME_TYPE)));
+  return below_equal;
+}
+
+
 void MacroAssembler::TryGetFunctionPrototype(Register function,
                                              Register result,
                                              Label* miss,
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 6753724..7827feb 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -922,6 +922,15 @@
                                Register map,
                                Register instance_type);
 
+  // Check if the object in register heap_object is a name. Afterwards the
+  // register map contains the object map and the register instance_type
+  // contains the instance_type. The registers map and instance_type can be the
+  // same in which case it contains the instance type afterwards. Either of the
+  // registers map and instance_type can be the same as heap_object.
+  Condition IsObjectNameType(Register heap_object,
+                             Register map,
+                             Register instance_type);
+
   // FCmp compares and pops the two values on top of the FPU stack.
   // The flag results are similar to integer cmp, but requires unsigned
   // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
@@ -965,6 +974,9 @@
   // Abort execution if argument is not a string, enabled via --debug-code.
   void AssertString(Register object);
 
+  // Abort execution if argument is not a name, enabled via --debug-code.
+  void AssertName(Register object);
+
   // Abort execution if argument is not the root value with the given index,
   // enabled via --debug-code.
   void AssertRootValue(Register src,
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index c471569..0e8e74e 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -110,14 +110,14 @@
 // the property. This function may return false negatives, so miss_label
 // must always call a backup property check that is complete.
 // This function is safe to call if the receiver has fast properties.
-// Name must be an internalized string and receiver must be a heap object.
+// Name must be unique and receiver must be a heap object.
 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
                                              Label* miss_label,
                                              Register receiver,
-                                             Handle<String> name,
+                                             Handle<Name> name,
                                              Register r0,
                                              Register r1) {
-  ASSERT(name->IsInternalizedString());
+  ASSERT(name->IsUniqueName());
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(counters->negative_lookups(), 1);
   __ IncrementCounter(counters->negative_lookups_miss(), 1);
@@ -146,12 +146,12 @@
   __ j(not_equal, miss_label);
 
   Label done;
-  StringDictionaryLookupStub::GenerateNegativeLookup(masm,
-                                                     miss_label,
-                                                     &done,
-                                                     properties,
-                                                     name,
-                                                     r1);
+  NameDictionaryLookupStub::GenerateNegativeLookup(masm,
+                                                   miss_label,
+                                                   &done,
+                                                   properties,
+                                                   name,
+                                                   r1);
   __ bind(&done);
   __ DecrementCounter(counters->negative_lookups_miss(), 1);
 }
@@ -193,7 +193,7 @@
   __ JumpIfSmi(receiver, &miss);
 
   // Get the map of the receiver and compute the hash.
-  __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
+  __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset));
   // Use only the low 32 bits of the map pointer.
   __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
   __ xor_(scratch, Immediate(flags));
@@ -205,7 +205,7 @@
   ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch);
 
   // Primary miss: Compute hash for secondary probe.
-  __ movl(scratch, FieldOperand(name, String::kHashFieldOffset));
+  __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset));
   __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
   __ xor_(scratch, Immediate(flags));
   __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
@@ -533,7 +533,7 @@
   void Compile(MacroAssembler* masm,
                Handle<JSObject> object,
                Handle<JSObject> holder,
-               Handle<String> name,
+               Handle<Name> name,
                LookupResult* lookup,
                Register receiver,
                Register scratch1,
@@ -565,7 +565,7 @@
                         Register scratch3,
                         Handle<JSObject> interceptor_holder,
                         LookupResult* lookup,
-                        Handle<String> name,
+                        Handle<Name> name,
                         const CallOptimization& optimization,
                         Label* miss_label) {
     ASSERT(optimization.is_constant_call());
@@ -658,7 +658,7 @@
                       Register scratch1,
                       Register scratch2,
                       Register scratch3,
-                      Handle<String> name,
+                      Handle<Name> name,
                       Handle<JSObject> interceptor_holder,
                       Label* miss_label) {
     Register holder =
@@ -746,7 +746,7 @@
                                       Handle<JSObject> object,
                                       int index,
                                       Handle<Map> transition,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Register receiver_reg,
                                       Register name_reg,
                                       Register scratch1,
@@ -874,7 +874,7 @@
 // property.
 static void GenerateCheckPropertyCell(MacroAssembler* masm,
                                       Handle<GlobalObject> global,
-                                      Handle<String> name,
+                                      Handle<Name> name,
                                       Register scratch,
                                       Label* miss) {
   Handle<JSGlobalPropertyCell> cell =
@@ -892,7 +892,7 @@
 static void GenerateCheckPropertyCells(MacroAssembler* masm,
                                        Handle<JSObject> object,
                                        Handle<JSObject> holder,
-                                       Handle<String> name,
+                                       Handle<Name> name,
                                        Register scratch,
                                        Label* miss) {
   Handle<JSObject> current = object;
@@ -923,7 +923,7 @@
                                        Register holder_reg,
                                        Register scratch1,
                                        Register scratch2,
-                                       Handle<String> name,
+                                       Handle<Name> name,
                                        int save_at_depth,
                                        Label* miss,
                                        PrototypeCheckType check) {
@@ -957,11 +957,12 @@
     if (!current->HasFastProperties() &&
         !current->IsJSGlobalObject() &&
         !current->IsJSGlobalProxy()) {
-      if (!name->IsInternalizedString()) {
-        name = factory()->InternalizeString(name);
+      if (!name->IsUniqueName()) {
+        ASSERT(name->IsString());
+        name = factory()->InternalizeString(Handle<String>::cast(name));
       }
       ASSERT(current->property_dictionary()->FindEntry(*name) ==
-             StringDictionary::kNotFound);
+             NameDictionary::kNotFound);
 
       GenerateDictionaryNegativeLookup(masm(), miss, reg, name,
                                        scratch1, scratch2);
@@ -1047,7 +1048,7 @@
     Handle<JSObject> object,
     Register object_reg,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     Label* success,
     Handle<ExecutableAccessorInfo> callback) {
   Label miss;
@@ -1065,21 +1066,21 @@
 
     // Probe the dictionary.
     Label probe_done;
-    StringDictionaryLookupStub::GeneratePositiveLookup(masm(),
-                                                       &miss,
-                                                       &probe_done,
-                                                       dictionary,
-                                                       this->name(),
-                                                       scratch2(),
-                                                       scratch3());
+    NameDictionaryLookupStub::GeneratePositiveLookup(masm(),
+                                                     &miss,
+                                                     &probe_done,
+                                                     dictionary,
+                                                     this->name(),
+                                                     scratch2(),
+                                                     scratch3());
     __ bind(&probe_done);
 
     // If probing finds an entry in the dictionary, scratch3 contains the
     // index into the dictionary. Check that the value is the callback.
     Register index = scratch3();
     const int kElementsStartOffset =
-        StringDictionary::kHeaderSize +
-        StringDictionary::kElementsStartIndex * kPointerSize;
+        NameDictionary::kHeaderSize +
+        NameDictionary::kElementsStartIndex * kPointerSize;
     const int kValueOffset = kElementsStartOffset + kPointerSize;
     __ movq(scratch2(),
             Operand(dictionary, index, times_pointer_size,
@@ -1097,7 +1098,7 @@
 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
     Handle<JSObject> object,
     Handle<JSObject> last,
-    Handle<String> name,
+    Handle<Name> name,
     Label* success,
     Handle<GlobalObject> global) {
   Label miss;
@@ -1200,7 +1201,7 @@
     Handle<JSObject> object,
     Handle<JSObject> interceptor_holder,
     LookupResult* lookup,
-    Handle<String> name) {
+    Handle<Name> name) {
   ASSERT(interceptor_holder->HasNamedInterceptor());
   ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
 
@@ -1288,7 +1289,7 @@
 }
 
 
-void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
+void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
   if (kind_ == Code::KEYED_CALL_IC) {
     __ Cmp(rcx, name);
     __ j(not_equal, miss);
@@ -1298,7 +1299,7 @@
 
 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
                                                    Handle<JSObject> holder,
-                                                   Handle<String> name,
+                                                   Handle<Name> name,
                                                    Label* miss) {
   ASSERT(holder->IsGlobalObject());
 
@@ -1356,7 +1357,7 @@
 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
                                                 Handle<JSObject> holder,
                                                 PropertyIndex index,
-                                                Handle<String> name) {
+                                                Handle<Name> name) {
   // ----------- S t a t e -------------
   // rcx                 : function name
   // rsp[0]              : return address
@@ -2145,7 +2146,7 @@
 
 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
                                               Handle<JSObject> holder,
-                                              Handle<String> name,
+                                              Handle<Name> name,
                                               CheckType check,
                                               Label* success) {
   // ----------- S t a t e -------------
@@ -2261,13 +2262,13 @@
 Handle<Code> CallStubCompiler::CompileCallConstant(
     Handle<Object> object,
     Handle<JSObject> holder,
-    Handle<String> name,
+    Handle<Name> name,
     CheckType check,
     Handle<JSFunction> function) {
   if (HasCustomCallGenerator(function)) {
     Handle<Code> code = CompileCustomCall(object, holder,
                                           Handle<JSGlobalPropertyCell>::null(),
-                                          function, name);
+                                          function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2285,7 +2286,7 @@
 
 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
                                                       Handle<JSObject> holder,
-                                                      Handle<String> name) {
+                                                      Handle<Name> name) {
   // ----------- S t a t e -------------
   // rcx                 : function name
   // rsp[0]              : return address
@@ -2348,7 +2349,7 @@
     Handle<GlobalObject> holder,
     Handle<JSGlobalPropertyCell> cell,
     Handle<JSFunction> function,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   // rcx                 : function name
   // rsp[0]              : return address
@@ -2360,7 +2361,8 @@
   // -----------------------------------
 
   if (HasCustomCallGenerator(function)) {
-    Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
+    Handle<Code> code = CompileCustomCall(
+        object, holder, cell, function, Handle<String>::cast(name));
     // A null handle means bail out to the regular compiler code below.
     if (!code.is_null()) return code;
   }
@@ -2409,7 +2411,7 @@
 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
                                                   int index,
                                                   Handle<Map> transition,
-                                                  Handle<String> name) {
+                                                  Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
@@ -2440,7 +2442,7 @@
 
 
 Handle<Code> StoreStubCompiler::CompileStoreCallback(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<ExecutableAccessorInfo> callback) {
@@ -2527,7 +2529,7 @@
 
 
 Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
-    Handle<String> name,
+    Handle<Name> name,
     Handle<JSObject> receiver,
     Handle<JSObject> holder,
     Handle<JSFunction> setter) {
@@ -2556,7 +2558,7 @@
 
 Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
     Handle<JSObject> receiver,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
@@ -2603,7 +2605,7 @@
 Handle<Code> StoreStubCompiler::CompileStoreGlobal(
     Handle<GlobalObject> object,
     Handle<JSGlobalPropertyCell> cell,
-    Handle<String> name) {
+    Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
@@ -2651,7 +2653,7 @@
 Handle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object,
                                                        int index,
                                                        Handle<Map> transition,
-                                                       Handle<String> name) {
+                                                       Handle<Name> name) {
   // ----------- S t a t e -------------
   //  -- rax     : value
   //  -- rcx     : key
@@ -2703,7 +2705,7 @@
   Handle<Code> stub =
       KeyedStoreElementStub(is_js_array,
                             elements_kind,
-                            grow_mode_).GetCode(isolate());
+                            store_mode_).GetCode(isolate());
 
   __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
 
@@ -2756,7 +2758,7 @@
 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
     Handle<JSObject> object,
     Handle<JSObject> last,
-    Handle<String> name,
+    Handle<Name> name,
     Handle<GlobalObject> global) {
   Label success;
 
@@ -2769,7 +2771,7 @@
   __ ret(0);
 
   // Return the generated code.
-  return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
+  return GetCode(kind(), Code::NONEXISTENT, name);
 }
 
 
@@ -2787,7 +2789,7 @@
 }
 
 
-void KeyedLoadStubCompiler::GenerateNameCheck(Handle<String> name,
+void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
                                               Register name_reg,
                                               Label* miss) {
   __ Cmp(name_reg, name);
@@ -2836,7 +2838,7 @@
     Handle<JSObject> object,
     Handle<GlobalObject> global,
     Handle<JSGlobalPropertyCell> cell,
-    Handle<String> name,
+    Handle<Name> name,
     bool is_dont_delete) {
   Label success, miss;
   // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
@@ -2869,7 +2871,7 @@
   __ ret(0);
 
   // Return the generated code.
-  return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
+  return GetICCode(kind(), Code::NORMAL, name);
 }
 
 
@@ -2896,14 +2898,14 @@
   GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
 
   // Return the generated code.
-  return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
+  return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
 }
 
 
 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
     MapHandleList* receiver_maps,
     CodeHandleList* handlers,
-    Handle<String> name,
+    Handle<Name> name,
     Code::StubType type,
     IcCheckType check) {
   Label miss;
@@ -2928,7 +2930,7 @@
   // Return the generated code.
   InlineCacheState state =
       receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
-  return GetCode(Code::IC_FRAGMENT, type, name, state);
+  return GetICCode(kind(), type, name, state);
 }
 
 
@@ -3333,7 +3335,7 @@
     MacroAssembler* masm,
     bool is_js_array,
     ElementsKind elements_kind,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : key
@@ -3358,7 +3360,7 @@
   // Check that the key is within bounds.
   if (is_js_array) {
     __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
-    if (grow_mode == ALLOW_JSARRAY_GROWTH) {
+    if (IsGrowStoreMode(store_mode)) {
       __ j(above_equal, &grow);
     } else {
       __ j(above_equal, &miss_force_generic);
@@ -3402,7 +3404,7 @@
   Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
   __ jmp(ic_miss, RelocInfo::CODE_TARGET);
 
-  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (is_js_array && IsGrowStoreMode(store_mode)) {
     // Grow the array by a single element if possible.
     __ bind(&grow);
 
@@ -3475,7 +3477,7 @@
 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
     MacroAssembler* masm,
     bool is_js_array,
-    KeyedAccessGrowMode grow_mode) {
+    KeyedAccessStoreMode store_mode) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : key
@@ -3498,7 +3500,7 @@
   // Check that the key is within bounds.
   if (is_js_array) {
       __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
-      if (grow_mode == ALLOW_JSARRAY_GROWTH) {
+      if (IsGrowStoreMode(store_mode)) {
         __ j(above_equal, &grow);
       } else {
         __ j(above_equal, &miss_force_generic);
@@ -3528,7 +3530,7 @@
   Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
   __ jmp(ic_miss, RelocInfo::CODE_TARGET);
 
-  if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) {
+  if (is_js_array && IsGrowStoreMode(store_mode)) {
     // Grow the array by a single element if possible.
     __ bind(&grow);
 
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index 8ed3f52..ce42b0d 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -64,6 +64,7 @@
     'test-dataflow.cc',
     'test-date.cc',
     'test-debug.cc',
+    'test-declarative-accessors.cc',
     'test-decls.cc',
     'test-deoptimization.cc',
     'test-dictionary.cc',
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index eb0d907..ee9995b 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -59,6 +59,7 @@
         'test-dataflow.cc',
         'test-date.cc',
         'test-debug.cc',
+        'test-declarative-accessors.cc',
         'test-decls.cc',
         'test-deoptimization.cc',
         'test-dictionary.cc',
diff --git a/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 14bcb1a..cfbdb12 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -252,7 +252,7 @@
 
 
   if (CpuFeatures::IsSupported(VFP3)) {
-    CpuFeatures::Scope scope(VFP3);
+    CpuFeatureScope scope(&assm, VFP3);
 
     __ mov(ip, Operand(sp));
     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
@@ -370,7 +370,7 @@
   Assembler assm(isolate, NULL, 0);
 
   if (CpuFeatures::IsSupported(ARMv7)) {
-    CpuFeatures::Scope scope(ARMv7);
+    CpuFeatureScope scope(&assm, ARMv7);
     // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
     __ ubfx(r0, r0, 1, 12);  // 0b00..010101010101 = 0x555
     __ sbfx(r0, r0, 0, 5);   // 0b11..111111110101 = -11
@@ -407,7 +407,7 @@
   Assembler assm(isolate, NULL, 0);
 
   if (CpuFeatures::IsSupported(ARMv7)) {
-    CpuFeatures::Scope scope(ARMv7);
+    CpuFeatureScope scope(&assm, ARMv7);
     __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
     __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
     __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
@@ -451,7 +451,7 @@
   Assembler assm(isolate, NULL, 0);
 
   if (CpuFeatures::IsSupported(VFP3)) {
-    CpuFeatures::Scope scope(VFP3);
+    CpuFeatureScope scope(&assm, VFP3);
 
     Label wrong_exception;
 
@@ -655,7 +655,7 @@
   Assembler assm(isolate, NULL, 0);
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(&assm, VFP2);
 
     __ mov(ip, Operand(sp));
     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
@@ -767,7 +767,7 @@
   Assembler assm(isolate, NULL, 0);
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(&assm, VFP2);
 
     __ mov(ip, Operand(sp));
     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
@@ -883,7 +883,7 @@
   Assembler assm(isolate, NULL, 0);
 
   if (CpuFeatures::IsSupported(VFP2)) {
-    CpuFeatures::Scope scope(VFP2);
+    CpuFeatureScope scope(&assm, VFP2);
 
     __ mov(ip, Operand(sp));
     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
@@ -1070,7 +1070,7 @@
 
 
   if (CpuFeatures::IsSupported(VFP3)) {
-    CpuFeatures::Scope scope(VFP3);
+    CpuFeatureScope scope(&assm, VFP3);
 
     __ stm(db_w, sp, r4.bit() | lr.bit());
 
diff --git a/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index 76eca0d..e92e48f 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -180,7 +180,7 @@
   Assembler assm(isolate, buffer, sizeof buffer);
 
   CHECK(CpuFeatures::IsSupported(SSE2));
-  { CpuFeatures::Scope fscope(SSE2);
+  { CpuFeatureScope fscope(&assm, SSE2);
     __ cvttss2si(eax, Operand(esp, 4));
     __ ret(0);
   }
@@ -216,7 +216,7 @@
   Assembler assm(isolate, buffer, sizeof buffer);
 
   CHECK(CpuFeatures::IsSupported(SSE2));
-  CpuFeatures::Scope fscope(SSE2);
+  CpuFeatureScope fscope(&assm, SSE2);
   __ cvttsd2si(eax, Operand(esp, 4));
   __ ret(0);
 
@@ -269,12 +269,11 @@
   if (!CpuFeatures::IsSupported(SSE2)) return;
 
   v8::HandleScope scope;
-  CHECK(CpuFeatures::IsSupported(SSE2));
-  CpuFeatures::Scope fscope(SSE2);
   v8::internal::byte buffer[256];
   Isolate* isolate = Isolate::Current();
   Assembler assm(isolate, buffer, sizeof buffer);
 
+  CpuFeatureScope fscope(&assm, SSE2);
   __ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
   __ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
   __ addsd(xmm0, xmm1);
@@ -316,11 +315,10 @@
   if (!CpuFeatures::IsSupported(SSE2)) return;
 
   v8::HandleScope scope;
-  CHECK(CpuFeatures::IsSupported(SSE2));
-  CpuFeatures::Scope fscope(SSE2);
   v8::internal::byte buffer[256];
   Isolate* isolate = Isolate::Current();
   Assembler assm(isolate, buffer, sizeof buffer);
+  CpuFeatureScope fscope(&assm, SSE2);
   __ mov(eax, Operand(esp, 4));
   __ cvtsi2sd(xmm0, eax);
   // Copy xmm0 to st(0) using eight bytes of stack.
diff --git a/test/cctest/test-circular-queue.cc b/test/cctest/test-circular-queue.cc
index 2861b1f..12b593f 100644
--- a/test/cctest/test-circular-queue.cc
+++ b/test/cctest/test-circular-queue.cc
@@ -1,4 +1,29 @@
 // Copyright 2010 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.
 //
 // Tests of the circular queue.
 
diff --git a/test/cctest/test-conversions.cc b/test/cctest/test-conversions.cc
index 7c29746..4815b1b 100644
--- a/test/cctest/test-conversions.cc
+++ b/test/cctest/test-conversions.cc
@@ -1,4 +1,29 @@
 // Copyright 2011 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 <stdlib.h>
 
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index d294f19..114a8e7 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -1,4 +1,29 @@
 // Copyright 2010 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.
 //
 // Tests of profiles generator and utilities.
 
@@ -20,7 +45,7 @@
 TEST(StartStop) {
   CpuProfilesCollection profiles;
   ProfileGenerator generator(&profiles);
-  ProfilerEventsProcessor processor(&generator, NULL, 100);
+  ProfilerEventsProcessor processor(&generator);
   processor.Start();
   processor.Stop();
   processor.Join();
@@ -84,7 +109,7 @@
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
-  ProfilerEventsProcessor processor(&generator, NULL, 100);
+  ProfilerEventsProcessor processor(&generator);
   processor.Start();
 
   // Enqueue code creation events.
@@ -145,7 +170,7 @@
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
-  ProfilerEventsProcessor processor(&generator, NULL, 100);
+  ProfilerEventsProcessor processor(&generator);
   processor.Start();
 
   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
@@ -235,7 +260,7 @@
   CpuProfilesCollection profiles;
   profiles.StartProfiling("", 1);
   ProfileGenerator generator(&profiles);
-  ProfilerEventsProcessor processor(&generator, NULL, 100);
+  ProfilerEventsProcessor processor(&generator);
   processor.Start();
 
   processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
diff --git a/test/cctest/test-declarative-accessors.cc b/test/cctest/test-declarative-accessors.cc
new file mode 100644
index 0000000..150059a
--- /dev/null
+++ b/test/cctest/test-declarative-accessors.cc
@@ -0,0 +1,302 @@
+// 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 <stdlib.h>
+
+#include "v8.h"
+
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+class HandleArray : public Malloced {
+ public:
+  static const unsigned kArraySize = 200;
+  explicit HandleArray() {}
+  ~HandleArray() { Reset(v8::Isolate::GetCurrent()); }
+  void Reset(v8::Isolate* isolate) {
+    for (unsigned i = 0; i < kArraySize; i++) {
+      if (handles_[i].IsEmpty()) continue;
+      handles_[i].Dispose(isolate);
+      handles_[i].Clear();
+    }
+  }
+  v8::Persistent<v8::Value> handles_[kArraySize];
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HandleArray);
+};
+
+
+// An aligned character array of size 1024.
+class AlignedArray : public Malloced {
+ public:
+  static const unsigned kArraySize = 1024/sizeof(uint64_t);
+  AlignedArray() { Reset(); }
+
+  void Reset() {
+    for (unsigned i = 0; i < kArraySize; i++) {
+      data_[i] = 0;
+    }
+  }
+
+  template<typename T>
+  T As() { return reinterpret_cast<T>(data_); }
+
+ private:
+  uint64_t data_[kArraySize];
+  DISALLOW_COPY_AND_ASSIGN(AlignedArray);
+};
+
+
+class DescriptorTestHelper {
+ public:
+  DescriptorTestHelper() :
+      isolate_(NULL), array_(new AlignedArray), handle_array_(new HandleArray) {
+    v8::V8::Initialize();
+    isolate_ = v8::Isolate::GetCurrent();
+  }
+  v8::Isolate* isolate_;
+  // Data objects.
+  SmartPointer<AlignedArray> array_;
+  SmartPointer<HandleArray> handle_array_;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DescriptorTestHelper);
+};
+
+
+static v8::Local<v8::ObjectTemplate> CreateConstructor(
+    v8::Handle<v8::Context> context,
+    const char* class_name,
+    int internal_field,
+    const char* descriptor_name = NULL,
+    v8::Handle<v8::DeclaredAccessorDescriptor> descriptor =
+        v8::Handle<v8::DeclaredAccessorDescriptor>()) {
+  v8::Local<v8::FunctionTemplate> constructor = v8::FunctionTemplate::New();
+  v8::Local<v8::ObjectTemplate> obj_template = constructor->InstanceTemplate();
+  // Setup object template.
+  if (descriptor_name != NULL && !descriptor.IsEmpty()) {
+    bool added_accessor =
+        obj_template->SetAccessor(v8_str(descriptor_name), descriptor);
+    CHECK(added_accessor);
+  }
+  obj_template->SetInternalFieldCount((internal_field+1)*2 + 7);
+  context->Global()->Set(v8_str(class_name), constructor->GetFunction());
+  return obj_template;
+}
+
+
+static void VerifyRead(v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
+                       int internal_field,
+                       void* internal_object,
+                       v8::Handle<v8::Value> expected_value) {
+  v8::HandleScope scope;
+  LocalContext local_context;
+  v8::Handle<v8::Context> context = local_context.local();
+  CreateConstructor(context, "Accessible", internal_field, "x", descriptor);
+  // Setup object.
+  CompileRun("var accessible = new Accessible();");
+  v8::Local<v8::Object> obj(
+      v8::Object::Cast(*context->Global()->Get(v8_str("accessible"))));
+  obj->SetAlignedPointerInInternalField(internal_field, internal_object);
+  bool added_accessor;
+  added_accessor = obj->SetAccessor(v8_str("y"), descriptor);
+  CHECK(added_accessor);
+  added_accessor = obj->SetAccessor(v8_str("13"), descriptor);
+  CHECK(added_accessor);
+  // Test access from template getter.
+  v8::Local<v8::Value> value;
+  value = CompileRun("accessible.x;");
+  CHECK_EQ(expected_value, value);
+  value = CompileRun("accessible['x'];");
+  CHECK_EQ(expected_value, value);
+  // Test access from object getter.
+  value = CompileRun("accessible.y;");
+  CHECK_EQ(expected_value, value);
+  value = CompileRun("accessible['y'];");
+  CHECK_EQ(expected_value, value);
+  value = CompileRun("accessible[13];");
+  CHECK_EQ(expected_value, value);
+  value = CompileRun("accessible['13'];");
+  CHECK_EQ(expected_value, value);
+}
+
+
+static v8::Handle<v8::Value> Convert(int32_t value, v8::Isolate* isolate) {
+  return v8::Integer::New(value, isolate);
+}
+
+
+static v8::Handle<v8::Value> Convert(float value, v8::Isolate*) {
+  return v8::Number::New(value);
+}
+
+
+static v8::Handle<v8::Value> Convert(double value, v8::Isolate*) {
+  return v8::Number::New(value);
+}
+
+
+typedef v8::ObjectOperationDescriptor OOD;
+
+template<typename T>
+static void TestPrimitiveValue(
+    T value,
+    v8::DeclaredAccessorDescriptorDataType data_type,
+    DescriptorTestHelper* helper) {
+  v8::HandleScope handle_scope;
+  int index = 17;
+  int internal_field = 6;
+  v8::Handle<v8::DeclaredAccessorDescriptor> descriptor =
+      OOD::NewInternalFieldDereference(helper->isolate_, internal_field)
+      ->NewRawShift(helper->isolate_, static_cast<uint16_t>(index*sizeof(T)))
+      ->NewPrimitiveValue(helper->isolate_, data_type, 0);
+  v8::Handle<v8::Value> expected = Convert(value, helper->isolate_);
+  helper->array_->Reset();
+  helper->array_->As<T*>()[index] = value;
+  VerifyRead(descriptor, internal_field, *helper->array_, expected);
+}
+
+
+TEST(PrimitiveValueRead) {
+  DescriptorTestHelper helper;
+  TestPrimitiveValue<int32_t>(203, v8::kDescriptorInt32Type, &helper);
+  TestPrimitiveValue<float>(23.7f, v8::kDescriptorFloatType, &helper);
+  TestPrimitiveValue<double>(23.7, v8::kDescriptorDoubleType, &helper);
+}
+
+
+template<typename T>
+static void TestBitmaskCompare(T bitmask,
+                               T compare_value,
+                               DescriptorTestHelper* helper) {
+  v8::HandleScope handle_scope;
+  int index = 13;
+  int internal_field = 4;
+  v8::Handle<v8::RawOperationDescriptor> raw_descriptor =
+      OOD::NewInternalFieldDereference(helper->isolate_, internal_field)
+      ->NewRawShift(helper->isolate_, static_cast<uint16_t>(index*sizeof(T)));
+  v8::Handle<v8::DeclaredAccessorDescriptor> descriptor;
+  switch (sizeof(T)) {
+    case 1:
+      descriptor = raw_descriptor->NewBitmaskCompare8(
+            helper->isolate_,
+            static_cast<uint8_t>(bitmask),
+            static_cast<uint8_t>(compare_value));
+      break;
+    case 2:
+      descriptor = raw_descriptor->NewBitmaskCompare16(
+          helper->isolate_,
+          static_cast<uint16_t>(bitmask),
+          static_cast<uint16_t>(compare_value));
+      break;
+    case 4:
+      descriptor = raw_descriptor->NewBitmaskCompare32(
+          helper->isolate_,
+          static_cast<uint32_t>(bitmask),
+          static_cast<uint32_t>(compare_value));
+      break;
+    default:
+      CHECK(false);
+      break;
+  }
+  AlignedArray* array = *helper->array_;
+  array->Reset();
+  VerifyRead(descriptor, internal_field, array, v8::False(helper->isolate_));
+  array->As<T*>()[index] = compare_value;
+  VerifyRead(descriptor, internal_field, array, v8::True(helper->isolate_));
+  helper->array_->As<T*>()[index] = compare_value & bitmask;
+  VerifyRead(descriptor, internal_field, array, v8::True(helper->isolate_));
+}
+
+
+TEST(BitmaskCompareRead) {
+  DescriptorTestHelper helper;
+  TestBitmaskCompare<uint8_t>(0xf3, 0xa8, &helper);
+  TestBitmaskCompare<uint16_t>(0xfefe, 0x7d42, &helper);
+  TestBitmaskCompare<uint32_t>(0xfefeab18, 0x1234fdec, &helper);
+}
+
+
+TEST(PointerCompareRead) {
+  DescriptorTestHelper helper;
+  v8::HandleScope handle_scope;
+  int index = 35;
+  int internal_field = 3;
+  void* ptr = helper.isolate_;
+  v8::Handle<v8::DeclaredAccessorDescriptor> descriptor =
+      OOD::NewInternalFieldDereference(helper.isolate_, internal_field)
+      ->NewRawShift(helper.isolate_, static_cast<uint16_t>(index*sizeof(ptr)))
+      ->NewPointerCompare(helper.isolate_, ptr);
+  AlignedArray* array = *helper.array_;
+  VerifyRead(descriptor, internal_field, array, v8::False(helper.isolate_));
+  array->As<uintptr_t*>()[index] = reinterpret_cast<uintptr_t>(ptr);
+  VerifyRead(descriptor, internal_field, array, v8::True(helper.isolate_));
+}
+
+
+TEST(PointerDereferenceRead) {
+  DescriptorTestHelper helper;
+  v8::HandleScope handle_scope;
+  int first_index = 13;
+  int internal_field = 7;
+  int second_index = 11;
+  int pointed_to_index = 75;
+  uint16_t expected = 0x1425;
+  v8::Handle<v8::DeclaredAccessorDescriptor> descriptor =
+      OOD::NewInternalFieldDereference(helper.isolate_, internal_field)
+      ->NewRawShift(helper.isolate_, first_index*kPointerSize)
+      ->NewRawDereference(helper.isolate_)
+      ->NewRawShift(helper.isolate_,
+                    static_cast<uint16_t>(second_index*sizeof(int16_t)))
+      ->NewPrimitiveValue(helper.isolate_, v8::kDescriptorInt16Type, 0);
+  AlignedArray* array = *helper.array_;
+  array->As<uintptr_t**>()[first_index] =
+      &array->As<uintptr_t*>()[pointed_to_index];
+  VerifyRead(descriptor, internal_field, array, v8::Integer::New(0));
+  second_index += pointed_to_index*sizeof(uintptr_t)/sizeof(uint16_t);
+  array->As<uint16_t*>()[second_index] = expected;
+  VerifyRead(descriptor, internal_field, array, v8::Integer::New(expected));
+}
+
+
+TEST(HandleDereferenceRead) {
+  DescriptorTestHelper helper;
+  v8::HandleScope handle_scope;
+  int index = 13;
+  int internal_field = 0;
+  v8::Handle<v8::DeclaredAccessorDescriptor> descriptor =
+      OOD::NewInternalFieldDereference(helper.isolate_, internal_field)
+      ->NewRawShift(helper.isolate_, index*kPointerSize)
+      ->NewHandleDereference(helper.isolate_);
+  HandleArray* array = *helper.handle_array_;
+  v8::Handle<v8::String> expected = v8_str("whatever");
+  array->handles_[index] = v8::Persistent<v8::Value>::New(helper.isolate_,
+                                                          expected);
+  VerifyRead(descriptor, internal_field, array, expected);
+}
+
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index 8d0a18e..58e18a6 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -424,7 +424,7 @@
   SET_UP();
 
   if (CpuFeatures::IsSupported(VFP3)) {
-    CpuFeatures::Scope scope(VFP3);
+    CpuFeatureScope scope(&assm, VFP3);
     COMPARE(vmov(d0, r2, r3),
             "ec432b10       vmov d0, r2, r3");
     COMPARE(vmov(r2, r3, d0),
@@ -834,7 +834,7 @@
           "e7210002       str r0, [r1, -r2]!");
 
   if (CpuFeatures::IsSupported(ARMv7)) {
-    CpuFeatures::Scope scope(ARMv7);
+    CpuFeatureScope scope(&assm, ARMv7);
     COMPARE(ldrd(r0, r1, MemOperand(r1)),
             "e1c100d0       ldrd r0, [r1, #+0]");
     COMPARE(ldrd(r2, r3, MemOperand(r3, 127)),
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 59d1e04..49e6738 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -108,12 +108,12 @@
   __ nop();
   {
     CHECK(CpuFeatures::IsSupported(CPUID));
-    CpuFeatures::Scope fscope(CPUID);
+    CpuFeatureScope fscope(&assm, CPUID);
     __ cpuid();
   }
   {
     CHECK(CpuFeatures::IsSupported(RDTSC));
-    CpuFeatures::Scope fscope(RDTSC);
+    CpuFeatureScope fscope(&assm, RDTSC);
     __ rdtsc();
   }
   __ movsx_b(edx, ecx);
@@ -369,7 +369,7 @@
   __ nop();
   {
     if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope fscope(SSE2);
+      CpuFeatureScope fscope(&assm, SSE2);
       __ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
       __ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
       __ addsd(xmm1, xmm0);
@@ -391,7 +391,7 @@
   // cmov.
   {
     if (CpuFeatures::IsSupported(CMOV)) {
-      CpuFeatures::Scope use_cmov(CMOV);
+      CpuFeatureScope use_cmov(&assm, CMOV);
       __ cmov(overflow, eax, Operand(eax, 0));
       __ cmov(no_overflow, eax, Operand(eax, 1));
       __ cmov(below, eax, Operand(eax, 2));
@@ -414,7 +414,7 @@
   // andpd, cmpltsd, movaps, psllq, psrlq, por.
   {
     if (CpuFeatures::IsSupported(SSE2)) {
-      CpuFeatures::Scope fscope(SSE2);
+      CpuFeatureScope fscope(&assm, SSE2);
       __ andpd(xmm0, xmm1);
       __ andpd(xmm1, xmm2);
 
@@ -444,7 +444,7 @@
   {
     if (CpuFeatures::IsSupported(SSE2) &&
         CpuFeatures::IsSupported(SSE4_1)) {
-      CpuFeatures::Scope scope(SSE4_1);
+      CpuFeatureScope scope(&assm, SSE4_1);
       __ pextrd(eax, xmm0, 1);
       __ pinsrd(xmm1, eax, 0);
     }
diff --git a/test/cctest/test-diy-fp.cc b/test/cctest/test-diy-fp.cc
index dd6476f..145e317 100644
--- a/test/cctest/test-diy-fp.cc
+++ b/test/cctest/test-diy-fp.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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 <stdlib.h>
 
diff --git a/test/cctest/test-double.cc b/test/cctest/test-double.cc
index 6ef42c6..0e50bdc 100644
--- a/test/cctest/test-double.cc
+++ b/test/cctest/test-double.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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 <stdlib.h>
 
diff --git a/test/cctest/test-fast-dtoa.cc b/test/cctest/test-fast-dtoa.cc
index d311713..46f9757 100644
--- a/test/cctest/test-fast-dtoa.cc
+++ b/test/cctest/test-fast-dtoa.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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 <stdlib.h>
 
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 93ae8fc..8ef970f 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -1,4 +1,29 @@
 // Copyright 2011 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.
 //
 // Tests for heap profiler
 
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index c45c7b6..f94fe53 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -1,4 +1,29 @@
 // Copyright 2012 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 <stdlib.h>
 
@@ -2019,6 +2044,65 @@
 }
 
 
+// Test pretenuring of array literals allocated with HAllocate.
+TEST(OptimizedPretenuringArrayLiterals) {
+  i::FLAG_allow_natives_syntax = true;
+  InitializeVM();
+  if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
+  v8::HandleScope scope;
+
+  AlwaysAllocateScope always_allocate;
+  v8::Local<v8::Value> res = CompileRun(
+      "function f() {"
+      "  var numbers = new Array(1, 2, 3);"
+      "  numbers[0] = 3.14;"
+      "  return numbers;"
+      "};"
+      "f(); f(); f();"
+      "%OptimizeFunctionOnNextCall(f);"
+      "f();");
+  CHECK_EQ(static_cast<int>(3.14),
+           v8::Object::Cast(*res)->Get(v8_str("0"))->Int32Value());
+
+  Handle<JSObject> o =
+      v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+
+  // TODO(hpayer): remove InNewSpace check and test if object was allocated
+  // in old pointer space.
+  CHECK(!HEAP->InOldPointerSpace(*o));
+  CHECK(HEAP->InNewSpace(*o));
+}
+
+
+// Test regular array literals allocation.
+TEST(OptimizedAllocationArrayLiterals) {
+  i::FLAG_allow_natives_syntax = true;
+  InitializeVM();
+  if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
+  if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
+  v8::HandleScope scope;
+
+  AlwaysAllocateScope always_allocate;
+  v8::Local<v8::Value> res = CompileRun(
+      "function f() {"
+      "  var numbers = new Array(1, 2, 3);"
+      "  numbers[0] = 3.14;"
+      "  return numbers;"
+      "};"
+      "f(); f(); f();"
+      "%OptimizeFunctionOnNextCall(f);"
+      "f();");
+  CHECK_EQ(static_cast<int>(3.14),
+           v8::Object::Cast(*res)->Get(v8_str("0"))->Int32Value());
+
+  Handle<JSObject> o =
+      v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
+
+  CHECK(HEAP->InNewSpace(*o));
+}
+
+
 static int CountMapTransitions(Map* map) {
   return map->transitions()->number_of_transitions();
 }
diff --git a/test/cctest/test-lock.cc b/test/cctest/test-lock.cc
index 9039e02..d4387d0 100644
--- a/test/cctest/test-lock.cc
+++ b/test/cctest/test-lock.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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.
 //
 // Tests of the TokenLock class from lock.h
 
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 9883bfa..d75c219 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2009 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.
 //
 // Tests of logging functions from log.h
 
diff --git a/test/cctest/test-platform-linux.cc b/test/cctest/test-platform-linux.cc
index 47b99f0..6bb2902 100644
--- a/test/cctest/test-platform-linux.cc
+++ b/test/cctest/test-platform-linux.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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.
 //
 // Tests of the TokenLock class from lock.h
 
diff --git a/test/cctest/test-platform-macos.cc b/test/cctest/test-platform-macos.cc
index d80fa54..5bc5f97 100644
--- a/test/cctest/test-platform-macos.cc
+++ b/test/cctest/test-platform-macos.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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.
 //
 // Tests of the TokenLock class from lock.h
 
diff --git a/test/cctest/test-platform-nullos.cc b/test/cctest/test-platform-nullos.cc
index c0d6ae5..3afbd90 100644
--- a/test/cctest/test-platform-nullos.cc
+++ b/test/cctest/test-platform-nullos.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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.
 //
 // Tests of the TokenLock class from lock.h
 
diff --git a/test/cctest/test-platform-tls.cc b/test/cctest/test-platform-tls.cc
index 7f33aa2..cc9ffeb 100644
--- a/test/cctest/test-platform-tls.cc
+++ b/test/cctest/test-platform-tls.cc
@@ -1,4 +1,29 @@
 // Copyright 2011 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.
 //
 // Tests of fast TLS support.
 
diff --git a/test/cctest/test-platform-win32.cc b/test/cctest/test-platform-win32.cc
index 668ccdb..1f96ce6 100644
--- a/test/cctest/test-platform-win32.cc
+++ b/test/cctest/test-platform-win32.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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.
 //
 // Tests of the TokenLock class from lock.h
 
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index def829c..5ea0c52 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -1,4 +1,29 @@
 // Copyright 2010 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.
 //
 // Tests of profiles generator and utilities.
 
diff --git a/test/cctest/test-sockets.cc b/test/cctest/test-sockets.cc
index 2f7941c..a9e31fc 100644
--- a/test/cctest/test-sockets.cc
+++ b/test/cctest/test-sockets.cc
@@ -1,4 +1,29 @@
 // Copyright 2009 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 "platform.h"
diff --git a/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index bf56dd1..c232b07 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -1,4 +1,29 @@
 // Copyright 2012 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.
 
 // Check that we can traverse very deep stacks of ConsStrings using
 // StringCharacterStram.  Check that Get(int) works on very deep stacks
diff --git a/test/cctest/test-strtod.cc b/test/cctest/test-strtod.cc
index da6b07b..952f57c 100644
--- a/test/cctest/test-strtod.cc
+++ b/test/cctest/test-strtod.cc
@@ -1,4 +1,29 @@
 // Copyright 2006-2008 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 <stdlib.h>
 
diff --git a/test/cctest/test-unbound-queue.cc b/test/cctest/test-unbound-queue.cc
index 3dc87ae..6d02fff 100644
--- a/test/cctest/test-unbound-queue.cc
+++ b/test/cctest/test-unbound-queue.cc
@@ -1,4 +1,29 @@
 // Copyright 2010 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.
 //
 // Tests of the unbound queue.
 
diff --git a/test/mjsunit/elements-kind.js b/test/mjsunit/elements-kind.js
index 92bdac7..d952556 100644
--- a/test/mjsunit/elements-kind.js
+++ b/test/mjsunit/elements-kind.js
@@ -28,6 +28,10 @@
 // Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
 // Flags: --notrack_allocation_sites
 
+// Limit the number of stress runs to reduce polymorphism it defeats some of
+// they assumptions made about how elements transitions work because transition
+// stubs end up going generic.  Flags: --stress-runs=2
+
 // Test element kind of objects.
 // Since --smi-only-arrays affects builtins, its default setting at compile
 // time sticks if built with snapshot.  If --smi-only-arrays is deactivated
diff --git a/test/mjsunit/harmony/symbols.js b/test/mjsunit/harmony/symbols.js
index baec514..13a1010 100644
--- a/test/mjsunit/harmony/symbols.js
+++ b/test/mjsunit/harmony/symbols.js
@@ -114,14 +114,115 @@
 TestSet()
 
 
-function TestMap() {
-  var map = new Map;
+function TestCollections() {
+  var set = new Set
+  var map = new Map
+  var weakmap = new WeakMap
   for (var i in symbols) {
+    set.add(symbols[i])
     map.set(symbols[i], i)
+    weakmap.set(symbols[i], i)
+  }
+  assertEquals(symbols.length, set.size)
+  assertEquals(symbols.length, map.size)
+  for (var i in symbols) {
+    assertTrue(set.has(symbols[i]))
+    assertTrue(map.has(symbols[i]))
+    assertTrue(weakmap.has(symbols[i]))
+    assertEquals(i, map.get(symbols[i]))
+    assertEquals(i, weakmap.get(symbols[i]))
   }
   for (var i in symbols) {
-    assertTrue(map.has(symbols[i]))
-    assertEquals(i, map.get(symbols[i]))
+    assertTrue(set.delete(symbols[i]))
+    assertTrue(map.delete(symbols[i]))
+    assertTrue(weakmap.delete(symbols[i]))
+  }
+  assertEquals(0, set.size)
+  assertEquals(0, map.size)
+}
+TestCollections()
+
+
+
+function TestKeySet(obj) {
+  // Set the even symbols via assignment.
+  for (var i = 0; i < symbols.length; i += 2) {
+    obj[symbols[i]] = i
   }
 }
-TestMap()
+
+
+function TestKeyDefine(obj) {
+  // Set the odd symbols via defineProperty (as non-enumerable).
+  for (var i = 1; i < symbols.length; i += 2) {
+    Object.defineProperty(obj, symbols[i], {value: i, configurable: true})
+  }
+}
+
+
+function TestKeyGet(obj) {
+  var obj2 = Object.create(obj)
+  for (var i in symbols) {
+    assertEquals(i|0, obj[symbols[i]])
+    assertEquals(i|0, obj2[symbols[i]])
+  }
+}
+
+
+function TestKeyHas() {
+  for (var i in symbols) {
+    assertTrue(symbols[i] in obj)
+    assertTrue(Object.hasOwnProperty.call(obj, symbols[i]))
+  }
+}
+
+
+function TestKeyEnum(obj) {
+  for (var name in obj) {
+    assertFalse(%_IsSymbol(name))
+  }
+}
+
+
+function TestKeyKeys(obj) {
+  assertEquals(0, Object.keys(obj).length)
+  assertTrue(symbols.length <= Object.getOwnPropertyNames(obj).length)
+}
+
+
+function TestKeyDescriptor(obj) {
+  for (var i in symbols) {
+    var desc = Object.getOwnPropertyDescriptor(obj, symbols[i]);
+    assertEquals(i|0, desc.value)
+    assertTrue(desc.configurable)
+    assertEquals(i % 2 == 0, desc.writable)
+    assertEquals(i % 2 == 0, desc.enumerable)
+    assertEquals(i % 2 == 0,
+        Object.prototype.propertyIsEnumerable.call(obj, symbols[i]))
+  }
+}
+
+
+function TestKeyDelete(obj) {
+  for (var i in symbols) {
+    delete obj[symbols[i]]
+  }
+  for (var i in symbols) {
+    assertEquals(undefined, Object.getOwnPropertyDescriptor(obj, symbols[i]))
+  }
+}
+
+
+var objs = [{}, [], Object.create(null), Object(1), new Map, function(){}]
+
+for (var i in objs) {
+  var obj = objs[i]
+  TestKeySet(obj)
+  TestKeyDefine(obj)
+  TestKeyGet(obj)
+  TestKeyHas(obj)
+  TestKeyEnum(obj)
+  TestKeyKeys(obj)
+  TestKeyDescriptor(obj)
+  TestKeyDelete(obj)
+}
diff --git a/test/mjsunit/math-floor-of-div-nosudiv.js b/test/mjsunit/math-floor-of-div-nosudiv.js
index 5baed2d..3ce966c 100644
--- a/test/mjsunit/math-floor-of-div-nosudiv.js
+++ b/test/mjsunit/math-floor-of-div-nosudiv.js
@@ -184,7 +184,7 @@
 %OptimizeFunctionOnNextCall(test_div);
 test_div();
 
-// Test for ia32/x64 flooring correctness.
+// Test for flooring correctness.
 var values2 = [1, 3, 10, 99, 100, 101, 0x7fffffff];
 function test_div2() {
   for (var i = 0; i < values2.length; i++) {
diff --git a/test/mjsunit/math-floor-of-div.js b/test/mjsunit/math-floor-of-div.js
index c7ef289..d528b85 100644
--- a/test/mjsunit/math-floor-of-div.js
+++ b/test/mjsunit/math-floor-of-div.js
@@ -184,7 +184,7 @@
 %OptimizeFunctionOnNextCall(test_div);
 test_div();
 
-// Test for ia32/x64 flooring correctness.
+// Test for flooring correctness.
 var values2 = [1, 3, 10, 99, 100, 101, 0x7fffffff];
 function test_div2() {
   for (var i = 0; i < values2.length; i++) {
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 26c8359..1c3602c 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -81,10 +81,6 @@
 tools/tickprocessor: PASS, SKIP if ($arch == android_arm || $arch == android_ia32)
 
 ##############################################################################
-# This test is the same as math-floor-of-div for non ARM architectures.
-math-floor-of-div-nosudiv: PASS, SKIP if ($arch != arm && $arch != android_arm)
-
-##############################################################################
 # Long running test that reproduces memory leak and should be run manually.
 regress/regress-2073: SKIP
 
diff --git a/test/mjsunit/parallel-optimize-disabled.js b/test/mjsunit/parallel-optimize-disabled.js
new file mode 100644
index 0000000..2487964
--- /dev/null
+++ b/test/mjsunit/parallel-optimize-disabled.js
@@ -0,0 +1,46 @@
+// 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.
+
+// Flags: --nodead-code-elimination --parallel-recompilation
+// Flags: --allow-natives-syntax
+
+function g() {  // g() cannot be optimized.
+  const x = 1;
+  x++;
+}
+
+function f(x) {
+  g();
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(g, "parallel");
+%OptimizeFunctionOnNextCall(f);
+f(0);  // g() is disabled for optimization on inlining attempt.
+g();  // Attempt to optimize g() should not run into any assertion.
+
diff --git a/test/mjsunit/regress/regress-2565.js b/test/mjsunit/regress/regress-2565.js
new file mode 100644
index 0000000..a77806a
--- /dev/null
+++ b/test/mjsunit/regress/regress-2565.js
@@ -0,0 +1,32 @@
+// 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.
+
+Object.freeze(Object.prototype);
+var p = {};
+var o = Object.create(p);
+assertSame(p, o.__proto__);
+assertSame(p, Object.getPrototypeOf(o));
diff --git a/test/mjsunit/regress/regress-2566.js b/test/mjsunit/regress/regress-2566.js
new file mode 100644
index 0000000..582bad9
--- /dev/null
+++ b/test/mjsunit/regress/regress-2566.js
@@ -0,0 +1,34 @@
+// 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.
+
+function setProp(obj, prop, val) {
+  obj[prop] = val;
+}
+var obj = [];
+setProp(obj, 'length', 1);
+setProp(obj, 0, 5);
+assertEquals(1, obj.length);
diff --git a/test/mjsunit/regress/regress-2568.js b/test/mjsunit/regress/regress-2568.js
new file mode 100644
index 0000000..7918e14
--- /dev/null
+++ b/test/mjsunit/regress/regress-2568.js
@@ -0,0 +1,46 @@
+// 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.
+
+function pluck1(a, key) {
+    return a.map(function(item) { return item[key]; });
+};
+assertArrayEquals([2, 2], pluck1([[0, 0], [0, 0]], 'length'));
+assertArrayEquals([1, 3], pluck1([[1, 2], [3, 4]], '0'));
+
+function pluck2(a, key) {
+    return a.map(function(item) { return item[key]; });
+};
+assertArrayEquals([2, 2], pluck2(["ab", "cd"], 'length'));
+assertArrayEquals(["a", "c"], pluck2(["ab", "cd"], '0'));
+
+function pluck3(a, key) {
+    return a.map(function(item) { return item[key]; });
+};
+f = function() { 1 };
+f.prototype = g = function() { 2 };
+assertArrayEquals([g, g], pluck3([f, f], 'prototype'));
+assertArrayEquals([undefined, undefined], pluck3([f, f], '0'));
diff --git a/test/mjsunit/regress/regress-2570.js b/test/mjsunit/regress/regress-2570.js
new file mode 100644
index 0000000..f9060e8
--- /dev/null
+++ b/test/mjsunit/regress/regress-2570.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.
+
+var o = ["\u56e7",   // Switch JSON stringifier to two-byte mode.
+         "\u00e6"];  // Latin-1 character.
+
+assertEquals('["\u56e7","\u00e6"]', JSON.stringify(o));
diff --git a/tools/grokdump.py b/tools/grokdump.py
index 603453a..2fbe3b4 100755
--- a/tools/grokdump.py
+++ b/tools/grokdump.py
@@ -1145,8 +1145,104 @@
 
 
 class Map(HeapObject):
+  def Decode(self, offset, size, value):
+    return (value >> offset) & ((1 << size) - 1)
+
+  # Instance Sizes
+  def InstanceSizesOffset(self):
+    return self.heap.PointerSize()
+
+  def InstanceSizeOffset(self):
+    return self.InstanceSizesOffset()
+
+  def InObjectProperties(self):
+    return self.InstanceSizeOffset() + 1
+
+  def PreAllocatedPropertyFields(self):
+    return self.InObjectProperties() + 1
+
+  def VisitorId(self):
+    return self.PreAllocatedPropertyFields() + 1
+
+  # Instance Attributes
+  def InstanceAttributesOffset(self):
+    return self.InstanceSizesOffset() + self.heap.IntSize()
+
   def InstanceTypeOffset(self):
-    return self.heap.PointerSize() + self.heap.IntSize()
+    return self.InstanceAttributesOffset()
+
+  def UnusedPropertyFieldsOffset(self):
+    return self.InstanceTypeOffset() + 1
+
+  def BitFieldOffset(self):
+    return self.UnusedPropertyFieldsOffset() + 1
+
+  def BitField2Offset(self):
+    return self.BitFieldOffset() + 1
+
+  # Other fields
+  def PrototypeOffset(self):
+    return self.InstanceAttributesOffset() + self.heap.IntSize()
+
+  def ConstructorOffset(self):
+    return self.PrototypeOffset() + self.heap.PointerSize()
+
+  def TransitionsOrBackPointerOffset(self):
+    return self.ConstructorOffset() + self.heap.PointerSize()
+
+  def DescriptorsOffset(self):
+    return self.TransitionsOrBackPointerOffset() + self.heap.PointerSize()
+
+  def CodeCacheOffset(self):
+    return self.DescriptorsOffset() + self.heap.PointerSize()
+
+  def DependentCodeOffset(self):
+    return self.CodeCacheOffset() + self.heap.PointerSize()
+
+  def BitField3Offset(self):
+    return self.DependentCodeOffset() + self.heap.PointerSize()
+
+  def ReadByte(self, offset):
+    return self.heap.reader.ReadU8(self.address + offset)
+
+  def Print(self, p):
+    p.Print("Map(%08x)" % (self.address))
+    p.Print("- size: %d, inobject: %d, preallocated: %d, visitor: %d" % (
+        self.ReadByte(self.InstanceSizeOffset()),
+        self.ReadByte(self.InObjectProperties()),
+        self.ReadByte(self.PreAllocatedPropertyFields()),
+        self.VisitorId()))
+
+    bitfield = self.ReadByte(self.BitFieldOffset())
+    bitfield2 = self.ReadByte(self.BitField2Offset())
+    p.Print("- %s, unused: %d, bf: %d, bf2: %d" % (
+        INSTANCE_TYPES[self.ReadByte(self.InstanceTypeOffset())],
+        self.ReadByte(self.UnusedPropertyFieldsOffset()),
+        bitfield, bitfield2))
+
+    p.Print("- kind: %s" % (self.Decode(3, 5, bitfield2)))
+
+    bitfield3 = self.ObjectField(self.BitField3Offset())
+    p.Print(
+        "- EnumLength: %d NumberOfOwnDescriptors: %d OwnsDescriptors: %s" % (
+            self.Decode(0, 11, bitfield3),
+            self.Decode(11, 11, bitfield3),
+            self.Decode(25, 1, bitfield3)))
+    p.Print("- IsShared: %s" % (self.Decode(22, 1, bitfield3)))
+    p.Print("- FunctionWithPrototype: %s" % (self.Decode(23, 1, bitfield3)))
+    p.Print("- DictionaryMap: %s" % (self.Decode(24, 1, bitfield3)))
+
+    descriptors = self.ObjectField(self.DescriptorsOffset())
+    if descriptors.__class__ == FixedArray:
+      DescriptorArray(descriptors).Print(p)
+    else:
+      p.Print("Descriptors: %s" % (descriptors))
+
+    transitions = self.ObjectField(self.TransitionsOrBackPointerOffset())
+    if transitions.__class__ == FixedArray:
+      TransitionArray(transitions).Print(p)
+    else:
+      p.Print("TransitionsOrBackPointer: %s" % (transitions))
 
   def __init__(self, heap, map, address):
     HeapObject.__init__(self, heap, map, address)
@@ -1280,6 +1376,12 @@
   def ElementsOffset(self):
     return self.heap.PointerSize() * 2
 
+  def MemberOffset(self, i):
+    return self.ElementsOffset() + self.heap.PointerSize() * i
+
+  def Get(self, i):
+    return self.ObjectField(self.MemberOffset(i))
+
   def __init__(self, heap, map, address):
     HeapObject.__init__(self, heap, map, address)
     self.length = self.SmiField(self.LengthOffset())
@@ -1305,6 +1407,111 @@
     return "FixedArray(%08x, length=%d)" % (self.address, self.length)
 
 
+class DescriptorArray(object):
+  def __init__(self, array):
+    self.array = array
+
+  def Length(self):
+    return self.array.Get(0)
+
+  def Decode(self, offset, size, value):
+    return (value >> offset) & ((1 << size) - 1)
+
+  TYPES = [
+      "normal",
+      "field",
+      "function",
+      "callbacks"
+  ]
+
+  def Type(self, value):
+    return DescriptorArray.TYPES[self.Decode(0, 3, value)]
+
+  def Attributes(self, value):
+    attributes = self.Decode(3, 3, value)
+    result = []
+    if (attributes & 0): result += ["ReadOnly"]
+    if (attributes & 1): result += ["DontEnum"]
+    if (attributes & 2): result += ["DontDelete"]
+    return "[" + (",".join(result)) + "]"
+
+  def Deleted(self, value):
+    return self.Decode(6, 1, value) == 1
+
+  def Storage(self, value):
+    return self.Decode(7, 11, value)
+
+  def Pointer(self, value):
+    return self.Decode(18, 11, value)
+
+  def Details(self, di, value):
+    return (
+        di,
+        self.Type(value),
+        self.Attributes(value),
+        self.Storage(value),
+        self.Pointer(value)
+    )
+
+
+  def Print(self, p):
+    length = self.Length()
+    array = self.array
+
+    p.Print("Descriptors(%08x, length=%d)" % (array.address, length))
+    p.Print("[et] %s" % (array.Get(1)))
+
+    for di in xrange(length):
+      i = 2 + di * 3
+      p.Print("0x%x" % (array.address + array.MemberOffset(i)))
+      p.Print("[%i] name:    %s" % (di, array.Get(i + 0)))
+      p.Print("[%i] details: %s %s enum %i pointer %i" % \
+              self.Details(di, array.Get(i + 1)))
+      p.Print("[%i] value:   %s" % (di, array.Get(i + 2)))
+
+    end = self.array.length // 3
+    if length != end:
+      p.Print("[%i-%i] slack descriptors" % (length, end))
+
+
+class TransitionArray(object):
+  def __init__(self, array):
+    self.array = array
+
+  def IsSimpleTransition(self):
+    return self.array.length <= 2
+
+  def Length(self):
+    # SimpleTransition cases
+    if self.IsSimpleTransition():
+      return self.array.length - 1
+    return (self.array.length - 3) // 2
+
+  def Print(self, p):
+    length = self.Length()
+    array = self.array
+
+    p.Print("Transitions(%08x, length=%d)" % (array.address, length))
+    p.Print("[backpointer] %s" % (array.Get(0)))
+    if self.IsSimpleTransition():
+      if length == 1:
+        p.Print("[simple target] %s" % (array.Get(1)))
+      return
+
+    elements = array.Get(1)
+    if elements is not None:
+      p.Print("[elements   ] %s" % (elements))
+
+    prototype = array.Get(2)
+    if prototype is not None:
+      p.Print("[prototype  ] %s" % (prototype))
+
+    for di in xrange(length):
+      i = 3 + di * 2
+      p.Print("[%i] symbol: %s" % (di, array.Get(i + 0)))
+      p.Print("[%i] target: %s" % (di, array.Get(i + 1)))
+
+
 class JSFunction(HeapObject):
   def CodeEntryOffset(self):
     return 3 * self.heap.PointerSize()
@@ -1720,6 +1927,30 @@
     else:
       print "Address cannot be interpreted as object!"
 
+  def do_do_desc(self, address):
+    """
+      Print a descriptor array in a readable format.
+    """
+    start = int(address, 16)
+    if ((start & 1) == 1): start = start + 1
+    DescriptorArray(FixedArray(self.heap, None, start)).Print(Printer())
+
+  def do_do_map(self, address):
+    """
+      Print a descriptor array in a readable format.
+    """
+    start = int(address, 16)
+    if ((start & 1) == 1): start = start - 1
+    Map(self.heap, None, start).Print(Printer())
+
+  def do_do_trans(self, address):
+    """
+      Print a transition array in a readable format.
+    """
+    start = int(address, 16)
+    if ((start & 1) == 1): start = start - 1
+    TransitionArray(FixedArray(self.heap, None, start)).Print(Printer())
+
   def do_dp(self, address):
     """
      Interpret memory at the given address as being on a V8 heap page
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 6ebf3f6..2d6eaf9 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -1005,7 +1005,7 @@
           'include_dirs++': [
             '<(shim_headers_path)',
           ],
-          'direct_dependent_settings': {
+          'all_dependent_settings': {
             'include_dirs+++': [
               '<(shim_headers_path)',
             ],