Update V8 to r4924 as required by WebKit r61871

Change-Id: Ic819dad0c1c9e035b8ffd306c96656ba87c5e85a
diff --git a/ChangeLog b/ChangeLog
index 941c314..95c1133 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2010-06-23: Version 2.2.19
+
+        Fix bug that causes the build to break when profillingsupport=off
+        (issue 738).
+
+        Added expose-externalize-string flag for testing extensions.
+
+        Resolve linker issues with using V8 as a DLL causing a number of
+        problems with unresolved symbols.
+
+        Fix build failure for cctests when ENABLE_DEBUGGER_SUPPORT is not
+        defined.
+
+        Performance improvements on all platforms.
+
+
+2010-06-16: Version 2.2.18
+
+        Added API functions to retrieve information on indexed properties
+        managed by the embedding layer.  Fixes bug 737.
+
+        Make ES5 Object.defineProperty support array elements.  Fixes bug 619.
+
+        Add heap profiling to the API.
+
+        Remove old named property query from the API.
+
+        Incremental performance improvements.
+
+
 2010-06-14: Version 2.2.17
 
         Improved debugger support for stepping out of functions.
diff --git a/V8_MERGE_REVISION b/V8_MERGE_REVISION
index 1a569dd..428ddac 100644
--- a/V8_MERGE_REVISION
+++ b/V8_MERGE_REVISION
@@ -1,4 +1,4 @@
 We use a V8 revision that has been used for a Chromium release.
 
-http://src.chromium.org/svn/releases/6.0.436.0/DEPS
-http://v8.googlecode.com/svn/trunk@4851
+http://src.chromium.org/svn/releases/6.0.450.0/DEPS
+http://v8.googlecode.com/svn/trunk@4924
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index bb41072..3e1952c 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -184,6 +184,147 @@
 };
 
 
+class HeapGraphNode;
+
+
+/**
+ * HeapSnapshotEdge represents a directed connection between heap
+ * graph nodes: from retaners to retained nodes.
+ */
+class V8EXPORT HeapGraphEdge {
+ public:
+  enum Type {
+    CONTEXT_VARIABLE = 0,  // A variable from a function context.
+    ELEMENT = 1,           // An element of an array.
+    PROPERTY = 2,          // A named object property.
+    INTERNAL = 3           // A link that can't be accessed from JS,
+                           // thus, its name isn't a real property name.
+  };
+
+  /** Returns edge type (see HeapGraphEdge::Type). */
+  Type GetType() const;
+
+  /**
+   * Returns edge name. This can be a variable name, an element index, or
+   * a property name.
+   */
+  Handle<Value> GetName() const;
+
+  /** Returns origin node. */
+  const HeapGraphNode* GetFromNode() const;
+
+  /** Returns destination node. */
+  const HeapGraphNode* GetToNode() const;
+};
+
+
+class V8EXPORT HeapGraphPath {
+ public:
+  /** Returns the number of edges in the path. */
+  int GetEdgesCount() const;
+
+  /** Returns an edge from the path. */
+  const HeapGraphEdge* GetEdge(int index) const;
+
+  /** Returns origin node. */
+  const HeapGraphNode* GetFromNode() const;
+
+  /** Returns destination node. */
+  const HeapGraphNode* GetToNode() const;
+};
+
+
+/**
+ * HeapGraphNode represents a node in a heap graph.
+ */
+class V8EXPORT HeapGraphNode {
+ public:
+  enum Type {
+    INTERNAL = 0,   // Internal node, a virtual one, for housekeeping.
+    ARRAY = 1,      // An array of elements.
+    STRING = 2,     // A string.
+    OBJECT = 3,     // A JS object (except for arrays and strings).
+    CODE = 4,       // Compiled code.
+    CLOSURE = 5     // Function closure.
+  };
+
+  /** Returns node type (see HeapGraphNode::Type). */
+  Type GetType() const;
+
+  /**
+   * Returns node name. Depending on node's type this can be the name
+   * of the constructor (for objects), the name of the function (for
+   * closures), string value, or an empty string (for compiled code).
+   */
+  Handle<String> GetName() const;
+
+  /** Returns node's own size, in bytes. */
+  int GetSelfSize() const;
+
+  /** Returns node's network (self + reachable nodes) size, in bytes. */
+  int GetTotalSize() const;
+
+  /**
+   * Returns node's private size, in bytes. That is, the size of memory
+   * that will be reclaimed having this node collected.
+   */
+  int GetPrivateSize() const;
+
+  /** Returns child nodes count of the node. */
+  int GetChildrenCount() const;
+
+  /** Retrieves a child by index. */
+  const HeapGraphEdge* GetChild(int index) const;
+
+  /** Returns retainer nodes count of the node. */
+  int GetRetainersCount() const;
+
+  /** Returns a retainer by index. */
+  const HeapGraphEdge* GetRetainer(int index) const;
+
+  /** Returns the number of simple retaining paths from the root to the node. */
+  int GetRetainingPathsCount() const;
+
+  /** Returns a retaining path by index. */
+  const HeapGraphPath* GetRetainingPath(int index) const;
+};
+
+
+/**
+ * HeapSnapshots record the state of the JS heap at some moment.
+ */
+class V8EXPORT HeapSnapshot {
+ public:
+  /** Returns heap snapshot UID (assigned by the profiler.) */
+  unsigned GetUid() const;
+
+  /** Returns heap snapshot title. */
+  Handle<String> GetTitle() const;
+
+  /** Returns the root node of the heap graph. */
+  const HeapGraphNode* GetHead() const;
+};
+
+
+/**
+ * Interface for controlling heap profiling.
+ */
+class V8EXPORT HeapProfiler {
+ public:
+  /** Returns the number of snapshots taken. */
+  static int GetSnapshotsCount();
+
+  /** Returns a snapshot by index. */
+  static const HeapSnapshot* GetSnapshot(int index);
+
+  /** Returns a profile by uid. */
+  static const HeapSnapshot* FindSnapshot(unsigned uid);
+
+  /** Takes a heap snapshot and returns it. Title may be an empty string. */
+  static const HeapSnapshot* TakeSnapshot(Handle<String> title);
+};
+
+
 }  // namespace v8
 
 
diff --git a/include/v8.h b/include/v8.h
index 24b4cbe..b625618 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1570,6 +1570,9 @@
    *       the backing store is preserved while V8 has a reference.
    */
   void SetIndexedPropertiesToPixelData(uint8_t* data, int length);
+  bool HasIndexedPropertiesInPixelData();
+  uint8_t* GetIndexedPropertiesPixelData();
+  int GetIndexedPropertiesPixelDataLength();
 
   /**
    * Set the backing store of the indexed properties to be managed by the
@@ -1581,6 +1584,10 @@
   void SetIndexedPropertiesToExternalArrayData(void* data,
                                                ExternalArrayType array_type,
                                                int number_of_elements);
+  bool HasIndexedPropertiesInExternalArrayData();
+  void* GetIndexedPropertiesExternalArrayData();
+  ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
+  int GetIndexedPropertiesExternalArrayDataLength();
 
   static Local<Object> New();
   static inline Object* Cast(Value* obj);
@@ -1761,20 +1768,11 @@
 
 /**
  * Returns a non-empty handle if the interceptor intercepts the request.
- * The result is either boolean (true if property exists and false
- * otherwise) or an integer encoding property attributes.
+ * The result is an integer encoding property attributes (like v8::None,
+ * v8::DontEnum, etc.)
  */
-#ifdef USE_NEW_QUERY_CALLBACKS
 typedef Handle<Integer> (*NamedPropertyQuery)(Local<String> property,
                                               const AccessorInfo& info);
-#else
-typedef Handle<Boolean> (*NamedPropertyQuery)(Local<String> property,
-                                              const AccessorInfo& info);
-#endif
-
-typedef Handle<Value> (*NamedPropertyQueryImpl)(Local<String> property,
-                                                const AccessorInfo& info);
-
 
 
 /**
@@ -2026,16 +2024,7 @@
                                        NamedPropertyQuery query,
                                        NamedPropertyDeleter remover,
                                        NamedPropertyEnumerator enumerator,
-                                       Handle<Value> data) {
-    NamedPropertyQueryImpl casted =
-        reinterpret_cast<NamedPropertyQueryImpl>(query);
-    SetNamedInstancePropertyHandlerImpl(getter,
-                                        setter,
-                                        casted,
-                                        remover,
-                                        enumerator,
-                                        data);
-  }
+                                       Handle<Value> data);
   void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,
                                          IndexedPropertySetter setter,
                                          IndexedPropertyQuery query,
@@ -2047,13 +2036,6 @@
 
   friend class Context;
   friend class ObjectTemplate;
- private:
-  void SetNamedInstancePropertyHandlerImpl(NamedPropertyGetter getter,
-                                           NamedPropertySetter setter,
-                                           NamedPropertyQueryImpl query,
-                                           NamedPropertyDeleter remover,
-                                           NamedPropertyEnumerator enumerator,
-                                           Handle<Value> data);
 };
 
 
@@ -2111,7 +2093,8 @@
    *
    * \param getter The callback to invoke when getting a property.
    * \param setter The callback to invoke when setting a property.
-   * \param query The callback to invoke to check if an object has a property.
+   * \param query The callback to invoke to check if a property is present,
+   *   and if present, get its attributes.
    * \param deleter The callback to invoke when deleting a property.
    * \param enumerator The callback to invoke to enumerate all the named
    *   properties of an object.
@@ -2123,26 +2106,7 @@
                                NamedPropertyQuery query = 0,
                                NamedPropertyDeleter deleter = 0,
                                NamedPropertyEnumerator enumerator = 0,
-                               Handle<Value> data = Handle<Value>()) {
-    NamedPropertyQueryImpl casted =
-        reinterpret_cast<NamedPropertyQueryImpl>(query);
-    SetNamedPropertyHandlerImpl(getter,
-                                setter,
-                                casted,
-                                deleter,
-                                enumerator,
-                                data);
-  }
-
- private:
-  void SetNamedPropertyHandlerImpl(NamedPropertyGetter getter,
-                                   NamedPropertySetter setter,
-                                   NamedPropertyQueryImpl query,
-                                   NamedPropertyDeleter deleter,
-                                   NamedPropertyEnumerator enumerator,
-                                   Handle<Value> data);
-
- public:
+                               Handle<Value> data = Handle<Value>());
 
   /**
    * Sets an indexed property handler on the object template.
@@ -3247,11 +3211,9 @@
   static const int kFullStringRepresentationMask = 0x07;
   static const int kExternalTwoByteRepresentationTag = 0x02;
 
-  // These constants are compiler dependent so their values must be
-  // defined within the implementation.
-  V8EXPORT static int kJSObjectType;
-  V8EXPORT static int kFirstNonstringType;
-  V8EXPORT static int kProxyType;
+  static const int kJSObjectType = 0x9f;
+  static const int kFirstNonstringType = 0x80;
+  static const int kProxyType = 0x85;
 
   static inline bool HasHeapObjectTag(internal::Object* value) {
     return ((reinterpret_cast<intptr_t>(value) & kHeapObjectTagMask) ==
diff --git a/src/api.cc b/src/api.cc
index cb5e96d..464ca54 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -34,6 +34,7 @@
 #include "debug.h"
 #include "execution.h"
 #include "global-handles.h"
+#include "heap-profiler.h"
 #include "messages.h"
 #include "platform.h"
 #include "profile-generator-inl.h"
@@ -105,9 +106,6 @@
 
 
 static FatalErrorCallback exception_behavior = NULL;
-int i::Internals::kJSObjectType = JS_OBJECT_TYPE;
-int i::Internals::kFirstNonstringType = FIRST_NONSTRING_TYPE;
-int i::Internals::kProxyType = PROXY_TYPE;
 
 static void DefaultFatalErrorHandler(const char* location,
                                      const char* message) {
@@ -853,10 +851,10 @@
 }
 
 
-void FunctionTemplate::SetNamedInstancePropertyHandlerImpl(
+void FunctionTemplate::SetNamedInstancePropertyHandler(
       NamedPropertyGetter getter,
       NamedPropertySetter setter,
-      NamedPropertyQueryImpl query,
+      NamedPropertyQuery query,
       NamedPropertyDeleter remover,
       NamedPropertyEnumerator enumerator,
       Handle<Value> data) {
@@ -987,13 +985,12 @@
 }
 
 
-void ObjectTemplate::SetNamedPropertyHandlerImpl(NamedPropertyGetter getter,
-                                                 NamedPropertySetter setter,
-                                                 NamedPropertyQueryImpl query,
-                                                 NamedPropertyDeleter remover,
-                                                 NamedPropertyEnumerator
-                                                    enumerator,
-                                                 Handle<Value> data) {
+void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
+                                             NamedPropertySetter setter,
+                                             NamedPropertyQuery query,
+                                             NamedPropertyDeleter remover,
+                                             NamedPropertyEnumerator enumerator,
+                                             Handle<Value> data) {
   if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
   ENTER_V8;
   HandleScope scope;
@@ -1001,12 +998,12 @@
   i::FunctionTemplateInfo* constructor =
       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
   i::Handle<i::FunctionTemplateInfo> cons(constructor);
-  Utils::ToLocal(cons)->SetNamedInstancePropertyHandlerImpl(getter,
-                                                            setter,
-                                                            query,
-                                                            remover,
-                                                            enumerator,
-                                                            data);
+  Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
+                                                        setter,
+                                                        query,
+                                                        remover,
+                                                        enumerator,
+                                                        data);
 }
 
 
@@ -2613,6 +2610,35 @@
 }
 
 
+bool v8::Object::HasIndexedPropertiesInPixelData() {
+  ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  return self->HasPixelElements();
+}
+
+
+uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
+  ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  if (self->HasPixelElements()) {
+    return i::PixelArray::cast(self->elements())->external_pointer();
+  } else {
+    return NULL;
+  }
+}
+
+
+int v8::Object::GetIndexedPropertiesPixelDataLength() {
+  ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  if (self->HasPixelElements()) {
+    return i::PixelArray::cast(self->elements())->length();
+  } else {
+    return -1;
+  }
+}
+
+
 void v8::Object::SetIndexedPropertiesToExternalArrayData(
     void* data,
     ExternalArrayType array_type,
@@ -2637,6 +2663,60 @@
 }
 
 
+bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
+  ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  return self->HasExternalArrayElements();
+}
+
+
+void* v8::Object::GetIndexedPropertiesExternalArrayData() {
+  ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  if (self->HasExternalArrayElements()) {
+    return i::ExternalArray::cast(self->elements())->external_pointer();
+  } else {
+    return NULL;
+  }
+}
+
+
+ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
+  ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
+             return static_cast<ExternalArrayType>(-1));
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  switch (self->elements()->map()->instance_type()) {
+    case i::EXTERNAL_BYTE_ARRAY_TYPE:
+      return kExternalByteArray;
+    case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
+      return kExternalUnsignedByteArray;
+    case i::EXTERNAL_SHORT_ARRAY_TYPE:
+      return kExternalShortArray;
+    case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
+      return kExternalUnsignedShortArray;
+    case i::EXTERNAL_INT_ARRAY_TYPE:
+      return kExternalIntArray;
+    case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
+      return kExternalUnsignedIntArray;
+    case i::EXTERNAL_FLOAT_ARRAY_TYPE:
+      return kExternalFloatArray;
+    default:
+      return static_cast<ExternalArrayType>(-1);
+  }
+}
+
+
+int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
+  ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
+  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
+  if (self->HasExternalArrayElements()) {
+    return i::ExternalArray::cast(self->elements())->length();
+  } else {
+    return -1;
+  }
+}
+
+
 Local<v8::Object> Function::NewInstance() const {
   return NewInstance(0, NULL);
 }
@@ -4363,6 +4443,197 @@
           *Utils::OpenHandle(*title)));
 }
 
+
+HeapGraphEdge::Type HeapGraphEdge::GetType() const {
+  IsDeadCheck("v8::HeapGraphEdge::GetType");
+  return static_cast<HeapGraphEdge::Type>(
+      reinterpret_cast<const i::HeapGraphEdge*>(this)->type());
+}
+
+
+Handle<Value> HeapGraphEdge::GetName() const {
+  IsDeadCheck("v8::HeapGraphEdge::GetName");
+  const i::HeapGraphEdge* edge =
+      reinterpret_cast<const i::HeapGraphEdge*>(this);
+  switch (edge->type()) {
+    case i::HeapGraphEdge::CONTEXT_VARIABLE:
+    case i::HeapGraphEdge::INTERNAL:
+    case i::HeapGraphEdge::PROPERTY:
+      return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+          edge->name())));
+    case i::HeapGraphEdge::ELEMENT:
+      return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
+          edge->index())));
+    default: UNREACHABLE();
+  }
+  return ImplementationUtilities::Undefined();
+}
+
+
+const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
+  IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
+  const i::HeapEntry* from =
+      reinterpret_cast<const i::HeapGraphEdge*>(this)->from();
+  return reinterpret_cast<const HeapGraphNode*>(from);
+}
+
+
+const HeapGraphNode* HeapGraphEdge::GetToNode() const {
+  IsDeadCheck("v8::HeapGraphEdge::GetToNode");
+  const i::HeapEntry* to =
+      reinterpret_cast<const i::HeapGraphEdge*>(this)->to();
+  return reinterpret_cast<const HeapGraphNode*>(to);
+}
+
+
+int HeapGraphPath::GetEdgesCount() const {
+  return reinterpret_cast<const i::HeapGraphPath*>(this)->path()->length();
+}
+
+
+const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
+  return reinterpret_cast<const HeapGraphEdge*>(
+      reinterpret_cast<const i::HeapGraphPath*>(this)->path()->at(index));
+}
+
+
+const HeapGraphNode* HeapGraphPath::GetFromNode() const {
+  return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
+}
+
+
+const HeapGraphNode* HeapGraphPath::GetToNode() const {
+  const int count = GetEdgesCount();
+  return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
+}
+
+
+HeapGraphNode::Type HeapGraphNode::GetType() const {
+  IsDeadCheck("v8::HeapGraphNode::GetType");
+  return static_cast<HeapGraphNode::Type>(
+      reinterpret_cast<const i::HeapEntry*>(this)->type());
+}
+
+
+Handle<String> HeapGraphNode::GetName() const {
+  IsDeadCheck("v8::HeapGraphNode::GetName");
+  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+      reinterpret_cast<const i::HeapEntry*>(this)->name())));
+}
+
+
+int HeapGraphNode::GetSelfSize() const {
+  IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
+  return reinterpret_cast<const i::HeapEntry*>(this)->self_size();
+}
+
+
+int HeapGraphNode::GetTotalSize() const {
+  IsDeadCheck("v8::HeapSnapshot::GetHead");
+  return const_cast<i::HeapEntry*>(
+      reinterpret_cast<const i::HeapEntry*>(this))->TotalSize();
+}
+
+
+int HeapGraphNode::GetPrivateSize() const {
+  IsDeadCheck("v8::HeapSnapshot::GetPrivateSize");
+  return const_cast<i::HeapEntry*>(
+      reinterpret_cast<const i::HeapEntry*>(this))->NonSharedTotalSize();
+}
+
+
+int HeapGraphNode::GetChildrenCount() const {
+  IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
+  return reinterpret_cast<const i::HeapEntry*>(this)->children()->length();
+}
+
+
+const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
+  IsDeadCheck("v8::HeapSnapshot::GetChild");
+  return reinterpret_cast<const HeapGraphEdge*>(
+      reinterpret_cast<const i::HeapEntry*>(this)->children()->at(index));
+}
+
+
+int HeapGraphNode::GetRetainersCount() const {
+  IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
+  return reinterpret_cast<const i::HeapEntry*>(this)->retainers()->length();
+}
+
+
+const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
+  IsDeadCheck("v8::HeapSnapshot::GetRetainer");
+  return reinterpret_cast<const HeapGraphEdge*>(
+      reinterpret_cast<const i::HeapEntry*>(this)->retainers()->at(index));
+}
+
+
+int HeapGraphNode::GetRetainingPathsCount() const {
+  IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
+  return const_cast<i::HeapEntry*>(
+      reinterpret_cast<const i::HeapEntry*>(
+          this))->GetRetainingPaths()->length();
+}
+
+
+const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
+  IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
+  return reinterpret_cast<const HeapGraphPath*>(
+      const_cast<i::HeapEntry*>(
+          reinterpret_cast<const i::HeapEntry*>(
+              this))->GetRetainingPaths()->at(index));
+}
+
+
+unsigned HeapSnapshot::GetUid() const {
+  IsDeadCheck("v8::HeapSnapshot::GetUid");
+  return reinterpret_cast<const i::HeapSnapshot*>(this)->uid();
+}
+
+
+Handle<String> HeapSnapshot::GetTitle() const {
+  IsDeadCheck("v8::HeapSnapshot::GetTitle");
+  const i::HeapSnapshot* snapshot =
+      reinterpret_cast<const i::HeapSnapshot*>(this);
+  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+      snapshot->title())));
+}
+
+
+const HeapGraphNode* HeapSnapshot::GetHead() const {
+  IsDeadCheck("v8::HeapSnapshot::GetHead");
+  const i::HeapSnapshot* snapshot =
+      reinterpret_cast<const i::HeapSnapshot*>(this);
+  return reinterpret_cast<const HeapGraphNode*>(snapshot->const_root());
+}
+
+
+int HeapProfiler::GetSnapshotsCount() {
+  IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
+  return i::HeapProfiler::GetSnapshotsCount();
+}
+
+
+const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
+  IsDeadCheck("v8::HeapProfiler::GetSnapshot");
+  return reinterpret_cast<const HeapSnapshot*>(
+      i::HeapProfiler::GetSnapshot(index));
+}
+
+
+const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
+  IsDeadCheck("v8::HeapProfiler::FindSnapshot");
+  return reinterpret_cast<const HeapSnapshot*>(
+      i::HeapProfiler::FindSnapshot(uid));
+}
+
+
+const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title) {
+  IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
+  return reinterpret_cast<const HeapSnapshot*>(
+      i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title)));
+}
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 8ca9126..114ec23 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -45,11 +45,6 @@
 namespace v8 {
 namespace internal {
 
-Condition NegateCondition(Condition cc) {
-  ASSERT(cc != al);
-  return static_cast<Condition>(cc ^ ne);
-}
-
 
 void RelocInfo::apply(intptr_t delta) {
   if (RelocInfo::IsInternalReference(rmode_)) {
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 025f28e..f8d98db 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -279,6 +279,25 @@
     15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
 const Instr kBlxRegPattern =
     B24 | B21 | 15 * B16 | 15 * B12 | 15 * B8 | 3 * B4;
+const Instr kMovMvnMask = 0x6d * B21 | 0xf * B16;
+const Instr kMovMvnPattern = 0xd * B21;
+const Instr kMovMvnFlip = B22;
+const Instr kMovLeaveCCMask = 0xdff * B16;
+const Instr kMovLeaveCCPattern = 0x1a0 * B16;
+const Instr kMovwMask = 0xff * B20;
+const Instr kMovwPattern = 0x30 * B20;
+const Instr kMovwLeaveCCFlip = 0x5 * B21;
+const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
+const Instr kCmpCmnPattern = 0x15 * B20;
+const Instr kCmpCmnFlip = B21;
+const Instr kALUMask = 0x6f * B21;
+const Instr kAddPattern = 0x4 * B21;
+const Instr kSubPattern = 0x2 * B21;
+const Instr kBicPattern = 0xe * B21;
+const Instr kAndPattern = 0x0 * B21;
+const Instr kAddSubFlip = 0x6 * B21;
+const Instr kAndBicFlip = 0xe * B21;
+
 // A mask for the Rd register for push, pop, ldr, str instructions.
 const Instr kRdMask = 0x0000f000;
 static const int kRdShift = 12;
@@ -375,6 +394,12 @@
 }
 
 
+void Assembler::CodeTargetAlign() {
+  // Preferred alignment of jump targets on some ARM chips.
+  Align(8);
+}
+
+
 bool Assembler::IsNop(Instr instr, int type) {
   // Check for mov rx, rx.
   ASSERT(0 <= type && type <= 14);  // mov pc, pc is not a nop.
@@ -626,7 +651,16 @@
 }
 
 
+static Instr EncodeMovwImmediate(uint32_t immediate) {
+  ASSERT(immediate < 0x10000);
+  return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
+}
+
+
 // Low-level code emission routines depending on the addressing mode.
+// If this returns true then you have to use the rotate_imm and immed_8
+// that it returns, because it may have already changed the instruction
+// to match them!
 static bool fits_shifter(uint32_t imm32,
                          uint32_t* rotate_imm,
                          uint32_t* immed_8,
@@ -640,11 +674,43 @@
       return true;
     }
   }
-  // If the opcode is mov or mvn and if ~imm32 fits, change the opcode.
-  if (instr != NULL && (*instr & 0xd*B21) == 0xd*B21) {
-    if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
-      *instr ^= 0x2*B21;
-      return true;
+  // If the opcode is one with a complementary version and the complementary
+  // immediate fits, change the opcode.
+  if (instr != NULL) {
+    if ((*instr & kMovMvnMask) == kMovMvnPattern) {
+      if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
+        *instr ^= kMovMvnFlip;
+        return true;
+      } else if ((*instr & kMovLeaveCCMask) == kMovLeaveCCPattern) {
+        if (CpuFeatures::IsSupported(ARMv7)) {
+          if (imm32 < 0x10000) {
+            *instr ^= kMovwLeaveCCFlip;
+            *instr |= EncodeMovwImmediate(imm32);
+            *rotate_imm = *immed_8 = 0;  // Not used for movw.
+            return true;
+          }
+        }
+      }
+    } else if ((*instr & kCmpCmnMask) == kCmpCmnPattern) {
+      if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
+        *instr ^= kCmpCmnFlip;
+        return true;
+      }
+    } else {
+      Instr alu_insn = (*instr & kALUMask);
+      if (alu_insn == kAddPattern ||
+          alu_insn == kSubPattern) {
+        if (fits_shifter(-imm32, rotate_imm, immed_8, NULL)) {
+          *instr ^= kAddSubFlip;
+          return true;
+        }
+      } else if (alu_insn == kAndPattern ||
+                 alu_insn == kBicPattern) {
+        if (fits_shifter(~imm32, rotate_imm, immed_8, NULL)) {
+          *instr ^= kAndBicFlip;
+          return true;
+        }
+      }
     }
   }
   return false;
@@ -655,7 +721,7 @@
 // if they can be encoded in the ARM's 12 bits of immediate-offset instruction
 // space.  There is no guarantee that the relocated location can be similarly
 // encoded.
-static bool MustUseIp(RelocInfo::Mode rmode) {
+static bool MustUseConstantPool(RelocInfo::Mode rmode) {
   if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
 #ifdef DEBUG
     if (!Serializer::enabled()) {
@@ -670,6 +736,14 @@
 }
 
 
+bool Operand::is_single_instruction() const {
+  if (rm_.is_valid()) return true;
+  if (MustUseConstantPool(rmode_)) return false;
+  uint32_t dummy1, dummy2;
+  return fits_shifter(imm32_, &dummy1, &dummy2, NULL);
+}
+
+
 void Assembler::addrmod1(Instr instr,
                          Register rn,
                          Register rd,
@@ -680,19 +754,34 @@
     // Immediate.
     uint32_t rotate_imm;
     uint32_t immed_8;
-    if (MustUseIp(x.rmode_) ||
+    if (MustUseConstantPool(x.rmode_) ||
         !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) {
       // The immediate operand cannot be encoded as a shifter operand, so load
       // it first to register ip and change the original instruction to use ip.
       // However, if the original instruction is a 'mov rd, x' (not setting the
       // condition code), then replace it with a 'ldr rd, [pc]'.
-      RecordRelocInfo(x.rmode_, x.imm32_);
       CHECK(!rn.is(ip));  // rn should never be ip, or will be trashed
       Condition cond = static_cast<Condition>(instr & CondMask);
       if ((instr & ~CondMask) == 13*B21) {  // mov, S not set
-        ldr(rd, MemOperand(pc, 0), cond);
+        if (MustUseConstantPool(x.rmode_) ||
+            !CpuFeatures::IsSupported(ARMv7)) {
+          RecordRelocInfo(x.rmode_, x.imm32_);
+          ldr(rd, MemOperand(pc, 0), cond);
+        } else {
+          // Will probably use movw, will certainly not use constant pool.
+          mov(rd, Operand(x.imm32_ & 0xffff), LeaveCC, cond);
+          movt(rd, static_cast<uint32_t>(x.imm32_) >> 16, cond);
+        }
       } else {
-        ldr(ip, MemOperand(pc, 0), cond);
+        // If this is not a mov or mvn instruction we may still be able to avoid
+        // a constant pool entry by using mvn or movw.
+        if (!MustUseConstantPool(x.rmode_) &&
+            (instr & kMovMvnMask) != kMovMvnPattern) {
+          mov(ip, x, LeaveCC, cond);
+        } else {
+          RecordRelocInfo(x.rmode_, x.imm32_);
+          ldr(ip, MemOperand(pc, 0), cond);
+        }
         addrmod1(instr, rn, rd, Operand(ip));
       }
       return;
@@ -1003,6 +1092,17 @@
 }
 
 
+void Assembler::movw(Register reg, uint32_t immediate, Condition cond) {
+  ASSERT(immediate < 0x10000);
+  mov(reg, Operand(immediate), LeaveCC, cond);
+}
+
+
+void Assembler::movt(Register reg, uint32_t immediate, Condition cond) {
+  emit(cond | 0x34*B20 | reg.code()*B12 | EncodeMovwImmediate(immediate));
+}
+
+
 void Assembler::bic(Register dst, Register src1, const Operand& src2,
                     SBit s, Condition cond) {
   addrmod1(cond | 14*B21 | s, src1, dst, src2);
@@ -1183,7 +1283,7 @@
     // Immediate.
     uint32_t rotate_imm;
     uint32_t immed_8;
-    if (MustUseIp(src.rmode_) ||
+    if (MustUseConstantPool(src.rmode_) ||
         !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
       // Immediate operand cannot be encoded, load it first to register ip.
       RecordRelocInfo(src.rmode_, src.imm32_);
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index e5d42f9..869227a 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -279,7 +279,10 @@
 
 
 // Returns the equivalent of !cc.
-INLINE(Condition NegateCondition(Condition cc));
+inline Condition NegateCondition(Condition cc) {
+  ASSERT(cc != al);
+  return static_cast<Condition>(cc ^ ne);
+}
 
 
 // Corresponds to transposing the operands of a comparison.
@@ -418,6 +421,15 @@
   // Return true if this is a register operand.
   INLINE(bool is_reg() const);
 
+  // Return true of this operand fits in one instruction so that no
+  // 2-instruction solution with a load into the ip register is necessary.
+  bool is_single_instruction() const;
+
+  inline int32_t immediate() const {
+    ASSERT(!rm_.is_valid());
+    return imm32_;
+  }
+
   Register rm() const { return rm_; }
 
  private:
@@ -532,6 +544,27 @@
 extern const Instr kBlxRegMask;
 extern const Instr kBlxRegPattern;
 
+extern const Instr kMovMvnMask;
+extern const Instr kMovMvnPattern;
+extern const Instr kMovMvnFlip;
+
+extern const Instr kMovLeaveCCMask;
+extern const Instr kMovLeaveCCPattern;
+extern const Instr kMovwMask;
+extern const Instr kMovwPattern;
+extern const Instr kMovwLeaveCCFlip;
+
+extern const Instr kCmpCmnMask;
+extern const Instr kCmpCmnPattern;
+extern const Instr kCmpCmnFlip;
+
+extern const Instr kALUMask;
+extern const Instr kAddPattern;
+extern const Instr kSubPattern;
+extern const Instr kAndPattern;
+extern const Instr kBicPattern;
+extern const Instr kAddSubFlip;
+extern const Instr kAndBicFlip;
 
 class Assembler : public Malloced {
  public:
@@ -670,6 +703,8 @@
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2 (>= 4).
   void Align(int m);
+  // Aligns code to something that's optimal for a jump target for the platform.
+  void CodeTargetAlign();
 
   // Branch instructions
   void b(int branch_offset, Condition cond = al);
@@ -748,6 +783,13 @@
     mov(dst, Operand(src), s, cond);
   }
 
+  // ARMv7 instructions for loading a 32 bit immediate in two instructions.
+  // This may actually emit a different mov instruction, but on an ARMv7 it
+  // is guaranteed to only emit one instruction.
+  void movw(Register reg, uint32_t immediate, Condition cond = al);
+  // The constant for movt should be in the range 0-0xffff.
+  void movt(Register reg, uint32_t immediate, Condition cond = al);
+
   void bic(Register dst, Register src1, const Operand& src2,
            SBit s = LeaveCC, Condition cond = al);
 
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index ddbb977..b1f29ba 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -136,7 +136,8 @@
   __ str(scratch1, FieldMemOperand(result, JSArray::kElementsOffset));
 
   // Clear the heap tag on the elements array.
-  __ and_(scratch1, scratch1, Operand(~kHeapObjectTagMask));
+  ASSERT(kSmiTag == 0);
+  __ sub(scratch1, scratch1, Operand(kHeapObjectTag));
 
   // Initialize the FixedArray and fill it with holes. FixedArray length is
   // stored as a smi.
@@ -240,9 +241,10 @@
          FieldMemOperand(result, JSArray::kElementsOffset));
 
   // Clear the heap tag on the elements array.
-  __ and_(elements_array_storage,
-          elements_array_storage,
-          Operand(~kHeapObjectTagMask));
+  ASSERT(kSmiTag == 0);
+  __ sub(elements_array_storage,
+         elements_array_storage,
+         Operand(kHeapObjectTag));
   // Initialize the fixed array and fill it with holes. FixedArray length is
   // stored as a smi.
   // result: JSObject
@@ -617,12 +619,10 @@
     // The field instance sizes contains both pre-allocated property fields and
     // in-object properties.
     __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
-    __ and_(r6,
-            r0,
-            Operand(0x000000FF << Map::kPreAllocatedPropertyFieldsByte * 8));
-    __ add(r3, r3, Operand(r6, LSR, Map::kPreAllocatedPropertyFieldsByte * 8));
-    __ and_(r6, r0, Operand(0x000000FF << Map::kInObjectPropertiesByte * 8));
-    __ sub(r3, r3, Operand(r6, LSR, Map::kInObjectPropertiesByte * 8), SetCC);
+    __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8);
+    __ add(r3, r3, Operand(r6));
+    __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8);
+    __ sub(r3, r3, Operand(r6), SetCC);
 
     // Done if no extra properties are to be allocated.
     __ b(eq, &allocated);
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 1ca236d..8e87614 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -268,8 +268,7 @@
             // Load the offset into r3.
             int slot_offset =
                 FixedArray::kHeaderSize + slot->index() * kPointerSize;
-            __ mov(r3, Operand(slot_offset));
-            __ RecordWrite(r2, r3, r1);
+            __ RecordWrite(r2, Operand(slot_offset), r3, r1);
           }
         }
       }
@@ -342,56 +341,27 @@
     }
   }
 
-  // Generate the return sequence if necessary.
-  if (has_valid_frame() || function_return_.is_linked()) {
-    if (!function_return_.is_linked()) {
-      CodeForReturnPosition(info->function());
-    }
-    // exit
-    // r0: result
-    // sp: stack pointer
-    // fp: frame pointer
-    // cp: callee's context
+  // Handle the return from the function.
+  if (has_valid_frame()) {
+    // If there is a valid frame, control flow can fall off the end of
+    // the body.  In that case there is an implicit return statement.
+    ASSERT(!function_return_is_shadowed_);
+    frame_->PrepareForReturn();
     __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
-
+    if (function_return_.is_bound()) {
+      function_return_.Jump();
+    } else {
+      function_return_.Bind();
+      GenerateReturnSequence();
+    }
+  } else if (function_return_.is_linked()) {
+    // If the return target has dangling jumps to it, then we have not
+    // yet generated the return sequence.  This can happen when (a)
+    // control does not flow off the end of the body so we did not
+    // compile an artificial return statement just above, and (b) there
+    // are return statements in the body but (c) they are all shadowed.
     function_return_.Bind();
-    if (FLAG_trace) {
-      // Push the return value on the stack as the parameter.
-      // Runtime::TraceExit returns the parameter as it is.
-      frame_->EmitPush(r0);
-      frame_->CallRuntime(Runtime::kTraceExit, 1);
-    }
-
-#ifdef DEBUG
-    // Add a label for checking the size of the code used for returning.
-    Label check_exit_codesize;
-    masm_->bind(&check_exit_codesize);
-#endif
-    // Make sure that the constant pool is not emitted inside of the return
-    // sequence.
-    { Assembler::BlockConstPoolScope block_const_pool(masm_);
-      // Tear down the frame which will restore the caller's frame pointer and
-      // the link register.
-      frame_->Exit();
-
-      // Here we use masm_-> instead of the __ macro to avoid the code coverage
-      // tool from instrumenting as we rely on the code size here.
-      int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
-      masm_->add(sp, sp, Operand(sp_delta));
-      masm_->Jump(lr);
-
-#ifdef DEBUG
-      // Check that the size of the code used for returning matches what is
-      // expected by the debugger. If the sp_delts above cannot be encoded in
-      // the add instruction the add will generate two instructions.
-      int return_sequence_length =
-          masm_->InstructionsGeneratedSince(&check_exit_codesize);
-      CHECK(return_sequence_length ==
-            Assembler::kJSReturnSequenceInstructions ||
-            return_sequence_length ==
-            Assembler::kJSReturnSequenceInstructions + 1);
-#endif
-    }
+    GenerateReturnSequence();
   }
 
   // Adjust for function-level loop nesting.
@@ -1203,7 +1173,7 @@
         switch (op) {
           case Token::BIT_OR:  __ orr(tos, tos, Operand(value)); break;
           case Token::BIT_XOR: __ eor(tos, tos, Operand(value)); break;
-          case Token::BIT_AND: __ and_(tos, tos, Operand(value)); break;
+          case Token::BIT_AND: __ And(tos, tos, Operand(value)); break;
           default: UNREACHABLE();
         }
         frame_->EmitPush(tos, TypeInfo::Smi());
@@ -1215,7 +1185,7 @@
         switch (op) {
           case Token::BIT_OR:  __ orr(tos, tos, Operand(value)); break;
           case Token::BIT_XOR: __ eor(tos, tos, Operand(value)); break;
-          case Token::BIT_AND: __ and_(tos, tos, Operand(value)); break;
+          case Token::BIT_AND: __ And(tos, tos, Operand(value)); break;
           default: UNREACHABLE();
         }
         deferred->BindExit();
@@ -1958,8 +1928,56 @@
     // returning thus making it easier to merge.
     frame_->EmitPop(r0);
     frame_->PrepareForReturn();
+    if (function_return_.is_bound()) {
+      // If the function return label is already bound we reuse the
+      // code by jumping to the return site.
+      function_return_.Jump();
+    } else {
+      function_return_.Bind();
+      GenerateReturnSequence();
+    }
+  }
+}
 
-    function_return_.Jump();
+
+void CodeGenerator::GenerateReturnSequence() {
+  if (FLAG_trace) {
+    // Push the return value on the stack as the parameter.
+    // Runtime::TraceExit returns the parameter as it is.
+    frame_->EmitPush(r0);
+    frame_->CallRuntime(Runtime::kTraceExit, 1);
+  }
+
+#ifdef DEBUG
+  // Add a label for checking the size of the code used for returning.
+  Label check_exit_codesize;
+  masm_->bind(&check_exit_codesize);
+#endif
+  // Make sure that the constant pool is not emitted inside of the return
+  // sequence.
+  { Assembler::BlockConstPoolScope block_const_pool(masm_);
+    // Tear down the frame which will restore the caller's frame pointer and
+    // the link register.
+    frame_->Exit();
+
+    // Here we use masm_-> instead of the __ macro to avoid the code coverage
+    // tool from instrumenting as we rely on the code size here.
+    int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
+    masm_->add(sp, sp, Operand(sp_delta));
+    masm_->Jump(lr);
+    DeleteFrame();
+
+#ifdef DEBUG
+    // Check that the size of the code used for returning matches what is
+    // expected by the debugger. If the sp_delts above cannot be encoded in
+    // the add instruction the add will generate two instructions.
+    int return_sequence_length =
+        masm_->InstructionsGeneratedSince(&check_exit_codesize);
+    CHECK(return_sequence_length ==
+          Assembler::kJSReturnSequenceInstructions ||
+          return_sequence_length ==
+          Assembler::kJSReturnSequenceInstructions + 1);
+#endif
   }
 }
 
@@ -3090,9 +3108,8 @@
       exit.Branch(eq);
       // scratch is loaded with context when calling SlotOperand above.
       int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
-      __ mov(r3, Operand(offset));
       // r1 could be identical with tos, but that doesn't matter.
-      __ RecordWrite(scratch, r3, r1);
+      __ RecordWrite(scratch, Operand(offset), r3, r1);
     }
     // If we definitely did not jump over the assignment, we do not need
     // to bind the exit label.  Doing so can defeat peephole
@@ -3445,8 +3462,7 @@
     __ str(r0, FieldMemOperand(r1, offset));
 
     // Update the write barrier for the array address.
-    __ mov(r3, Operand(offset));
-    __ RecordWrite(r1, r3, r2);
+    __ RecordWrite(r1, Operand(offset), r3, r2);
   }
   ASSERT_EQ(original_height + 1, frame_->height());
 }
@@ -4069,28 +4085,34 @@
       VirtualFrame::SpilledScope spilled_scope(frame_);
 
       Load(property->obj());
-      if (!property->is_synthetic()) {
-        // Duplicate receiver for later use.
-        __ ldr(r0, MemOperand(sp, 0));
-        frame_->EmitPush(r0);
-      }
-      Load(property->key());
-      EmitKeyedLoad();
-      // Put the function below the receiver.
       if (property->is_synthetic()) {
+        Load(property->key());
+        EmitKeyedLoad();
+        // Put the function below the receiver.
         // Use the global receiver.
         frame_->EmitPush(r0);  // Function.
         LoadGlobalReceiver(r0);
+        // Call the function.
+        CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position());
+        frame_->EmitPush(r0);
       } else {
-        // Switch receiver and function.
-        frame_->EmitPop(r1);  // Receiver.
-        frame_->EmitPush(r0);  // Function.
-        frame_->EmitPush(r1);  // Receiver.
-      }
+        // Load the arguments.
+        int arg_count = args->length();
+        for (int i = 0; i < arg_count; i++) {
+          Load(args->at(i));
+        }
 
-      // Call the function.
-      CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position());
-      frame_->EmitPush(r0);
+        // Set the name register and call the IC initialization code.
+        Load(property->key());
+        frame_->EmitPop(r2);  // Function name.
+
+        InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+        Handle<Code> stub = ComputeKeyedCallInitialize(arg_count, in_loop);
+        CodeForSourcePosition(node->position());
+        frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
+        __ ldr(cp, frame_->Context());
+        frame_->EmitPush(r0);
+      }
     }
 
   } else {
@@ -4254,8 +4276,7 @@
   // Store the value.
   __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
   // Update the write barrier.
-  __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
-  __ RecordWrite(r1, r2, r3);
+  __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3);
   // Leave.
   leave.Bind();
   frame_->EmitPush(r0);
@@ -4685,7 +4706,8 @@
   Label slow_allocate_heapnumber;
   Label heapnumber_allocated;
 
-  __ AllocateHeapNumber(r4, r1, r2, &slow_allocate_heapnumber);
+  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
   __ jmp(&heapnumber_allocated);
 
   __ bind(&slow_allocate_heapnumber);
@@ -6628,8 +6650,12 @@
   // Gets the wrong answer for 0, but we already checked for that case above.
   __ CountLeadingZeros(source_, mantissa, zeros_);
   // Compute exponent and or it into the exponent register.
-  // We use mantissa as a scratch register here.
-  __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias));
+  // We use mantissa as a scratch register here.  Use a fudge factor to
+  // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts
+  // that fit in the ARM's constant field.
+  int fudge = 0x400;
+  __ rsb(mantissa, zeros_, Operand(31 + HeapNumber::kExponentBias - fudge));
+  __ add(mantissa, mantissa, Operand(fudge));
   __ orr(exponent,
          exponent,
          Operand(mantissa, LSL, HeapNumber::kExponentShift));
@@ -6702,15 +6728,12 @@
                                           bool never_nan_nan) {
   Label not_identical;
   Label heap_number, return_equal;
-  Register exp_mask_reg = r5;
   __ cmp(r0, r1);
   __ b(ne, &not_identical);
 
   // The two objects are identical.  If we know that one of them isn't NaN then
   // we now know they test equal.
   if (cc != eq || !never_nan_nan) {
-    __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
-
     // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
     // so we do the second best thing - test it ourselves.
     // They are both equal and they are not both Smis so both of them are not
@@ -6771,8 +6794,9 @@
       // Read top bits of double representation (second word of value).
       __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
       // Test that exponent bits are all set.
-      __ and_(r3, r2, Operand(exp_mask_reg));
-      __ cmp(r3, Operand(exp_mask_reg));
+      __ Sbfx(r3, r2, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+      // NaNs have all-one exponents so they sign extend to -1.
+      __ cmp(r3, Operand(-1));
       __ b(ne, &return_equal);
 
       // Shift out flag and all exponent bits, retaining only mantissa.
@@ -6893,14 +6917,14 @@
   Register rhs_mantissa = exp_first ? r1 : r0;
   Register lhs_mantissa = exp_first ? r3 : r2;
   Label one_is_nan, neither_is_nan;
-  Label lhs_not_nan_exp_mask_is_loaded;
 
-  Register exp_mask_reg = r5;
-
-  __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
-  __ and_(r4, lhs_exponent, Operand(exp_mask_reg));
-  __ cmp(r4, Operand(exp_mask_reg));
-  __ b(ne, &lhs_not_nan_exp_mask_is_loaded);
+  __ Sbfx(r4,
+          lhs_exponent,
+          HeapNumber::kExponentShift,
+          HeapNumber::kExponentBits);
+  // NaNs have all-one exponents so they sign extend to -1.
+  __ cmp(r4, Operand(-1));
+  __ b(ne, lhs_not_nan);
   __ mov(r4,
          Operand(lhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
          SetCC);
@@ -6909,10 +6933,12 @@
   __ b(ne, &one_is_nan);
 
   __ bind(lhs_not_nan);
-  __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
-  __ bind(&lhs_not_nan_exp_mask_is_loaded);
-  __ and_(r4, rhs_exponent, Operand(exp_mask_reg));
-  __ cmp(r4, Operand(exp_mask_reg));
+  __ Sbfx(r4,
+          rhs_exponent,
+          HeapNumber::kExponentShift,
+          HeapNumber::kExponentBits);
+  // NaNs have all-one exponents so they sign extend to -1.
+  __ cmp(r4, Operand(-1));
   __ b(ne, &neither_is_nan);
   __ mov(r4,
          Operand(rhs_exponent, LSL, HeapNumber::kNonMantissaBitsInTopWord),
@@ -7178,7 +7204,7 @@
 
 
 void RecordWriteStub::Generate(MacroAssembler* masm) {
-  __ RecordWriteHelper(object_, offset_, scratch_);
+  __ RecordWriteHelper(object_, Operand(offset_), offset_, scratch_);
   __ Ret();
 }
 
@@ -7338,12 +7364,16 @@
   bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_;
 
   ASSERT((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0)));
+  Register heap_number_map = r6;
 
   if (ShouldGenerateSmiCode()) {
+    __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
     // Smi-smi case (overflow).
     // Since both are Smis there is no heap number to overwrite, so allocate.
-    // The new heap number is in r5.  r6 and r7 are scratch.
-    __ AllocateHeapNumber(r5, r6, r7, lhs.is(r0) ? &slow_reverse : &slow);
+    // The new heap number is in r5.  r3 and r7 are scratch.
+    __ AllocateHeapNumber(
+        r5, r3, r7, heap_number_map, lhs.is(r0) ? &slow_reverse : &slow);
 
     // If we have floating point hardware, inline ADD, SUB, MUL, and DIV,
     // using registers d7 and d6 for the double values.
@@ -7356,14 +7386,14 @@
       __ vmov(s13, r7);
       __ vcvt_f64_s32(d6, s13);
     } else {
-      // Write Smi from rhs to r3 and r2 in double format.  r6 is scratch.
+      // Write Smi from rhs to r3 and r2 in double format.  r3 is scratch.
       __ mov(r7, Operand(rhs));
-      ConvertToDoubleStub stub1(r3, r2, r7, r6);
+      ConvertToDoubleStub stub1(r3, r2, r7, r9);
       __ push(lr);
       __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
-      // Write Smi from lhs to r1 and r0 in double format.  r6 is scratch.
+      // Write Smi from lhs to r1 and r0 in double format.  r9 is scratch.
       __ mov(r7, Operand(lhs));
-      ConvertToDoubleStub stub2(r1, r0, r7, r6);
+      ConvertToDoubleStub stub2(r1, r0, r7, r9);
       __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
       __ pop(lr);
     }
@@ -7372,6 +7402,7 @@
 
   // We branch here if at least one of r0 and r1 is not a Smi.
   __ bind(not_smi);
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
 
   // After this point we have the left hand side in r1 and the right hand side
   // in r0.
@@ -7394,18 +7425,22 @@
         default:
           break;
       }
+      // Restore heap number map register.
+      __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
     }
 
     if (mode_ == NO_OVERWRITE) {
       // In the case where there is no chance of an overwritable float we may as
       // well do the allocation immediately while r0 and r1 are untouched.
-      __ AllocateHeapNumber(r5, r6, r7, &slow);
+      __ AllocateHeapNumber(r5, r3, r7, heap_number_map, &slow);
     }
 
     // Move r0 to a double in r2-r3.
     __ tst(r0, Operand(kSmiTagMask));
     __ b(eq, &r0_is_smi);  // It's a Smi so don't check it's a heap number.
-    __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
+    __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
+    __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+    __ cmp(r4, heap_number_map);
     __ b(ne, &slow);
     if (mode_ == OVERWRITE_RIGHT) {
       __ mov(r5, Operand(r0));  // Overwrite this heap number.
@@ -7423,7 +7458,7 @@
     __ bind(&r0_is_smi);
     if (mode_ == OVERWRITE_RIGHT) {
       // We can't overwrite a Smi so get address of new heap number into r5.
-    __ AllocateHeapNumber(r5, r6, r7, &slow);
+    __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
     }
 
     if (use_fp_registers) {
@@ -7435,7 +7470,7 @@
     } else {
       // Write Smi from r0 to r3 and r2 in double format.
       __ mov(r7, Operand(r0));
-      ConvertToDoubleStub stub3(r3, r2, r7, r6);
+      ConvertToDoubleStub stub3(r3, r2, r7, r4);
       __ push(lr);
       __ Call(stub3.GetCode(), RelocInfo::CODE_TARGET);
       __ pop(lr);
@@ -7448,6 +7483,8 @@
       __ tst(r1, Operand(kSmiTagMask));
       __ b(ne, &r1_is_not_smi);
       GenerateTypeTransition(masm);
+      // Restore heap number map register.
+      __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
       __ jmp(&r1_is_smi);
     }
 
@@ -7457,7 +7494,9 @@
     __ tst(r1, Operand(kSmiTagMask));
     __ b(eq, &r1_is_smi);  // It's a Smi so don't check it's a heap number.
     __ bind(&r1_is_not_smi);
-    __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
+    __ ldr(r4, FieldMemOperand(r1, HeapNumber::kMapOffset));
+    __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+    __ cmp(r4, heap_number_map);
     __ b(ne, &slow);
     if (mode_ == OVERWRITE_LEFT) {
       __ mov(r5, Operand(r1));  // Overwrite this heap number.
@@ -7475,7 +7514,7 @@
     __ bind(&r1_is_smi);
     if (mode_ == OVERWRITE_LEFT) {
       // We can't overwrite a Smi so get address of new heap number into r5.
-    __ AllocateHeapNumber(r5, r6, r7, &slow);
+    __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
     }
 
     if (use_fp_registers) {
@@ -7487,7 +7526,7 @@
     } else {
       // Write Smi from r1 to r1 and r0 in double format.
       __ mov(r7, Operand(r1));
-      ConvertToDoubleStub stub4(r1, r0, r7, r6);
+      ConvertToDoubleStub stub4(r1, r0, r7, r9);
       __ push(lr);
       __ Call(stub4.GetCode(), RelocInfo::CODE_TARGET);
       __ pop(lr);
@@ -7548,13 +7587,14 @@
     }
   }
 
-
   if (lhs.is(r0)) {
     __ b(&slow);
     __ bind(&slow_reverse);
     __ Swap(r0, r1, ip);
   }
 
+  heap_number_map = no_reg;  // Don't use this any more from here on.
+
   // We jump to here if something goes wrong (one param is not a number of any
   // sort or new-space allocation fails).
   __ bind(&slow);
@@ -7633,7 +7673,10 @@
   // Get exponent word.
   __ ldr(scratch, FieldMemOperand(source, HeapNumber::kExponentOffset));
   // Get exponent alone in scratch2.
-  __ and_(scratch2, scratch, Operand(HeapNumber::kExponentMask));
+  __ Ubfx(scratch2,
+          scratch,
+          HeapNumber::kExponentShift,
+          HeapNumber::kExponentBits);
   // Load dest with zero.  We use this either for the final shift or
   // for the answer.
   __ mov(dest, Operand(0));
@@ -7641,9 +7684,14 @@
   // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased).  This is
   // the exponent that we are fastest at and also the highest exponent we can
   // handle here.
-  const uint32_t non_smi_exponent =
-      (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift;
-  __ cmp(scratch2, Operand(non_smi_exponent));
+  const uint32_t non_smi_exponent = HeapNumber::kExponentBias + 30;
+  // The non_smi_exponent, 0x41d, is too big for ARM's immediate field so we
+  // split it up to avoid a constant pool entry.  You can't do that in general
+  // for cmp because of the overflow flag, but we know the exponent is in the
+  // range 0-2047 so there is no overflow.
+  int fudge_factor = 0x400;
+  __ sub(scratch2, scratch2, Operand(fudge_factor));
+  __ cmp(scratch2, Operand(non_smi_exponent - fudge_factor));
   // If we have a match of the int32-but-not-Smi exponent then skip some logic.
   __ b(eq, &right_exponent);
   // If the exponent is higher than that then go to slow case.  This catches
@@ -7653,17 +7701,14 @@
   // We know the exponent is smaller than 30 (biased).  If it is less than
   // 0 (biased) then the number is smaller in magnitude than 1.0 * 2^0, ie
   // it rounds to zero.
-  const uint32_t zero_exponent =
-      (HeapNumber::kExponentBias + 0) << HeapNumber::kExponentShift;
-  __ sub(scratch2, scratch2, Operand(zero_exponent), SetCC);
+  const uint32_t zero_exponent = HeapNumber::kExponentBias + 0;
+  __ sub(scratch2, scratch2, Operand(zero_exponent - fudge_factor), SetCC);
   // Dest already has a Smi zero.
   __ b(lt, &done);
   if (!CpuFeatures::IsSupported(VFP3)) {
-    // We have a shifted exponent between 0 and 30 in scratch2.
-    __ mov(dest, Operand(scratch2, LSR, HeapNumber::kExponentShift));
-    // We now have the exponent in dest.  Subtract from 30 to get
-    // how much to shift down.
-    __ rsb(dest, dest, Operand(30));
+    // We have an exponent between 0 and 30 in scratch2.  Subtract from 30 to
+    // get how much to shift down.
+    __ rsb(dest, scratch2, Operand(30));
   }
   __ bind(&right_exponent);
   if (CpuFeatures::IsSupported(VFP3)) {
@@ -7715,9 +7760,13 @@
   Label rhs_is_smi, lhs_is_smi;
   Label done_checking_rhs, done_checking_lhs;
 
+  Register heap_number_map = r6;
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
   __ tst(lhs, Operand(kSmiTagMask));
   __ b(eq, &lhs_is_smi);  // It's a Smi so don't check it's a heap number.
-  __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
+  __ ldr(r4, FieldMemOperand(lhs, HeapNumber::kMapOffset));
+  __ cmp(r4, heap_number_map);
   __ b(ne, &slow);
   GetInt32(masm, lhs, r3, r5, r4, &slow);
   __ jmp(&done_checking_lhs);
@@ -7727,7 +7776,8 @@
 
   __ tst(rhs, Operand(kSmiTagMask));
   __ b(eq, &rhs_is_smi);  // It's a Smi so don't check it's a heap number.
-  __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
+  __ ldr(r4, FieldMemOperand(rhs, HeapNumber::kMapOffset));
+  __ cmp(r4, heap_number_map);
   __ b(ne, &slow);
   GetInt32(masm, rhs, r2, r5, r4, &slow);
   __ jmp(&done_checking_rhs);
@@ -7787,8 +7837,8 @@
       break;
     }
     case NO_OVERWRITE: {
-      // Get a new heap number in r5.  r6 and r7 are scratch.
-      __ AllocateHeapNumber(r5, r6, r7, &slow);
+      // Get a new heap number in r5.  r4 and r7 are scratch.
+      __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
     }
     default: break;
   }
@@ -7807,8 +7857,8 @@
 
   if (mode_ != NO_OVERWRITE) {
     __ bind(&have_to_allocate);
-    // Get a new heap number in r5.  r6 and r7 are scratch.
-    __ AllocateHeapNumber(r5, r6, r7, &slow);
+    // Get a new heap number in r5.  r4 and r7 are scratch.
+    __ AllocateHeapNumber(r5, r4, r7, heap_number_map, &slow);
     __ jmp(&got_a_heap_number);
   }
 
@@ -7934,10 +7984,11 @@
   }
 
   OS::SNPrintF(Vector<char>(name_, len),
-               "GenericBinaryOpStub_%s_%s%s",
+               "GenericBinaryOpStub_%s_%s%s_%s",
                op_name,
                overwrite_name,
-               specialized_on_rhs_ ? "_ConstantRhs" : 0);
+               specialized_on_rhs_ ? "_ConstantRhs" : "",
+               BinaryOpIC::GetName(runtime_operands_type_));
   return name_;
 }
 
@@ -8130,6 +8181,28 @@
         }
         __ Ret();
         __ bind(&smi_is_unsuitable);
+      } else if (op_ == Token::MOD &&
+                 runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
+                 runtime_operands_type_ != BinaryOpIC::STRINGS) {
+        // Do generate a bit of smi code for modulus even though the default for
+        // modulus is not to do it, but as the ARM processor has no coprocessor
+        // support for modulus checking for smis makes sense.
+        Label slow;
+        ASSERT(!ShouldGenerateSmiCode());
+        ASSERT(kSmiTag == 0);  // Adjust code below.
+        // Check for two positive smis.
+        __ orr(smi_test_reg, lhs, Operand(rhs));
+        __ tst(smi_test_reg, Operand(0x80000000u | kSmiTagMask));
+        __ b(ne, &slow);
+        // Check that rhs is a power of two and not zero.
+        __ sub(scratch, rhs, Operand(1), SetCC);
+        __ b(mi, &slow);
+        __ tst(rhs, scratch);
+        __ b(ne, &slow);
+        // Calculate power of two modulus.
+        __ and_(result, lhs, Operand(scratch));
+        __ Ret();
+        __ bind(&slow);
       }
       HandleBinaryOpSlowCases(
           masm,
@@ -8276,20 +8349,13 @@
     __ bind(&loaded);
     // r2 = low 32 bits of double value
     // r3 = high 32 bits of double value
-    // Compute hash:
+    // Compute hash (the shifts are arithmetic):
     //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
     __ eor(r1, r2, Operand(r3));
-    __ eor(r1, r1, Operand(r1, LSR, 16));
-    __ eor(r1, r1, Operand(r1, LSR, 8));
+    __ eor(r1, r1, Operand(r1, ASR, 16));
+    __ eor(r1, r1, Operand(r1, ASR, 8));
     ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
-    if (CpuFeatures::IsSupported(ARMv7)) {
-      const int kTranscendentalCacheSizeBits = 9;
-      ASSERT_EQ(1 << kTranscendentalCacheSizeBits,
-                TranscendentalCache::kCacheSize);
-      __ ubfx(r1, r1, 0, kTranscendentalCacheSizeBits);
-    } else {
-      __ and_(r1, r1, Operand(TranscendentalCache::kCacheSize - 1));
-    }
+    __ And(r1, r1, Operand(TranscendentalCache::kCacheSize - 1));
 
     // r2 = low 32 bits of double value.
     // r3 = high 32 bits of double value.
@@ -8364,6 +8430,9 @@
 void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
   Label slow, done;
 
+  Register heap_number_map = r6;
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+
   if (op_ == Token::SUB) {
     // Check whether the value is a smi.
     Label try_float;
@@ -8384,7 +8453,9 @@
     __ b(&done);
 
     __ bind(&try_float);
-    __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE);
+    __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+    __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+    __ cmp(r1, heap_number_map);
     __ b(ne, &slow);
     // r0 is a heap number.  Get a new heap number in r1.
     if (overwrite_) {
@@ -8392,7 +8463,7 @@
       __ eor(r2, r2, Operand(HeapNumber::kSignMask));  // Flip sign.
       __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
     } else {
-      __ AllocateHeapNumber(r1, r2, r3, &slow);
+      __ AllocateHeapNumber(r1, r2, r3, r6, &slow);
       __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
       __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
       __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset));
@@ -8402,7 +8473,9 @@
     }
   } else if (op_ == Token::BIT_NOT) {
     // Check if the operand is a heap number.
-    __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE);
+    __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
+    __ AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+    __ cmp(r1, heap_number_map);
     __ b(ne, &slow);
 
     // Convert the heap number is r0 to an untagged integer in r1.
@@ -8422,7 +8495,7 @@
       // Allocate a fresh heap number, but don't overwrite r0 until
       // we're sure we can do it without going through the slow case
       // that needs the value in r0.
-      __ AllocateHeapNumber(r2, r3, r4, &slow);
+      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
       __ mov(r0, Operand(r2));
     }
 
@@ -9248,15 +9321,11 @@
   // regexp_data: RegExp data (FixedArray)
   // Check the representation and encoding of the subject string.
   Label seq_string;
-  const int kStringRepresentationEncodingMask =
-      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
   __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
   __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
-  __ and_(r1, r0, Operand(kStringRepresentationEncodingMask));
-  // First check for sequential string.
-  ASSERT_EQ(0, kStringTag);
-  ASSERT_EQ(0, kSeqStringTag);
-  __ tst(r1, Operand(kIsNotStringMask | kStringRepresentationMask));
+  // First check for flat string.
+  __ tst(r0, Operand(kIsNotStringMask | kStringRepresentationMask));
+  ASSERT_EQ(0, kStringTag | kSeqStringTag);
   __ b(eq, &seq_string);
 
   // subject: Subject string
@@ -9266,8 +9335,9 @@
   // string. In that case the subject string is just the first part of the cons
   // string. Also in this case the first part of the cons string is known to be
   // a sequential string or an external string.
-  __ and_(r0, r0, Operand(kStringRepresentationMask));
-  __ cmp(r0, Operand(kConsStringTag));
+  ASSERT(kExternalStringTag !=0);
+  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
+  __ tst(r0, Operand(kIsNotStringMask | kExternalStringTag));
   __ b(ne, &runtime);
   __ ldr(r0, FieldMemOperand(subject, ConsString::kSecondOffset));
   __ LoadRoot(r1, Heap::kEmptyStringRootIndex);
@@ -9276,25 +9346,20 @@
   __ ldr(subject, FieldMemOperand(subject, ConsString::kFirstOffset));
   __ ldr(r0, FieldMemOperand(subject, HeapObject::kMapOffset));
   __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+  // Is first part a flat string?
   ASSERT_EQ(0, kSeqStringTag);
   __ tst(r0, Operand(kStringRepresentationMask));
   __ b(nz, &runtime);
-  __ and_(r1, r0, Operand(kStringRepresentationEncodingMask));
 
   __ bind(&seq_string);
-  // r1: suject string type & kStringRepresentationEncodingMask
   // subject: Subject string
   // regexp_data: RegExp data (FixedArray)
-  // Check that the irregexp code has been generated for an ascii string. If
-  // it has, the field contains a code object otherwise it contains the hole.
-#ifdef DEBUG
-  const int kSeqAsciiString = kStringTag | kSeqStringTag | kAsciiStringTag;
-  const int kSeqTwoByteString = kStringTag | kSeqStringTag | kTwoByteStringTag;
-  CHECK_EQ(4, kSeqAsciiString);
-  CHECK_EQ(0, kSeqTwoByteString);
-#endif
+  // r0: Instance type of subject string
+  ASSERT_EQ(4, kAsciiStringTag);
+  ASSERT_EQ(0, kTwoByteStringTag);
   // Find the code object based on the assumptions above.
-  __ mov(r3, Operand(r1, ASR, 2), SetCC);
+  __ and_(r0, r0, Operand(kStringEncodingMask));
+  __ mov(r3, Operand(r0, ASR, 2), SetCC);
   __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
   __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
 
@@ -9412,17 +9477,15 @@
                              RegExpImpl::kLastCaptureCountOffset));
   // Store last subject and last input.
   __ mov(r3, last_match_info_elements);  // Moved up to reduce latency.
-  __ mov(r2, Operand(RegExpImpl::kLastSubjectOffset));  // Ditto.
   __ str(subject,
          FieldMemOperand(last_match_info_elements,
                          RegExpImpl::kLastSubjectOffset));
-  __ RecordWrite(r3, r2, r7);
+  __ RecordWrite(r3, Operand(RegExpImpl::kLastSubjectOffset), r2, r7);
   __ str(subject,
          FieldMemOperand(last_match_info_elements,
                          RegExpImpl::kLastInputOffset));
   __ mov(r3, last_match_info_elements);
-  __ mov(r2, Operand(RegExpImpl::kLastInputOffset));
-  __ RecordWrite(r3, r2, r7);
+  __ RecordWrite(r3, Operand(RegExpImpl::kLastInputOffset), r2, r7);
 
   // Get the static offsets vector filled by the native regexp code.
   ExternalReference address_of_static_offsets_vector =
@@ -10524,13 +10587,14 @@
     __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
     __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
   }
-  Label non_ascii, allocated;
+  Label non_ascii, allocated, ascii_data;
   ASSERT_EQ(0, kTwoByteStringTag);
   __ tst(r4, Operand(kStringEncodingMask));
   __ tst(r5, Operand(kStringEncodingMask), ne);
   __ b(eq, &non_ascii);
 
   // Allocate an ASCII cons string.
+  __ bind(&ascii_data);
   __ AllocateAsciiConsString(r7, r6, r4, r5, &string_add_runtime);
   __ bind(&allocated);
   // Fill the fields of the cons string.
@@ -10542,6 +10606,19 @@
   __ Ret();
 
   __ bind(&non_ascii);
+  // At least one of the strings is two-byte. Check whether it happens
+  // to contain only ascii characters.
+  // r4: first instance type.
+  // r5: second instance type.
+  __ tst(r4, Operand(kAsciiDataHintMask));
+  __ tst(r5, Operand(kAsciiDataHintMask), ne);
+  __ b(ne, &ascii_data);
+  __ eor(r4, r4, Operand(r5));
+  ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
+  __ and_(r4, r4, Operand(kAsciiStringTag | kAsciiDataHintTag));
+  __ cmp(r4, Operand(kAsciiStringTag | kAsciiDataHintTag));
+  __ b(eq, &ascii_data);
+
   // Allocate a two byte cons string.
   __ AllocateTwoByteConsString(r7, r6, r4, r5, &string_add_runtime);
   __ jmp(&allocated);
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 91adff0..be4d556 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -315,6 +315,12 @@
   // Main code generation function
   void Generate(CompilationInfo* info);
 
+  // Generate the return sequence code.  Should be called no more than
+  // once per compiled function, immediately after binding the return
+  // target (which can not be done more than once).  The return value should
+  // be in r0.
+  void GenerateReturnSequence();
+
   // Returns the arguments allocation mode.
   ArgumentsAllocationMode ArgumentsMode();
 
@@ -663,7 +669,9 @@
   }
 
   void Generate(MacroAssembler* masm);
-  void HandleNonSmiBitwiseOp(MacroAssembler* masm, Register lhs, Register rhs);
+  void HandleNonSmiBitwiseOp(MacroAssembler* masm,
+                             Register lhs,
+                             Register rhs);
   void HandleBinaryOpSlowCases(MacroAssembler* masm,
                                Label* not_smi,
                                Register lhs,
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index e36f595..fa9adbd 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -284,6 +284,9 @@
     // with immediate
   inline int RotateField() const { return Bits(11, 8); }
   inline int Immed8Field() const { return Bits(7, 0); }
+  inline int Immed4Field() const { return Bits(19, 16); }
+  inline int ImmedMovwMovtField() const {
+      return Immed4Field() << 12 | Offset12Field(); }
 
   // Fields used in Load/Store instructions
   inline int PUField() const { return Bits(24, 23); }
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index 1c05bc3..4005369 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -101,6 +101,7 @@
   void PrintSRegister(int reg);
   void PrintDRegister(int reg);
   int FormatVFPRegister(Instr* instr, const char* format);
+  void PrintMovwMovt(Instr* instr);
   int FormatVFPinstruction(Instr* instr, const char* format);
   void PrintCondition(Instr* instr);
   void PrintShiftRm(Instr* instr);
@@ -375,6 +376,16 @@
 }
 
 
+// Print the movw or movt instruction.
+void Decoder::PrintMovwMovt(Instr* instr) {
+  int imm = instr->ImmedMovwMovtField();
+  int rd = instr->RdField();
+  PrintRegister(rd);
+  out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
+                                       ", #%d", imm);
+}
+
+
 // FormatOption takes a formatting string and interprets it based on
 // the current instructions. The format string points to the first
 // character of the option string (the option escape has already been
@@ -430,7 +441,12 @@
       return 1;
     }
     case 'm': {
-      if (format[1] == 'e') {  // 'memop: load/store instructions
+      if (format[1] == 'w') {
+        // 'mw: movt/movw instructions.
+        PrintMovwMovt(instr);
+        return 2;
+      }
+      if (format[1] == 'e') {  // 'memop: load/store instructions.
         ASSERT(STRING_STARTS_WITH(format, "memop"));
         if (instr->HasL()) {
           Print("ldr");
@@ -776,7 +792,7 @@
         if (instr->HasS()) {
           Format(instr, "tst'cond 'rn, 'shift_op");
         } else {
-          Unknown(instr);  // not used by V8
+          Format(instr, "movw'cond 'mw");
         }
         break;
       }
@@ -794,7 +810,7 @@
         if (instr->HasS()) {
           Format(instr, "cmp'cond 'rn, 'shift_op");
         } else {
-          Unknown(instr);  // not used by V8
+          Format(instr, "movt'cond 'mw");
         }
         break;
       }
diff --git a/src/arm/fast-codegen-arm.cc b/src/arm/fast-codegen-arm.cc
index 48eaf46..36ac2aa 100644
--- a/src/arm/fast-codegen-arm.cc
+++ b/src/arm/fast-codegen-arm.cc
@@ -102,8 +102,7 @@
   }
 
   if (needs_write_barrier) {
-    __ mov(scratch1(), Operand(offset));
-    __ RecordWrite(scratch0(), scratch1(), scratch2());
+    __ RecordWrite(scratch0(), Operand(offset), scratch1(), scratch2());
   }
 
   if (destination().is(accumulator1())) {
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index e619663..6732873 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -110,10 +110,10 @@
           __ mov(r1, Operand(Context::SlotOffset(slot->index())));
           __ str(r0, MemOperand(cp, r1));
           // Update the write barrier. This clobbers all involved
-          // registers, so we have use a third register to avoid
+          // registers, so we have to use two more registers to avoid
           // clobbering cp.
           __ mov(r2, Operand(cp));
-          __ RecordWrite(r2, r1, r0);
+          __ RecordWrite(r2, Operand(r1), r3, r0);
         }
       }
     }
@@ -666,8 +666,10 @@
   __ str(src, location);
   // Emit the write barrier code if the location is in the heap.
   if (dst->type() == Slot::CONTEXT) {
-    __ mov(scratch2, Operand(Context::SlotOffset(dst->index())));
-    __ RecordWrite(scratch1, scratch2, src);
+    __ RecordWrite(scratch1,
+                   Operand(Context::SlotOffset(dst->index())),
+                   scratch2,
+                   src);
   }
 }
 
@@ -715,10 +717,9 @@
           __ str(result_register(),
                  CodeGenerator::ContextOperand(cp, slot->index()));
           int offset = Context::SlotOffset(slot->index());
-          __ mov(r2, Operand(offset));
           // We know that we have written a function, which is not a smi.
           __ mov(r1, Operand(cp));
-          __ RecordWrite(r1, r2, result_register());
+          __ RecordWrite(r1, Operand(offset), r2, result_register());
         }
         break;
 
@@ -1252,8 +1253,7 @@
 
     // Update the write barrier for the array store with r0 as the scratch
     // register.
-    __ mov(r2, Operand(offset));
-    __ RecordWrite(r1, r2, result_register());
+    __ RecordWrite(r1, Operand(offset), r2, result_register());
   }
 
   if (result_saved) {
@@ -1493,8 +1493,7 @@
         // RecordWrite may destroy all its register arguments.
         __ mov(r3, result_register());
         int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
-        __ mov(r2, Operand(offset));
-        __ RecordWrite(r1, r2, r3);
+        __ RecordWrite(r1, Operand(offset), r2, r3);
         break;
       }
 
@@ -1648,6 +1647,30 @@
 }
 
 
+void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
+                                            Expression* key,
+                                            RelocInfo::Mode mode) {
+  // Code common for calls using the IC.
+  ZoneList<Expression*>* args = expr->arguments();
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    VisitForValue(args->at(i), kStack);
+  }
+  VisitForValue(key, kAccumulator);
+  __ mov(r2, r0);
+  // Record source position for debugger.
+  SetSourcePosition(expr->position());
+  // Call the IC initialization code.
+  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
+  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
+                                                              in_loop);
+  __ Call(ic, mode);
+  // Restore context register.
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  Apply(context_, r0);
+}
+
+
 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
   // Code common for calls using the call stub.
   ZoneList<Expression*>* args = expr->arguments();
@@ -1743,35 +1766,28 @@
       VisitForValue(prop->obj(), kStack);
       EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
     } else {
-      // Call to a keyed property, use keyed load IC followed by function
-      // call.
+      // Call to a keyed property.
+      // For a synthetic property use keyed load IC followed by function call,
+      // for a regular property use keyed CallIC.
       VisitForValue(prop->obj(), kStack);
-      VisitForValue(prop->key(), kAccumulator);
-      // Record source code position for IC call.
-      SetSourcePosition(prop->position());
       if (prop->is_synthetic()) {
+        VisitForValue(prop->key(), kAccumulator);
+        // Record source code position for IC call.
+        SetSourcePosition(prop->position());
         __ pop(r1);  // We do not need to keep the receiver.
-      } else {
-        __ ldr(r1, MemOperand(sp, 0));  // Keep receiver, to call function on.
-      }
 
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
-      __ Call(ic, RelocInfo::CODE_TARGET);
-      if (prop->is_synthetic()) {
+        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+        __ Call(ic, RelocInfo::CODE_TARGET);
         // Push result (function).
         __ push(r0);
         // Push Global receiver.
         __ ldr(r1, CodeGenerator::GlobalObject());
         __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
         __ push(r1);
+        EmitCallWithStub(expr);
       } else {
-        // Pop receiver.
-        __ pop(r1);
-        // Push result (function).
-        __ push(r0);
-        __ push(r1);
+        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
       }
-      EmitCallWithStub(expr);
     }
   } else {
     // Call to some other expression.  If the expression is an anonymous
@@ -2140,7 +2156,8 @@
   Label slow_allocate_heapnumber;
   Label heapnumber_allocated;
 
-  __ AllocateHeapNumber(r4, r1, r2, &slow_allocate_heapnumber);
+  __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
   __ jmp(&heapnumber_allocated);
 
   __ bind(&slow_allocate_heapnumber);
@@ -2259,8 +2276,7 @@
   __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
   // Update the write barrier.  Save the value as it will be
   // overwritten by the write barrier code and is needed afterward.
-  __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
-  __ RecordWrite(r1, r2, r3);
+  __ RecordWrite(r1, Operand(JSValue::kValueOffset - kHeapObjectTag), r2, r3);
 
   __ bind(&done);
   Apply(context_, r0);
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index d0a32e8..c6de4d8 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -167,16 +167,22 @@
                                          Label* miss,
                                          Register elements,
                                          Register key,
+                                         Register result,
                                          Register t0,
                                          Register t1,
                                          Register t2) {
   // Register use:
   //
-  // elements - holds the slow-case elements of the receiver and is unchanged.
+  // elements - holds the slow-case elements of the receiver on entry.
+  //            Unchanged unless 'result' is the same register.
   //
-  // key      - holds the smi key on entry and is unchanged if a branch is
-  //            performed to the miss label.
-  //            Holds the result on exit if the load succeeded.
+  // key      - holds the smi key on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // result   - holds the result on exit if the load succeeded.
+  //            Allowed to be the same as 'key' or 'result'.
+  //            Unchanged on bailout so 'key' or 'result' can be used
+  //            in further computation.
   //
   // Scratch registers:
   //
@@ -248,7 +254,7 @@
   // Get the value at the masked, scaled index and return.
   const int kValueOffset =
       NumberDictionary::kElementsStartOffset + kPointerSize;
-  __ ldr(key, FieldMemOperand(t2, kValueOffset));
+  __ ldr(result, FieldMemOperand(t2, kValueOffset));
 }
 
 
@@ -298,22 +304,159 @@
 }
 
 
+// Checks the receiver for special cases (value type, slow case bits).
+// Falls through for regular JS object.
+static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Label* slow) {
+  // Check that the object isn't a smi.
+  __ BranchOnSmi(receiver, slow);
+  // Get the map of the receiver.
+  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  // Check bit field.
+  __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
+  __ tst(scratch2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
+  __ b(ne, slow);
+  // Check that the object is some kind of JS object EXCEPT JS Value type.
+  // In the case that the object is a value-wrapper object,
+  // we enter the runtime system to make sure that indexing into string
+  // objects work as intended.
+  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
+  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ cmp(scratch1, Operand(JS_OBJECT_TYPE));
+  __ b(lt, slow);
+}
+
+
+// Loads an indexed element from a fast case array.
+static void GenerateFastArrayLoad(MacroAssembler* masm,
+                                  Register receiver,
+                                  Register key,
+                                  Register elements,
+                                  Register scratch1,
+                                  Register scratch2,
+                                  Register result,
+                                  Label* not_fast_array,
+                                  Label* out_of_range) {
+  // Register use:
+  //
+  // receiver - holds the receiver on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // key      - holds the smi key on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // elements - holds the elements of the receiver on exit.
+  //
+  // result   - holds the result on exit if the load succeeded.
+  //            Allowed to be the the same as 'receiver' or 'key'.
+  //            Unchanged on bailout so 'receiver' and 'key' can be safely
+  //            used by further computation.
+  //
+  // Scratch registers:
+  //
+  // scratch1 - used to hold elements map and elements length.
+  //            Holds the elements map if not_fast_array branch is taken.
+  //
+  // scratch2 - used to hold the loaded value.
+
+  __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
+  __ cmp(scratch1, ip);
+  __ b(ne, not_fast_array);
+  // Check that the key (index) is within bounds.
+  __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
+  __ cmp(key, Operand(scratch1));
+  __ b(hs, out_of_range);
+  // Fast case: Do the load.
+  __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  // The key is a smi.
+  ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
+  __ ldr(scratch2,
+         MemOperand(scratch1, key, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+  __ cmp(scratch2, ip);
+  // In case the loaded value is the_hole we have to consult GetProperty
+  // to ensure the prototype chain is searched.
+  __ b(eq, out_of_range);
+  __ mov(result, scratch2);
+}
+
+
+// Checks whether a key is an array index string or a symbol string.
+// Falls through if a key is a symbol.
+static void GenerateKeyStringCheck(MacroAssembler* masm,
+                                   Register key,
+                                   Register map,
+                                   Register hash,
+                                   Label* index_string,
+                                   Label* not_symbol) {
+  // The key is not a smi.
+  // Is it a string?
+  __ CompareObjectType(key, map, hash, FIRST_NONSTRING_TYPE);
+  __ b(ge, not_symbol);
+
+  // Is the string an array index, with cached numeric value?
+  __ ldr(hash, FieldMemOperand(key, String::kHashFieldOffset));
+  __ tst(hash, Operand(String::kContainsCachedArrayIndexMask));
+  __ b(eq, index_string);
+
+  // Is the string a symbol?
+  // map: key map
+  __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  ASSERT(kSymbolTag != 0);
+  __ tst(hash, Operand(kIsSymbolMask));
+  __ b(eq, not_symbol);
+}
+
+
+// Picks out an array index from the hash field.
+static void GenerateIndexFromHash(MacroAssembler* masm,
+                                  Register key,
+                                  Register hash) {
+  // Register use:
+  //   key - holds the overwritten key on exit.
+  //   hash - holds the key's hash. Clobbered.
+
+  // If the hash field contains an array index pick it out. The assert checks
+  // that the constants for the maximum number of digits for an array index
+  // cached in the hash field and the number of bits reserved for it does not
+  // conflict.
+  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
+         (1 << String::kArrayIndexValueBits));
+  // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
+  // the low kHashShift bits.
+  ASSERT(String::kHashShift >= kSmiTagSize);
+  // Here we actually clobber the key which will be used if calling into
+  // runtime later. However as the new key is the numeric value of a string key
+  // there is no difference in using either key.
+  ASSERT(String::kHashShift >= kSmiTagSize);
+  __ Ubfx(hash, hash, String::kHashShift, String::kArrayIndexValueBits);
+  __ mov(key, Operand(hash, LSL, kSmiTagSize));
+}
+
+
 // Defined in ic.cc.
 Object* CallIC_Miss(Arguments args);
 
-void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+// The generated code does not accept smi keys.
+// The generated code falls through if both probes miss.
+static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
+                                          int argc,
+                                          Code::Kind kind) {
   // ----------- S t a t e -------------
+  //  -- r1    : receiver
   //  -- r2    : name
-  //  -- lr    : return address
   // -----------------------------------
   Label number, non_number, non_string, boolean, probe, miss;
 
-  // Get the receiver of the function from the stack into r1.
-  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
-
   // Probe the stub cache.
   Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
+      Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
   StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg);
 
   // If the stub cache probing failed, the receiver might be a value.
@@ -355,9 +498,7 @@
   __ bind(&probe);
   StubCache::GenerateProbe(masm, flags, r1, r2, r3, no_reg);
 
-  // Cache miss: Jump to runtime.
   __ bind(&miss);
-  GenerateMiss(masm, argc);
 }
 
 
@@ -390,7 +531,7 @@
 }
 
 
-void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+static void GenerateCallNormal(MacroAssembler* masm, int argc) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -443,13 +584,11 @@
   __ CheckAccessGlobalProxy(r1, r0, &miss);
   __ b(&invoke);
 
-  // Cache miss: Jump to runtime.
   __ bind(&miss);
-  GenerateMiss(masm, argc);
 }
 
 
-void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
   // ----------- S t a t e -------------
   //  -- r2    : name
   //  -- lr    : return address
@@ -465,7 +604,7 @@
 
   // Call the entry.
   __ mov(r0, Operand(2));
-  __ mov(r1, Operand(ExternalReference(IC_Utility(kCallIC_Miss))));
+  __ mov(r1, Operand(ExternalReference(IC_Utility(id))));
 
   CEntryStub stub(1);
   __ CallStub(&stub);
@@ -496,18 +635,165 @@
 }
 
 
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
+}
+
+
+void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack into r1.
+  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC);
+  GenerateMiss(masm, argc);
+}
+
+
+void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  GenerateCallNormal(masm, argc);
+  GenerateMiss(masm, argc);
+}
+
+
 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
-  UNREACHABLE();
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
 }
 
 
 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
-  UNREACHABLE();
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack into r1.
+  __ 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;
+
+  // Check that the key is a smi.
+  __ BranchOnNotSmi(r2, &check_string);
+  __ 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.
+
+  GenerateKeyedLoadReceiverCheck(masm, r1, r0, r3, &slow_call);
+
+  GenerateFastArrayLoad(
+      masm, r1, r2, r4, r3, r0, r1, &check_number_dictionary, &slow_load);
+  __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1, r0, r3);
+
+  __ bind(&do_call);
+  // receiver in r1 is not used after this point.
+  // r2: key
+  // r1: function
+
+  // Check that the value in r1 is a JSFunction.
+  __ BranchOnSmi(r1, &slow_call);
+  __ CompareObjectType(r1, r0, r0, JS_FUNCTION_TYPE);
+  __ b(ne, &slow_call);
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
+
+  __ bind(&check_number_dictionary);
+  // r2: key
+  // r3: elements map
+  // r4: elements
+  // Check whether the elements is a number dictionary.
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(r3, ip);
+  __ b(ne, &slow_load);
+  __ mov(r0, Operand(r2, ASR, kSmiTagSize));
+  // r0: untagged index
+  GenerateNumberDictionaryLoad(masm, &slow_load, r4, r2, r1, r0, r3, r5);
+  __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1, r0, r3);
+  __ jmp(&do_call);
+
+  __ bind(&slow_load);
+  // This branch is taken when calling KeyedCallIC_Miss is neither required
+  // nor beneficial.
+  __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1, r0, r3);
+  __ EnterInternalFrame();
+  __ push(r2);  // save the key
+  __ Push(r1, r2);  // pass the receiver and the key
+  __ CallRuntime(Runtime::kKeyedGetProperty, 2);
+  __ pop(r2);  // restore the key
+  __ LeaveInternalFrame();
+  __ mov(r1, r0);
+  __ jmp(&do_call);
+
+  __ bind(&check_string);
+  GenerateKeyStringCheck(masm, r2, r0, r3, &index_string, &slow_call);
+
+  // The key is known to be a symbol.
+  // 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.
+  GenerateKeyedLoadReceiverCheck(masm, r1, r0, r3, &lookup_monomorphic_cache);
+
+  __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset));
+  __ ldr(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
+  __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
+  __ cmp(r3, ip);
+  __ b(ne, &lookup_monomorphic_cache);
+
+  GenerateDictionaryLoad(
+      masm, &slow_load, r1, r2, r1, r0, r3, r4, DICTIONARY_CHECK_DONE);
+  __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1, r0, r3);
+  __ jmp(&do_call);
+
+  __ bind(&lookup_monomorphic_cache);
+  __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1, r0, r3);
+  GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
+  // Fall through on miss.
+
+  __ bind(&slow_call);
+  // This branch is taken if:
+  // - the receiver requires boxing or access check,
+  // - the key is neither smi nor symbol,
+  // - 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);
+  GenerateIndexFromHash(masm, r2, r3);
+  // Now jump to the place where smi keys are handled.
+  __ jmp(&index_smi);
 }
 
 
 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
-  UNREACHABLE();
+  // ----------- S t a t e -------------
+  //  -- r2    : name
+  //  -- lr    : return address
+  // -----------------------------------
+
+  GenerateCallNormal(masm, argc);
+  GenerateMiss(masm, argc);
 }
 
 
@@ -759,49 +1045,16 @@
   Register key = r0;
   Register receiver = r1;
 
-  // Check that the object isn't a smi.
-  __ BranchOnSmi(receiver, &slow);
-  // Get the map of the receiver.
-  __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
-  // Check bit field.
-  __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
-  __ tst(r3, Operand(kSlowCaseBitFieldMask));
-  __ b(ne, &slow);
-  // Check that the object is some kind of JS object EXCEPT JS Value type.
-  // In the case that the object is a value-wrapper object,
-  // we enter the runtime system to make sure that indexing into string
-  // objects work as intended.
-  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
-  __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
-  __ cmp(r2, Operand(JS_OBJECT_TYPE));
-  __ b(lt, &slow);
+  GenerateKeyedLoadReceiverCheck(masm, receiver, r2, r3, &slow);
 
   // Check that the key is a smi.
   __ BranchOnNotSmi(key, &check_string);
   __ 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.
-  __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
-  __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset));
-  __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
-  __ cmp(r3, ip);
-  __ b(ne, &check_pixel_array);
-  // Check that the key (index) is within bounds.
-  __ ldr(r3, FieldMemOperand(r4, FixedArray::kLengthOffset));
-  __ cmp(key, Operand(r3));
-  __ b(hs, &slow);
-  // Fast case: Do the load.
-  __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
-  // The key is a smi.
-  ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
-  __ ldr(r2, MemOperand(r3, key, LSL, kPointerSizeLog2 - kSmiTagSize));
-  __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
-  __ cmp(r2, ip);
-  // In case the loaded value is the_hole we have to consult GetProperty
-  // to ensure the prototype chain is searched.
-  __ b(eq, &slow);
-  __ mov(r0, r2);
+
+  GenerateFastArrayLoad(
+      masm, receiver, key, r4, r3, r2, r0, &check_pixel_array, &slow);
   __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3);
   __ Ret();
 
@@ -831,7 +1084,7 @@
   __ cmp(r3, ip);
   __ b(ne, &slow);
   __ mov(r2, Operand(r0, ASR, kSmiTagSize));
-  GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r2, r3, r5);
+  GenerateNumberDictionaryLoad(masm, &slow, r4, r0, r0, r2, r3, r5);
   __ Ret();
 
   // Slow case, key and receiver still in r0 and r1.
@@ -840,24 +1093,7 @@
   GenerateRuntimeGetProperty(masm);
 
   __ bind(&check_string);
-  // The key is not a smi.
-  // Is it a string?
-  // r0: key
-  // r1: receiver
-  __ CompareObjectType(r0, r2, r3, FIRST_NONSTRING_TYPE);
-  __ b(ge, &slow);
-
-  // Is the string an array index, with cached numeric value?
-  __ ldr(r3, FieldMemOperand(r0, String::kHashFieldOffset));
-  __ tst(r3, Operand(String::kContainsCachedArrayIndexMask));
-  __ b(eq, &index_string);
-
-  // Is the string a symbol?
-  // r2: key map
-  __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
-  ASSERT(kSymbolTag != 0);
-  __ tst(r3, Operand(kIsSymbolMask));
-  __ b(eq, &slow);
+  GenerateKeyStringCheck(masm, key, r2, r3, &index_string, &slow);
 
   // If the receiver is a fast-case object, check the keyed lookup
   // cache. Otherwise probe the dictionary.
@@ -873,7 +1109,7 @@
   __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift));
   __ ldr(r4, FieldMemOperand(r0, String::kHashFieldOffset));
   __ eor(r3, r3, Operand(r4, ASR, String::kHashShift));
-  __ and_(r3, r3, Operand(KeyedLookupCache::kCapacityMask));
+  __ And(r3, r3, Operand(KeyedLookupCache::kCapacityMask));
 
   // Load the key (consisting of map and symbol) from the cache and
   // check for match.
@@ -918,25 +1154,8 @@
   __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1, r2, r3);
   __ Ret();
 
-  __ b(&slow);
-  // If the hash field contains an array index pick it out. The assert checks
-  // that the constants for the maximum number of digits for an array index
-  // cached in the hash field and the number of bits reserved for it does not
-  // conflict.
-  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
-         (1 << String::kArrayIndexValueBits));
   __ bind(&index_string);
-  // r0: key (string)
-  // r1: receiver
-  // r3: hash field
-  // We want the smi-tagged index in r0.  kArrayIndexValueMask has zeros in
-  // the low kHashShift bits.
-  ASSERT(String::kHashShift >= kSmiTagSize);
-  __ and_(r3, r3, Operand(String::kArrayIndexValueMask));
-  // Here we actually clobber the key (r0) which will be used if calling into
-  // runtime later. However as the new key is the numeric value of a string key
-  // there is no difference in using either key.
-  __ mov(r0, Operand(r3, ASR, String::kHashShift - kSmiTagSize));
+  GenerateIndexFromHash(masm, key, r3);
   // Now jump to the place where smi keys are handled.
   __ jmp(&index_smi);
 }
@@ -1120,7 +1339,8 @@
     __ bind(&box_int);
     // Allocate a HeapNumber for the result and perform int-to-double
     // conversion. Use r0 for result as key is not needed any more.
-    __ AllocateHeapNumber(r0, r3, r4, &slow);
+    __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+    __ AllocateHeapNumber(r0, r3, r4, r6, &slow);
 
     if (CpuFeatures::IsSupported(VFP3)) {
       CpuFeatures::Scope scope(VFP3);
@@ -1151,7 +1371,8 @@
       // Allocate a HeapNumber for the result and perform int-to-double
       // conversion. Don't use r0 and r1 as AllocateHeapNumber clobbers all
       // registers - also when jumping due to exhausted young space.
-      __ AllocateHeapNumber(r2, r3, r4, &slow);
+      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
 
       __ vcvt_f64_u32(d0, s0);
       __ sub(r1, r2, Operand(kHeapObjectTag));
@@ -1188,7 +1409,8 @@
       // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber
       // clobbers all registers - also when jumping due to exhausted young
       // space.
-      __ AllocateHeapNumber(r4, r5, r6, &slow);
+      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+      __ AllocateHeapNumber(r4, r5, r7, r6, &slow);
 
       __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset));
       __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
@@ -1204,7 +1426,8 @@
       // Allocate a HeapNumber for the result. Don't use r0 and r1 as
       // AllocateHeapNumber clobbers all registers - also when jumping due to
       // exhausted young space.
-      __ AllocateHeapNumber(r2, r3, r4, &slow);
+      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+      __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
       __ vcvt_f64_f32(d0, s0);
       __ sub(r1, r2, Operand(kHeapObjectTag));
       __ vstr(d0, r1, HeapNumber::kValueOffset);
@@ -1215,7 +1438,8 @@
       // Allocate a HeapNumber for the result. Don't use r0 and r1 as
       // AllocateHeapNumber clobbers all registers - also when jumping due to
       // exhausted young space.
-      __ AllocateHeapNumber(r3, r4, r5, &slow);
+      __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
+      __ AllocateHeapNumber(r3, r4, r5, r6, &slow);
       // VFP is not available, do manual single to double conversion.
 
       // r2: floating point value (binary32)
@@ -1473,7 +1697,7 @@
   __ Ret(eq);
   // Update write barrier for the elements array address.
   __ sub(r4, r5, Operand(elements));
-  __ RecordWrite(elements, r4, r5);
+  __ RecordWrite(elements, Operand(r4), r5, r6);
 
   __ Ret();
 }
@@ -1665,32 +1889,29 @@
   if (CpuFeatures::IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
 
-    // vldr requires offset to be a multiple of 4 so we can not
-    // include -kHeapObjectTag into it.
-    __ sub(r5, r0, Operand(kHeapObjectTag));
-    __ vldr(d0, r5, HeapNumber::kValueOffset);
 
     if (array_type == kExternalFloatArray) {
+      // vldr requires offset to be a multiple of 4 so we can not
+      // include -kHeapObjectTag into it.
+      __ sub(r5, r0, Operand(kHeapObjectTag));
+      __ vldr(d0, r5, HeapNumber::kValueOffset);
       __ vcvt_f32_f64(s0, d0);
       __ vmov(r5, s0);
       __ str(r5, MemOperand(r3, r4, LSL, 2));
     } else {
-      Label done;
-
       // Need to perform float-to-int conversion.
-      // Test for NaN.
-      __ vcmp(d0, d0);
-      // Move vector status bits to normal status bits.
-      __ vmrs(v8::internal::pc);
-      __ mov(r5, Operand(0), LeaveCC, vs);  // NaN converts to 0.
-      __ b(vs, &done);
+      // Test for NaN or infinity (both give zero).
+      __ ldr(r6, FieldMemOperand(r5, HeapNumber::kExponentOffset));
 
-      // Test whether exponent equal to 0x7FF (infinity or NaN).
-      __ vmov(r6, r7, d0);
-      __ mov(r5, Operand(0x7FF00000));
-      __ and_(r6, r6, Operand(r5));
-      __ teq(r6, Operand(r5));
-      __ mov(r6, Operand(0), LeaveCC, eq);
+      // Hoisted load.  vldr requires offset to be a multiple of 4 so we can not
+      // include -kHeapObjectTag into it.
+      __ sub(r5, r0, Operand(kHeapObjectTag));
+      __ vldr(d0, r5, HeapNumber::kValueOffset);
+
+      __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
+      // NaNs and Infinities have all-one exponents so they sign extend to -1.
+      __ cmp(r6, Operand(-1));
+      __ mov(r5, Operand(Smi::FromInt(0)), LeaveCC, eq);
 
       // Not infinity or NaN simply convert to int.
       if (IsElementTypeSigned(array_type)) {
@@ -1698,10 +1919,8 @@
       } else {
         __ vcvt_u32_f64(s0, d0, ne);
       }
-
       __ vmov(r5, s0, ne);
 
-      __ bind(&done);
       switch (array_type) {
         case kExternalByteArray:
         case kExternalUnsignedByteArray:
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 6292b58..29e168c 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -216,6 +216,71 @@
 }
 
 
+void MacroAssembler::And(Register dst, Register src1, const Operand& src2,
+                         Condition cond) {
+  if (!CpuFeatures::IsSupported(ARMv7) || src2.is_single_instruction()) {
+    and_(dst, src1, src2, LeaveCC, cond);
+    return;
+  }
+  int32_t immediate = src2.immediate();
+  if (immediate == 0) {
+    mov(dst, Operand(0), LeaveCC, cond);
+    return;
+  }
+  if (IsPowerOf2(immediate + 1) && ((immediate & 1) != 0)) {
+    ubfx(dst, src1, 0, WhichPowerOf2(immediate + 1), cond);
+    return;
+  }
+  and_(dst, src1, src2, LeaveCC, cond);
+}
+
+
+void MacroAssembler::Ubfx(Register dst, Register src1, int lsb, int width,
+                          Condition cond) {
+  ASSERT(lsb < 32);
+  if (!CpuFeatures::IsSupported(ARMv7)) {
+    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
+    and_(dst, src1, Operand(mask), LeaveCC, cond);
+    if (lsb != 0) {
+      mov(dst, Operand(dst, LSR, lsb), LeaveCC, cond);
+    }
+  } else {
+    ubfx(dst, src1, lsb, width, cond);
+  }
+}
+
+
+void MacroAssembler::Sbfx(Register dst, Register src1, int lsb, int width,
+                          Condition cond) {
+  ASSERT(lsb < 32);
+  if (!CpuFeatures::IsSupported(ARMv7)) {
+    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
+    and_(dst, src1, Operand(mask), LeaveCC, cond);
+    int shift_up = 32 - lsb - width;
+    int shift_down = lsb + shift_up;
+    if (shift_up != 0) {
+      mov(dst, Operand(dst, LSL, shift_up), LeaveCC, cond);
+    }
+    if (shift_down != 0) {
+      mov(dst, Operand(dst, ASR, shift_down), LeaveCC, cond);
+    }
+  } else {
+    sbfx(dst, src1, lsb, width, cond);
+  }
+}
+
+
+void MacroAssembler::Bfc(Register dst, int lsb, int width, Condition cond) {
+  ASSERT(lsb < 32);
+  if (!CpuFeatures::IsSupported(ARMv7)) {
+    int mask = (1 << (width + lsb)) - 1 - ((1 << lsb) - 1);
+    bic(dst, dst, Operand(mask));
+  } else {
+    bfc(dst, lsb, width, cond);
+  }
+}
+
+
 void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
   // Empty the const pool.
   CheckConstPool(true, true);
@@ -245,31 +310,32 @@
 
 
 void MacroAssembler::RecordWriteHelper(Register object,
-                                       Register offset,
-                                       Register scratch) {
+                                       Operand offset,
+                                       Register scratch0,
+                                       Register scratch1) {
   if (FLAG_debug_code) {
     // Check that the object is not in new space.
     Label not_in_new_space;
-    InNewSpace(object, scratch, ne, &not_in_new_space);
+    InNewSpace(object, scratch1, ne, &not_in_new_space);
     Abort("new-space object passed to RecordWriteHelper");
     bind(&not_in_new_space);
   }
 
-  mov(ip, Operand(Page::kPageAlignmentMask));  // Load mask only once.
-
-  // Calculate region number.
-  add(offset, object, Operand(offset));  // Add offset into the object.
-  and_(offset, offset, Operand(ip));  // Offset into page of the object.
-  mov(offset, Operand(offset, LSR, Page::kRegionSizeLog2));
+  // Add offset into the object.
+  add(scratch0, object, offset);
 
   // Calculate page address.
-  bic(object, object, Operand(ip));
+  Bfc(object, 0, kPageSizeBits);
+
+  // Calculate region number.
+  Ubfx(scratch0, scratch0, Page::kRegionSizeLog2,
+       kPageSizeBits - Page::kRegionSizeLog2);
 
   // Mark region dirty.
-  ldr(scratch, MemOperand(object, Page::kDirtyFlagOffset));
+  ldr(scratch1, MemOperand(object, Page::kDirtyFlagOffset));
   mov(ip, Operand(1));
-  orr(scratch, scratch, Operand(ip, LSL, offset));
-  str(scratch, MemOperand(object, Page::kDirtyFlagOffset));
+  orr(scratch1, scratch1, Operand(ip, LSL, scratch0));
+  str(scratch1, MemOperand(object, Page::kDirtyFlagOffset));
 }
 
 
@@ -287,21 +353,23 @@
 // Will clobber 4 registers: object, offset, scratch, ip.  The
 // register 'object' contains a heap object pointer.  The heap object
 // tag is shifted away.
-void MacroAssembler::RecordWrite(Register object, Register offset,
-                                 Register scratch) {
+void MacroAssembler::RecordWrite(Register object,
+                                 Operand offset,
+                                 Register scratch0,
+                                 Register scratch1) {
   // The compiled code assumes that record write doesn't change the
   // context register, so we check that none of the clobbered
   // registers are cp.
-  ASSERT(!object.is(cp) && !offset.is(cp) && !scratch.is(cp));
+  ASSERT(!object.is(cp) && !scratch0.is(cp) && !scratch1.is(cp));
 
   Label done;
 
   // First, test that the object is not in the new space.  We cannot set
   // region marks for new space pages.
-  InNewSpace(object, scratch, eq, &done);
+  InNewSpace(object, scratch0, eq, &done);
 
   // Record the actual write.
-  RecordWriteHelper(object, offset, scratch);
+  RecordWriteHelper(object, offset, scratch0, scratch1);
 
   bind(&done);
 
@@ -309,8 +377,8 @@
   // turned on to provoke errors.
   if (FLAG_debug_code) {
     mov(object, Operand(BitCast<int32_t>(kZapValue)));
-    mov(offset, Operand(BitCast<int32_t>(kZapValue)));
-    mov(scratch, Operand(BitCast<int32_t>(kZapValue)));
+    mov(scratch0, Operand(BitCast<int32_t>(kZapValue)));
+    mov(scratch1, Operand(BitCast<int32_t>(kZapValue)));
   }
 }
 
@@ -1460,6 +1528,16 @@
 }
 
 
+void MacroAssembler::AssertRegisterIsRoot(Register reg,
+                                          Heap::RootListIndex index) {
+  if (FLAG_debug_code) {
+    LoadRoot(ip, index);
+    cmp(reg, ip);
+    Check(eq, "Register did not match expected root");
+  }
+}
+
+
 void MacroAssembler::Check(Condition cc, const char* msg) {
   Label L;
   b(cc, &L);
@@ -1578,6 +1656,7 @@
 void MacroAssembler::AllocateHeapNumber(Register result,
                                         Register scratch1,
                                         Register scratch2,
+                                        Register heap_number_map,
                                         Label* gc_required) {
   // Allocate an object in the heap for the heap number and tag it as a heap
   // object.
@@ -1588,9 +1667,9 @@
                      gc_required,
                      TAG_OBJECT);
 
-  // Get heap number map and store it in the allocated object.
-  LoadRoot(scratch1, Heap::kHeapNumberMapRootIndex);
-  str(scratch1, FieldMemOperand(result, HeapObject::kMapOffset));
+  // Store heap number map in the allocated object.
+  AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+  str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
 }
 
 
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 87f7b5f..e02a6c8 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -93,6 +93,15 @@
             Register scratch = no_reg,
             Condition cond = al);
 
+
+  void And(Register dst, Register src1, const Operand& src2,
+           Condition cond = al);
+  void Ubfx(Register dst, Register src, int lsb, int width,
+            Condition cond = al);
+  void Sbfx(Register dst, Register src, int lsb, int width,
+            Condition cond = al);
+  void Bfc(Register dst, int lsb, int width, Condition cond = al);
+
   void Call(Label* target);
   void Move(Register dst, Handle<Object> value);
   // May do nothing if the registers are identical.
@@ -119,13 +128,19 @@
 
   // For the page containing |object| mark the region covering [object+offset]
   // dirty. The object address must be in the first 8K of an allocated page.
-  void RecordWriteHelper(Register object, Register offset, Register scratch);
+  void RecordWriteHelper(Register object,
+                         Operand offset,
+                         Register scratch0,
+                         Register scratch1);
 
   // For the page containing |object| mark the region covering [object+offset]
   // dirty. The object address must be in the first 8K of an allocated page.
-  // The 'scratch' register is used in the implementation and all 3 registers
+  // The 'scratch' registers are used in the implementation and all 3 registers
   // are clobbered by the operation, as well as the ip register.
-  void RecordWrite(Register object, Register offset, Register scratch);
+  void RecordWrite(Register object,
+                   Operand offset,
+                   Register scratch0,
+                   Register scratch1);
 
   // Push two registers.  Pushes leftmost register first (to highest address).
   void Push(Register src1, Register src2, Condition cond = al) {
@@ -364,6 +379,7 @@
   void AllocateHeapNumber(Register result,
                           Register scratch1,
                           Register scratch2,
+                          Register heap_number_map,
                           Label* gc_required);
 
   // ---------------------------------------------------------------------------
@@ -543,6 +559,7 @@
   // Calls Abort(msg) if the condition cc is not satisfied.
   // Use --debug_code to enable.
   void Assert(Condition cc, const char* msg);
+  void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
 
   // Like Assert(), but always enabled.
   void Check(Condition cc, const char* msg);
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 3bdca38..77776c2 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -1859,7 +1859,9 @@
           SetNZFlags(alu_out);
           SetCFlag(shifter_carry_out);
         } else {
-          UNIMPLEMENTED();
+          // Format(instr, "movw'cond 'rd, 'imm").
+          alu_out = instr->ImmedMovwMovtField();
+          set_register(rd, alu_out);
         }
         break;
       }
@@ -1888,7 +1890,10 @@
           SetCFlag(!BorrowFrom(rn_val, shifter_operand));
           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
         } else {
-          UNIMPLEMENTED();
+          // Format(instr, "movt'cond 'rd, 'imm").
+          alu_out = (get_register(rd) & 0xffff) |
+              (instr->ImmedMovwMovtField() << 16);
+          set_register(rd, alu_out);
         }
         break;
       }
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 3992d6c..3e5ba11 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -336,9 +336,8 @@
     __ b(eq, &exit);
 
     // Update the write barrier for the array address.
-    // Pass the value being stored in the now unused name_reg.
-    __ mov(name_reg, Operand(offset));
-    __ RecordWrite(receiver_reg, name_reg, scratch);
+    // Pass the now unused name_reg as a scratch register.
+    __ RecordWrite(receiver_reg, Operand(offset), name_reg, scratch);
   } else {
     // Write to the properties array.
     int offset = index * kPointerSize + FixedArray::kHeaderSize;
@@ -352,8 +351,7 @@
 
     // Update the write barrier for the array address.
     // Ok to clobber receiver_reg and name_reg, since we return.
-    __ mov(name_reg, Operand(offset));
-    __ RecordWrite(scratch, name_reg, receiver_reg);
+    __ RecordWrite(scratch, Operand(offset), name_reg, receiver_reg);
   }
 
   // Return the value (register r0).
@@ -1019,6 +1017,14 @@
 }
 
 
+void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
+  if (kind_ == Code::KEYED_CALL_IC) {
+    __ cmp(r2, Operand(Handle<String>(name)));
+    __ b(ne, miss);
+  }
+}
+
+
 void CallStubCompiler::GenerateMissBranch() {
   Handle<Code> ic = ComputeCallMiss(arguments().immediate(), kind_);
   __ Jump(ic, RelocInfo::CODE_TARGET);
@@ -1035,6 +1041,8 @@
   // -----------------------------------
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   const int argc = arguments().immediate();
 
   // Get the receiver of the function from the stack into r0.
@@ -1078,6 +1086,8 @@
 
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the receiver from the stack
   const int argc = arguments().immediate();
   __ ldr(r1, MemOperand(sp, argc * kPointerSize));
@@ -1127,6 +1137,8 @@
 
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the receiver from the stack
   const int argc = arguments().immediate();
   __ ldr(r1, MemOperand(sp, argc * kPointerSize));
@@ -1198,6 +1210,8 @@
 
   Label miss_in_smi_check;
 
+  GenerateNameCheck(name, &miss_in_smi_check);
+
   // Get the receiver from the stack
   const int argc = arguments().immediate();
   __ ldr(r1, MemOperand(sp, argc * kPointerSize));
@@ -1337,6 +1351,8 @@
 
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the number of arguments.
   const int argc = arguments().immediate();
 
@@ -1384,6 +1400,8 @@
   // -----------------------------------
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the number of arguments.
   const int argc = arguments().immediate();
 
diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc
index 334ca35..8b90f42 100644
--- a/src/arm/virtual-frame-arm.cc
+++ b/src/arm/virtual-frame-arm.cc
@@ -367,6 +367,7 @@
                                   int dropped_args) {
   switch (code->kind()) {
     case Code::CALL_IC:
+    case Code::KEYED_CALL_IC:
     case Code::FUNCTION:
       break;
     case Code::KEYED_LOAD_IC:
diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h
index e97ad49..d8dc5c6 100644
--- a/src/arm/virtual-frame-arm.h
+++ b/src/arm/virtual-frame-arm.h
@@ -212,10 +212,9 @@
   void Enter();
   void Exit();
 
-  // Prepare for returning from the frame by spilling locals and
-  // dropping all non-locals elements in the virtual frame.  This
+  // Prepare for returning from the frame by elements in the virtual frame. This
   // avoids generating unnecessary merge code when jumping to the
-  // shared return site.  Emits code for spills.
+  // shared return site. No spill code emitted. Value to return should be in r0.
   inline void PrepareForReturn();
 
   // Number of local variables after when we use a loop for allocating.
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 0874131..bbd69ec 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1462,6 +1462,7 @@
   }
 
   if (FLAG_expose_gc) InstallExtension("v8/gc");
+  if (FLAG_expose_externalize_string) InstallExtension("v8/externalize");
 
   if (extensions == NULL) return true;
   // Install required extensions
diff --git a/src/checks.h b/src/checks.h
index c2e40ba..13374d8 100644
--- a/src/checks.h
+++ b/src/checks.h
@@ -155,9 +155,9 @@
 static inline void CheckEqualsHelper(const char* file,
                                      int line,
                                      const char* expected_source,
-                                     void* expected,
+                                     const void* expected,
                                      const char* value_source,
-                                     void* value) {
+                                     const void* value) {
   if (expected != value) {
     V8_Fatal(file, line,
              "CHECK_EQ(%s, %s) failed\n#   Expected: %p\n#   Found: %p",
@@ -170,9 +170,9 @@
 static inline void CheckNonEqualsHelper(const char* file,
                                         int line,
                                         const char* expected_source,
-                                        void* expected,
+                                        const void* expected,
                                         const char* value_source,
-                                        void* value) {
+                                        const void* value) {
   if (expected == value) {
     V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n#   Value: %p",
              expected_source, value_source, value);
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index 77fa1dd..d5e91cb 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -295,7 +295,6 @@
 }
 
 
-
 ScriptBreakPoint.prototype.hit_count = function() {
   return this.hit_count_;
 };
@@ -389,7 +388,10 @@
   // Create a break point object and set the break point.
   break_point = MakeBreakPoint(pos, this.line(), this.column(), this);
   break_point.setIgnoreCount(this.ignoreCount());
-  %SetScriptBreakPoint(script, pos, break_point);
+  pos = %SetScriptBreakPoint(script, pos, break_point);
+  if (!IS_UNDEFINED(pos)) {
+    this.actual_location = script.locationFromPosition(pos);
+  }
 
   return break_point;
 };
diff --git a/src/debug.cc b/src/debug.cc
index 98e366c..d513b31 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1028,8 +1028,8 @@
 
 
 void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
-                          int source_position,
-                          Handle<Object> break_point_object) {
+                          Handle<Object> break_point_object,
+                          int* source_position) {
   HandleScope scope;
 
   if (!EnsureDebugInfo(shared)) {
@@ -1043,9 +1043,11 @@
 
   // Find the break point and change it.
   BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
-  it.FindBreakLocationFromPosition(source_position);
+  it.FindBreakLocationFromPosition(*source_position);
   it.SetBreakPoint(break_point_object);
 
+  *source_position = it.position();
+
   // At least one active break point now.
   ASSERT(debug_info->GetBreakPointCount() > 0);
 }
diff --git a/src/debug.h b/src/debug.h
index 1c67471..6019294 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -230,8 +230,8 @@
 
   static Object* Break(Arguments args);
   static void SetBreakPoint(Handle<SharedFunctionInfo> shared,
-                            int source_position,
-                            Handle<Object> break_point_object);
+                            Handle<Object> break_point_object,
+                            int* source_position);
   static void ClearBreakPoint(Handle<Object> break_point_object);
   static void ClearAllBreakPoints();
   static void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
diff --git a/src/execution.cc b/src/execution.cc
index 006d358..a6b15cc 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -679,7 +679,7 @@
 
 // --- G C   E x t e n s i o n ---
 
-const char* GCExtension::kSource = "native function gc();";
+const char* const GCExtension::kSource = "native function gc();";
 
 
 v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
@@ -695,7 +695,115 @@
 }
 
 
-static GCExtension kGCExtension;
-v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
+static GCExtension gc_extension;
+static v8::DeclareExtension gc_extension_declaration(&gc_extension);
+
+
+// --- E x t e r n a l i z e S t r i n g   E x t e n s i o n ---
+
+
+template <typename Char, typename Base>
+class SimpleStringResource : public Base {
+ public:
+  // Takes ownership of |data|.
+  SimpleStringResource(Char* data, size_t length)
+      : data_(data),
+        length_(length) {}
+
+  virtual ~SimpleStringResource() { delete data_; }
+
+  virtual const Char* data() const { return data_; }
+
+  virtual size_t length() const { return length_; }
+
+ private:
+  Char* const data_;
+  const size_t length_;
+};
+
+
+typedef SimpleStringResource<char, v8::String::ExternalAsciiStringResource>
+    SimpleAsciiStringResource;
+typedef SimpleStringResource<uc16, v8::String::ExternalStringResource>
+    SimpleTwoByteStringResource;
+
+
+const char* const ExternalizeStringExtension::kSource =
+    "native function externalizeString();"
+    "native function isAsciiString();";
+
+
+v8::Handle<v8::FunctionTemplate> ExternalizeStringExtension::GetNativeFunction(
+    v8::Handle<v8::String> str) {
+  if (strcmp(*v8::String::AsciiValue(str), "externalizeString") == 0) {
+    return v8::FunctionTemplate::New(ExternalizeStringExtension::Externalize);
+  } else {
+    ASSERT(strcmp(*v8::String::AsciiValue(str), "isAsciiString") == 0);
+    return v8::FunctionTemplate::New(ExternalizeStringExtension::IsAscii);
+  }
+}
+
+
+v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
+    const v8::Arguments& args) {
+  if (args.Length() < 1 || !args[0]->IsString()) {
+    return v8::ThrowException(v8::String::New(
+        "First parameter to externalizeString() must be a string."));
+  }
+  bool force_two_byte = false;
+  if (args.Length() >= 2) {
+    if (args[1]->IsBoolean()) {
+      force_two_byte = args[1]->BooleanValue();
+    } else {
+      return v8::ThrowException(v8::String::New(
+          "Second parameter to externalizeString() must be a boolean."));
+    }
+  }
+  bool result = false;
+  Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
+  if (string->IsExternalString()) {
+    return v8::ThrowException(v8::String::New(
+        "externalizeString() can't externalize twice."));
+  }
+  if (string->IsAsciiRepresentation() && !force_two_byte) {
+    char* data = new char[string->length()];
+    String::WriteToFlat(*string, data, 0, string->length());
+    SimpleAsciiStringResource* resource = new SimpleAsciiStringResource(
+        data, string->length());
+    result = string->MakeExternal(resource);
+    if (result && !string->IsSymbol()) {
+      i::ExternalStringTable::AddString(*string);
+    }
+  } else {
+    uc16* data = new uc16[string->length()];
+    String::WriteToFlat(*string, data, 0, string->length());
+    SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
+        data, string->length());
+    result = string->MakeExternal(resource);
+    if (result && !string->IsSymbol()) {
+      i::ExternalStringTable::AddString(*string);
+    }
+  }
+  if (!result) {
+    return v8::ThrowException(v8::String::New("externalizeString() failed."));
+  }
+  return v8::Undefined();
+}
+
+
+v8::Handle<v8::Value> ExternalizeStringExtension::IsAscii(
+    const v8::Arguments& args) {
+  if (args.Length() != 1 || !args[0]->IsString()) {
+    return v8::ThrowException(v8::String::New(
+        "isAsciiString() requires a single string argument."));
+  }
+  return Utils::OpenHandle(*args[0].As<v8::String>())->IsAsciiRepresentation() ?
+      v8::True() : v8::False();
+}
+
+
+static ExternalizeStringExtension externalize_extension;
+static v8::DeclareExtension externalize_extension_declaration(
+    &externalize_extension);
 
 } }  // namespace v8::internal
diff --git a/src/execution.h b/src/execution.h
index e683e12..2823503 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -316,10 +316,21 @@
       v8::Handle<v8::String> name);
   static v8::Handle<v8::Value> GC(const v8::Arguments& args);
  private:
-  static const char* kSource;
+  static const char* const kSource;
 };
 
 
+class ExternalizeStringExtension : public v8::Extension {
+ public:
+  ExternalizeStringExtension() : v8::Extension("v8/externalize", kSource) {}
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+      v8::Handle<v8::String> name);
+  static v8::Handle<v8::Value> Externalize(const v8::Arguments& args);
+  static v8::Handle<v8::Value> IsAscii(const v8::Arguments& args);
+ private:
+  static const char* const kSource;
+};
+
 } }  // namespace v8::internal
 
 #endif  // V8_EXECUTION_H_
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 91477f9..02e8f16 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -123,6 +123,8 @@
 DEFINE_string(expose_natives_as, NULL, "expose natives in global object")
 DEFINE_string(expose_debug_as, NULL, "expose debug in global object")
 DEFINE_bool(expose_gc, false, "expose gc extension")
+DEFINE_bool(expose_externalize_string, false,
+            "expose externalize string extension")
 DEFINE_int(stack_trace_limit, 10, "number of stack frames to capture")
 DEFINE_bool(disable_native_files, false, "disable builtin natives files")
 
@@ -191,7 +193,7 @@
             "print more details following each garbage collection")
 DEFINE_bool(collect_maps, true,
             "garbage collect maps from which no objects can be reached")
-DEFINE_bool(flush_code, false,
+DEFINE_bool(flush_code, true,
             "flush code that we expect not to use again before full gc")
 
 // v8.cc
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index 90544f1..73b9748 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -30,8 +30,8 @@
 #include "heap-profiler.h"
 #include "frames-inl.h"
 #include "global-handles.h"
+#include "profile-generator.h"
 #include "string-stream.h"
-#include "zone-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -314,6 +314,83 @@
 }  // namespace
 
 
+HeapProfiler* HeapProfiler::singleton_ = NULL;
+
+HeapProfiler::HeapProfiler()
+    : snapshots_(new HeapSnapshotsCollection()),
+      next_snapshot_uid_(1) {
+}
+
+
+HeapProfiler::~HeapProfiler() {
+  delete snapshots_;
+}
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+void HeapProfiler::Setup() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (singleton_ == NULL) {
+    singleton_ = new HeapProfiler();
+  }
+#endif
+}
+
+
+void HeapProfiler::TearDown() {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  delete singleton_;
+  singleton_ = NULL;
+#endif
+}
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+HeapSnapshot* HeapProfiler::TakeSnapshot(const char* name) {
+  ASSERT(singleton_ != NULL);
+  return singleton_->TakeSnapshotImpl(name);
+}
+
+
+HeapSnapshot* HeapProfiler::TakeSnapshot(String* name) {
+  ASSERT(singleton_ != NULL);
+  return singleton_->TakeSnapshotImpl(name);
+}
+
+
+HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name) {
+  Heap::CollectAllGarbage(false);
+  HeapSnapshot* result = snapshots_->NewSnapshot(name, next_snapshot_uid_++);
+  HeapSnapshotGenerator generator(result);
+  generator.GenerateSnapshot();
+  return result;
+}
+
+
+HeapSnapshot* HeapProfiler::TakeSnapshotImpl(String* name) {
+  return TakeSnapshotImpl(snapshots_->GetName(name));
+}
+
+
+int HeapProfiler::GetSnapshotsCount() {
+  ASSERT(singleton_ != NULL);
+  return singleton_->snapshots_->snapshots()->length();
+}
+
+
+HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
+  ASSERT(singleton_ != NULL);
+  return singleton_->snapshots_->snapshots()->at(index);
+}
+
+
+HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
+  ASSERT(singleton_ != NULL);
+  return singleton_->snapshots_->GetSnapshot(uid);
+}
+
+
 const JSObjectsClusterTreeConfig::Key JSObjectsClusterTreeConfig::kNoKey;
 const JSObjectsClusterTreeConfig::Value JSObjectsClusterTreeConfig::kNoValue;
 
diff --git a/src/heap-profiler.h b/src/heap-profiler.h
index d6f2650..b593b99 100644
--- a/src/heap-profiler.h
+++ b/src/heap-profiler.h
@@ -28,26 +28,56 @@
 #ifndef V8_HEAP_PROFILER_H_
 #define V8_HEAP_PROFILER_H_
 
-#include "zone.h"
+#include "zone-inl.h"
 
 namespace v8 {
 namespace internal {
 
 #ifdef ENABLE_LOGGING_AND_PROFILING
 
+class HeapSnapshot;
+class HeapSnapshotsCollection;
+
+#endif
+
 // The HeapProfiler writes data to the log files, which can be postprocessed
 // to generate .hp files for use by the GHC/Valgrind tool hp2ps.
 class HeapProfiler {
  public:
+  static void Setup();
+  static void TearDown();
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  static HeapSnapshot* TakeSnapshot(const char* name);
+  static HeapSnapshot* TakeSnapshot(String* name);
+  static int GetSnapshotsCount();
+  static HeapSnapshot* GetSnapshot(int index);
+  static HeapSnapshot* FindSnapshot(unsigned uid);
+
+  // Obsolete interface.
   // Write a single heap sample to the log file.
   static void WriteSample();
 
  private:
+  HeapProfiler();
+  ~HeapProfiler();
+  HeapSnapshot* TakeSnapshotImpl(const char* name);
+  HeapSnapshot* TakeSnapshotImpl(String* name);
+
+  // Obsolete interface.
   // Update the array info with stats from obj.
   static void CollectStats(HeapObject* obj, HistogramInfo* info);
+
+  HeapSnapshotsCollection* snapshots_;
+  unsigned next_snapshot_uid_;
+
+  static HeapProfiler* singleton_;
+#endif  // ENABLE_LOGGING_AND_PROFILING
 };
 
 
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
 // JSObjectsCluster describes a group of JS objects that are
 // considered equivalent in terms of a particular profile.
 class JSObjectsCluster BASE_EMBEDDED {
diff --git a/src/heap.cc b/src/heap.cc
index 3fc7d02..f1ec56c 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1929,6 +1929,18 @@
     return Failure::OutOfMemoryException();
   }
 
+  bool is_ascii_data_in_two_byte_string = false;
+  if (!is_ascii) {
+    // At least one of the strings uses two-byte representation so we
+    // can't use the fast case code for short ascii strings below, but
+    // we can try to save memory if all chars actually fit in ascii.
+    is_ascii_data_in_two_byte_string =
+        first->HasOnlyAsciiChars() && second->HasOnlyAsciiChars();
+    if (is_ascii_data_in_two_byte_string) {
+      Counters::string_add_runtime_ext_to_ascii.Increment();
+    }
+  }
+
   // If the resulting string is small make a flat string.
   if (length < String::kMinNonFlatLength) {
     ASSERT(first->IsFlat());
@@ -1955,22 +1967,13 @@
       for (int i = 0; i < second_length; i++) *dest++ = src[i];
       return result;
     } else {
-      // For short external two-byte strings we check whether they can
-      // be represented using ascii.
-      if (!first_is_ascii) {
-        first_is_ascii = first->IsExternalTwoByteStringWithAsciiChars();
-      }
-      if (first_is_ascii && !second_is_ascii) {
-        second_is_ascii = second->IsExternalTwoByteStringWithAsciiChars();
-      }
-      if (first_is_ascii && second_is_ascii) {
+      if (is_ascii_data_in_two_byte_string) {
         Object* result = AllocateRawAsciiString(length);
         if (result->IsFailure()) return result;
         // Copy the characters into the new object.
         char* dest = SeqAsciiString::cast(result)->GetChars();
         String::WriteToFlat(first, dest, 0, first_length);
         String::WriteToFlat(second, dest + first_length, 0, second_length);
-        Counters::string_add_runtime_ext_to_ascii.Increment();
         return result;
       }
 
@@ -1984,7 +1987,8 @@
     }
   }
 
-  Map* map = is_ascii ? cons_ascii_string_map() : cons_string_map();
+  Map* map = (is_ascii || is_ascii_data_in_two_byte_string) ?
+      cons_ascii_string_map() : cons_string_map();
 
   Object* result = Allocate(map, NEW_SPACE);
   if (result->IsFailure()) return result;
@@ -2070,7 +2074,23 @@
     return Failure::OutOfMemoryException();
   }
 
-  Map* map = Heap::external_string_map();
+  // For small strings we check whether the resource contains only
+  // ascii characters.  If yes, we use a different string map.
+  bool is_ascii = true;
+  if (length >= static_cast<size_t>(String::kMinNonFlatLength)) {
+    is_ascii = false;
+  } else {
+    const uc16* data = resource->data();
+    for (size_t i = 0; i < length; i++) {
+      if (data[i] > String::kMaxAsciiCharCode) {
+        is_ascii = false;
+        break;
+      }
+    }
+  }
+
+  Map* map = is_ascii ?
+      Heap::external_string_with_ascii_data_map() : Heap::external_string_map();
   Object* result = Allocate(map, NEW_SPACE);
   if (result->IsFailure()) return result;
 
@@ -2244,6 +2264,12 @@
   ThreadManager::IterateArchivedThreads(&threadvisitor);
   if (threadvisitor.FoundCode()) return;
 
+  // Check that there are heap allocated locals in the scopeinfo. If
+  // there is, we are potentially using eval and need the scopeinfo
+  // for variable resolution.
+  if (ScopeInfo<>::HasHeapAllocatedLocals(function_info->code()))
+    return;
+
   HandleScope scope;
   // Compute the lazy compilable version of the code.
   function_info->set_code(*ComputeLazyCompile(function_info->length()));
@@ -2853,6 +2879,9 @@
   if (map == cons_ascii_string_map()) return cons_ascii_symbol_map();
   if (map == external_string_map()) return external_symbol_map();
   if (map == external_ascii_string_map()) return external_ascii_symbol_map();
+  if (map == external_string_with_ascii_data_map()) {
+    return external_symbol_with_ascii_data_map();
+  }
 
   // No match found.
   return NULL;
diff --git a/src/heap.h b/src/heap.h
index 0db4008..a8f8c34 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -69,10 +69,12 @@
   V(Map, cons_symbol_map, ConsSymbolMap)                                       \
   V(Map, cons_ascii_symbol_map, ConsAsciiSymbolMap)                            \
   V(Map, external_symbol_map, ExternalSymbolMap)                               \
+  V(Map, external_symbol_with_ascii_data_map, ExternalSymbolWithAsciiDataMap)  \
   V(Map, external_ascii_symbol_map, ExternalAsciiSymbolMap)                    \
   V(Map, cons_string_map, ConsStringMap)                                       \
   V(Map, cons_ascii_string_map, ConsAsciiStringMap)                            \
   V(Map, external_string_map, ExternalStringMap)                               \
+  V(Map, external_string_with_ascii_data_map, ExternalStringWithAsciiDataMap)  \
   V(Map, external_ascii_string_map, ExternalAsciiStringMap)                    \
   V(Map, undetectable_string_map, UndetectableStringMap)                       \
   V(Map, undetectable_ascii_string_map, UndetectableAsciiStringMap)            \
@@ -1882,8 +1884,8 @@
   };
   inline static int Hash(const Converter& c) {
     uint32_t hash = (c.integers[0] ^ c.integers[1]);
-    hash ^= hash >> 16;
-    hash ^= hash >> 8;
+    hash ^= static_cast<int32_t>(hash) >> 16;
+    hash ^= static_cast<int32_t>(hash) >> 8;
     return (hash & (kCacheSize - 1));
   }
 
diff --git a/src/ia32/assembler-ia32-inl.h b/src/ia32/assembler-ia32-inl.h
index a851b42..eb2a04d 100644
--- a/src/ia32/assembler-ia32-inl.h
+++ b/src/ia32/assembler-ia32-inl.h
@@ -43,10 +43,6 @@
 namespace v8 {
 namespace internal {
 
-Condition NegateCondition(Condition cc) {
-  return static_cast<Condition>(cc ^ 1);
-}
-
 
 // The modes possibly affected by apply must be in kApplyMask.
 void RelocInfo::apply(intptr_t delta) {
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index d4dff33..ce2099d 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -378,6 +378,11 @@
 }
 
 
+void Assembler::CodeTargetAlign() {
+  Align(16);  // Preferred alignment of jump targets on ia32.
+}
+
+
 void Assembler::cpuid() {
   ASSERT(CpuFeatures::IsEnabled(CPUID));
   EnsureSpace ensure_space(this);
@@ -2154,17 +2159,6 @@
 }
 
 
-void Assembler::comisd(XMMRegister dst, XMMRegister src) {
-  ASSERT(CpuFeatures::IsEnabled(SSE2));
-  EnsureSpace ensure_space(this);
-  last_pc_ = pc_;
-  EMIT(0x66);
-  EMIT(0x0F);
-  EMIT(0x2F);
-  emit_sse_operand(dst, src);
-}
-
-
 void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
   ASSERT(CpuFeatures::IsEnabled(SSE2));
   EnsureSpace ensure_space(this);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 7dcbab5..c76c55c 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -146,7 +146,10 @@
 // Negation of the default no_condition (-1) results in a non-default
 // no_condition value (-2). As long as tests for no_condition check
 // for condition < 0, this will work as expected.
-inline Condition NegateCondition(Condition cc);
+inline Condition NegateCondition(Condition cc) {
+  return static_cast<Condition>(cc ^ 1);
+}
+
 
 // Corresponds to transposing the operands of a comparison.
 inline Condition ReverseCondition(Condition cc) {
@@ -172,12 +175,14 @@
   };
 }
 
+
 enum Hint {
   no_hint = 0,
   not_taken = 0x2e,
   taken = 0x3e
 };
 
+
 // The result of negating a hint is as if the corresponding condition
 // were negated by NegateCondition.  That is, no_hint is mapped to
 // itself and not_taken and taken are mapped to each other.
@@ -502,6 +507,8 @@
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2.
   void Align(int m);
+  // Aligns code to something that's optimal for a jump target for the platform.
+  void CodeTargetAlign();
 
   // Stack
   void pushad();
@@ -779,7 +786,6 @@
   void xorpd(XMMRegister dst, XMMRegister src);
   void sqrtsd(XMMRegister dst, XMMRegister src);
 
-  void comisd(XMMRegister dst, XMMRegister src);
   void ucomisd(XMMRegister dst, XMMRegister src);
   void movmskpd(Register dst, XMMRegister src);
 
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 29b6c69..6b07472 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -604,6 +604,10 @@
     RegisterFile empty_regs;
     SetFrame(clone, &empty_regs);
     __ bind(&allocation_failed);
+    if (!CpuFeatures::IsSupported(SSE2)) {
+      // Pop the value from the floating point stack.
+      __ fstp(0);
+    }
     unsafe_bailout_->Jump();
 
     done.Bind(value);
@@ -2991,7 +2995,7 @@
                               &not_numbers);
     LoadComparisonOperandSSE2(masm_, right_side, xmm1, left_side, right_side,
                               &not_numbers);
-    __ comisd(xmm0, xmm1);
+    __ ucomisd(xmm0, xmm1);
   } else {
     Label check_right, compare;
 
@@ -3278,6 +3282,9 @@
 
 
 void CodeGenerator::VisitStatementsAndSpill(ZoneList<Statement*>* statements) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
   ASSERT(in_spilled_code());
   set_in_spilled_code(false);
   VisitStatements(statements);
@@ -3285,14 +3292,20 @@
     frame_->SpillAll();
   }
   set_in_spilled_code(true);
+
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
 }
 
 
 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
+#ifdef DEBUG
+  int original_height = frame_->height();
+#endif
   ASSERT(!in_spilled_code());
   for (int i = 0; has_valid_frame() && i < statements->length(); i++) {
     Visit(statements->at(i));
   }
+  ASSERT(!has_valid_frame() || frame_->height() == original_height);
 }
 
 
@@ -6909,8 +6922,7 @@
   __ bind(&cache_miss);
   __ push(cache_);  // store a reference to cache
   __ push(key_);  // store a key
-  Handle<Object> receiver(Top::global_context()->global());
-  __ push(Immediate(receiver));
+  __ push(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ push(key_);
   // On ia32 function must be in edi.
   __ mov(edi, FieldOperand(cache_, JSFunctionResultCache::kFactoryOffset));
@@ -7298,7 +7310,7 @@
     // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3.
     __ addsd(xmm2, xmm3);
     // xmm2 now has 0.5.
-    __ comisd(xmm2, xmm1);
+    __ ucomisd(xmm2, xmm1);
     call_runtime.Branch(not_equal);
     // Calculates square root.
     __ movsd(xmm1, xmm0);
@@ -10285,15 +10297,15 @@
   // ST[0] == double value
   // ebx = low 32 bits of double value
   // edx = high 32 bits of double value
-  // Compute hash:
+  // Compute hash (the shifts are arithmetic):
   //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
   __ mov(ecx, ebx);
   __ xor_(ecx, Operand(edx));
   __ mov(eax, ecx);
-  __ shr(eax, 16);
+  __ sar(eax, 16);
   __ xor_(ecx, Operand(eax));
   __ mov(eax, ecx);
-  __ shr(eax, 8);
+  __ sar(eax, 8);
   __ xor_(ecx, Operand(eax));
   ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
   __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
@@ -11305,58 +11317,58 @@
 
   // ecx: RegExp data (FixedArray)
   // Check the representation and encoding of the subject string.
-  Label seq_string, seq_two_byte_string, check_code;
-  const int kStringRepresentationEncodingMask =
-      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
+  Label seq_ascii_string, seq_two_byte_string, check_code;
   __ mov(eax, Operand(esp, kSubjectOffset));
   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
   __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
-  __ and_(ebx, kStringRepresentationEncodingMask);
-  // First check for sequential string.
-  ASSERT_EQ(0, kStringTag);
-  ASSERT_EQ(0, kSeqStringTag);
+  // First check for flat two byte string.
+  __ and_(ebx,
+          kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask);
+  ASSERT_EQ(0, kStringTag | kSeqStringTag | kTwoByteStringTag);
+  __ j(zero, &seq_two_byte_string);
+  // Any other flat string must be a flat ascii string.
   __ test(Operand(ebx),
           Immediate(kIsNotStringMask | kStringRepresentationMask));
-  __ j(zero, &seq_string);
+  __ j(zero, &seq_ascii_string);
 
   // Check for flat cons string.
   // A flat cons string is a cons string where the second part is the empty
   // string. In that case the subject string is just the first part of the cons
   // string. Also in this case the first part of the cons string is known to be
   // a sequential string or an external string.
-  __ and_(ebx, kStringRepresentationMask);
-  __ cmp(ebx, kConsStringTag);
-  __ j(not_equal, &runtime);
+  ASSERT(kExternalStringTag !=0);
+  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
+  __ test(Operand(ebx),
+          Immediate(kIsNotStringMask | kExternalStringTag));
+  __ j(not_zero, &runtime);
+  // String is a cons string.
   __ mov(edx, FieldOperand(eax, ConsString::kSecondOffset));
   __ cmp(Operand(edx), Factory::empty_string());
   __ j(not_equal, &runtime);
   __ mov(eax, FieldOperand(eax, ConsString::kFirstOffset));
   __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset));
-  ASSERT_EQ(0, kSeqStringTag);
-  __ test(ebx, Immediate(kStringRepresentationMask));
+  // String is a cons string with empty second part.
+  // eax: first part of cons string.
+  // ebx: map of first part of cons string.
+  // Is first part a flat two byte string?
+  __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
+            kStringRepresentationMask | kStringEncodingMask);
+  ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag);
+  __ j(zero, &seq_two_byte_string);
+  // Any other flat string must be ascii.
+  __ test_b(FieldOperand(ebx, Map::kInstanceTypeOffset),
+            kStringRepresentationMask);
   __ j(not_zero, &runtime);
-  __ and_(ebx, kStringRepresentationEncodingMask);
 
-  __ bind(&seq_string);
-  // eax: subject string (sequential either ascii to two byte)
-  // ebx: suject string type & kStringRepresentationEncodingMask
+  __ bind(&seq_ascii_string);
+  // eax: subject string (flat ascii)
   // ecx: RegExp data (FixedArray)
-  // Check that the irregexp code has been generated for an ascii string. If
-  // it has, the field contains a code object otherwise it contains the hole.
-  const int kSeqTwoByteString = kStringTag | kSeqStringTag | kTwoByteStringTag;
-  __ cmp(ebx, kSeqTwoByteString);
-  __ j(equal, &seq_two_byte_string);
-  if (FLAG_debug_code) {
-    __ cmp(ebx, kStringTag | kSeqStringTag | kAsciiStringTag);
-    __ Check(equal, "Expected sequential ascii string");
-  }
   __ mov(edx, FieldOperand(ecx, JSRegExp::kDataAsciiCodeOffset));
   __ Set(edi, Immediate(1));  // Type is ascii.
   __ jmp(&check_code);
 
   __ bind(&seq_two_byte_string);
-  // eax: subject string
+  // eax: subject string (flat two byte)
   // ecx: RegExp data (FixedArray)
   __ mov(edx, FieldOperand(ecx, JSRegExp::kDataUC16CodeOffset));
   __ Set(edi, Immediate(0));  // Type is two byte.
@@ -11584,7 +11596,7 @@
       CpuFeatures::Scope fscope(SSE2);
       __ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
       __ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
-      __ comisd(xmm0, xmm1);
+      __ ucomisd(xmm0, xmm1);
     } else {
       __ fld_d(FieldOperand(object, HeapNumber::kValueOffset));
       __ fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
@@ -11809,7 +11821,7 @@
       CpuFeatures::Scope use_cmov(CMOV);
 
       FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
-      __ comisd(xmm0, xmm1);
+      __ ucomisd(xmm0, xmm1);
 
       // Don't base result on EFLAGS when a NaN is involved.
       __ j(parity_even, &unordered, not_taken);
@@ -12840,7 +12852,7 @@
 
   // If result is not supposed to be flat allocate a cons string object. If both
   // strings are ascii the result is an ascii cons string.
-  Label non_ascii, allocated;
+  Label non_ascii, allocated, ascii_data;
   __ mov(edi, FieldOperand(eax, HeapObject::kMapOffset));
   __ movzx_b(ecx, FieldOperand(edi, Map::kInstanceTypeOffset));
   __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
@@ -12849,6 +12861,7 @@
   ASSERT(kStringEncodingMask == kAsciiStringTag);
   __ test(ecx, Immediate(kAsciiStringTag));
   __ j(zero, &non_ascii);
+  __ bind(&ascii_data);
   // Allocate an acsii cons string.
   __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
   __ bind(&allocated);
@@ -12863,6 +12876,19 @@
   __ IncrementCounter(&Counters::string_add_native, 1);
   __ ret(2 * kPointerSize);
   __ bind(&non_ascii);
+  // At least one of the strings is two-byte. Check whether it happens
+  // to contain only ascii characters.
+  // ecx: first instance type AND second instance type.
+  // edi: second instance type.
+  __ test(ecx, Immediate(kAsciiDataHintMask));
+  __ j(not_zero, &ascii_data);
+  __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  __ xor_(edi, Operand(ecx));
+  ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
+  __ and_(edi, kAsciiStringTag | kAsciiDataHintTag);
+  __ cmp(edi, kAsciiStringTag | kAsciiDataHintTag);
+  __ j(equal, &ascii_data);
   // Allocate a two byte cons string.
   __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
   __ jmp(&allocated);
@@ -12897,7 +12923,7 @@
   __ j(zero, &string_add_runtime);
 
   __ bind(&make_flat_ascii_string);
-  // Both strings are ascii strings. As they are short they are both flat.
+  // Both strings are ascii strings.  As they are short they are both flat.
   // ebx: length of resulting flat string as a smi
   __ SmiUntag(ebx);
   __ AllocateAsciiString(eax, ebx, ecx, edx, edi, &string_add_runtime);
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index f339d2e..b0c07b7 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -306,22 +306,22 @@
 // Falls through for regular JS object.
 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
                                            Register receiver,
-                                           Register r0,
+                                           Register map,
                                            Label* slow) {
   // Register use:
   //   receiver - holds the receiver and is unchanged.
   // Scratch registers:
-  //   r0 - used to hold the map of the receiver.
+  //   map - used to hold the map of the receiver.
 
   // Check that the object isn't a smi.
   __ test(receiver, Immediate(kSmiTagMask));
   __ j(zero, slow, not_taken);
 
   // Get the map of the receiver.
-  __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset));
+  __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
 
   // Check bit field.
-  __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
+  __ test_b(FieldOperand(map, Map::kBitFieldOffset),
             KeyedLoadIC::kSlowCaseBitFieldMask);
   __ j(not_zero, slow, not_taken);
   // Check that the object is some kind of JS object EXCEPT JS Value type.
@@ -330,7 +330,7 @@
   // into string objects works as intended.
   ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
 
-  __ CmpInstanceType(r0, JS_OBJECT_TYPE);
+  __ CmpInstanceType(map, JS_OBJECT_TYPE);
   __ j(below, slow, not_taken);
 }
 
@@ -371,7 +371,7 @@
 
 
 // Checks whether a key is an array index string or a symbol string.
-// Falls through if a key is a symbol.
+// Falls through if the key is a symbol.
 static void GenerateKeyStringCheck(MacroAssembler* masm,
                                    Register key,
                                    Register map,
@@ -399,11 +399,9 @@
 
 
 // Picks out an array index from the hash field.
-// The generated code never falls through.
 static void GenerateIndexFromHash(MacroAssembler* masm,
                                   Register key,
-                                  Register hash,
-                                  Label* index_smi) {
+                                  Register hash) {
   // Register use:
   //   key - holds the overwritten key on exit.
   //   hash - holds the key's hash. Clobbered.
@@ -415,8 +413,6 @@
          (1 << String::kArrayIndexValueBits));
   // We want the smi-tagged index in key.  kArrayIndexValueMask has zeros in
   // the low kHashShift bits.
-  // key: string key
-  // ebx: hash field.
   ASSERT(String::kHashShift >= kSmiTagSize);
   __ and_(hash, String::kArrayIndexValueMask);
   __ shr(hash, String::kHashShift - kSmiTagSize);
@@ -424,8 +420,6 @@
   // runtime later. However as the new key is the numeric value of a string key
   // there is no difference in using either key.
   __ mov(key, hash);
-  // Now jump to the place where smi keys are handled.
-  __ jmp(index_smi);
 }
 
 
@@ -574,7 +568,9 @@
   __ ret(0);
 
   __ bind(&index_string);
-  GenerateIndexFromHash(masm, eax, ebx, &index_smi);
+  GenerateIndexFromHash(masm, eax, ebx);
+  // Now jump to the place where smi keys are handled.
+  __ jmp(&index_smi);
 }
 
 
@@ -1125,13 +1121,12 @@
 // The generated code falls through if both probes miss.
 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
                                           int argc,
-                                          Code::Kind kind,
-                                          Label* miss) {
+                                          Code::Kind kind) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- edx                 : receiver
   // -----------------------------------
-  Label number, non_number, non_string, boolean, probe;
+  Label number, non_number, non_string, boolean, probe, miss;
 
   // Probe the stub cache.
   Code::Flags flags =
@@ -1166,7 +1161,7 @@
   __ cmp(edx, Factory::true_value());
   __ j(equal, &boolean, not_taken);
   __ cmp(edx, Factory::false_value());
-  __ j(not_equal, miss, taken);
+  __ j(not_equal, &miss, taken);
   __ bind(&boolean);
   StubCompiler::GenerateLoadGlobalFunctionPrototype(
       masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
@@ -1174,6 +1169,7 @@
   // Probe the stub cache for the value object.
   __ bind(&probe);
   StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
+  __ bind(&miss);
 }
 
 
@@ -1214,8 +1210,8 @@
   __ InvokeFunction(edi, actual, JUMP_FUNCTION);
 }
 
-// The generated code never falls through.
-static void GenerateCallNormal(MacroAssembler* masm, int argc, Label* miss) {
+// The generated code falls through if the call should be handled by runtime.
+static void GenerateCallNormal(MacroAssembler* masm, int argc) {
   // ----------- S t a t e -------------
   //  -- ecx                 : name
   //  -- esp[0]              : return address
@@ -1223,20 +1219,20 @@
   //  -- ...
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
-  Label global_object, non_global_object;
+  Label miss, global_object, non_global_object;
 
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
 
   // Check that the receiver isn't a smi.
   __ test(edx, Immediate(kSmiTagMask));
-  __ j(zero, miss, not_taken);
+  __ j(zero, &miss, not_taken);
 
   // Check that the receiver is a valid JS object.
   __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
   __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset));
   __ cmp(eax, FIRST_JS_OBJECT_TYPE);
-  __ j(below, miss, not_taken);
+  __ j(below, &miss, not_taken);
 
   // If this assert fails, we have to check upper bound too.
   ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
@@ -1252,8 +1248,8 @@
   // Check that the global object does not require access checks.
   __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
             1 << Map::kIsAccessCheckNeeded);
-  __ j(not_equal, miss, not_taken);
-  GenerateNormalHelper(masm, argc, true, miss);
+  __ j(not_equal, &miss, not_taken);
+  GenerateNormalHelper(masm, argc, true, &miss);
 
   // Accessing non-global object: Check for access to global proxy.
   Label global_proxy, invoke;
@@ -1264,14 +1260,16 @@
   // require access checks.
   __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
             1 << Map::kIsAccessCheckNeeded);
-  __ j(not_equal, miss, not_taken);
+  __ j(not_equal, &miss, not_taken);
   __ bind(&invoke);
-  GenerateNormalHelper(masm, argc, false, miss);
+  GenerateNormalHelper(masm, argc, false, &miss);
 
   // Global object proxy access: Check access rights.
   __ bind(&global_proxy);
-  __ CheckAccessGlobalProxy(edx, eax, miss);
+  __ CheckAccessGlobalProxy(edx, eax, &miss);
   __ jmp(&invoke);
+
+  __ bind(&miss);
 }
 
 
@@ -1337,24 +1335,36 @@
   //  -- esp[(argc + 1) * 4] : receiver
   // -----------------------------------
 
-  Label miss;
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
-  GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, &miss);
-  __ bind(&miss);
+  GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC);
   GenerateMiss(masm, argc);
 }
 
 
 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
-  Label miss;
-  GenerateCallNormal(masm, argc, &miss);
-  __ bind(&miss);
+  // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
+  // -----------------------------------
+
+  GenerateCallNormal(masm, argc);
   GenerateMiss(masm, argc);
 }
 
 
 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
+  // -----------------------------------
+
   GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
 }
 
@@ -1385,13 +1395,8 @@
 
   GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call);
 
-  GenerateFastArrayLoad(masm,
-                        edx,
-                        ecx,
-                        eax,
-                        edi,
-                        &check_number_dictionary,
-                        &slow_load);
+  GenerateFastArrayLoad(
+      masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
   __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
 
   __ bind(&do_call);
@@ -1417,14 +1422,8 @@
   __ SmiUntag(ebx);
   // ebx: untagged index
   // Receiver in edx will be clobbered, need to reload it on miss.
-  GenerateNumberDictionaryLoad(masm,
-                               &slow_reload_receiver,
-                               eax,
-                               ecx,
-                               ebx,
-                               edx,
-                               edi,
-                               edi);
+  GenerateNumberDictionaryLoad(
+      masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
   __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
   __ jmp(&do_call);
 
@@ -1459,21 +1458,14 @@
          Immediate(Factory::hash_table_map()));
   __ j(not_equal, &lookup_monomorphic_cache, not_taken);
 
-  GenerateDictionaryLoad(masm,
-                         &slow_load,
-                         edx,
-                         ecx,
-                         ebx,
-                         eax,
-                         edi,
-                         edi,
-                         DICTIONARY_CHECK_DONE);
+  GenerateDictionaryLoad(
+      masm, &slow_load, edx, ecx, ebx, eax, edi, edi, DICTIONARY_CHECK_DONE);
   __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
   __ jmp(&do_call);
 
   __ bind(&lookup_monomorphic_cache);
   __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
-  GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &slow_call);
+  GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
   // Fall through on miss.
 
   __ bind(&slow_call);
@@ -1487,19 +1479,35 @@
   GenerateMiss(masm, argc);
 
   __ bind(&index_string);
-  GenerateIndexFromHash(masm, ecx, ebx, &index_smi);
+  GenerateIndexFromHash(masm, ecx, ebx);
+  // Now jump to the place where smi keys are handled.
+  __ jmp(&index_smi);
 }
 
 
 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
-  Label miss;
-  GenerateCallNormal(masm, argc, &miss);
-  __ bind(&miss);
+  // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
+  // -----------------------------------
+
+  GenerateCallNormal(masm, argc);
   GenerateMiss(masm, argc);
 }
 
 
 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  //  -- ecx                 : name
+  //  -- esp[0]              : return address
+  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- ...
+  //  -- esp[(argc + 1) * 4] : receiver
+  // -----------------------------------
+
   GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
 }
 
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 48d9e67..bab0435 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -816,8 +816,13 @@
   __ push(other);
   __ push(receiver);  // receiver
   __ push(reg);  // holder
-  __ mov(other, Immediate(callback_handle));
-  __ push(FieldOperand(other, AccessorInfo::kDataOffset));  // data
+  // Push data from AccessorInfo.
+  if (Heap::InNewSpace(callback_handle->data())) {
+    __ mov(other, Immediate(callback_handle));
+    __ push(FieldOperand(other, AccessorInfo::kDataOffset));
+  } else {
+    __ push(Immediate(Handle<Object>(callback_handle->data())));
+  }
   __ push(name_reg);  // name
   // Save a pointer to where we pushed the arguments pointer.
   // This will be passed as the const AccessorInfo& to the C++ callback.
diff --git a/src/ic.cc b/src/ic.cc
index 2b77a54..475f161 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -387,6 +387,7 @@
   return *delegate;
 }
 
+
 void CallICBase::ReceiverToObject(Handle<Object> object) {
   HandleScope scope;
   Handle<Object> receiver(object);
@@ -588,6 +589,9 @@
       state == MONOMORPHIC ||
       state == MONOMORPHIC_PROTOTYPE_FAILURE) {
     set_target(Code::cast(code));
+  } else if (state == MEGAMORPHIC) {
+    // Update the stub cache.
+    StubCache::Set(*name, GetCodeCacheMapForObject(*object), Code::cast(code));
   }
 
 #ifdef DEBUG
@@ -664,7 +668,6 @@
       Code* target = NULL;
       target = Builtins::builtin(Builtins::LoadIC_StringLength);
       set_target(target);
-      StubCache::Set(*name, map, target);
       return Smi::FromInt(String::cast(*object)->length());
     }
 
@@ -679,7 +682,6 @@
 
       Code* target = Builtins::builtin(Builtins::LoadIC_ArrayLength);
       set_target(target);
-      StubCache::Set(*name, map, target);
       return JSArray::cast(*object)->length();
     }
 
@@ -691,7 +693,6 @@
 #endif
       Code* target = Builtins::builtin(Builtins::LoadIC_FunctionPrototype);
       set_target(target);
-      StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
       return Accessors::FunctionGetPrototype(*object, 0);
     }
   }
@@ -733,6 +734,28 @@
       if (PatchInlinedLoad(address(), map, offset)) {
         set_target(megamorphic_stub());
         return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
+#ifdef DEBUG
+        if (FLAG_trace_ic) {
+          PrintF("[LoadIC : inline patch %s]\n", *name->ToCString());
+        }
+      } else {
+        if (FLAG_trace_ic) {
+          PrintF("[LoadIC : no inline patch %s (patching failed)]\n",
+                 *name->ToCString());
+        }
+      }
+    } else {
+      if (FLAG_trace_ic) {
+        PrintF("[LoadIC : no inline patch %s (not inobject)]\n",
+               *name->ToCString());
+      }
+    }
+  } else {
+    if (FLAG_use_ic && state == PREMONOMORPHIC) {
+      if (FLAG_trace_ic) {
+        PrintF("[LoadIC : no inline patch %s (not inlinable)]\n",
+               *name->ToCString());
+#endif
       }
     }
   }
@@ -847,6 +870,9 @@
     set_target(Code::cast(code));
   } else if (state == MONOMORPHIC) {
     set_target(megamorphic_stub());
+  } else if (state == MEGAMORPHIC) {
+    // Update the stub cache.
+    StubCache::Set(*name, GetCodeCacheMapForObject(*object), Code::cast(code));
   }
 
 #ifdef DEBUG
@@ -1110,7 +1136,6 @@
     return *value;
   }
 
-
   // Use specialized code for setting the length of arrays.
   if (receiver->IsJSArray()
       && name->Equals(Heap::length_symbol())
@@ -1120,7 +1145,6 @@
 #endif
     Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength);
     set_target(target);
-    StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
     return receiver->SetProperty(*name, *value, NONE);
   }
 
@@ -1208,8 +1232,11 @@
   if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
     set_target(Code::cast(code));
   } else if (state == MONOMORPHIC) {
-    // Only move to mega morphic if the target changes.
+    // Only move to megamorphic if the target changes.
     if (target() != Code::cast(code)) set_target(megamorphic_stub());
+  } else if (state == MEGAMORPHIC) {
+    // Update the stub cache.
+    StubCache::Set(*name, receiver->map(), Code::cast(code));
   }
 
 #ifdef DEBUG
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 9a1f1f1..3e9c5ea 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -1747,9 +1747,11 @@
     if ((mask & char_mask) == char_mask) need_mask = false;
     mask &= char_mask;
   } else {
-    // For 2-character preloads in ASCII mode we also use a 16 bit load with
-    // zero extend.
+    // For 2-character preloads in ASCII mode or 1-character preloads in
+    // TWO_BYTE mode we also use a 16 bit load with zero extend.
     if (details->characters() == 2 && compiler->ascii()) {
+      if ((mask & 0x7f7f) == 0x7f7f) need_mask = false;
+    } else if (details->characters() == 1 && !compiler->ascii()) {
       if ((mask & 0xffff) == 0xffff) need_mask = false;
     } else {
       if (mask == 0xffffffff) need_mask = false;
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index f9b20a4..b60e54d 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -552,12 +552,14 @@
     case CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
     case CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
     case EXTERNAL_ASCII_SYMBOL_TYPE:
+    case EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE:
     case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
     case ASCII_STRING_TYPE: return "ASCII_STRING";
     case STRING_TYPE: return "TWO_BYTE_STRING";
     case CONS_STRING_TYPE:
     case CONS_ASCII_STRING_TYPE: return "CONS_STRING";
     case EXTERNAL_ASCII_STRING_TYPE:
+    case EXTERNAL_STRING_WITH_ASCII_DATA_TYPE:
     case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
     case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
     case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 4112f93..d6571bf 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -237,31 +237,20 @@
 
 bool String::IsAsciiRepresentation() {
   uint32_t type = map()->instance_type();
-  if ((type & kStringRepresentationMask) == kConsStringTag &&
-      ConsString::cast(this)->second()->length() == 0) {
-    return ConsString::cast(this)->first()->IsAsciiRepresentation();
-  }
   return (type & kStringEncodingMask) == kAsciiStringTag;
 }
 
 
 bool String::IsTwoByteRepresentation() {
   uint32_t type = map()->instance_type();
-  if ((type & kStringRepresentationMask) == kConsStringTag &&
-             ConsString::cast(this)->second()->length() == 0) {
-    return ConsString::cast(this)->first()->IsTwoByteRepresentation();
-  }
   return (type & kStringEncodingMask) == kTwoByteStringTag;
 }
 
 
-bool String::IsExternalTwoByteStringWithAsciiChars() {
-  if (!IsExternalTwoByteString()) return false;
-  const uc16* data = ExternalTwoByteString::cast(this)->resource()->data();
-  for (int i = 0, len = length(); i < len; i++) {
-    if (data[i] > kMaxAsciiCharCode) return false;
-  }
-  return true;
+bool String::HasOnlyAsciiChars() {
+  uint32_t type = map()->instance_type();
+  return (type & kStringEncodingMask) == kAsciiStringTag ||
+         (type & kAsciiDataHintMask) == kAsciiDataHintTag;
 }
 
 
diff --git a/src/objects.cc b/src/objects.cc
index 1e4d4a4..63b77b7 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -678,6 +678,9 @@
 
 
 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
+  // Externalizing twice leaks the external resouce, so it's
+  // prohibited by the API.
+  ASSERT(!this->IsExternalString());
 #ifdef DEBUG
   if (FLAG_enable_slow_asserts) {
     // Assert that the resource and the string are equivalent.
@@ -697,13 +700,16 @@
     return false;
   }
   ASSERT(size >= ExternalString::kSize);
+  bool is_ascii = this->IsAsciiRepresentation();
   bool is_symbol = this->IsSymbol();
   int length = this->length();
   int hash_field = this->hash_field();
 
   // Morph the object to an external string by adjusting the map and
   // reinitializing the fields.
-  this->set_map(Heap::external_string_map());
+  this->set_map(is_ascii ?
+                Heap::external_string_with_ascii_data_map() :
+                Heap::external_string_map());
   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
   self->set_length(length);
   self->set_hash_field(hash_field);
@@ -713,7 +719,9 @@
   if (is_symbol) {
     self->Hash();  // Force regeneration of the hash value.
     // Now morph this external string into a external symbol.
-    this->set_map(Heap::external_symbol_map());
+    this->set_map(is_ascii ?
+                  Heap::external_symbol_with_ascii_data_map() :
+                  Heap::external_symbol_map());
   }
 
   // Fill the remainder of the string with dead wood.
@@ -2013,25 +2021,18 @@
   CustomArguments args(interceptor->data(), receiver, this);
   v8::AccessorInfo info(args.end());
   if (!interceptor->query()->IsUndefined()) {
-    v8::NamedPropertyQueryImpl query =
-        v8::ToCData<v8::NamedPropertyQueryImpl>(interceptor->query());
+    v8::NamedPropertyQuery query =
+        v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
     LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
-    v8::Handle<v8::Value> result;
+    v8::Handle<v8::Integer> result;
     {
       // Leaving JavaScript.
       VMState state(EXTERNAL);
       result = query(v8::Utils::ToLocal(name_handle), info);
     }
     if (!result.IsEmpty()) {
-      // Temporary complicated logic, would be removed soon.
-      if (result->IsBoolean()) {
-        // Convert the boolean result to a property attribute
-        // specification.
-        return result->IsTrue() ? NONE : ABSENT;
-      } else {
-        ASSERT(result->IsInt32());
-        return static_cast<PropertyAttributes>(result->Int32Value());
-      }
+      ASSERT(result->IsInt32());
+      return static_cast<PropertyAttributes>(result->Int32Value());
     }
   } else if (!interceptor->getter()->IsUndefined()) {
     v8::NamedPropertyGetter getter =
@@ -8154,7 +8155,7 @@
 
 template<typename Shape, typename Key>
 Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
-  int entry = FindEntry(key);
+  int entry = this->FindEntry(key);
 
   // If the entry is present set the value;
   if (entry != Dictionary<Shape, Key>::kNotFound) {
@@ -8179,7 +8180,7 @@
                                     Object* value,
                                     PropertyDetails details) {
   // Valdate key is absent.
-  SLOW_ASSERT((FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
+  SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
   // Check whether the dictionary should be extended.
   Object* obj = EnsureCapacity(1, key);
   if (obj->IsFailure()) return obj;
@@ -8238,7 +8239,7 @@
                                          Object* value,
                                          PropertyDetails details) {
   UpdateMaxNumberKey(key);
-  SLOW_ASSERT(FindEntry(key) == kNotFound);
+  SLOW_ASSERT(this->FindEntry(key) == kNotFound);
   return Add(key, value, details);
 }
 
diff --git a/src/objects.h b/src/objects.h
index 095dd98..0c14665 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -320,6 +320,10 @@
     ExternalTwoByteString::kSize,                                              \
     external_symbol,                                                           \
     ExternalSymbol)                                                            \
+  V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE,                                      \
+    ExternalTwoByteString::kSize,                                              \
+    external_symbol_with_ascii_data,                                           \
+    ExternalSymbolWithAsciiData)                                               \
   V(EXTERNAL_ASCII_SYMBOL_TYPE,                                                \
     ExternalAsciiString::kSize,                                                \
     external_ascii_symbol,                                                     \
@@ -344,6 +348,10 @@
     ExternalTwoByteString::kSize,                                              \
     external_string,                                                           \
     ExternalString)                                                            \
+  V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE,                                      \
+    ExternalTwoByteString::kSize,                                              \
+    external_string_with_ascii_data,                                           \
+    ExternalStringWithAsciiData)                                               \
   V(EXTERNAL_ASCII_STRING_TYPE,                                                \
     ExternalAsciiString::kSize,                                                \
     external_ascii_string,                                                     \
@@ -412,6 +420,11 @@
 };
 const uint32_t kIsConsStringMask = 0x1;
 
+// If bit 7 is clear, then bit 3 indicates whether this two-byte
+// string actually contains ascii data.
+const uint32_t kAsciiDataHintMask = 0x08;
+const uint32_t kAsciiDataHintTag = 0x08;
+
 
 // A ConsString with an empty string as the right side is a candidate
 // for being shortcut by the garbage collector unless it is a
@@ -427,18 +440,22 @@
 
 enum InstanceType {
   // String types.
-  SYMBOL_TYPE = kSymbolTag | kSeqStringTag,
+  SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kSeqStringTag,
   ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kSeqStringTag,
-  CONS_SYMBOL_TYPE = kSymbolTag | kConsStringTag,
+  CONS_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kConsStringTag,
   CONS_ASCII_SYMBOL_TYPE = kAsciiStringTag | kSymbolTag | kConsStringTag,
-  EXTERNAL_SYMBOL_TYPE = kSymbolTag | kExternalStringTag,
+  EXTERNAL_SYMBOL_TYPE = kTwoByteStringTag | kSymbolTag | kExternalStringTag,
+  EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE =
+      kTwoByteStringTag | kSymbolTag | kExternalStringTag | kAsciiDataHintTag,
   EXTERNAL_ASCII_SYMBOL_TYPE =
       kAsciiStringTag | kSymbolTag | kExternalStringTag,
-  STRING_TYPE = kSeqStringTag,
+  STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
   ASCII_STRING_TYPE = kAsciiStringTag | kSeqStringTag,
-  CONS_STRING_TYPE = kConsStringTag,
+  CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
   CONS_ASCII_STRING_TYPE = kAsciiStringTag | kConsStringTag,
-  EXTERNAL_STRING_TYPE = kExternalStringTag,
+  EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
+  EXTERNAL_STRING_WITH_ASCII_DATA_TYPE =
+      kTwoByteStringTag | kExternalStringTag | kAsciiDataHintTag,
   EXTERNAL_ASCII_STRING_TYPE = kAsciiStringTag | kExternalStringTag,
   PRIVATE_EXTERNAL_ASCII_STRING_TYPE = EXTERNAL_ASCII_STRING_TYPE,
 
@@ -474,10 +491,12 @@
   TYPE_SWITCH_INFO_TYPE,
   SCRIPT_TYPE,
   CODE_CACHE_TYPE,
-#ifdef ENABLE_DEBUGGER_SUPPORT
+  // The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT
+  // is defined. However as include/v8.h contain some of the instance type
+  // constants always having them avoids them getting different numbers
+  // depending on whether ENABLE_DEBUGGER_SUPPORT is defined or not.
   DEBUG_INFO_TYPE,
   BREAK_POINT_INFO_TYPE,
-#endif
 
   FIXED_ARRAY_TYPE,
   SHARED_FUNCTION_INFO_TYPE,
@@ -511,6 +530,11 @@
 };
 
 
+STATIC_CHECK(JS_OBJECT_TYPE == Internals::kJSObjectType);
+STATIC_CHECK(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
+STATIC_CHECK(PROXY_TYPE == Internals::kProxyType);
+
+
 enum CompareResult {
   LESS      = -1,
   EQUAL     =  0,
@@ -1123,7 +1147,7 @@
   static const uint32_t kExponentMask = 0x7ff00000u;
   static const uint32_t kMantissaMask = 0xfffffu;
   static const int kMantissaBits = 52;
-  static const int KExponentBits = 11;
+  static const int kExponentBits = 11;
   static const int kExponentBias = 1023;
   static const int kExponentShift = 20;
   static const int kMantissaBitsInTopWord = 20;
@@ -2151,6 +2175,11 @@
 
   // Set the value for entry.
   void ValueAtPut(int entry, Object* value) {
+    // Check that this value can actually be written.
+    PropertyDetails details = DetailsAt(entry);
+    // If a value has not been initilized we allow writing to it even if
+    // it is read only (a declared const that has not been initialized).
+    if (details.IsReadOnly() && !ValueAt(entry)->IsTheHole()) return;
     this->set(HashTable<Shape, Key>::EntryToIndex(entry)+1, value);
   }
 
@@ -2832,14 +2861,14 @@
   // Flags layout.
   static const int kFlagsICStateShift        = 0;
   static const int kFlagsICInLoopShift       = 3;
-  static const int kFlagsKindShift           = 4;
-  static const int kFlagsTypeShift           = 8;
+  static const int kFlagsTypeShift           = 4;
+  static const int kFlagsKindShift           = 7;
   static const int kFlagsArgumentsCountShift = 11;
 
   static const int kFlagsICStateMask        = 0x00000007;  // 00000000111
   static const int kFlagsICInLoopMask       = 0x00000008;  // 00000001000
-  static const int kFlagsKindMask           = 0x000000F0;  // 00011110000
-  static const int kFlagsTypeMask           = 0x00000700;  // 11100000000
+  static const int kFlagsTypeMask           = 0x00000070;  // 00001110000
+  static const int kFlagsKindMask           = 0x00000780;  // 11110000000
   static const int kFlagsArgumentsCountMask = 0xFFFFF800;
 
   static const int kFlagsNotUsedInLookup =
@@ -4064,12 +4093,14 @@
   inline bool IsAsciiRepresentation();
   inline bool IsTwoByteRepresentation();
 
-  // Check whether this string is an external two-byte string that in
-  // fact contains only ascii characters.
+  // Returns whether this string has ascii chars, i.e. all of them can
+  // be ascii encoded.  This might be the case even if the string is
+  // two-byte.  Such strings may appear when the embedder prefers
+  // two-byte external representations even for ascii data.
   //
-  // Such strings may appear when the embedder prefers two-byte
-  // representations even for ascii data.
-  inline bool IsExternalTwoByteStringWithAsciiChars();
+  // NOTE: this should be considered only a hint.  False negatives are
+  // possible.
+  inline bool HasOnlyAsciiChars();
 
   // Get and set individual two byte chars in the string.
   inline void Set(int index, uint16_t value);
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 805ed3e..57ff661 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -818,7 +818,7 @@
                              HeapEntry* from,
                              HeapEntry* to)
     : type_(type), name_(name), from_(from), to_(to) {
-  ASSERT(type_ == CONTEXT_VARIABLE || type_ == PROPERTY);
+  ASSERT(type_ == CONTEXT_VARIABLE || type_ == PROPERTY || type_ == INTERNAL);
 }
 
 
@@ -845,26 +845,30 @@
 }
 
 
-void HeapEntry::SetClosureReference(const char* name, HeapEntry* entry) {
-  HeapGraphEdge* edge =
-      new HeapGraphEdge(HeapGraphEdge::CONTEXT_VARIABLE, name, this, entry);
+void HeapEntry::AddEdge(HeapGraphEdge* edge) {
   children_.Add(edge);
-  entry->retainers_.Add(edge);
+  edge->to()->retainers_.Add(edge);
+}
+
+
+void HeapEntry::SetClosureReference(const char* name, HeapEntry* entry) {
+  AddEdge(
+      new HeapGraphEdge(HeapGraphEdge::CONTEXT_VARIABLE, name, this, entry));
 }
 
 
 void HeapEntry::SetElementReference(int index, HeapEntry* entry) {
-  HeapGraphEdge* edge = new HeapGraphEdge(index, this, entry);
-  children_.Add(edge);
-  entry->retainers_.Add(edge);
+  AddEdge(new HeapGraphEdge(index, this, entry));
+}
+
+
+void HeapEntry::SetInternalReference(const char* name, HeapEntry* entry) {
+  AddEdge(new HeapGraphEdge(HeapGraphEdge::INTERNAL, name, this, entry));
 }
 
 
 void HeapEntry::SetPropertyReference(const char* name, HeapEntry* entry) {
-  HeapGraphEdge* edge =
-      new HeapGraphEdge(HeapGraphEdge::PROPERTY, name, this, entry);
-  children_.Add(edge);
-  entry->retainers_.Add(edge);
+  AddEdge(new HeapGraphEdge(HeapGraphEdge::PROPERTY, name, this, entry));
 }
 
 
@@ -1074,7 +1078,7 @@
 
 
 void HeapEntry::Print(int max_depth, int indent) {
-  OS::Print("%6d %6d %6d", self_size_, TotalSize(), NonSharedTotalSize());
+  OS::Print("%6d %6d %6d ", self_size_, TotalSize(), NonSharedTotalSize());
   if (type_ != STRING) {
     OS::Print("%s %.40s\n", TypeAsString(), name_);
   } else {
@@ -1100,6 +1104,9 @@
       case HeapGraphEdge::ELEMENT:
         OS::Print("  %*c %d: ", indent, ' ', edge->index());
         break;
+      case HeapGraphEdge::INTERNAL:
+        OS::Print("  %*c $%s: ", indent, ' ', edge->name());
+        break;
       case HeapGraphEdge::PROPERTY:
         OS::Print("  %*c %s: ", indent, ' ', edge->name());
         break;
@@ -1114,7 +1121,7 @@
 const char* HeapEntry::TypeAsString() {
   switch (type_) {
     case INTERNAL: return "/internal/";
-    case JS_OBJECT: return "/object/";
+    case OBJECT: return "/object/";
     case CLOSURE: return "/closure/";
     case STRING: return "/string/";
     case CODE: return "/code/";
@@ -1145,6 +1152,9 @@
       case HeapGraphEdge::ELEMENT:
         OS::Print("[%d] ", edge->index());
         break;
+      case HeapGraphEdge::INTERNAL:
+        OS::Print("[$%s] ", edge->name());
+        break;
       case HeapGraphEdge::PROPERTY:
         OS::Print("[%s] ", edge->name());
         break;
@@ -1262,7 +1272,7 @@
     return AddEntry(object, HeapEntry::CLOSURE, collection_->GetName(name));
   } else if (object->IsJSObject()) {
     return AddEntry(object,
-                    HeapEntry::JS_OBJECT,
+                    HeapEntry::OBJECT,
                     collection_->GetName(
                         JSObject::cast(object)->constructor_name()));
   } else if (object->IsJSGlobalPropertyCell()) {
@@ -1276,10 +1286,19 @@
     return AddEntry(object,
                     HeapEntry::STRING,
                     collection_->GetName(String::cast(object)));
-  } else if (object->IsCode()
-             || object->IsSharedFunctionInfo()
-             || object->IsScript()) {
+  } else if (object->IsCode()) {
     return AddEntry(object, HeapEntry::CODE);
+  } else if (object->IsSharedFunctionInfo()) {
+    SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
+    String* name = String::cast(shared->name())->length() > 0 ?
+        String::cast(shared->name()) : shared->inferred_name();
+    return AddEntry(object, HeapEntry::CODE, collection_->GetName(name));
+  } else if (object->IsScript()) {
+    Script* script = Script::cast(object);
+    return AddEntry(object,
+                    HeapEntry::CODE,
+                    script->name()->IsString() ?
+                    collection_->GetName(String::cast(script->name())) : "");
   } else if (object->IsFixedArray()) {
     return AddEntry(object, HeapEntry::ARRAY);
   }
@@ -1309,6 +1328,16 @@
 }
 
 
+void HeapSnapshot::SetInternalReference(HeapEntry* parent,
+                                        const char* reference_name,
+                                        Object* child) {
+  HeapEntry* child_entry = GetEntry(child);
+  if (child_entry != NULL) {
+    parent->SetInternalReference(reference_name, child_entry);
+  }
+}
+
+
 void HeapSnapshot::SetPropertyReference(HeapEntry* parent,
                                         String* reference_name,
                                         Object* child) {
@@ -1537,6 +1566,7 @@
         snapshot_->SetClosureReference(entry, local_name, context->get(idx));
       }
     }
+    snapshot_->SetInternalReference(entry, "code", func->shared());
   }
 }
 
diff --git a/src/profile-generator.h b/src/profile-generator.h
index 3f90702..4e423c8 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -429,9 +429,10 @@
 class HeapGraphEdge {
  public:
   enum Type {
-    CONTEXT_VARIABLE,
-    ELEMENT,
-    PROPERTY
+    CONTEXT_VARIABLE = v8::HeapGraphEdge::CONTEXT_VARIABLE,
+    ELEMENT = v8::HeapGraphEdge::ELEMENT,
+    PROPERTY = v8::HeapGraphEdge::PROPERTY,
+    INTERNAL = v8::HeapGraphEdge::INTERNAL
   };
 
   HeapGraphEdge(Type type, const char* name, HeapEntry* from, HeapEntry* to);
@@ -443,7 +444,7 @@
     return index_;
   }
   const char* name() const {
-    ASSERT(type_ == CONTEXT_VARIABLE || type_ == PROPERTY);
+    ASSERT(type_ == CONTEXT_VARIABLE || type_ == PROPERTY || type_ == INTERNAL);
     return name_;
   }
   HeapEntry* from() const { return from_; }
@@ -468,12 +469,12 @@
 class HeapEntry {
  public:
   enum Type {
-    INTERNAL,
-    ARRAY,
-    STRING,
-    JS_OBJECT,
-    CODE,
-    CLOSURE
+    INTERNAL = v8::HeapGraphNode::INTERNAL,
+    ARRAY = v8::HeapGraphNode::ARRAY,
+    STRING = v8::HeapGraphNode::STRING,
+    OBJECT = v8::HeapGraphNode::OBJECT,
+    CODE = v8::HeapGraphNode::CODE,
+    CLOSURE = v8::HeapGraphNode::CLOSURE
   };
 
   explicit HeapEntry(HeapSnapshot* snapshot)
@@ -533,6 +534,7 @@
   void PaintReachableFromOthers() { painted_ = kPaintReachableFromOthers; }
   void SetClosureReference(const char* name, HeapEntry* entry);
   void SetElementReference(int index, HeapEntry* entry);
+  void SetInternalReference(const char* name, HeapEntry* entry);
   void SetPropertyReference(const char* name, HeapEntry* entry);
   void SetAutoIndexReference(HeapEntry* entry);
 
@@ -542,6 +544,7 @@
   void Print(int max_depth, int indent);
 
  private:
+  void AddEdge(HeapGraphEdge* edge);
   int CalculateTotalSize();
   int CalculateNonSharedTotalSize();
   void FindRetainingPaths(HeapEntry* node, CachedHeapGraphPath* prev_path);
@@ -641,6 +644,8 @@
   void SetClosureReference(
       HeapEntry* parent, String* reference_name, Object* child);
   void SetElementReference(HeapEntry* parent, int index, Object* child);
+  void SetInternalReference(
+      HeapEntry* parent, const char* reference_name, Object* child);
   void SetPropertyReference(
       HeapEntry* parent, String* reference_name, Object* child);
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 88786e8..71148e6 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -626,9 +626,9 @@
       PropertyDetails details = dictionary->DetailsAt(entry);
       elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
       elms->set(VALUE_INDEX, dictionary->ValueAt(entry));
-      elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete()));
+      elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly()));
       elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum()));
-      elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly()));
+      elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete()));
       return *desc;
     } else {
       // Elements that are stored as array elements always has:
@@ -3849,11 +3849,29 @@
   int unchecked = flag->value();
   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
 
+  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
+
+  // Check if this is an element.
+  uint32_t index;
+  bool is_element = name->AsArrayIndex(&index);
+
+  // Special case for elements if any of the flags are true.
+  // If elements are in fast case we always implicitly assume that:
+  // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false.
+  if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) &&
+      is_element) {
+    // Normalize the elements to enable attributes on the property.
+    js_object->NormalizeElements();
+    NumberDictionary* dictionary = js_object->element_dictionary();
+    // Make sure that we never go back to fast case.
+    dictionary->set_requires_slow_elements();
+    PropertyDetails details = PropertyDetails(attr, NORMAL);
+    dictionary->Set(index, *obj_value, details);
+  }
+
   LookupResult result;
   js_object->LocalLookupRealNamedProperty(*name, &result);
 
-  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
-
   // Take special care when attributes are different and there is already
   // a property. For simplicity we normalize the property which enables us
   // to not worry about changing the instance_descriptor and creating a new
@@ -3869,6 +3887,7 @@
                                                           *obj_value,
                                                           attr);
   }
+
   return Runtime::SetObjectProperty(js_object, name, obj_value, attr);
 }
 
@@ -4927,16 +4946,6 @@
 }
 
 
-static inline SeqAsciiString* TryGetSeqAsciiString(String* s) {
-  if (!s->IsFlat() || !s->IsAsciiRepresentation()) return NULL;
-  if (s->IsConsString()) {
-    ASSERT(ConsString::cast(s)->second()->length() == 0);
-    return SeqAsciiString::cast(ConsString::cast(s)->first());
-  }
-  return SeqAsciiString::cast(s);
-}
-
-
 namespace {
 
 struct ToLowerTraits {
@@ -4983,7 +4992,7 @@
     unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
   NoHandleAllocation ha;
   CONVERT_CHECKED(String, s, args[0]);
-  s->TryFlatten();
+  s = s->TryFlattenGetString();
 
   const int length = s->length();
   // Assume that the string is not empty; we need this assumption later
@@ -4995,13 +5004,12 @@
   // character is also ascii.  This is currently the case, but it
   // might break in the future if we implement more context and locale
   // dependent upper/lower conversions.
-  SeqAsciiString* seq_ascii = TryGetSeqAsciiString(s);
-  if (seq_ascii != NULL) {
+  if (s->IsSeqAsciiString()) {
     Object* o = Heap::AllocateRawAsciiString(length);
     if (o->IsFailure()) return o;
     SeqAsciiString* result = SeqAsciiString::cast(o);
     bool has_changed_character = ConvertTraits::ConvertAscii(
-        result->GetChars(), seq_ascii->GetChars(), length);
+        result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length);
     return has_changed_character ? result : s;
   }
 
@@ -5545,7 +5553,7 @@
     if (first->IsString()) return first;
   }
 
-  bool ascii = special->IsAsciiRepresentation();
+  bool ascii = special->HasOnlyAsciiChars();
   int position = 0;
   for (int i = 0; i < array_length; i++) {
     int increment = 0;
@@ -5586,7 +5594,7 @@
       String* element = String::cast(elt);
       int element_length = element->length();
       increment = element_length;
-      if (ascii && !element->IsAsciiRepresentation()) {
+      if (ascii && !element->HasOnlyAsciiChars()) {
         ascii = false;
       }
     } else {
@@ -9042,7 +9050,7 @@
   Handle<Object> break_point_object_arg = args.at<Object>(2);
 
   // Set break point.
-  Debug::SetBreakPoint(shared, source_position, break_point_object_arg);
+  Debug::SetBreakPoint(shared, break_point_object_arg, &source_position);
 
   return Heap::undefined_value();
 }
@@ -9062,8 +9070,6 @@
   // The current candidate for the source position:
   int target_start_position = RelocInfo::kNoPosition;
   Handle<SharedFunctionInfo> target;
-  // The current candidate for the last function in script:
-  Handle<SharedFunctionInfo> last;
   while (!done) {
     HeapIterator iterator;
     for (HeapObject* obj = iterator.next();
@@ -9104,25 +9110,12 @@
               }
             }
           }
-
-          // Keep track of the last function in the script.
-          if (last.is_null() ||
-              shared->end_position() > last->start_position()) {
-            last = shared;
-          }
         }
       }
     }
 
-    // Make sure some candidate is selected.
     if (target.is_null()) {
-      if (!last.is_null()) {
-        // Position after the last function - use last.
-        target = last;
-      } else {
-        // Unable to find function - possibly script without any function.
-        return Heap::undefined_value();
-      }
+      return Heap::undefined_value();
     }
 
     // If the candidate found is compiled we are done. NOTE: when lazy
@@ -9140,8 +9133,9 @@
 }
 
 
-// Change the state of a break point in a script. NOTE: Regarding performance
-// see the NOTE for GetScriptFromScriptData.
+// Changes the state of a break point in a script and returns source position
+// where break point was set. NOTE: Regarding performance see the NOTE for
+// GetScriptFromScriptData.
 // args[0]: script to set break point in
 // args[1]: number: break source position (within the script source)
 // args[2]: number: break point object
@@ -9169,7 +9163,9 @@
     } else {
       position = source_position - shared->start_position();
     }
-    Debug::SetBreakPoint(shared, position, break_point_object_arg);
+    Debug::SetBreakPoint(shared, break_point_object_arg, &position);
+    position += shared->start_position();
+    return Smi::FromInt(position);
   }
   return  Heap::undefined_value();
 }
diff --git a/src/scanner.cc b/src/scanner.cc
index 8943119..286f515 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -200,6 +200,7 @@
 
 // ----------------------------------------------------------------------------
 // Keyword Matcher
+
 KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
   { "break",  KEYWORD_PREFIX, Token::BREAK },
   { NULL,     C,              Token::ILLEGAL },
@@ -335,7 +336,7 @@
 // Scanner
 
 Scanner::Scanner(ParserMode pre)
-    : stack_overflow_(false), is_pre_parsing_(pre == PREPARSE) { }
+    : is_pre_parsing_(pre == PREPARSE), stack_overflow_(false) { }
 
 
 void Scanner::Initialize(Handle<String> source,
diff --git a/src/scanner.h b/src/scanner.h
index d5efdff..2dce5a1 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -154,7 +154,12 @@
 //  *: Actually "future reserved keywords". These are the only ones we
 //     recognized, the remaining are allowed as identifiers.
  public:
-  KeywordMatcher() : state_(INITIAL), token_(Token::IDENTIFIER) {}
+  KeywordMatcher()
+      : state_(INITIAL),
+        token_(Token::IDENTIFIER),
+        keyword_(NULL),
+        counter_(0),
+        keyword_token_(Token::ILLEGAL) {}
 
   Token::Value token() { return token_; }
 
@@ -206,17 +211,6 @@
   // State map for first keyword character range.
   static FirstState first_states_[kFirstCharRangeLength];
 
-  // Current state.
-  State state_;
-  // Token for currently added characters.
-  Token::Value token_;
-
-  // Matching a specific keyword string (there is only one possible valid
-  // keyword with the current prefix).
-  const char* keyword_;
-  int counter_;
-  Token::Value keyword_token_;
-
   // If input equals keyword's character at position, continue matching keyword
   // from that position.
   inline bool MatchKeywordStart(uc32 input,
@@ -246,15 +240,26 @@
                            char match,
                            State new_state,
                            Token::Value keyword_token) {
-    if (input == match) {  // Matched "do".
-      state_ = new_state;
-      token_ = keyword_token;
-      return true;
+    if (input != match) {
+      return false;
     }
-    return false;
+    state_ = new_state;
+    token_ = keyword_token;
+    return true;
   }
 
   void Step(uc32 input);
+
+  // Current state.
+  State state_;
+  // Token for currently added characters.
+  Token::Value token_;
+
+  // Matching a specific keyword string (there is only one possible valid
+  // keyword with the current prefix).
+  const char* keyword_;
+  int counter_;
+  Token::Value keyword_token_;
 };
 
 
@@ -362,37 +367,6 @@
   static const int kNoEndPosition = 1;
 
  private:
-  void Init(Handle<String> source,
-            unibrow::CharacterStream* stream,
-            int start_position, int end_position,
-            ParserLanguage language);
-
-
-  // Different UTF16 buffers used to pull characters from. Based on input one of
-  // these will be initialized as the actual data source.
-  CharacterStreamUTF16Buffer char_stream_buffer_;
-  ExternalStringUTF16Buffer<ExternalTwoByteString, uint16_t>
-      two_byte_string_buffer_;
-  ExternalStringUTF16Buffer<ExternalAsciiString, char> ascii_string_buffer_;
-
-  // Source. Will point to one of the buffers declared above.
-  UTF16Buffer* source_;
-
-  // Used to convert the source string into a character stream when a stream
-  // is not passed to the scanner.
-  SafeStringInputBuffer safe_string_input_buffer_;
-
-  // Buffer to hold literal values (identifiers, strings, numbers)
-  // using 0-terminated UTF-8 encoding.
-  UTF8Buffer literal_buffer_1_;
-  UTF8Buffer literal_buffer_2_;
-
-  bool stack_overflow_;
-  static StaticResource<Utf8Decoder> utf8_decoder_;
-
-  // One Unicode character look-ahead; c0_ < 0 at the end of the input.
-  uc32 c0_;
-
   // The current and look-ahead token.
   struct TokenDesc {
     Token::Value token;
@@ -400,11 +374,10 @@
     UTF8Buffer* literal_buffer;
   };
 
-  TokenDesc current_;  // desc for current token (as returned by Next())
-  TokenDesc next_;     // desc for next token (one token look-ahead)
-  bool has_line_terminator_before_next_;
-  bool is_pre_parsing_;
-  bool is_parsing_json_;
+  void Init(Handle<String> source,
+            unibrow::CharacterStream* stream,
+            int start_position, int end_position,
+            ParserLanguage language);
 
   // Literal buffer support
   void StartLiteral();
@@ -426,6 +399,7 @@
       return SkipJavaScriptWhiteSpace();
     }
   }
+
   bool SkipJavaScriptWhiteSpace();
   bool SkipJsonWhiteSpace();
   Token::Value SkipSingleLineComment();
@@ -460,11 +434,13 @@
   // the integer part is zero), and may include an exponent part (e.g., "e-10").
   // Hexadecimal and octal numbers are not allowed.
   Token::Value ScanJsonNumber();
+
   // A JSON string (production JSONString) is subset of valid JavaScript string
   // literals. The string must only be double-quoted (not single-quoted), and
   // the only allowed backslash-escapes are ", /, \, b, f, n, r, t and
   // four-digit hex escapes (uXXXX). Any other use of backslashes is invalid.
   Token::Value ScanJsonString();
+
   // Used to recognizes one of the literals "true", "false", or "null". These
   // are the only valid JSON identifiers (productions JSONBooleanLiteral,
   // JSONNullLiteral).
@@ -489,6 +465,37 @@
   // Decodes a unicode escape-sequence which is part of an identifier.
   // If the escape sequence cannot be decoded the result is kBadRune.
   uc32 ScanIdentifierUnicodeEscape();
+
+  TokenDesc current_;  // desc for current token (as returned by Next())
+  TokenDesc next_;     // desc for next token (one token look-ahead)
+  bool has_line_terminator_before_next_;
+  bool is_pre_parsing_;
+  bool is_parsing_json_;
+
+  // Different UTF16 buffers used to pull characters from. Based on input one of
+  // these will be initialized as the actual data source.
+  CharacterStreamUTF16Buffer char_stream_buffer_;
+  ExternalStringUTF16Buffer<ExternalTwoByteString, uint16_t>
+      two_byte_string_buffer_;
+  ExternalStringUTF16Buffer<ExternalAsciiString, char> ascii_string_buffer_;
+
+  // Source. Will point to one of the buffers declared above.
+  UTF16Buffer* source_;
+
+  // Used to convert the source string into a character stream when a stream
+  // is not passed to the scanner.
+  SafeStringInputBuffer safe_string_input_buffer_;
+
+  // Buffer to hold literal values (identifiers, strings, numbers)
+  // using 0-terminated UTF-8 encoding.
+  UTF8Buffer literal_buffer_1_;
+  UTF8Buffer literal_buffer_2_;
+
+  bool stack_overflow_;
+  static StaticResource<Utf8Decoder> utf8_decoder_;
+
+  // One Unicode character look-ahead; c0_ < 0 at the end of the input.
+  uc32 c0_;
 };
 
 } }  // namespace v8::internal
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index 8b7e2ad..2091ca7 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -408,6 +408,18 @@
 
 
 template<class Allocator>
+bool ScopeInfo<Allocator>::HasHeapAllocatedLocals(Code* code) {
+  if (code->sinfo_size() > 0) {
+    Object** p = ContextEntriesAddr(code);
+    int n;  // number of context slots;
+    ReadInt(p, &n);
+    return n > 0;
+  }
+  return false;
+}
+
+
+template<class Allocator>
 int ScopeInfo<Allocator>::StackSlotIndex(Code* code, String* name) {
   ASSERT(name->IsSymbol());
   if (code->sinfo_size() > 0) {
diff --git a/src/scopeinfo.h b/src/scopeinfo.h
index 927ac66..9fb26d0 100644
--- a/src/scopeinfo.h
+++ b/src/scopeinfo.h
@@ -112,6 +112,9 @@
   // Return the number of context slots for code.
   static int NumberOfContextSlots(Code* code);
 
+  // Return if this has context slots besides MIN_CONTEXT_SLOTS;
+  static bool HasHeapAllocatedLocals(Code* code);
+
   // Lookup support for scope info embedded in Code objects. Returns
   // the stack slot index for a given slot name if the slot is
   // present; otherwise returns a value < 0. The name must be a symbol
diff --git a/src/serialize.cc b/src/serialize.cc
index e610e28..a6a516a 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -364,90 +364,102 @@
       UNCLASSIFIED,
       6,
       "RegExpStack::limit_address()");
-  Add(ExternalReference::new_space_start().address(),
+  Add(ExternalReference::address_of_regexp_stack_memory_address().address(),
       UNCLASSIFIED,
       7,
+      "RegExpStack::memory_address()");
+  Add(ExternalReference::address_of_regexp_stack_memory_size().address(),
+      UNCLASSIFIED,
+      8,
+      "RegExpStack::memory_size()");
+  Add(ExternalReference::address_of_static_offsets_vector().address(),
+      UNCLASSIFIED,
+      9,
+      "OffsetsVector::static_offsets_vector");
+  Add(ExternalReference::new_space_start().address(),
+      UNCLASSIFIED,
+      10,
       "Heap::NewSpaceStart()");
   Add(ExternalReference::new_space_mask().address(),
       UNCLASSIFIED,
-      8,
+      11,
       "Heap::NewSpaceMask()");
   Add(ExternalReference::heap_always_allocate_scope_depth().address(),
       UNCLASSIFIED,
-      9,
+      12,
       "Heap::always_allocate_scope_depth()");
   Add(ExternalReference::new_space_allocation_limit_address().address(),
       UNCLASSIFIED,
-      10,
+      13,
       "Heap::NewSpaceAllocationLimitAddress()");
   Add(ExternalReference::new_space_allocation_top_address().address(),
       UNCLASSIFIED,
-      11,
+      14,
       "Heap::NewSpaceAllocationTopAddress()");
 #ifdef ENABLE_DEBUGGER_SUPPORT
   Add(ExternalReference::debug_break().address(),
       UNCLASSIFIED,
-      12,
+      15,
       "Debug::Break()");
   Add(ExternalReference::debug_step_in_fp_address().address(),
       UNCLASSIFIED,
-      13,
+      16,
       "Debug::step_in_fp_addr()");
 #endif
   Add(ExternalReference::double_fp_operation(Token::ADD).address(),
       UNCLASSIFIED,
-      14,
+      17,
       "add_two_doubles");
   Add(ExternalReference::double_fp_operation(Token::SUB).address(),
       UNCLASSIFIED,
-      15,
+      18,
       "sub_two_doubles");
   Add(ExternalReference::double_fp_operation(Token::MUL).address(),
       UNCLASSIFIED,
-      16,
+      19,
       "mul_two_doubles");
   Add(ExternalReference::double_fp_operation(Token::DIV).address(),
       UNCLASSIFIED,
-      17,
+      20,
       "div_two_doubles");
   Add(ExternalReference::double_fp_operation(Token::MOD).address(),
       UNCLASSIFIED,
-      18,
+      21,
       "mod_two_doubles");
   Add(ExternalReference::compare_doubles().address(),
       UNCLASSIFIED,
-      19,
+      22,
       "compare_doubles");
 #ifndef V8_INTERPRETED_REGEXP
   Add(ExternalReference::re_case_insensitive_compare_uc16().address(),
       UNCLASSIFIED,
-      20,
+      23,
       "NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
   Add(ExternalReference::re_check_stack_guard_state().address(),
       UNCLASSIFIED,
-      21,
+      24,
       "RegExpMacroAssembler*::CheckStackGuardState()");
   Add(ExternalReference::re_grow_stack().address(),
       UNCLASSIFIED,
-      22,
+      25,
       "NativeRegExpMacroAssembler::GrowStack()");
   Add(ExternalReference::re_word_character_map().address(),
       UNCLASSIFIED,
-      23,
+      26,
       "NativeRegExpMacroAssembler::word_character_map");
 #endif  // V8_INTERPRETED_REGEXP
   // Keyed lookup cache.
   Add(ExternalReference::keyed_lookup_cache_keys().address(),
       UNCLASSIFIED,
-      24,
+      27,
       "KeyedLookupCache::keys()");
   Add(ExternalReference::keyed_lookup_cache_field_offsets().address(),
       UNCLASSIFIED,
-      25,
+      28,
       "KeyedLookupCache::field_offsets()");
   Add(ExternalReference::transcendental_cache_array_address().address(),
       UNCLASSIFIED,
-      26,
+      29,
       "TranscendentalCache::caches()");
 }
 
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 397988a..ffa92dd 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -121,7 +121,7 @@
         receiver->map()->UpdateCodeCache(cache_name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -139,7 +139,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -158,7 +158,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -177,7 +177,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -194,13 +194,12 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
 Object* StubCache::ComputeLoadNormal(String* name, JSObject* receiver) {
-  Code* code = Builtins::builtin(Builtins::LoadIC_Normal);
-  return Set(name, receiver->map(), code);
+  return Builtins::builtin(Builtins::LoadIC_Normal);
 }
 
 
@@ -223,7 +222,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -368,7 +367,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -385,7 +384,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -403,7 +402,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -420,7 +419,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -486,7 +485,7 @@
     Object* result = map->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, map, Code::cast(code));
+  return code;
 }
 
 
@@ -525,7 +524,7 @@
     Object* result = map->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, map, Code::cast(code));
+  return code;
 }
 
 
@@ -563,7 +562,7 @@
     Object* result = map->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, map, Code::cast(code));
+  return code;
 }
 
 
@@ -574,7 +573,7 @@
                                      JSObject* receiver) {
   Object* code = ComputeCallNormal(argc, in_loop, kind);
   if (code->IsFailure()) return code;
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -607,7 +606,7 @@
     Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
     if (result->IsFailure()) return result;
   }
-  return Set(name, receiver->map(), Code::cast(code));
+  return code;
 }
 
 
@@ -1106,6 +1105,7 @@
     Code* code = Code::cast(result);
     USE(code);
     Code::Kind kind = Code::ExtractKindFromFlags(flags);
+    USE(kind);
     PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
                             code, code->arguments_count()));
   }
diff --git a/src/utils.h b/src/utils.h
index ed6d9a4..d7c5b70 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -47,6 +47,41 @@
 }
 
 
+// X must be a power of 2.  Returns the number of trailing zeros.
+template <typename T>
+static inline int WhichPowerOf2(T x) {
+  ASSERT(IsPowerOf2(x));
+  ASSERT(x != 0);
+  if (x < 0) return 31;
+  int bits = 0;
+#ifdef DEBUG
+  int original_x = x;
+#endif
+  if (x >= 0x10000) {
+    bits += 16;
+    x >>= 16;
+  }
+  if (x >= 0x100) {
+    bits += 8;
+    x >>= 8;
+  }
+  if (x >= 0x10) {
+    bits += 4;
+    x >>= 4;
+  }
+  switch (x) {
+    default: UNREACHABLE();
+    case 8: bits++;  // Fall through.
+    case 4: bits++;  // Fall through.
+    case 2: bits++;  // Fall through.
+    case 1: break;
+  }
+  ASSERT_EQ(1 << bits, original_x);
+  return bits;
+  return 0;
+}
+
+
 // The C++ standard leaves the semantics of '>>' undefined for
 // negative signed operands. Most implementations do the right thing,
 // though.
diff --git a/src/v8.cc b/src/v8.cc
index 65ce2e1..2313967 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -32,6 +32,7 @@
 #include "serialize.h"
 #include "simulator.h"
 #include "stub-cache.h"
+#include "heap-profiler.h"
 #include "oprofile-agent.h"
 #include "log.h"
 
@@ -61,6 +62,7 @@
   Logger::Setup();
 
   CpuProfiler::Setup();
+  HeapProfiler::Setup();
 
   // Setup the platform OS support.
   OS::Setup();
@@ -149,6 +151,8 @@
 
   Top::TearDown();
 
+  HeapProfiler::TearDown();
+
   CpuProfiler::TearDown();
 
   Heap::TearDown();
diff --git a/src/version.cc b/src/version.cc
index d210dab..c9e8411 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,9 +34,9 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     2
-#define BUILD_NUMBER      18
+#define BUILD_NUMBER      19
 #define PATCH_LEVEL       0
-#define CANDIDATE_VERSION true
+#define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
 // shared library instead the generic SONAME generated from the V8 version
diff --git a/src/virtual-frame-light-inl.h b/src/virtual-frame-light-inl.h
index d08b5d2..19520a6 100644
--- a/src/virtual-frame-light-inl.h
+++ b/src/virtual-frame-light-inl.h
@@ -74,7 +74,9 @@
 
 
 void VirtualFrame::PrepareForReturn() {
-  SpillAll();
+  // Don't bother flushing tos registers as returning does not require more
+  // access to the expression stack.
+  top_of_stack_state_ = NO_TOS_REGISTERS;
 }
 
 
diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h
index 70bcdb1..01c60aa 100644
--- a/src/x64/assembler-x64-inl.h
+++ b/src/x64/assembler-x64-inl.h
@@ -35,16 +35,11 @@
 namespace v8 {
 namespace internal {
 
-inline Condition NegateCondition(Condition cc) {
-  return static_cast<Condition>(cc ^ 1);
-}
-
 
 // -----------------------------------------------------------------------------
 // Implementation of Assembler
 
 
-
 void Assembler::emitl(uint32_t x) {
   Memory::uint32_at(pc_) = x;
   pc_ += sizeof(uint32_t);
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index d77c09f..e665385 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -382,6 +382,11 @@
 }
 
 
+void Assembler::CodeTargetAlign() {
+  Align(16);  // Preferred alignment of jump targets on x64.
+}
+
+
 void Assembler::bind_to(Label* L, int pos) {
   ASSERT(!L->is_bound());  // Label may only be bound once.
   last_pc_ = NULL;
@@ -1148,6 +1153,15 @@
 }
 
 
+void Assembler::incl(Register dst) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  emit_optional_rex_32(dst);
+  emit(0xFF);
+  emit_modrm(0, dst);
+}
+
+
 void Assembler::int3() {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
@@ -2738,17 +2752,6 @@
 }
 
 
-void Assembler::comisd(XMMRegister dst, XMMRegister src) {
-  EnsureSpace ensure_space(this);
-  last_pc_ = pc_;
-  emit(0x66);
-  emit_optional_rex_32(dst, src);
-  emit(0x0f);
-  emit(0x2f);
-  emit_sse_operand(dst, src);
-}
-
-
 void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
   EnsureSpace ensure_space(this);
   last_pc_ = pc_;
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index c7e737c..f195439 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -215,7 +215,10 @@
 // Negation of the default no_condition (-1) results in a non-default
 // no_condition value (-2). As long as tests for no_condition check
 // for condition < 0, this will work as expected.
-inline Condition NegateCondition(Condition cc);
+inline Condition NegateCondition(Condition cc) {
+  return static_cast<Condition>(cc ^ 1);
+}
+
 
 // Corresponds to transposing the operands of a comparison.
 inline Condition ReverseCondition(Condition cc) {
@@ -241,6 +244,7 @@
   };
 }
 
+
 enum Hint {
   no_hint = 0,
   not_taken = 0x2e,
@@ -495,6 +499,8 @@
   // possible to align the pc offset to a multiple
   // of m. m must be a power of 2.
   void Align(int m);
+  // Aligns code to something that's optimal for a jump target for the platform.
+  void CodeTargetAlign();
 
   // Stack
   void pushfq();
@@ -761,6 +767,7 @@
 
   void incq(Register dst);
   void incq(const Operand& dst);
+  void incl(Register dst);
   void incl(const Operand& dst);
 
   void lea(Register dst, const Operand& src);
@@ -1122,7 +1129,6 @@
   void xorpd(XMMRegister dst, XMMRegister src);
   void sqrtsd(XMMRegister dst, XMMRegister src);
 
-  void comisd(XMMRegister dst, XMMRegister src);
   void ucomisd(XMMRegister dst, XMMRegister src);
 
   // The first argument is the reg field, the second argument is the r/m field.
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index f9692ce..3ba8906 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -262,63 +262,23 @@
 
 class FloatingPointHelper : public AllStatic {
  public:
-  // Code pattern for loading a floating point value. Input value must
-  // be either a smi or a heap number object (fp value). Requirements:
-  // operand on TOS+1. Returns operand as floating point number on FPU
-  // stack.
-  static void LoadFloatOperand(MacroAssembler* masm, Register scratch);
-
-  // Code pattern for loading a floating point value. Input value must
-  // be either a smi or a heap number object (fp value). Requirements:
-  // operand in src register. Returns operand as floating point number
-  // in XMM register.  May destroy src register.
-  static void LoadFloatOperand(MacroAssembler* masm,
-                               Register src,
-                               XMMRegister dst);
-
-  // Code pattern for loading a possible number into a XMM register.
-  // If the contents of src is not a number, control branches to
-  // the Label not_number.  If contents of src is a smi or a heap number
-  // object (fp value), it is loaded into the XMM register as a double.
-  // The register src is not changed, and src may not be kScratchRegister.
-  static void LoadFloatOperand(MacroAssembler* masm,
-                               Register src,
-                               XMMRegister dst,
-                               Label *not_number);
-
-  // Code pattern for loading floating point values. Input values must
-  // be either smi or heap number objects (fp values). Requirements:
-  // operand_1 in rdx, operand_2 in rax; Returns operands as
-  // floating point numbers in XMM registers.
-  static void LoadFloatOperands(MacroAssembler* masm,
-                                XMMRegister dst1,
-                                XMMRegister dst2);
-
-  // Similar to LoadFloatOperands, assumes that the operands are smis.
-  static void LoadFloatOperandsFromSmis(MacroAssembler* masm,
-                                        XMMRegister dst1,
-                                        XMMRegister dst2);
-
-  // Code pattern for loading floating point values onto the fp stack.
-  // Input values must be either smi or heap number objects (fp values).
-  // Requirements:
-  // Register version: operands in registers lhs and rhs.
-  // Stack version: operands on TOS+1 and TOS+2.
-  // Returns operands as floating point numbers on fp stack.
-  static void LoadFloatOperands(MacroAssembler* masm,
-                                Register lhs,
-                                Register rhs);
-
-  // Test if operands are smi or number objects (fp). Requirements:
-  // operand_1 in rax, operand_2 in rdx; falls through on float or smi
-  // operands, jumps to the non_float label otherwise.
-  static void CheckNumberOperands(MacroAssembler* masm,
-                                  Label* non_float);
+  // Load the operands from rdx and rax into xmm0 and xmm1, as doubles.
+  // If the operands are not both numbers, jump to not_numbers.
+  // Leaves rdx and rax unchanged.  SmiOperands assumes both are smis.
+  // NumberOperands assumes both are smis or heap numbers.
+  static void LoadSSE2SmiOperands(MacroAssembler* masm);
+  static void LoadSSE2NumberOperands(MacroAssembler* masm);
+  static void LoadSSE2UnknownOperands(MacroAssembler* masm,
+                                      Label* not_numbers);
 
   // Takes the operands in rdx and rax and loads them as integers in rax
   // and rcx.
   static void LoadAsIntegers(MacroAssembler* masm,
-                             Label* operand_conversion_failure);
+                             Label* operand_conversion_failure,
+                             Register heap_number_map);
+  // As above, but we know the operands to be numbers. In that case,
+  // conversion can't fail.
+  static void LoadNumbersAsIntegers(MacroAssembler* masm);
 };
 
 
@@ -3108,25 +3068,31 @@
         ref.GetValue();
         // Use global object as receiver.
         LoadGlobalReceiver();
+       // Call the function.
+        CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position());
       } else {
-        Reference ref(this, property, false);
-        ASSERT(ref.size() == 2);
-        Result key = frame_->Pop();
-        frame_->Dup();  // Duplicate the receiver.
-        frame_->Push(&key);
-        ref.GetValue();
-        // Top of frame contains function to call, with duplicate copy of
-        // receiver below it.  Swap them.
-        Result function = frame_->Pop();
-        Result receiver = frame_->Pop();
-        frame_->Push(&function);
-        frame_->Push(&receiver);
+        // Push the receiver onto the frame.
+        Load(property->obj());
+
+        // Load the arguments.
+        int arg_count = args->length();
+        for (int i = 0; i < arg_count; i++) {
+          Load(args->at(i));
+          frame_->SpillTop();
+        }
+
+        // Load the name of the function.
+        Load(property->key());
+
+        // Call the IC initialization code.
+        CodeForSourcePosition(node->position());
+        Result result = frame_->CallKeyedCallIC(RelocInfo::CODE_TARGET,
+                                                arg_count,
+                                                loop_nesting());
+        frame_->RestoreContextRegister();
+        frame_->Push(&result);
       }
-
-      // Call the function.
-      CallWithArguments(args, RECEIVER_MIGHT_BE_VALUE, node->position());
     }
-
   } else {
     // ----------------------------------
     // JavaScript example: 'foo(1, 2, 3)'  // foo is not global
@@ -4423,7 +4389,7 @@
   // Since xmm3 is 1 and xmm2 is -0.5 this is simply xmm2 + xmm3.
   __ addsd(xmm2, xmm3);
   // xmm2 now has 0.5.
-  __ comisd(xmm2, xmm1);
+  __ ucomisd(xmm2, xmm1);
   call_runtime.Branch(not_equal);
 
   // Calculates square root.
@@ -4763,8 +4729,8 @@
   __ cmpq(ArrayElement(cache_, dst_), key_);
   __ j(not_equal, &first_loop);
 
-  __ Integer32ToSmi(scratch_, dst_);
-  __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_);
+  __ Integer32ToSmiField(
+      FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_);
   __ movq(dst_, ArrayElement(cache_, dst_, 1));
   __ jmp(exit_label());
 
@@ -4785,16 +4751,15 @@
   __ cmpq(ArrayElement(cache_, dst_), key_);
   __ j(not_equal, &second_loop);
 
-  __ Integer32ToSmi(scratch_, dst_);
-  __ movq(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), scratch_);
+  __ Integer32ToSmiField(
+      FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_);
   __ movq(dst_, ArrayElement(cache_, dst_, 1));
   __ jmp(exit_label());
 
   __ bind(&cache_miss);
   __ push(cache_);  // store a reference to cache
   __ push(key_);  // store a key
-  Handle<Object> receiver(Top::global_context()->global());
-  __ Push(receiver);
+  __ push(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ push(key_);
   // On x64 function must be in rdi.
   __ movq(rdi, FieldOperand(cache_, JSFunctionResultCache::kFactoryOffset));
@@ -4809,50 +4774,50 @@
   // cache miss this optimization would hardly matter much.
 
   // Check if we could add new entry to cache.
-  __ movq(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
-  __ movq(r9, FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset));
-  __ SmiCompare(rbx, r9);
+  __ SmiToInteger32(rbx, FieldOperand(rcx, FixedArray::kLengthOffset));
+  __ SmiToInteger32(r9,
+                    FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset));
+  __ cmpl(rbx, r9);
   __ j(greater, &add_new_entry);
 
   // Check if we could evict entry after finger.
-  __ movq(rdx, FieldOperand(rcx, JSFunctionResultCache::kFingerOffset));
-  __ SmiToInteger32(rdx, rdx);
-  __ SmiToInteger32(rbx, rbx);
-  __ addq(rdx, kEntrySizeImm);
+  __ SmiToInteger32(rdx,
+                    FieldOperand(rcx, JSFunctionResultCache::kFingerOffset));
+  __ addl(rdx, kEntrySizeImm);
   Label forward;
-  __ cmpq(rbx, rdx);
+  __ cmpl(rbx, rdx);
   __ j(greater, &forward);
   // Need to wrap over the cache.
   __ movl(rdx, kEntriesIndexImm);
   __ bind(&forward);
-  __ Integer32ToSmi(r9, rdx);
+  __ movl(r9, rdx);
   __ jmp(&update_cache);
 
   __ bind(&add_new_entry);
-  // r9 holds cache size as smi.
-  __ SmiToInteger32(rdx, r9);
-  __ SmiAddConstant(rbx, r9, Smi::FromInt(JSFunctionResultCache::kEntrySize));
-  __ movq(FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset), rbx);
+  // r9 holds cache size as int32.
+  __ leal(rbx, Operand(r9, JSFunctionResultCache::kEntrySize));
+  __ Integer32ToSmiField(
+      FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset), rbx);
 
   // Update the cache itself.
-  // rdx holds the index as int.
-  // r9 holds the index as smi.
+  // r9 holds the index as int32.
   __ bind(&update_cache);
   __ pop(rbx);  // restore the key
-  __ movq(FieldOperand(rcx, JSFunctionResultCache::kFingerOffset), r9);
+  __ Integer32ToSmiField(
+      FieldOperand(rcx, JSFunctionResultCache::kFingerOffset), r9);
   // Store key.
-  __ movq(ArrayElement(rcx, rdx), rbx);
+  __ movq(ArrayElement(rcx, r9), rbx);
   __ RecordWrite(rcx, 0, rbx, r9);
 
   // Store value.
   __ pop(rcx);  // restore the cache.
-  __ movq(rdx, FieldOperand(rcx, JSFunctionResultCache::kFingerOffset));
-  __ SmiAddConstant(rdx, rdx, Smi::FromInt(1));
-  __ movq(r9, rdx);
-  __ SmiToInteger32(rdx, rdx);
+  __ SmiToInteger32(rdx,
+                    FieldOperand(rcx, JSFunctionResultCache::kFingerOffset));
+  __ incl(rdx);
+  // Backup rax, because the RecordWrite macro clobbers its arguments.
   __ movq(rbx, rax);
-  __ movq(ArrayElement(rcx, rdx), rbx);
-  __ RecordWrite(rcx, 0, rbx, r9);
+  __ movq(ArrayElement(rcx, rdx), rax);
+  __ RecordWrite(rcx, 0, rbx, rdx);
 
   if (!dst_.is(rax)) {
     __ movq(dst_, rax);
@@ -6507,7 +6472,7 @@
                         &not_numbers);
   LoadComparisonOperand(masm_, right_side, xmm1, left_side, right_side,
                         &not_numbers);
-  __ comisd(xmm0, xmm1);
+  __ ucomisd(xmm0, xmm1);
   // Bail out if a NaN is involved.
   not_numbers.Branch(parity_even, left_side, right_side);
 
@@ -8178,7 +8143,7 @@
   // ST[0] == double value
   // rbx = bits of double value.
   // rdx = also bits of double value.
-  // Compute hash (h is 32 bits, bits are 64):
+  // Compute hash (h is 32 bits, bits are 64 and the shifts are arithmetic):
   //   h = h0 = bits ^ (bits >> 32);
   //   h ^= h >> 16;
   //   h ^= h >> 8;
@@ -8189,9 +8154,9 @@
   __ movl(rcx, rdx);
   __ movl(rax, rdx);
   __ movl(rdi, rdx);
-  __ shrl(rdx, Immediate(8));
-  __ shrl(rcx, Immediate(16));
-  __ shrl(rax, Immediate(24));
+  __ sarl(rdx, Immediate(8));
+  __ sarl(rcx, Immediate(16));
+  __ sarl(rax, Immediate(24));
   __ xorl(rcx, rdx);
   __ xorl(rax, rdi);
   __ xorl(rcx, rax);
@@ -8293,7 +8258,7 @@
   // Move exponent and sign bits to low bits.
   __ shr(rdi, Immediate(HeapNumber::kMantissaBits));
   // Remove sign bit.
-  __ andl(rdi, Immediate((1 << HeapNumber::KExponentBits) - 1));
+  __ andl(rdi, Immediate((1 << HeapNumber::kExponentBits) - 1));
   int supported_exponent_limit = (63 + HeapNumber::kExponentBias);
   __ cmpl(rdi, Immediate(supported_exponent_limit));
   __ j(below, &in_range);
@@ -8370,7 +8335,7 @@
   // Double to remove sign bit, shift exponent down to least significant bits.
   // and subtract bias to get the unshifted, unbiased exponent.
   __ lea(double_exponent, Operand(double_value, double_value, times_1, 0));
-  __ shr(double_exponent, Immediate(64 - HeapNumber::KExponentBits));
+  __ shr(double_exponent, Immediate(64 - HeapNumber::kExponentBits));
   __ subl(double_exponent, Immediate(HeapNumber::kExponentBias));
   // Check whether the exponent is too big for a 63 bit unsigned integer.
   __ cmpl(double_exponent, Immediate(63));
@@ -8546,18 +8511,18 @@
 
   // rcx: RegExp data (FixedArray)
   // Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
-  __ movq(rbx, FieldOperand(rcx, JSRegExp::kDataTagOffset));
-  __ SmiCompare(rbx, Smi::FromInt(JSRegExp::IRREGEXP));
+  __ SmiToInteger32(rbx, FieldOperand(rcx, JSRegExp::kDataTagOffset));
+  __ cmpl(rbx, Immediate(JSRegExp::IRREGEXP));
   __ j(not_equal, &runtime);
 
   // rcx: RegExp data (FixedArray)
   // Check that the number of captures fit in the static offsets vector buffer.
-  __ movq(rdx, FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
+  __ SmiToInteger32(rdx,
+                    FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
   // Calculate number of capture registers (number_of_captures + 1) * 2.
-  __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rdx, 1);
-  __ addq(rdx, Immediate(2));  // rdx was number_of_captures * 2.
+  __ leal(rdx, Operand(rdx, rdx, times_1, 2));
   // Check that the static offsets vector buffer is large enough.
-  __ cmpq(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize));
+  __ cmpl(rdx, Immediate(OffsetsVector::kStaticOffsetsVectorSize));
   __ j(above, &runtime);
 
   // rcx: RegExp data (FixedArray)
@@ -8567,17 +8532,15 @@
   __ JumpIfSmi(rax, &runtime);
   Condition is_string = masm->IsObjectStringType(rax, rbx, rbx);
   __ j(NegateCondition(is_string), &runtime);
-  // Get the length of the string to rbx.
-  __ movq(rbx, FieldOperand(rax, String::kLengthOffset));
 
-  // rbx: Length of subject string as smi
-  // rcx: RegExp data (FixedArray)
-  // rdx: Number of capture registers
+  // rax: Subject string.
+  // rcx: RegExp data (FixedArray).
+  // rdx: Number of capture registers.
   // Check that the third argument is a positive smi less than the string
   // length. A negative value will be greater (unsigned comparison).
-  __ movq(rax, Operand(rsp, kPreviousIndexOffset));
-  __ JumpIfNotSmi(rax, &runtime);
-  __ SmiCompare(rax, rbx);
+  __ movq(rbx, Operand(rsp, kPreviousIndexOffset));
+  __ JumpIfNotSmi(rbx, &runtime);
+  __ SmiCompare(rbx, FieldOperand(rax, String::kLengthOffset));
   __ j(above_equal, &runtime);
 
   // rcx: RegExp data (FixedArray)
@@ -8595,65 +8558,63 @@
   // Check that the last match info has space for the capture registers and the
   // additional information. Ensure no overflow in add.
   ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
-  __ movq(rax, FieldOperand(rbx, FixedArray::kLengthOffset));
-  __ SmiToInteger32(rax, rax);
+  __ SmiToInteger32(rax, FieldOperand(rbx, FixedArray::kLengthOffset));
   __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead));
   __ cmpl(rdx, rax);
   __ j(greater, &runtime);
 
-  // ecx: RegExp data (FixedArray)
+  // rcx: RegExp data (FixedArray)
   // Check the representation and encoding of the subject string.
-  Label seq_string, seq_two_byte_string, check_code;
-  const int kStringRepresentationEncodingMask =
-      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask;
+  Label seq_ascii_string, seq_two_byte_string, check_code;
   __ movq(rax, Operand(rsp, kSubjectOffset));
   __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
   __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
-  __ andb(rbx, Immediate(kStringRepresentationEncodingMask));
-  // First check for sequential string.
-  ASSERT_EQ(0, kStringTag);
-  ASSERT_EQ(0, kSeqStringTag);
+  // First check for flat two byte string.
+  __ andb(rbx, Immediate(
+      kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask));
+  ASSERT_EQ(0, kStringTag | kSeqStringTag | kTwoByteStringTag);
+  __ j(zero, &seq_two_byte_string);
+  // Any other flat string must be a flat ascii string.
   __ testb(rbx, Immediate(kIsNotStringMask | kStringRepresentationMask));
-  __ j(zero, &seq_string);
+  __ j(zero, &seq_ascii_string);
 
   // Check for flat cons string.
   // A flat cons string is a cons string where the second part is the empty
   // string. In that case the subject string is just the first part of the cons
   // string. Also in this case the first part of the cons string is known to be
   // a sequential string or an external string.
-  __ andb(rbx, Immediate(kStringRepresentationMask));
-  __ cmpb(rbx, Immediate(kConsStringTag));
-  __ j(not_equal, &runtime);
+  ASSERT(kExternalStringTag !=0);
+  ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
+  __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag));
+  __ j(not_zero, &runtime);
+  // String is a cons string.
   __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset));
   __ Cmp(rdx, Factory::empty_string());
   __ j(not_equal, &runtime);
   __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset));
   __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
-  __ movzxbl(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
-  ASSERT_EQ(0, kSeqStringTag);
-  __ testb(rbx, Immediate(kStringRepresentationMask));
+  // String is a cons string with empty second part.
+  // eax: first part of cons string.
+  // ebx: map of first part of cons string.
+  // Is first part a flat two byte string?
+  __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
+           Immediate(kStringRepresentationMask | kStringEncodingMask));
+  ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag);
+  __ j(zero, &seq_two_byte_string);
+  // Any other flat string must be ascii.
+  __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
+           Immediate(kStringRepresentationMask));
   __ j(not_zero, &runtime);
-  __ andb(rbx, Immediate(kStringRepresentationEncodingMask));
 
-  __ bind(&seq_string);
-  // rax: subject string (sequential either ascii to two byte)
-  // rbx: suject string type & kStringRepresentationEncodingMask
+  __ bind(&seq_ascii_string);
+  // rax: subject string (sequential ascii)
   // rcx: RegExp data (FixedArray)
-  // Check that the irregexp code has been generated for an ascii string. If
-  // it has, the field contains a code object otherwise it contains the hole.
-  const int kSeqTwoByteString = kStringTag | kSeqStringTag | kTwoByteStringTag;
-  __ cmpb(rbx, Immediate(kSeqTwoByteString));
-  __ j(equal, &seq_two_byte_string);
-  if (FLAG_debug_code) {
-    __ cmpb(rbx, Immediate(kStringTag | kSeqStringTag | kAsciiStringTag));
-    __ Check(equal, "Expected sequential ascii string");
-  }
   __ movq(r12, FieldOperand(rcx, JSRegExp::kDataAsciiCodeOffset));
   __ Set(rdi, 1);  // Type is ascii.
   __ jmp(&check_code);
 
   __ bind(&seq_two_byte_string);
-  // rax: subject string
+  // rax: subject string (flat two-byte)
   // rcx: RegExp data (FixedArray)
   __ movq(r12, FieldOperand(rcx, JSRegExp::kDataUC16CodeOffset));
   __ Set(rdi, 0);  // Type is two byte.
@@ -8670,8 +8631,7 @@
   // r12: code
   // Load used arguments before starting to push arguments for call to native
   // RegExp code to avoid handling changing stack height.
-  __ movq(rbx, Operand(rsp, kPreviousIndexOffset));
-  __ SmiToInteger64(rbx, rbx);  // Previous index from smi.
+  __ SmiToInteger64(rbx, Operand(rsp, kPreviousIndexOffset));
 
   // rax: subject string
   // rbx: previous index
@@ -8783,10 +8743,10 @@
   __ bind(&success);
   __ movq(rax, Operand(rsp, kJSRegExpOffset));
   __ movq(rcx, FieldOperand(rax, JSRegExp::kDataOffset));
-  __ movq(rdx, FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
+  __ SmiToInteger32(rax,
+                    FieldOperand(rcx, JSRegExp::kIrregexpCaptureCountOffset));
   // Calculate number of capture registers (number_of_captures + 1) * 2.
-  __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rdx, 1);
-  __ addq(rdx, Immediate(2));  // rdx was number_of_captures * 2.
+  __ leal(rdx, Operand(rax, rax, times_1, 2));
 
   // rdx: Number of capture registers
   // Load last_match_info which is still known to be a fast case JSArray.
@@ -8829,7 +8789,7 @@
                        rdx,
                        times_pointer_size,
                        RegExpImpl::kFirstCaptureOffset),
-                       rdi);
+          rdi);
   __ jmp(&next_capture);
   __ bind(&done);
 
@@ -8873,9 +8833,9 @@
 
   // Make the hash mask from the length of the number string cache. It
   // contains two elements (number and string) for each cache entry.
-  __ movq(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
-  // Divide smi tagged length by two.
-  __ PositiveSmiDivPowerOfTwoToInteger32(mask, mask, 1);
+  __ SmiToInteger32(
+      mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
+  __ shrl(mask, Immediate(1));
   __ subq(mask, Immediate(1));  // Make mask.
 
   // Calculate the entry in the number string cache. The hash value in the
@@ -8905,15 +8865,14 @@
     CpuFeatures::Scope fscope(SSE2);
     __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
     __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
-    __ comisd(xmm0, xmm1);
+    __ ucomisd(xmm0, xmm1);
     __ j(parity_even, not_found);  // Bail out if NaN is involved.
     __ j(not_equal, not_found);  // The cache did not contain this value.
     __ jmp(&load_result_from_cache);
   }
 
   __ bind(&is_smi);
-  __ movq(scratch, object);
-  __ SmiToInteger32(scratch, scratch);
+  __ SmiToInteger32(scratch, object);
   GenerateConvertHashCodeToIndex(masm, scratch, mask);
 
   Register index = scratch;
@@ -9107,12 +9066,8 @@
   if (include_number_compare_) {
     Label non_number_comparison;
     Label unordered;
-    FloatingPointHelper::LoadFloatOperand(masm, rdx, xmm0,
-                                          &non_number_comparison);
-    FloatingPointHelper::LoadFloatOperand(masm, rax, xmm1,
-                                          &non_number_comparison);
-
-    __ comisd(xmm0, xmm1);
+    FloatingPointHelper::LoadSSE2UnknownOperands(masm, &non_number_comparison);
+    __ ucomisd(xmm0, xmm1);
 
     // Don't base result on EFLAGS when a NaN is involved.
     __ j(parity_even, &unordered);
@@ -9340,29 +9295,30 @@
   __ j(equal, &adaptor_frame);
 
   // Get the length from the frame.
-  __ movq(rcx, Operand(rsp, 1 * kPointerSize));
+  __ SmiToInteger32(rcx, Operand(rsp, 1 * kPointerSize));
   __ jmp(&try_allocate);
 
   // Patch the arguments.length and the parameters pointer.
   __ bind(&adaptor_frame);
-  __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ movq(Operand(rsp, 1 * kPointerSize), rcx);
+  __ SmiToInteger32(rcx,
+                    Operand(rdx,
+                            ArgumentsAdaptorFrameConstants::kLengthOffset));
+  // Space on stack must already hold a smi.
+  __ Integer32ToSmiField(Operand(rsp, 1 * kPointerSize), rcx);
   // Do not clobber the length index for the indexing operation since
   // it is used compute the size for allocation later.
-  SmiIndex index = masm->SmiToIndex(rbx, rcx, kPointerSizeLog2);
-  __ lea(rdx, Operand(rdx, index.reg, index.scale, kDisplacement));
+  __ lea(rdx, Operand(rdx, rcx, times_pointer_size, kDisplacement));
   __ movq(Operand(rsp, 2 * kPointerSize), rdx);
 
   // Try the new space allocation. Start out with computing the size of
   // the arguments object and the elements array.
   Label add_arguments_object;
   __ bind(&try_allocate);
-  __ testq(rcx, rcx);
+  __ testl(rcx, rcx);
   __ j(zero, &add_arguments_object);
-  index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2);
-  __ lea(rcx, Operand(index.reg, index.scale, FixedArray::kHeaderSize));
+  __ leal(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
   __ bind(&add_arguments_object);
-  __ addq(rcx, Immediate(Heap::kArgumentsObjectSize));
+  __ addl(rcx, Immediate(Heap::kArgumentsObjectSize));
 
   // Do the allocation of both objects in one go.
   __ AllocateInNewSpace(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
@@ -9374,10 +9330,13 @@
   __ movq(rdi, Operand(rdi, offset));
 
   // Copy the JS object part.
-  for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) {
-    __ movq(kScratchRegister, FieldOperand(rdi, i));
-    __ movq(FieldOperand(rax, i), kScratchRegister);
-  }
+  STATIC_ASSERT(JSObject::kHeaderSize == 3 * kPointerSize);
+  __ movq(kScratchRegister, FieldOperand(rdi, 0 * kPointerSize));
+  __ movq(rdx, FieldOperand(rdi, 1 * kPointerSize));
+  __ movq(rbx, FieldOperand(rdi, 2 * kPointerSize));
+  __ movq(FieldOperand(rax, 0 * kPointerSize), kScratchRegister);
+  __ movq(FieldOperand(rax, 1 * kPointerSize), rdx);
+  __ movq(FieldOperand(rax, 2 * kPointerSize), rbx);
 
   // Setup the callee in-object property.
   ASSERT(Heap::arguments_callee_index == 0);
@@ -9391,7 +9350,7 @@
 
   // If there are no actual arguments, we're done.
   Label done;
-  __ testq(rcx, rcx);
+  __ SmiTest(rcx);
   __ j(zero, &done);
 
   // Get the parameters pointer from the stack and untag the length.
@@ -9413,7 +9372,7 @@
   __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), kScratchRegister);
   __ addq(rdi, Immediate(kPointerSize));
   __ subq(rdx, Immediate(kPointerSize));
-  __ decq(rcx);
+  __ decl(rcx);
   __ j(not_zero, &loop);
 
   // Return and remove the on-stack parameters.
@@ -9964,86 +9923,73 @@
 }
 
 
-void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
-                                           Register number) {
-  Label load_smi, done;
-
-  __ JumpIfSmi(number, &load_smi);
-  __ fld_d(FieldOperand(number, HeapNumber::kValueOffset));
-  __ jmp(&done);
-
-  __ bind(&load_smi);
-  __ SmiToInteger32(number, number);
-  __ push(number);
-  __ fild_s(Operand(rsp, 0));
-  __ pop(number);
-
-  __ bind(&done);
-}
-
-
-void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
-                                           Register src,
-                                           XMMRegister dst) {
-  Label load_smi, done;
-
-  __ JumpIfSmi(src, &load_smi);
-  __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset));
-  __ jmp(&done);
-
-  __ bind(&load_smi);
-  __ SmiToInteger32(src, src);
-  __ cvtlsi2sd(dst, src);
-
-  __ bind(&done);
-}
-
-
-void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
-                                           Register src,
-                                           XMMRegister dst,
-                                           Label* not_number) {
-  Label load_smi, done;
-  ASSERT(!src.is(kScratchRegister));
-  __ JumpIfSmi(src, &load_smi);
-  __ LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
-  __ cmpq(FieldOperand(src, HeapObject::kMapOffset), kScratchRegister);
-  __ j(not_equal, not_number);
-  __ movsd(dst, FieldOperand(src, HeapNumber::kValueOffset));
-  __ jmp(&done);
-
-  __ bind(&load_smi);
-  __ SmiToInteger32(kScratchRegister, src);
-  __ cvtlsi2sd(dst, kScratchRegister);
-
-  __ bind(&done);
-}
-
-
-void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
-                                            XMMRegister dst1,
-                                            XMMRegister dst2) {
-  __ movq(kScratchRegister, rdx);
-  LoadFloatOperand(masm, kScratchRegister, dst1);
-  __ movq(kScratchRegister, rax);
-  LoadFloatOperand(masm, kScratchRegister, dst2);
-}
-
-
-void FloatingPointHelper::LoadFloatOperandsFromSmis(MacroAssembler* masm,
-                                                    XMMRegister dst1,
-                                                    XMMRegister dst2) {
+void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) {
   __ SmiToInteger32(kScratchRegister, rdx);
-  __ cvtlsi2sd(dst1, kScratchRegister);
+  __ cvtlsi2sd(xmm0, kScratchRegister);
   __ SmiToInteger32(kScratchRegister, rax);
-  __ cvtlsi2sd(dst2, kScratchRegister);
+  __ cvtlsi2sd(xmm1, kScratchRegister);
+}
+
+
+void FloatingPointHelper::LoadSSE2NumberOperands(MacroAssembler* masm) {
+  Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, done;
+  // Load operand in rdx into xmm0.
+  __ JumpIfSmi(rdx, &load_smi_rdx);
+  __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
+  // Load operand in rax into xmm1.
+  __ JumpIfSmi(rax, &load_smi_rax);
+  __ bind(&load_nonsmi_rax);
+  __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
+  __ jmp(&done);
+
+  __ bind(&load_smi_rdx);
+  __ SmiToInteger32(kScratchRegister, rdx);
+  __ cvtlsi2sd(xmm0, kScratchRegister);
+  __ JumpIfNotSmi(rax, &load_nonsmi_rax);
+
+  __ bind(&load_smi_rax);
+  __ SmiToInteger32(kScratchRegister, rax);
+  __ cvtlsi2sd(xmm1, kScratchRegister);
+
+  __ bind(&done);
+}
+
+
+void FloatingPointHelper::LoadSSE2UnknownOperands(MacroAssembler* masm,
+                                                  Label* not_numbers) {
+  Label load_smi_rdx, load_nonsmi_rax, load_smi_rax, load_float_rax, done;
+  // Load operand in rdx into xmm0, or branch to not_numbers.
+  __ LoadRoot(rcx, Heap::kHeapNumberMapRootIndex);
+  __ JumpIfSmi(rdx, &load_smi_rdx);
+  __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), rcx);
+  __ j(not_equal, not_numbers);  // Argument in rdx is not a number.
+  __ movsd(xmm0, FieldOperand(rdx, HeapNumber::kValueOffset));
+  // Load operand in rax into xmm1, or branch to not_numbers.
+  __ JumpIfSmi(rax, &load_smi_rax);
+
+  __ bind(&load_nonsmi_rax);
+  __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), rcx);
+  __ j(not_equal, not_numbers);
+  __ movsd(xmm1, FieldOperand(rax, HeapNumber::kValueOffset));
+  __ jmp(&done);
+
+  __ bind(&load_smi_rdx);
+  __ SmiToInteger32(kScratchRegister, rdx);
+  __ cvtlsi2sd(xmm0, kScratchRegister);
+  __ JumpIfNotSmi(rax, &load_nonsmi_rax);
+
+  __ bind(&load_smi_rax);
+  __ SmiToInteger32(kScratchRegister, rax);
+  __ cvtlsi2sd(xmm1, kScratchRegister);
+  __ bind(&done);
 }
 
 
 // Input: rdx, rax are the left and right objects of a bit op.
 // Output: rax, rcx are left and right integers for a bit op.
 void FloatingPointHelper::LoadAsIntegers(MacroAssembler* masm,
-                                         Label* conversion_failure) {
+                                         Label* conversion_failure,
+                                         Register heap_number_map) {
   // Check float operands.
   Label arg1_is_object, check_undefined_arg1;
   Label arg2_is_object, check_undefined_arg2;
@@ -10061,8 +10007,7 @@
   __ jmp(&load_arg2);
 
   __ bind(&arg1_is_object);
-  __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
-  __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
+  __ cmpq(FieldOperand(rdx, HeapObject::kMapOffset), heap_number_map);
   __ j(not_equal, &check_undefined_arg1);
   // Get the untagged integer version of the edx heap number in rcx.
   IntegerConvert(masm, rdx, rdx);
@@ -10083,8 +10028,7 @@
   __ jmp(&done);
 
   __ bind(&arg2_is_object);
-  __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
-  __ CompareRoot(rbx, Heap::kHeapNumberMapRootIndex);
+  __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map);
   __ j(not_equal, &check_undefined_arg2);
   // Get the untagged integer version of the eax heap number in ecx.
   IntegerConvert(masm, rcx, rax);
@@ -10093,51 +10037,35 @@
 }
 
 
-void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
-                                            Register lhs,
-                                            Register rhs) {
-  Label load_smi_lhs, load_smi_rhs, done_load_lhs, done;
-  __ JumpIfSmi(lhs, &load_smi_lhs);
-  __ fld_d(FieldOperand(lhs, HeapNumber::kValueOffset));
-  __ bind(&done_load_lhs);
+// Input: rdx, rax are the left and right objects of a bit op.
+// Output: rax, rcx are left and right integers for a bit op.
+void FloatingPointHelper::LoadNumbersAsIntegers(MacroAssembler* masm) {
+  if (FLAG_debug_code) {
+    // Both arguments can not be smis. That case is handled by smi-only code.
+    Label ok;
+    __ JumpIfNotBothSmi(rax, rdx, &ok);
+    __ Abort("Both arguments smi but not handled by smi-code.");
+    __ bind(&ok);
+  }
+  // Check float operands.
+  Label done;
+  Label rax_is_object;
+  Label rdx_is_object;
 
-  __ JumpIfSmi(rhs, &load_smi_rhs);
-  __ fld_d(FieldOperand(rhs, HeapNumber::kValueOffset));
+  __ JumpIfNotSmi(rdx, &rdx_is_object);
+  __ SmiToInteger32(rdx, rdx);
+
+  __ bind(&rax_is_object);
+  IntegerConvert(masm, rcx, rax);  // Uses rdi, rcx and rbx.
   __ jmp(&done);
 
-  __ bind(&load_smi_lhs);
-  __ SmiToInteger64(kScratchRegister, lhs);
-  __ push(kScratchRegister);
-  __ fild_d(Operand(rsp, 0));
-  __ pop(kScratchRegister);
-  __ jmp(&done_load_lhs);
-
-  __ bind(&load_smi_rhs);
-  __ SmiToInteger64(kScratchRegister, rhs);
-  __ push(kScratchRegister);
-  __ fild_d(Operand(rsp, 0));
-  __ pop(kScratchRegister);
+  __ bind(&rdx_is_object);
+  IntegerConvert(masm, rdx, rdx);  // Uses rdi, rcx and rbx.
+  __ JumpIfNotSmi(rax, &rax_is_object);
+  __ SmiToInteger32(rcx, rax);
 
   __ bind(&done);
-}
-
-
-void FloatingPointHelper::CheckNumberOperands(MacroAssembler* masm,
-                                              Label* non_float) {
-  Label test_other, done;
-  // Test if both operands are numbers (heap_numbers or smis).
-  // If not, jump to label non_float.
-  __ JumpIfSmi(rdx, &test_other);  // argument in rdx is OK
-  __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), Factory::heap_number_map());
-  __ j(not_equal, non_float);  // The argument in rdx is not a number.
-
-  __ bind(&test_other);
-  __ JumpIfSmi(rax, &done);  // argument in rax is OK
-  __ Cmp(FieldOperand(rax, HeapObject::kMapOffset), Factory::heap_number_map());
-  __ j(not_equal, non_float);  // The argument in rax is not a number.
-
-  // Fall-through: Both operands are numbers.
-  __ bind(&done);
+  __ movl(rax, rdx);
 }
 
 
@@ -10447,15 +10375,15 @@
       }
       // left is rdx, right is rax.
       __ AllocateHeapNumber(rbx, rcx, slow);
-      FloatingPointHelper::LoadFloatOperandsFromSmis(masm, xmm4, xmm5);
+      FloatingPointHelper::LoadSSE2SmiOperands(masm);
       switch (op_) {
-        case Token::ADD: __ addsd(xmm4, xmm5); break;
-        case Token::SUB: __ subsd(xmm4, xmm5); break;
-        case Token::MUL: __ mulsd(xmm4, xmm5); break;
-        case Token::DIV: __ divsd(xmm4, xmm5); break;
+        case Token::ADD: __ addsd(xmm0, xmm1); break;
+        case Token::SUB: __ subsd(xmm0, xmm1); break;
+        case Token::MUL: __ mulsd(xmm0, xmm1); break;
+        case Token::DIV: __ divsd(xmm0, xmm1); break;
         default: UNREACHABLE();
       }
-      __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm4);
+      __ movsd(FieldOperand(rbx, HeapNumber::kValueOffset), xmm0);
       __ movq(rax, rbx);
       GenerateReturn(masm);
     }
@@ -10518,22 +10446,23 @@
         Label not_floats;
         // rax: y
         // rdx: x
-      if (static_operands_type_.IsNumber() && FLAG_debug_code) {
-        // Assert at runtime that inputs are only numbers.
-        __ AbortIfNotNumber(rdx);
-        __ AbortIfNotNumber(rax);
-      } else {
-        FloatingPointHelper::CheckNumberOperands(masm, &call_runtime);
-      }
-        // Fast-case: Both operands are numbers.
-        // xmm4 and xmm5 are volatile XMM registers.
-        FloatingPointHelper::LoadFloatOperands(masm, xmm4, xmm5);
+        ASSERT(!static_operands_type_.IsSmi());
+        if (static_operands_type_.IsNumber()) {
+          if (FLAG_debug_code) {
+            // Assert at runtime that inputs are only numbers.
+            __ AbortIfNotNumber(rdx);
+            __ AbortIfNotNumber(rax);
+          }
+          FloatingPointHelper::LoadSSE2NumberOperands(masm);
+        } else {
+          FloatingPointHelper::LoadSSE2UnknownOperands(masm, &call_runtime);
+        }
 
         switch (op_) {
-          case Token::ADD: __ addsd(xmm4, xmm5); break;
-          case Token::SUB: __ subsd(xmm4, xmm5); break;
-          case Token::MUL: __ mulsd(xmm4, xmm5); break;
-          case Token::DIV: __ divsd(xmm4, xmm5); break;
+          case Token::ADD: __ addsd(xmm0, xmm1); break;
+          case Token::SUB: __ subsd(xmm0, xmm1); break;
+          case Token::MUL: __ mulsd(xmm0, xmm1); break;
+          case Token::DIV: __ divsd(xmm0, xmm1); break;
           default: UNREACHABLE();
         }
         // Allocate a heap number, if needed.
@@ -10568,7 +10497,7 @@
             break;
           default: UNREACHABLE();
         }
-        __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm4);
+        __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
         GenerateReturn(masm);
         __ bind(&not_floats);
         if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
@@ -10593,34 +10522,52 @@
       case Token::SAR:
       case Token::SHL:
       case Token::SHR: {
-        Label skip_allocation, non_smi_result;
-        FloatingPointHelper::LoadAsIntegers(masm, &call_runtime);
+        Label skip_allocation, non_smi_shr_result;
+        Register heap_number_map = r9;
+        __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+        if (static_operands_type_.IsNumber()) {
+          if (FLAG_debug_code) {
+            // Assert at runtime that inputs are only numbers.
+            __ AbortIfNotNumber(rdx);
+            __ AbortIfNotNumber(rax);
+          }
+          FloatingPointHelper::LoadNumbersAsIntegers(masm);
+        } else {
+          FloatingPointHelper::LoadAsIntegers(masm,
+                                              &call_runtime,
+                                              heap_number_map);
+        }
         switch (op_) {
           case Token::BIT_OR:  __ orl(rax, rcx); break;
           case Token::BIT_AND: __ andl(rax, rcx); break;
           case Token::BIT_XOR: __ xorl(rax, rcx); break;
           case Token::SAR: __ sarl_cl(rax); break;
           case Token::SHL: __ shll_cl(rax); break;
-          case Token::SHR: __ shrl_cl(rax); break;
+          case Token::SHR: {
+            __ shrl_cl(rax);
+            // Check if result is negative. This can only happen for a shift
+            // by zero.
+            __ testl(rax, rax);
+            __ j(negative, &non_smi_shr_result);
+            break;
+          }
           default: UNREACHABLE();
         }
-        if (op_ == Token::SHR) {
-          // Check if result is negative. This can only happen for a shift
-          // by zero, which also doesn't update the sign flag.
-          __ testl(rax, rax);
-          __ j(negative, &non_smi_result);
-        }
-        __ JumpIfNotValidSmiValue(rax, &non_smi_result);
-        // Tag smi result, if possible, and return.
+
+        STATIC_ASSERT(kSmiValueSize == 32);
+        // Tag smi result and return.
         __ Integer32ToSmi(rax, rax);
         GenerateReturn(masm);
 
-        // All ops except SHR return a signed int32 that we load in
-        // a HeapNumber.
-        if (op_ != Token::SHR && non_smi_result.is_linked()) {
-          __ bind(&non_smi_result);
+        // All bit-ops except SHR return a signed int32 that can be
+        // returned immediately as a smi.
+        // We might need to allocate a HeapNumber if we shift a negative
+        // number right by zero (i.e., convert to UInt32).
+        if (op_ == Token::SHR) {
+          ASSERT(non_smi_shr_result.is_linked());
+          __ bind(&non_smi_shr_result);
           // Allocate a heap number if needed.
-          __ movsxlq(rbx, rax);  // rbx: sign extended 32-bit result
+          __ movl(rbx, rax);  // rbx holds result value (uint32 value as int64).
           switch (mode_) {
             case OVERWRITE_LEFT:
             case OVERWRITE_RIGHT:
@@ -10631,22 +10578,33 @@
               __ JumpIfNotSmi(rax, &skip_allocation);
               // Fall through!
             case NO_OVERWRITE:
-              __ AllocateHeapNumber(rax, rcx, &call_runtime);
+              // Allocate heap number in new space.
+              // Not using AllocateHeapNumber macro in order to reuse
+              // already loaded heap_number_map.
+              __ AllocateInNewSpace(HeapNumber::kSize,
+                                    rax,
+                                    rcx,
+                                    no_reg,
+                                    &call_runtime,
+                                    TAG_OBJECT);
+              // Set the map.
+              if (FLAG_debug_code) {
+                __ AbortIfNotRootValue(heap_number_map,
+                                       Heap::kHeapNumberMapRootIndex,
+                                       "HeapNumberMap register clobbered.");
+              }
+              __ movq(FieldOperand(rax, HeapObject::kMapOffset),
+                      heap_number_map);
               __ bind(&skip_allocation);
               break;
             default: UNREACHABLE();
           }
           // Store the result in the HeapNumber and return.
-          __ movq(Operand(rsp, 1 * kPointerSize), rbx);
-          __ fild_s(Operand(rsp, 1 * kPointerSize));
-          __ fstp_d(FieldOperand(rax, HeapNumber::kValueOffset));
+          __ cvtqsi2sd(xmm0, rbx);
+          __ movsd(FieldOperand(rax, HeapNumber::kValueOffset), xmm0);
           GenerateReturn(masm);
         }
 
-        // SHR should return uint32 - go to runtime for non-smi/negative result.
-        if (op_ == Token::SHR) {
-          __ bind(&non_smi_result);
-        }
         break;
       }
       default: UNREACHABLE(); break;
@@ -10679,7 +10637,7 @@
       Label not_strings, both_strings, not_string1, string1, string1_smi2;
 
       // If this stub has already generated FP-specific code then the arguments
-      // are already in rdx, rax
+      // are already in rdx and rax.
       if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) {
         GenerateLoadArguments(masm);
       }
@@ -10828,19 +10786,13 @@
   __ push(rax);
 
   // Push this stub's key.
-  __ movq(rax, Immediate(MinorKey()));
-  __ Integer32ToSmi(rax, rax);
-  __ push(rax);
+  __ Push(Smi::FromInt(MinorKey()));
 
   // Although the operation and the type info are encoded into the key,
   // the encoding is opaque, so push them too.
-  __ movq(rax, Immediate(op_));
-  __ Integer32ToSmi(rax, rax);
-  __ push(rax);
+  __ Push(Smi::FromInt(op_));
 
-  __ movq(rax, Immediate(runtime_operands_type_));
-  __ Integer32ToSmi(rax, rax);
-  __ push(rax);
+  __ Push(Smi::FromInt(runtime_operands_type_));
 
   __ push(rcx);
 
@@ -11208,16 +11160,17 @@
   // If result is not supposed to be flat, allocate a cons string object. If
   // both strings are ascii the result is an ascii cons string.
   // rax: first string
-  // ebx: length of resulting flat string
+  // rbx: length of resulting flat string
   // rdx: second string
   // r8: instance type of first string
   // r9: instance type of second string
-  Label non_ascii, allocated;
+  Label non_ascii, allocated, ascii_data;
   __ movl(rcx, r8);
   __ and_(rcx, r9);
   ASSERT(kStringEncodingMask == kAsciiStringTag);
   __ testl(rcx, Immediate(kAsciiStringTag));
   __ j(zero, &non_ascii);
+  __ bind(&ascii_data);
   // Allocate an acsii cons string.
   __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime);
   __ bind(&allocated);
@@ -11231,6 +11184,18 @@
   __ IncrementCounter(&Counters::string_add_native, 1);
   __ ret(2 * kPointerSize);
   __ bind(&non_ascii);
+  // At least one of the strings is two-byte. Check whether it happens
+  // to contain only ascii characters.
+  // rcx: first instance type AND second instance type.
+  // r8: first instance type.
+  // r9: second instance type.
+  __ testb(rcx, Immediate(kAsciiDataHintMask));
+  __ j(not_zero, &ascii_data);
+  __ xor_(r8, r9);
+  ASSERT(kAsciiStringTag != 0 && kAsciiDataHintTag != 0);
+  __ andb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
+  __ cmpb(r8, Immediate(kAsciiStringTag | kAsciiDataHintTag));
+  __ j(equal, &ascii_data);
   // Allocate a two byte cons string.
   __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime);
   __ jmp(&allocated);
@@ -11238,7 +11203,7 @@
   // Handle creating a flat result. First check that both strings are not
   // external strings.
   // rax: first string
-  // ebx: length of resulting flat string as smi
+  // rbx: length of resulting flat string as smi
   // rdx: second string
   // r8: instance type of first string
   // r9: instance type of first string
@@ -11254,7 +11219,7 @@
   __ j(equal, &string_add_runtime);
   // Now check if both strings are ascii strings.
   // rax: first string
-  // ebx: length of resulting flat string
+  // rbx: length of resulting flat string
   // rdx: second string
   // r8: instance type of first string
   // r9: instance type of second string
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index d99ea84..1df1de3 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1729,6 +1729,30 @@
 }
 
 
+void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
+                                            Expression* key,
+                                            RelocInfo::Mode mode) {
+  // Code common for calls using the IC.
+  ZoneList<Expression*>* args = expr->arguments();
+  int arg_count = args->length();
+  for (int i = 0; i < arg_count; i++) {
+    VisitForValue(args->at(i), kStack);
+  }
+  VisitForValue(key, kAccumulator);
+  __ movq(rcx, rax);
+  // Record source position for debugger.
+  SetSourcePosition(expr->position());
+  // Call the IC initialization code.
+  InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
+  Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
+                                                              in_loop);
+  __ Call(ic, mode);
+  // Restore context register.
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  Apply(context_, rax);
+}
+
+
 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
   // Code common for calls using the call stub.
   ZoneList<Expression*>* args = expr->arguments();
@@ -1820,30 +1844,32 @@
       VisitForValue(prop->obj(), kStack);
       EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
     } else {
-      // Call to a keyed property, use keyed load IC followed by function
-      // call.
+      // Call to a keyed property.
+      // For a synthetic property use keyed load IC followed by function call,
+      // for a regular property use KeyedCallIC.
       VisitForValue(prop->obj(), kStack);
-      VisitForValue(prop->key(), kAccumulator);
-      __ movq(rdx, Operand(rsp, 0));
-      // Record source code position for IC call.
-      SetSourcePosition(prop->position());
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
-      __ call(ic, RelocInfo::CODE_TARGET);
-      // By emitting a nop we make sure that we do not have a "test rax,..."
-      // instruction after the call it is treated specially by the LoadIC code.
-      __ nop();
-      // Pop receiver.
-      __ pop(rbx);
-      // Push result (function).
-      __ push(rax);
-      // Push receiver object on stack.
       if (prop->is_synthetic()) {
+        VisitForValue(prop->key(), kAccumulator);
+        __ movq(rdx, Operand(rsp, 0));
+        // Record source code position for IC call.
+        SetSourcePosition(prop->position());
+        Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+        __ call(ic, RelocInfo::CODE_TARGET);
+        // By emitting a nop we make sure that we do not have a "test rax,..."
+        // instruction after the call as it is treated specially
+        // by the LoadIC code.
+        __ nop();
+        // Pop receiver.
+        __ pop(rbx);
+        // Push result (function).
+        __ push(rax);
+        // Push receiver object on stack.
         __ movq(rcx, CodeGenerator::GlobalObject());
         __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
+        EmitCallWithStub(expr);
       } else {
-        __ push(rbx);
+        EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
       }
-      EmitCallWithStub(expr);
     }
   } else {
     // Call to some other expression.  If the expression is an anonymous
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 89c21cb..6e77c89 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -57,19 +57,21 @@
                                    Register r2,
                                    Register name,
                                    Register r4,
+                                   Register result,
                                    DictionaryCheck check_dictionary) {
   // Register use:
   //
-  // r0   - used to hold the property dictionary.
+  // r0   - used to hold the property dictionary and is unchanged.
   //
-  // r1   - initially the receiver.
-  //      - unchanged on any jump to miss_label.
-  //      - holds the result on exit.
+  // r1   - used to hold the receiver and is unchanged.
   //
   // r2   - used to hold the capacity of the property dictionary.
   //
   // name - holds the name of the property and is unchanged.
+  //
   // r4   - used to hold the index into the property dictionary.
+  //
+  // result - holds the result on exit if the load succeeded.
 
   Label done;
 
@@ -148,7 +150,7 @@
 
   // Get the value at the masked, scaled index.
   const int kValueOffset = kElementsStartOffset + kPointerSize;
-  __ movq(r1,
+  __ movq(result,
           Operand(r0, r4, times_pointer_size, kValueOffset - kHeapObjectTag));
 }
 
@@ -159,14 +161,15 @@
                                          Register key,
                                          Register r0,
                                          Register r1,
-                                         Register r2) {
+                                         Register r2,
+                                         Register result) {
   // Register use:
   //
-  // elements - holds the slow-case elements of the receiver and is unchanged.
+  // elements - holds the slow-case elements of the receiver on entry.
+  //            Unchanged unless 'result' is the same register.
   //
-  // key      - holds the smi key on entry and is unchanged if a branch is
-  //            performed to the miss label.
-  //            Holds the result on exit if the load succeeded.
+  // key      - holds the smi key on entry.
+  //            Unchanged unless 'result' is the same register.
   //
   // Scratch registers:
   //
@@ -175,6 +178,12 @@
   // r1 - used to hold the capacity mask of the dictionary
   //
   // r2 - used for the index into the dictionary.
+  //
+  // result - holds the result on exit if the load succeeded.
+  //          Allowed to be the same as 'key' or 'result'.
+  //          Unchanged on bailout so 'key' or 'result' can be used
+  //          in further computation.
+
   Label done;
 
   // Compute the hash code from the untagged key.  This must be kept in sync
@@ -246,7 +255,7 @@
   // Get the value at the masked, scaled index.
   const int kValueOffset =
       NumberDictionary::kElementsStartOffset + kPointerSize;
-  __ movq(key, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
+  __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
 }
 
 
@@ -346,6 +355,142 @@
 }
 
 
+// Checks the receiver for special cases (value type, slow case bits).
+// Falls through for regular JS object.
+static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register map,
+                                           Label* slow) {
+  // Register use:
+  //   receiver - holds the receiver and is unchanged.
+  // Scratch registers:
+  //   map - used to hold the map of the receiver.
+
+  // Check that the object isn't a smi.
+  __ JumpIfSmi(receiver, slow);
+
+  // Check that the object is some kind of JS object EXCEPT JS Value type.
+  // In the case that the object is a value-wrapper object,
+  // we enter the runtime system to make sure that indexing
+  // into string objects work as intended.
+  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
+  __ CmpObjectType(receiver, JS_OBJECT_TYPE, map);
+  __ j(below, slow);
+
+  // Check bit field.
+  __ testb(FieldOperand(map, Map::kBitFieldOffset),
+           Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
+  __ j(not_zero, slow);
+}
+
+
+// Loads an indexed element from a fast case array.
+static void GenerateFastArrayLoad(MacroAssembler* masm,
+                                  Register receiver,
+                                  Register key,
+                                  Register elements,
+                                  Register scratch,
+                                  Register result,
+                                  Label* not_fast_array,
+                                  Label* out_of_range) {
+  // Register use:
+  //
+  // receiver - holds the receiver on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // key      - holds the smi key on entry.
+  //            Unchanged unless 'result' is the same register.
+  //
+  // elements - holds the elements of the receiver on exit.
+  //
+  // result   - holds the result on exit if the load succeeded.
+  //            Allowed to be the the same as 'receiver' or 'key'.
+  //            Unchanged on bailout so 'receiver' and 'key' can be safely
+  //            used by further computation.
+  //
+  // Scratch registers:
+  //
+  //   scratch - used to hold elements of the receiver and the loaded value.
+
+  __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
+  // Check that the object is in fast mode (not dictionary).
+  __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
+                 Heap::kFixedArrayMapRootIndex);
+  __ j(not_equal, not_fast_array);
+  // Check that the key (index) is within bounds.
+  __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
+  // Unsigned comparison rejects negative indices.
+  __ j(above_equal, out_of_range);
+  // Fast case: Do the load.
+  SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
+  __ movq(scratch, FieldOperand(elements,
+                                index.reg,
+                                index.scale,
+                                FixedArray::kHeaderSize));
+  __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
+  // In case the loaded value is the_hole we have to consult GetProperty
+  // to ensure the prototype chain is searched.
+  __ j(equal, out_of_range);
+  if (!result.is(scratch)) {
+    __ movq(result, scratch);
+  }
+}
+
+
+// Checks whether a key is an array index string or a symbol string.
+// Falls through if the key is a symbol.
+static void GenerateKeyStringCheck(MacroAssembler* masm,
+                                   Register key,
+                                   Register map,
+                                   Register hash,
+                                   Label* index_string,
+                                   Label* not_symbol) {
+  // 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_symbol);
+  // Is the string an array index, with cached numeric value?
+  __ movl(hash, FieldOperand(key, String::kHashFieldOffset));
+  __ testl(hash, Immediate(String::kContainsCachedArrayIndexMask));
+  __ j(zero, index_string);  // The value in hash is used at jump target.
+
+  // Is the string a symbol?
+  ASSERT(kSymbolTag != 0);
+  __ testb(FieldOperand(map, Map::kInstanceTypeOffset),
+           Immediate(kIsSymbolMask));
+  __ j(zero, not_symbol);
+}
+
+
+// Picks out an array index from the hash field.
+static void GenerateIndexFromHash(MacroAssembler* masm,
+                                  Register key,
+                                  Register hash) {
+  // Register use:
+  //   key - holds the overwritten key on exit.
+  //   hash - holds the key's hash. Clobbered.
+
+  // The assert checks that the constants for the maximum number of digits
+  // for an array index cached in the hash field and the number of bits
+  // reserved for it does not conflict.
+  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
+         (1 << String::kArrayIndexValueBits));
+  // We want the smi-tagged index in key. Even if we subsequently go to
+  // the slow case, converting the key to a smi is always valid.
+  // key: string key
+  // hash: key's hash field, including its array index value.
+  __ and_(hash, Immediate(String::kArrayIndexValueMask));
+  __ shr(hash, Immediate(String::kHashShift));
+  // Here we actually clobber the key which will be used if calling into
+  // runtime later. However as the new key is the numeric value of a string key
+  // there is no difference in using either key.
+  __ Integer32ToSmi(key, hash);
+}
+
+
 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- rax    : key
@@ -355,46 +500,22 @@
   Label slow, check_string, index_smi, index_string;
   Label check_pixel_array, probe_dictionary, check_number_dictionary;
 
-  // Check that the object isn't a smi.
-  __ JumpIfSmi(rdx, &slow);
-
-  // Check that the object is some kind of JS object EXCEPT JS Value type.
-  // In the case that the object is a value-wrapper object,
-  // we enter the runtime system to make sure that indexing
-  // into string objects work as intended.
-  ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
-  __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
-  __ j(below, &slow);
-
-  // Check bit field.
-  __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
-           Immediate(kSlowCaseBitFieldMask));
-  __ j(not_zero, &slow);
+  GenerateKeyedLoadReceiverCheck(masm, rdx, rcx, &slow);
 
   // Check that the key is a smi.
   __ JumpIfNotSmi(rax, &check_string);
   __ 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.
-  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
-  __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
-                 Heap::kFixedArrayMapRootIndex);
-  __ j(not_equal, &check_pixel_array);
-  // Check that the key (index) is within bounds.
-  __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
-  __ j(above_equal, &slow);  // Unsigned comparison rejects negative indices.
-  // Fast case: Do the load.
-  SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
-  __ movq(rbx, FieldOperand(rcx,
-                            index.reg,
-                            index.scale,
-                            FixedArray::kHeaderSize));
-  __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
-  // In case the loaded value is the_hole we have to consult GetProperty
-  // to ensure the prototype chain is searched.
-  __ j(equal, &slow);
-  __ movq(rax, rbx);
+
+  GenerateFastArrayLoad(masm,
+                        rdx,
+                        rax,
+                        rcx,
+                        rbx,
+                        rax,
+                        &check_pixel_array,
+                        &slow);
   __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
   __ ret(0);
 
@@ -423,7 +544,7 @@
   __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
                  Heap::kHashTableMapRootIndex);
   __ j(not_equal, &slow);
-  GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, r9, rdi);
+  GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, r9, rdi, rax);
   __ ret(0);
 
   __ bind(&slow);
@@ -434,22 +555,7 @@
   GenerateRuntimeGetProperty(masm);
 
   __ bind(&check_string);
-  // The key is not a smi.
-  // Is it a string?
-  // rdx: receiver
-  // rax: key
-  __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rcx);
-  __ j(above_equal, &slow);
-  // Is the string an array index, with cached numeric value?
-  __ movl(rbx, FieldOperand(rax, String::kHashFieldOffset));
-  __ testl(rbx, Immediate(String::kContainsCachedArrayIndexMask));
-  __ j(zero, &index_string);  // The value in rbx is used at jump target.
-
-  // Is the string a symbol?
-  ASSERT(kSymbolTag != 0);
-  __ testb(FieldOperand(rcx, Map::kInstanceTypeOffset),
-           Immediate(kIsSymbolMask));
-  __ j(zero, &slow);
+  GenerateKeyStringCheck(masm, rax, rcx, rbx, &index_string, &slow);
 
   // If the receiver is a fast-case object, check the keyed lookup
   // cache. Otherwise probe the dictionary leaving result in rcx.
@@ -509,29 +615,13 @@
                          rcx,
                          rax,
                          rdi,
+                         rax,
                          DICTIONARY_CHECK_DONE);
-  __ movq(rax, rdx);
   __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
   __ ret(0);
-  // If the hash field contains an array index pick it out. The assert checks
-  // that the constants for the maximum number of digits for an array index
-  // cached in the hash field and the number of bits reserved for it does not
-  // conflict.
-  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
-         (1 << String::kArrayIndexValueBits));
+
   __ bind(&index_string);
-  // We want the smi-tagged index in rax. Even if we subsequently go to
-  // the slow case, converting the key to a smi is always valid.
-  // rdx: receiver
-  // rax: key (a string)
-  // rbx: key's hash field, including its array index value.
-  __ and_(rbx, Immediate(String::kArrayIndexValueMask));
-  __ shr(rbx, Immediate(String::kHashShift));
-  // Here we actually clobber the key (rax) which will be used if calling into
-  // runtime later. However as the new key is the numeric value of a string key
-  // there is no difference in using either key.
-  __ Integer32ToSmi(rax, rbx);
-  // Now jump to the place where smi keys are handled.
+  GenerateIndexFromHash(masm, rax, rbx);
   __ jmp(&index_smi);
 }
 
@@ -803,19 +893,20 @@
   //  -- rdx     : receiver
   //  -- rsp[0]  : return address
   // -----------------------------------
-  Label slow, fast, array, extra, check_pixel_array;
+  Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array;
 
   // Check that the object isn't a smi.
-  __ JumpIfSmi(rdx, &slow);
+  __ JumpIfSmi(rdx, &slow_with_tagged_index);
   // Get the map from the receiver.
   __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
   // Check that the receiver does not require access checks.  We need
   // to do this because this generic stub does not perform map checks.
   __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
            Immediate(1 << Map::kIsAccessCheckNeeded));
-  __ j(not_zero, &slow);
+  __ j(not_zero, &slow_with_tagged_index);
   // Check that the key is a smi.
-  __ JumpIfNotSmi(rcx, &slow);
+  __ JumpIfNotSmi(rcx, &slow_with_tagged_index);
+  __ SmiToInteger32(rcx, rcx);
 
   __ CmpInstanceType(rbx, JS_ARRAY_TYPE);
   __ j(equal, &array);
@@ -826,27 +917,30 @@
   // Object case: Check key against length in the elements array.
   // rax: value
   // rdx: JSObject
-  // rcx: index (as a smi)
+  // rcx: index
   __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
   // Check that the object is in fast mode (not dictionary).
   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
                  Heap::kFixedArrayMapRootIndex);
   __ j(not_equal, &check_pixel_array);
-  __ SmiCompare(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
+  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
   // rax: value
   // rbx: FixedArray
-  // rcx: index (as a smi)
-  __ j(below, &fast);
+  // rcx: index
+  __ j(above, &fast);
 
   // Slow case: call runtime.
   __ bind(&slow);
+  __ Integer32ToSmi(rcx, rcx);
+  __ bind(&slow_with_tagged_index);
   GenerateRuntimeSetProperty(masm);
+  // Never returns to here.
 
   // Check whether the elements is a pixel array.
   // rax: value
   // rdx: receiver
   // rbx: receiver's elements array
-  // rcx: index (as a smi), zero-extended.
+  // rcx: index, zero-extended.
   __ bind(&check_pixel_array);
   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
                  Heap::kPixelArrayMapRootIndex);
@@ -854,21 +948,20 @@
   // Check that the value is a smi. If a conversion is needed call into the
   // runtime to convert and clamp.
   __ JumpIfNotSmi(rax, &slow);
-  __ SmiToInteger32(rdi, rcx);
-  __ cmpl(rdi, FieldOperand(rbx, PixelArray::kLengthOffset));
+  __ cmpl(rcx, FieldOperand(rbx, PixelArray::kLengthOffset));
   __ j(above_equal, &slow);
   // No more bailouts to slow case on this path, so key not needed.
-  __ SmiToInteger32(rcx, rax);
+  __ SmiToInteger32(rdi, rax);
   {  // Clamp the value to [0..255].
     Label done;
-    __ testl(rcx, Immediate(0xFFFFFF00));
+    __ testl(rdi, Immediate(0xFFFFFF00));
     __ j(zero, &done);
-    __ setcc(negative, rcx);  // 1 if negative, 0 if positive.
-    __ decb(rcx);  // 0 if negative, 255 if positive.
+    __ setcc(negative, rdi);  // 1 if negative, 0 if positive.
+    __ decb(rdi);  // 0 if negative, 255 if positive.
     __ bind(&done);
   }
   __ movq(rbx, FieldOperand(rbx, PixelArray::kExternalPointerOffset));
-  __ movb(Operand(rbx, rdi, times_1, 0), rcx);
+  __ movb(Operand(rbx, rcx, times_1, 0), rdi);
   __ ret(0);
 
   // Extra capacity case: Check if there is extra capacity to
@@ -878,14 +971,14 @@
   // rax: value
   // rdx: receiver (a JSArray)
   // rbx: receiver's elements array (a FixedArray)
-  // rcx: index (as a smi)
+  // rcx: index
   // flags: smicompare (rdx.length(), rbx)
   __ j(not_equal, &slow);  // do not leave holes in the array
-  __ SmiCompare(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
-  __ j(above_equal, &slow);
+  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
+  __ j(below_equal, &slow);
   // Increment index to get new length.
-  __ SmiAddConstant(rdi, rcx, Smi::FromInt(1));
-  __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
+  __ leal(rdi, Operand(rcx, 1));
+  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
   __ jmp(&fast);
 
   // Array case: Get the length and the elements array from the JS
@@ -894,7 +987,7 @@
   __ bind(&array);
   // rax: value
   // rdx: receiver (a JSArray)
-  // rcx: index (as a smi)
+  // rcx: index
   __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
                  Heap::kFixedArrayMapRootIndex);
@@ -902,26 +995,22 @@
 
   // Check the key against the length in the array, compute the
   // address to store into and fall through to fast case.
-  __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
+  __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
   __ j(below_equal, &extra);
 
   // Fast case: Do the store.
   __ bind(&fast);
   // rax: value
   // rbx: receiver's elements array (a FixedArray)
-  // rcx: index (as a smi)
+  // rcx: index
   Label non_smi_value;
-  __ JumpIfNotSmi(rax, &non_smi_value);
-  SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2);
-  __ movq(FieldOperand(rbx, index.reg, index.scale, FixedArray::kHeaderSize),
+  __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
           rax);
+  __ JumpIfNotSmi(rax, &non_smi_value);
   __ ret(0);
   __ bind(&non_smi_value);
   // Slow case that needs to retain rcx for use by RecordWrite.
   // Update write barrier for the elements array address.
-  SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rcx, kPointerSizeLog2);
-  __ movq(FieldOperand(rbx, index2.reg, index2.scale, FixedArray::kHeaderSize),
-          rax);
   __ movq(rdx, rax);
   __ RecordWriteNonSmi(rbx, 0, rdx, rcx);
   __ ret(0);
@@ -1109,7 +1198,11 @@
 }
 
 
-void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+// Defined in ic.cc.
+Object* CallIC_Miss(Arguments args);
+
+
+static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
   // ----------- S t a t e -------------
   // rcx                      : function name
   // rsp[0]                   : return address
@@ -1132,7 +1225,7 @@
   // Call the entry.
   CEntryStub stub(1);
   __ movq(rax, Immediate(2));
-  __ movq(rbx, ExternalReference(IC_Utility(kCallIC_Miss)));
+  __ movq(rbx, ExternalReference(IC_Utility(id)));
   __ CallStub(&stub);
 
   // Move result to rdi and exit the internal frame.
@@ -1160,27 +1253,20 @@
 }
 
 
-// Defined in ic.cc.
-Object* CallIC_Miss(Arguments args);
-
-void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+// The generated code does not accept smi keys.
+// The generated code falls through if both probes miss.
+static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
+                                          int argc,
+                                          Code::Kind kind) {
   // ----------- S t a t e -------------
   // rcx                      : function name
-  // rsp[0]                   : return address
-  // rsp[8]                   : argument argc
-  // rsp[16]                  : argument argc - 1
-  // ...
-  // rsp[argc * 8]            : argument 1
-  // rsp[(argc + 1) * 8]      : argument 0 = receiver
+  // rdx                      : receiver
   // -----------------------------------
   Label number, non_number, non_string, boolean, probe, miss;
 
-  // Get the receiver of the function from the stack; 1 ~ return address.
-  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
-
   // Probe the stub cache.
   Code::Flags flags =
-      Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
+      Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
   StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax);
 
   // If the stub cache probing failed, the receiver might be a value.
@@ -1219,9 +1305,7 @@
   __ bind(&probe);
   StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
 
-  // Cache miss: Jump to runtime.
   __ bind(&miss);
-  GenerateMiss(masm, argc);
 }
 
 
@@ -1240,19 +1324,16 @@
   // rsp[(argc + 1) * 8]    : argument 0 = receiver
   // -----------------------------------
   // Search dictionary - put result in register rdx.
-  GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, rdi, CHECK_DICTIONARY);
+  GenerateDictionaryLoad(
+     masm, miss, rax, rdx, rbx, rcx, rdi, rdi, CHECK_DICTIONARY);
 
-  // Move the result to register rdi and check that it isn't a smi.
-  __ movq(rdi, rdx);
-  __ JumpIfSmi(rdx, miss);
-
+  __ JumpIfSmi(rdi, miss);
   // Check that the value is a JavaScript function.
-  __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx);
+  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rdx);
   __ j(not_equal, miss);
 
   // Patch the receiver with the global proxy if necessary.
   if (is_global_object) {
-    __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
     __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
     __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
   }
@@ -1263,7 +1344,8 @@
 }
 
 
-void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+// The generated code falls through if the call should be handled by runtime.
+static void GenerateCallNormal(MacroAssembler* masm, int argc) {
   // ----------- S t a t e -------------
   // rcx                    : function name
   // rsp[0]                 : return address
@@ -1324,24 +1406,197 @@
   __ CheckAccessGlobalProxy(rdx, rax, &miss);
   __ jmp(&invoke);
 
-  // Cache miss: Jump to runtime.
   __ bind(&miss);
+}
+
+
+void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  // rcx                      : function name
+  // rsp[0]                   : return address
+  // rsp[8]                   : argument argc
+  // rsp[16]                  : argument argc - 1
+  // ...
+  // rsp[argc * 8]            : argument 1
+  // rsp[(argc + 1) * 8]      : argument 0 = receiver
+  // -----------------------------------
+  GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
+}
+
+
+void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  // rcx                      : function name
+  // rsp[0]                   : return address
+  // rsp[8]                   : argument argc
+  // rsp[16]                  : argument argc - 1
+  // ...
+  // rsp[argc * 8]            : argument 1
+  // rsp[(argc + 1) * 8]      : argument 0 = receiver
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack; 1 ~ return address.
+  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+  GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC);
+  GenerateMiss(masm, argc);
+}
+
+
+void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+  // ----------- S t a t e -------------
+  // rcx                      : function name
+  // rsp[0]                   : return address
+  // rsp[8]                   : argument argc
+  // rsp[16]                  : argument argc - 1
+  // ...
+  // rsp[argc * 8]            : argument 1
+  // rsp[(argc + 1) * 8]      : argument 0 = receiver
+  // -----------------------------------
+
+  GenerateCallNormal(masm, argc);
   GenerateMiss(masm, argc);
 }
 
 
 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
-  UNREACHABLE();
+  // ----------- S t a t e -------------
+  // rcx                      : function name
+  // rsp[0]                   : return address
+  // rsp[8]                   : argument argc
+  // rsp[16]                  : argument argc - 1
+  // ...
+  // rsp[argc * 8]            : argument 1
+  // rsp[(argc + 1) * 8]      : argument 0 = receiver
+  // -----------------------------------
+
+  GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
 }
 
 
 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
-  UNREACHABLE();
+  // ----------- S t a t e -------------
+  // rcx                      : function name
+  // rsp[0]                   : return address
+  // rsp[8]                   : argument argc
+  // rsp[16]                  : argument argc - 1
+  // ...
+  // rsp[argc * 8]            : argument 1
+  // rsp[(argc + 1) * 8]      : argument 0 = receiver
+  // -----------------------------------
+
+  // Get the receiver of the function from the stack; 1 ~ return address.
+  __ movq(rdx, Operand(rsp, (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;
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(rcx, &check_string);
+
+  __ 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.
+
+  GenerateKeyedLoadReceiverCheck(masm, rdx, rax, &slow_call);
+
+  GenerateFastArrayLoad(
+      masm, rdx, rcx, rax, rbx, rdi, &check_number_dictionary, &slow_load);
+  __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
+
+  __ bind(&do_call);
+  // receiver in rdx is not used after this point.
+  // rcx: key
+  // rdi: function
+
+  // Check that the value in edi is a JavaScript function.
+  __ JumpIfSmi(rdi, &slow_call);
+  __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax);
+  __ j(not_equal, &slow_call);
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
+
+  __ bind(&check_number_dictionary);
+  // eax: elements
+  // ecx: smi key
+  // Check whether the elements is a number dictionary.
+  __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
+                 Heap::kHashTableMapRootIndex);
+  __ SmiToInteger32(rbx, rcx);
+  // ebx: untagged index
+  GenerateNumberDictionaryLoad(masm, &slow_load, rax, rcx, rbx, r9, rdi, rdi);
+  __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
+  __ jmp(&do_call);
+
+  __ bind(&slow_load);
+  // This branch is taken when calling KeyedCallIC_Miss is neither required
+  // nor beneficial.
+  __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
+  __ EnterInternalFrame();
+  __ push(rcx);  // save the key
+  __ push(rdx);  // pass the receiver
+  __ push(rcx);  // pass the key
+  __ CallRuntime(Runtime::kKeyedGetProperty, 2);
+  __ pop(rcx);  // restore the key
+  __ LeaveInternalFrame();
+  __ movq(rdi, rax);
+  __ jmp(&do_call);
+
+  __ bind(&check_string);
+  GenerateKeyStringCheck(masm, rcx, rax, rbx, &index_string, &slow_call);
+
+  // The key is known to be a symbol.
+  // 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.
+  GenerateKeyedLoadReceiverCheck(masm, rdx, rax, &lookup_monomorphic_cache);
+
+  __ movq(rbx, FieldOperand(rdx, JSObject::kPropertiesOffset));
+  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
+                 Heap::kHashTableMapRootIndex);
+  __ j(not_equal, &lookup_monomorphic_cache);
+
+  GenerateDictionaryLoad(
+      masm, &slow_load, rbx, rdx, rax, rcx, rdi, rdi, DICTIONARY_CHECK_DONE);
+  __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
+  __ jmp(&do_call);
+
+  __ bind(&lookup_monomorphic_cache);
+  __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
+  GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
+  // Fall through on miss.
+
+  __ bind(&slow_call);
+  // This branch is taken if:
+  // - the receiver requires boxing or access check,
+  // - the key is neither smi nor symbol,
+  // - 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);
+  GenerateIndexFromHash(masm, rcx, rbx);
+  // Now jump to the place where smi keys are handled.
+  __ jmp(&index_smi);
 }
 
 
 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
-  UNREACHABLE();
+  // ----------- S t a t e -------------
+  // rcx                      : function name
+  // rsp[0]                   : return address
+  // rsp[8]                   : argument argc
+  // rsp[16]                  : argument argc - 1
+  // ...
+  // rsp[argc * 8]            : argument 1
+  // rsp[(argc + 1) * 8]      : argument 0 = receiver
+  // -----------------------------------
+
+  GenerateCallNormal(masm, argc);
+  GenerateMiss(masm, argc);
 }
 
 
@@ -1452,7 +1707,7 @@
   // Search the dictionary placing the result in rax.
   __ bind(&probe);
   GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx,
-                         rcx, rdi, CHECK_DICTIONARY);
+                         rcx, rdi, rax, CHECK_DICTIONARY);
   __ ret(0);
 
   // Global object access: Check access rights.
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 3823cad..24bac7d 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -35,6 +35,7 @@
 #include "macro-assembler-x64.h"
 #include "serialize.h"
 #include "debug.h"
+#include "heap.h"
 
 namespace v8 {
 namespace internal {
@@ -96,8 +97,8 @@
 
   // Compute number of region covering addr. See Page::GetRegionNumberForAddress
   // method for more details.
-  and_(addr, Immediate(Page::kPageAlignmentMask));
   shrl(addr, Immediate(Page::kRegionSizeLog2));
+  andl(addr, Immediate(Page::kPageAlignmentMask >> Page::kRegionSizeLog2));
 
   // Set dirty mark for region.
   bts(Operand(object, Page::kDirtyFlagOffset), addr);
@@ -106,25 +107,25 @@
 
 // For page containing |object| mark region covering [object+offset] dirty.
 // object is the object being stored into, value is the object being stored.
-// If offset is zero, then the smi_index register contains the array index into
-// the elements array represented as a smi. Otherwise it can be used as a
-// scratch register.
+// If offset is zero, then the index register contains the array index into
+// the elements array represented a zero extended int32. Otherwise it can be
+// used as a scratch register.
 // All registers are clobbered by the operation.
 void MacroAssembler::RecordWrite(Register object,
                                  int offset,
                                  Register value,
-                                 Register smi_index) {
+                                 Register index) {
   // The compiled code assumes that record write doesn't change the
   // context register, so we check that none of the clobbered
   // registers are rsi.
-  ASSERT(!object.is(rsi) && !value.is(rsi) && !smi_index.is(rsi));
+  ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi));
 
   // First, check if a write barrier is even needed. The tests below
   // catch stores of Smis and stores into young gen.
   Label done;
   JumpIfSmi(value, &done);
 
-  RecordWriteNonSmi(object, offset, value, smi_index);
+  RecordWriteNonSmi(object, offset, value, index);
   bind(&done);
 
   // Clobber all input registers when running with the debug-code flag
@@ -135,7 +136,7 @@
   if (FLAG_debug_code) {
     movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
-    movq(smi_index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
+    movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
   }
 }
 
@@ -143,7 +144,7 @@
 void MacroAssembler::RecordWriteNonSmi(Register object,
                                        int offset,
                                        Register scratch,
-                                       Register smi_index) {
+                                       Register index) {
   Label done;
 
   if (FLAG_debug_code) {
@@ -151,6 +152,16 @@
     JumpIfNotSmi(object, &okay);
     Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis");
     bind(&okay);
+
+    if (offset == 0) {
+      // index must be int32.
+      Register tmp = index.is(rax) ? rbx : rax;
+      push(tmp);
+      movl(tmp, index);
+      cmpq(tmp, index);
+      Check(equal, "Index register for RecordWrite must be untagged int32.");
+      pop(tmp);
+    }
   }
 
   // Test that the object address is not in the new space. We cannot
@@ -163,16 +174,15 @@
   ASSERT(IsAligned(offset, kPointerSize) ||
          IsAligned(offset + kHeapObjectTag, kPointerSize));
 
-  Register dst = smi_index;
+  Register dst = index;
   if (offset != 0) {
     lea(dst, Operand(object, offset));
   } else {
     // array access: calculate the destination address in the same manner as
     // KeyedStoreIC::GenerateGeneric.
-    SmiIndex index = SmiToIndex(smi_index, smi_index, kPointerSizeLog2);
     lea(dst, FieldOperand(object,
-                          index.reg,
-                          index.scale,
+                          index,
+                          times_pointer_size,
                           FixedArray::kHeaderSize));
   }
   RecordWriteHelper(object, dst, scratch);
@@ -184,7 +194,7 @@
   if (FLAG_debug_code) {
     movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
     movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
-    movq(smi_index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
+    movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
   }
 }
 
@@ -446,13 +456,8 @@
 
 
 void MacroAssembler::Set(const Operand& dst, int64_t x) {
-  if (x == 0) {
-    xor_(kScratchRegister, kScratchRegister);
-    movq(dst, kScratchRegister);
-  } else if (is_int32(x)) {
+  if (is_int32(x)) {
     movq(dst, Immediate(static_cast<int32_t>(x)));
-  } else if (is_uint32(x)) {
-    movl(dst, Immediate(static_cast<uint32_t>(x)));
   } else {
     movq(kScratchRegister, x, RelocInfo::NONE);
     movq(dst, kScratchRegister);
@@ -485,6 +490,23 @@
 }
 
 
+void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
+  if (FLAG_debug_code) {
+    testb(dst, Immediate(0x01));
+    Label ok;
+    j(zero, &ok);
+    if (allow_stub_calls()) {
+      Abort("Integer32ToSmiField writing to non-smi location");
+    } else {
+      int3();
+    }
+    bind(&ok);
+  }
+  ASSERT(kSmiShift % kBitsPerByte == 0);
+  movl(Operand(dst, kSmiShift / kBitsPerByte), src);
+}
+
+
 void MacroAssembler::Integer64PlusConstantToSmi(Register dst,
                                                 Register src,
                                                 int constant) {
@@ -520,6 +542,11 @@
 }
 
 
+void MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
+  movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
+}
+
+
 void MacroAssembler::SmiTest(Register src) {
   testq(src, src);
 }
@@ -556,6 +583,11 @@
 }
 
 
+void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
+  cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
+}
+
+
 void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
                                                            Register src,
                                                            int power) {
@@ -696,15 +728,12 @@
       movq(dst, src1);
       addq(dst, src2);
     }
-    Assert(no_overflow, "Smi addition onverflow");
+    Assert(no_overflow, "Smi addition overflow");
   } else if (dst.is(src1)) {
-    addq(dst, src2);
-    Label smi_result;
-    j(no_overflow, &smi_result);
-    // Restore src1.
-    subq(src1, src2);
-    jmp(on_not_smi_result);
-    bind(&smi_result);
+    movq(kScratchRegister, src1);
+    addq(kScratchRegister, src2);
+    j(overflow, on_not_smi_result);
+    movq(dst, kScratchRegister);
   } else {
     movq(dst, src1);
     addq(dst, src2);
@@ -727,15 +756,11 @@
       movq(dst, src1);
       subq(dst, src2);
     }
-    Assert(no_overflow, "Smi substraction onverflow");
+    Assert(no_overflow, "Smi subtraction overflow");
   } else if (dst.is(src1)) {
+    cmpq(dst, src2);
+    j(overflow, on_not_smi_result);
     subq(dst, src2);
-    Label smi_result;
-    j(no_overflow, &smi_result);
-    // Restore src1.
-    addq(src1, src2);
-    jmp(on_not_smi_result);
-    bind(&smi_result);
   } else {
     movq(dst, src1);
     subq(dst, src2);
@@ -757,15 +782,12 @@
       movq(dst, src1);
       subq(dst, src2);
     }
-    Assert(no_overflow, "Smi substraction onverflow");
+    Assert(no_overflow, "Smi subtraction overflow");
   } else if (dst.is(src1)) {
-    subq(dst, src2);
-    Label smi_result;
-    j(no_overflow, &smi_result);
-    // Restore src1.
-    addq(src1, src2);
-    jmp(on_not_smi_result);
-    bind(&smi_result);
+    movq(kScratchRegister, src1);
+    subq(kScratchRegister, src2);
+    j(overflow, on_not_smi_result);
+    movq(src1, kScratchRegister);
   } else {
     movq(dst, src1);
     subq(dst, src2);
@@ -883,12 +905,9 @@
     ASSERT(!dst.is(kScratchRegister));
 
     Move(kScratchRegister, constant);
-    addq(dst, kScratchRegister);
-    Label result_ok;
-    j(no_overflow, &result_ok);
-    subq(dst, kScratchRegister);
-    jmp(on_not_smi_result);
-    bind(&result_ok);
+    addq(kScratchRegister, dst);
+    j(overflow, on_not_smi_result);
+    movq(dst, kScratchRegister);
   } else {
     Move(dst, constant);
     addq(dst, src);
@@ -910,10 +929,12 @@
   } else {
     // Subtract by adding the negative, to do it in two operations.
     if (constant->value() == Smi::kMinValue) {
-      Move(kScratchRegister, constant);
-      movq(dst, src);
-      subq(dst, kScratchRegister);
+      Move(dst, constant);
+      // Adding and subtracting the min-value gives the same result, it only
+      // differs on the overflow bit, which we don't check here.
+      addq(dst, src);
     } else {
+      // Subtract by adding the negation.
       Move(dst, Smi::FromInt(-constant->value()));
       addq(dst, src);
     }
@@ -931,21 +952,32 @@
     }
   } else if (dst.is(src)) {
     ASSERT(!dst.is(kScratchRegister));
-
-    Move(kScratchRegister, constant);
-    subq(dst, kScratchRegister);
-    Label sub_success;
-    j(no_overflow, &sub_success);
-    addq(src, kScratchRegister);
-    jmp(on_not_smi_result);
-    bind(&sub_success);
+    if (constant->value() == Smi::kMinValue) {
+      // Subtracting min-value from any non-negative value will overflow.
+      // We test the non-negativeness before doing the subtraction.
+      testq(src, src);
+      j(not_sign, on_not_smi_result);
+      Move(kScratchRegister, constant);
+      subq(dst, kScratchRegister);
+    } else {
+      // Subtract by adding the negation.
+      Move(kScratchRegister, Smi::FromInt(-constant->value()));
+      addq(kScratchRegister, dst);
+      j(overflow, on_not_smi_result);
+      movq(dst, kScratchRegister);
+    }
   } else {
     if (constant->value() == Smi::kMinValue) {
-      Move(kScratchRegister, constant);
-      movq(dst, src);
-      subq(dst, kScratchRegister);
-      j(overflow, on_not_smi_result);
+      // Subtracting min-value from any non-negative value will overflow.
+      // We test the non-negativeness before doing the subtraction.
+      testq(src, src);
+      j(not_sign, on_not_smi_result);
+      Move(dst, constant);
+      // Adding and subtracting the min-value gives the same result, it only
+      // differs on the overflow bit, which we don't check here.
+      addq(dst, src);
     } else {
+      // Subtract by adding the negation.
       Move(dst, Smi::FromInt(-(constant->value())));
       addq(dst, src);
       j(overflow, on_not_smi_result);
@@ -1695,6 +1727,17 @@
 }
 
 
+void MacroAssembler::AbortIfNotRootValue(Register src,
+                                         Heap::RootListIndex root_value_index,
+                                         const char* message) {
+  ASSERT(!src.is(kScratchRegister));
+  LoadRoot(kScratchRegister, root_value_index);
+  cmpq(src, kScratchRegister);
+  Check(equal, message);
+}
+
+
+
 Condition MacroAssembler::IsObjectStringType(Register heap_object,
                                              Register map,
                                              Register instance_type) {
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 0acce05..bb0b681 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -203,6 +203,9 @@
   // NOTICE: Destroys the dst register even if unsuccessful!
   void Integer32ToSmi(Register dst, Register src, Label* on_overflow);
 
+  // Stores an integer32 value into a memory field that already holds a smi.
+  void Integer32ToSmiField(const Operand& dst, Register src);
+
   // Adds constant to src and tags the result as a smi.
   // Result must be a valid smi.
   void Integer64PlusConstantToSmi(Register dst, Register src, int constant);
@@ -214,6 +217,7 @@
 
   // Convert smi to 64-bit integer (sign extended if necessary).
   void SmiToInteger64(Register dst, Register src);
+  void SmiToInteger64(Register dst, const Operand& src);
 
   // Multiply a positive smi's integer value by a power of two.
   // Provides result as 64-bit integer value.
@@ -234,6 +238,8 @@
   void SmiCompare(Register dst, const Operand& src);
   void SmiCompare(const Operand& dst, Register src);
   void SmiCompare(const Operand& dst, Smi* src);
+  // Compare the int32 in src register to the value of the smi stored at dst.
+  void SmiCompareInteger32(const Operand& dst, Register src);
   // Sets sign and zero flags depending on value of smi in register.
   void SmiTest(Register src);
 
@@ -550,6 +556,11 @@
   // Abort execution if argument is not a smi. Used in debug code.
   void AbortIfNotSmi(Register object);
 
+  // Abort execution if argument is not the root value with the given index.
+  void AbortIfNotRootValue(Register src,
+                           Heap::RootListIndex root_value_index,
+                           const char* message);
+
   // ---------------------------------------------------------------------------
   // Exception handling
 
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index cc54470..1e103ac 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -706,6 +706,15 @@
 
 #define __ ACCESS_MASM((masm()))
 
+
+void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) {
+  if (kind_ == Code::KEYED_CALL_IC) {
+    __ Cmp(rcx, Handle<String>(name));
+    __ j(not_equal, miss);
+  }
+}
+
+
 void CallStubCompiler::GenerateMissBranch() {
   Handle<Code> ic = ComputeCallMiss(arguments().immediate(), kind_);
   __ Jump(ic, RelocInfo::CODE_TARGET);
@@ -740,6 +749,8 @@
 
   Label miss_in_smi_check;
 
+  GenerateNameCheck(name, &miss_in_smi_check);
+
   // Get the receiver from the stack.
   const int argc = arguments().immediate();
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
@@ -881,6 +892,8 @@
   // -----------------------------------
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the receiver from the stack.
   const int argc = arguments().immediate();
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
@@ -938,6 +951,8 @@
 
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the receiver from the stack.
   const int argc = arguments().immediate();
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
@@ -970,30 +985,30 @@
       Label call_builtin, exit, with_write_barrier, attempt_to_grow_elements;
 
       // Get the array's length into rax and calculate new length.
-      __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
+      __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
       STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
-      __ SmiAddConstant(rax, rax, Smi::FromInt(argc));
+      __ addl(rax, Immediate(argc));
 
       // Get the element's length into rcx.
-      __ movq(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
+      __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
 
       // Check if we could survive without allocation.
-      __ SmiCompare(rax, rcx);
+      __ cmpl(rax, rcx);
       __ j(greater, &attempt_to_grow_elements);
 
       // Save new length.
-      __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
+      __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
 
       // Push the element.
       __ movq(rcx, Operand(rsp, argc * kPointerSize));
-      SmiIndex index =
-          masm()->SmiToIndex(kScratchRegister, rax, times_pointer_size);
       __ lea(rdx, FieldOperand(rbx,
-                               index.reg, index.scale,
+                               rax, times_pointer_size,
                                FixedArray::kHeaderSize - argc * kPointerSize));
       __ movq(Operand(rdx, 0), rcx);
 
       // Check if value is a smi.
+      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
+
       __ JumpIfNotSmi(rcx, &with_write_barrier);
 
       __ bind(&exit);
@@ -1005,6 +1020,7 @@
 
       RecordWriteStub stub(rbx, rdx, rcx);
       __ CallStub(&stub);
+
       __ ret((argc + 1) * kPointerSize);
 
       __ bind(&attempt_to_grow_elements);
@@ -1019,9 +1035,8 @@
       __ movq(rcx, Operand(rcx, 0));
 
       // Check if it's the end of elements.
-      index = masm()->SmiToIndex(kScratchRegister, rax, times_pointer_size);
       __ lea(rdx, FieldOperand(rbx,
-                               index.reg, index.scale,
+                               rax, times_pointer_size,
                                FixedArray::kHeaderSize - argc * kPointerSize));
       __ cmpq(rdx, rcx);
       __ j(not_equal, &call_builtin);
@@ -1049,8 +1064,9 @@
       // Increment element's and array's sizes.
       __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset),
                         Smi::FromInt(kAllocationDelta));
+      // Make new length a smi before returning it.
+      __ Integer32ToSmi(rax, rax);
       __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
-
       // Elements are in new space, so write barrier is not required.
       __ ret((argc + 1) * kPointerSize);
 
@@ -1092,6 +1108,8 @@
 
   Label miss, return_undefined, call_builtin;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the receiver from the stack.
   const int argc = arguments().immediate();
   __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
@@ -1111,28 +1129,26 @@
   __ j(not_equal, &miss);
 
   // Get the array's length into rcx and calculate new length.
-  __ movq(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
-  __ SmiSubConstant(rcx, rcx, Smi::FromInt(1));
-  __ SmiTest(rcx);
+  __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
+  __ subl(rcx, Immediate(1));
   __ j(negative, &return_undefined);
 
   // Get the last element.
   __ Move(r9, Factory::the_hole_value());
-  SmiIndex index =
-      masm()->SmiToIndex(r8, rcx, times_pointer_size);
   __ movq(rax, FieldOperand(rbx,
-                            index.reg, index.scale,
+                            rcx, times_pointer_size,
                             FixedArray::kHeaderSize));
   // Check if element is already the hole.
   __ cmpq(rax, r9);
+  // If so, call slow-case to also check prototypes for value.
   __ j(equal, &call_builtin);
 
   // Set the array's length.
-  __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
+  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
 
-  // Fill with the hole and return original value..
+  // Fill with the hole and return original value.
   __ movq(FieldOperand(rbx,
-                       index.reg, index.scale,
+                       rcx, times_pointer_size,
                        FixedArray::kHeaderSize),
           r9);
   __ ret((argc + 1) * kPointerSize);
@@ -1190,6 +1206,8 @@
   // -----------------------------------
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the number of arguments.
   const int argc = arguments().immediate();
 
@@ -1254,6 +1272,8 @@
   // rsp[(argc + 1) * 8] : argument 0 = receiver
   Label miss;
 
+  GenerateNameCheck(name, &miss);
+
   // Get the number of arguments.
   const int argc = arguments().immediate();
 
diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc
index a0acd6a..e65378d 100644
--- a/src/x64/virtual-frame-x64.cc
+++ b/src/x64/virtual-frame-x64.cc
@@ -961,16 +961,18 @@
   // Sync elements below the range if they have not been materialized
   // on the stack.
   int start = Min(begin, stack_pointer_ + 1);
+  int end_or_stack_pointer = Min(stack_pointer_, end);
+  // Emit normal push instructions for elements above stack pointer
+  // and use mov instructions if we are below stack pointer.
+  int i = start;
 
-  // If positive we have to adjust the stack pointer.
-  int delta = end - stack_pointer_;
-  if (delta > 0) {
-    stack_pointer_ = end;
-    __ subq(rsp, Immediate(delta * kPointerSize));
-  }
-
-  for (int i = start; i <= end; i++) {
+  while (i <= end_or_stack_pointer) {
     if (!elements_[i].is_synced()) SyncElementBelowStackPointer(i);
+    i++;
+  }
+  while (i <= end) {
+    SyncElementByPushing(i);
+    i++;
   }
 }
 
@@ -1164,6 +1166,25 @@
 }
 
 
+Result VirtualFrame::CallKeyedCallIC(RelocInfo::Mode mode,
+                                     int arg_count,
+                                     int loop_nesting) {
+  // Function name, arguments, and receiver are found on top of the frame
+  // and dropped by the call.  The IC expects the name in rcx and the rest
+  // on the stack, and drops them all.
+  InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
+  Handle<Code> ic =
+      cgen()->ComputeKeyedCallInitialize(arg_count, in_loop);
+  Result name = Pop();
+  // Spill args, receiver, and function.  The call will drop args and
+  // receiver.
+  PrepareForCall(arg_count + 1, arg_count + 1);
+  name.ToRegister(rcx);
+  name.Unuse();
+  return RawCallCodeObject(ic, mode);
+}
+
+
 Result VirtualFrame::CallConstructor(int arg_count) {
   // Arguments, receiver, and function are on top of the frame.  The
   // IC expects arg count in rax, function in rdi, and the arguments
diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h
index affe18f..dc270fe 100644
--- a/src/x64/virtual-frame-x64.h
+++ b/src/x64/virtual-frame-x64.h
@@ -369,6 +369,8 @@
   // The argument count does not include the receiver.
   Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
 
+  Result CallKeyedCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
+
   // Allocate and call JS function as constructor.  Arguments,
   // receiver (global object), and function are found on top of the
   // frame.  Function is not dropped.  The argument count does not
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 9123125..c426db4 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -27,8 +27,6 @@
 
 #include <limits.h>
 
-#define USE_NEW_QUERY_CALLBACKS
-
 #include "v8.h"
 
 #include "api.h"
@@ -9637,6 +9635,45 @@
 }
 
 
+THREADED_TEST(PixelArrayInfo) {
+  v8::HandleScope scope;
+  LocalContext context;
+  for (int size = 0; size < 100; size += 10) {
+    uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
+    v8::Handle<v8::Object> obj = v8::Object::New();
+    obj->SetIndexedPropertiesToPixelData(pixel_data, size);
+    CHECK(obj->HasIndexedPropertiesInPixelData());
+    CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
+    CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
+    free(pixel_data);
+  }
+}
+
+
+static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
+  switch (array_type) {
+    case v8::kExternalByteArray:
+    case v8::kExternalUnsignedByteArray:
+      return 1;
+      break;
+    case v8::kExternalShortArray:
+    case v8::kExternalUnsignedShortArray:
+      return 2;
+      break;
+    case v8::kExternalIntArray:
+    case v8::kExternalUnsignedIntArray:
+    case v8::kExternalFloatArray:
+      return 4;
+      break;
+    default:
+      UNREACHABLE();
+      return -1;
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+
 template <class ExternalArrayClass, class ElementType>
 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
                                     int64_t low,
@@ -9644,25 +9681,7 @@
   v8::HandleScope scope;
   LocalContext context;
   const int kElementCount = 40;
-  int element_size = 0;
-  switch (array_type) {
-    case v8::kExternalByteArray:
-    case v8::kExternalUnsignedByteArray:
-      element_size = 1;
-      break;
-    case v8::kExternalShortArray:
-    case v8::kExternalUnsignedShortArray:
-      element_size = 2;
-      break;
-    case v8::kExternalIntArray:
-    case v8::kExternalUnsignedIntArray:
-    case v8::kExternalFloatArray:
-      element_size = 4;
-      break;
-    default:
-      UNREACHABLE();
-      break;
-  }
+  int element_size = ExternalArrayElementSize(array_type);
   ElementType* array_data =
       static_cast<ElementType*>(malloc(kElementCount * element_size));
   i::Handle<ExternalArrayClass> array =
@@ -10043,6 +10062,35 @@
 }
 
 
+void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
+  v8::HandleScope scope;
+  LocalContext context;
+  for (int size = 0; size < 100; size += 10) {
+    int element_size = ExternalArrayElementSize(array_type);
+    void* external_data = malloc(size * element_size);
+    v8::Handle<v8::Object> obj = v8::Object::New();
+    obj->SetIndexedPropertiesToExternalArrayData(
+        external_data, array_type, size);
+    CHECK(obj->HasIndexedPropertiesInExternalArrayData());
+    CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
+    CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
+    CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
+    free(external_data);
+  }
+}
+
+
+THREADED_TEST(ExternalArrayInfo) {
+  ExternalArrayInfoTestHelper(v8::kExternalByteArray);
+  ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
+  ExternalArrayInfoTestHelper(v8::kExternalShortArray);
+  ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
+  ExternalArrayInfoTestHelper(v8::kExternalIntArray);
+  ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
+  ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
+}
+
+
 THREADED_TEST(ScriptContextDependence) {
   v8::HandleScope scope;
   LocalContext c1;
@@ -10127,7 +10175,13 @@
                     stackTrace->GetFrame(0));
     checkStackFrame(origin, "baz", 8, 3, false, true,
                     stackTrace->GetFrame(1));
-    checkStackFrame(NULL, "", 1, 1, true, false,
+#ifdef ENABLE_DEBUGGER_SUPPORT
+    bool is_eval = true;
+#else  // ENABLE_DEBUGGER_SUPPORT
+    bool is_eval = false;
+#endif  // ENABLE_DEBUGGER_SUPPORT
+
+    checkStackFrame(NULL, "", 1, 1, is_eval, false,
                     stackTrace->GetFrame(2));
     // The last frame is an anonymous function that has the initial call to foo.
     checkStackFrame(origin, "", 10, 1, false, false,
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 4c3ff5e..e689637 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -25,9 +25,9 @@
 // (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>
+#ifdef ENABLE_DEBUGGER_SUPPORT
 
-#define USE_NEW_QUERY_CALLBACKS
+#include <stdlib.h>
 
 #include "v8.h"
 
@@ -194,8 +194,9 @@
   static int break_point = 0;
   Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
   Debug::SetBreakPoint(
-      shared, position,
-      Handle<Object>(v8::internal::Smi::FromInt(++break_point)));
+      shared,
+      Handle<Object>(v8::internal::Smi::FromInt(++break_point)),
+      &position);
   return break_point;
 }
 
@@ -2029,6 +2030,51 @@
 }
 
 
+// Test top level script break points set on lines.
+TEST(ScriptBreakPointLineTopLevel) {
+  v8::HandleScope scope;
+  DebugLocalContext env;
+  env.ExposeDebug();
+
+  v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+                                   v8::Undefined());
+
+  v8::Local<v8::String> script = v8::String::New(
+    "function f() {\n"
+    "  a = 1;                   // line 1\n"
+    "}\n"
+    "a = 2;                     // line 3\n");
+  v8::Local<v8::Function> f;
+  {
+    v8::HandleScope scope;
+    v8::Script::Compile(script, v8::String::New("test.html"))->Run();
+  }
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+
+  Heap::CollectAllGarbage(false);
+
+  SetScriptBreakPointByNameFromJS("test.html", 3, -1);
+
+  // Call f and check that there was no break points.
+  break_point_hit_count = 0;
+  f->Call(env->Global(), 0, NULL);
+  CHECK_EQ(0, break_point_hit_count);
+
+  // Recompile and run script and check that break point was hit.
+  break_point_hit_count = 0;
+  v8::Script::Compile(script, v8::String::New("test.html"))->Run();
+  CHECK_EQ(1, break_point_hit_count);
+
+  // Call f and check that there are still no break points.
+  break_point_hit_count = 0;
+  f = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+  CHECK_EQ(0, break_point_hit_count);
+
+  v8::Debug::SetDebugEventListener(NULL);
+  CheckDebuggerUnloaded();
+}
+
+
 // Test that it is possible to remove the last break point for a function
 // inside the break handling of that break point.
 TEST(RemoveBreakPointInBreak) {
@@ -6571,3 +6617,4 @@
   CheckDebuggerUnloaded();
 }
 
+#endif  // ENABLE_DEBUGGER_SUPPORT
diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc
index c4be35e..7587da8 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -27,8 +27,6 @@
 
 #include <stdlib.h>
 
-#define USE_NEW_QUERY_CALLBACKS
-
 #include "v8.h"
 
 #include "heap.h"
diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc
index 3189e5e..5903fe6 100644
--- a/test/cctest/test-disasm-arm.cc
+++ b/test/cctest/test-disasm-arm.cc
@@ -248,6 +248,72 @@
   COMPARE(mvn(r5, Operand(r4), SetCC, cc),
           "31f05004       mvnccs r5, r4");
 
+  // Instructions autotransformed by the assembler.
+  // mov -> mvn.
+  COMPARE(mov(r3, Operand(-1), LeaveCC, al),
+          "e3e03000       mvn r3, #0");
+  COMPARE(mov(r4, Operand(-2), SetCC, al),
+          "e3f04001       mvns r4, #1");
+  COMPARE(mov(r5, Operand(0x0ffffff0), SetCC, ne),
+          "13f052ff       mvnnes r5, #-268435441");
+  COMPARE(mov(r6, Operand(-1), LeaveCC, ne),
+          "13e06000       mvnne r6, #0");
+
+  // mvn -> mov.
+  COMPARE(mvn(r3, Operand(-1), LeaveCC, al),
+          "e3a03000       mov r3, #0");
+  COMPARE(mvn(r4, Operand(-2), SetCC, al),
+          "e3b04001       movs r4, #1");
+  COMPARE(mvn(r5, Operand(0x0ffffff0), SetCC, ne),
+          "13b052ff       movnes r5, #-268435441");
+  COMPARE(mvn(r6, Operand(-1), LeaveCC, ne),
+          "13a06000       movne r6, #0");
+
+  // mov -> movw.
+  if (CpuFeatures::IsSupported(ARMv7)) {
+    COMPARE(mov(r5, Operand(0x01234), LeaveCC, ne),
+            "13015234       movwne r5, #4660");
+    // We only disassemble one instruction so the eor instruction is not here.
+    COMPARE(eor(r5, r4, Operand(0x1234), LeaveCC, ne),
+            "1301c234       movwne ip, #4660");
+    // Movw can't do setcc so we don't get that here.  Mov immediate with setcc
+    // is pretty strange anyway.
+    COMPARE(mov(r5, Operand(0x01234), SetCC, ne),
+            "159fc000       ldrne ip, [pc, #+0]");
+    // We only disassemble one instruction so the eor instruction is not here.
+    // The eor does the setcc so we get a movw here.
+    COMPARE(eor(r5, r4, Operand(0x1234), SetCC, ne),
+            "1301c234       movwne ip, #4660");
+
+    COMPARE(movt(r5, 0x4321, ne),
+            "13445321       movtne r5, #17185");
+    COMPARE(movw(r5, 0xabcd, eq),
+            "030a5bcd       movweq r5, #43981");
+  }
+
+  // Eor doesn't have an eor-negative variant, but we can do an mvn followed by
+  // an eor to get the same effect.
+  COMPARE(eor(r5, r4, Operand(0xffffff34), SetCC, ne),
+          "13e0c0cb       mvnne ip, #203");
+
+  // and <-> bic.
+  COMPARE(and_(r3, r5, Operand(0xfc03ffff)),
+          "e3c537ff       bic r3, r5, #66846720");
+  COMPARE(bic(r3, r5, Operand(0xfc03ffff)),
+          "e20537ff       and r3, r5, #66846720");
+
+  // sub <-> add.
+  COMPARE(add(r3, r5, Operand(-1024)),
+          "e2453b01       sub r3, r5, #1024");
+  COMPARE(sub(r3, r5, Operand(-1024)),
+          "e2853b01       add r3, r5, #1024");
+
+  // cmp <-> cmn.
+  COMPARE(cmp(r3, Operand(-1024)),
+          "e3730b01       cmn r3, #1024");
+  COMPARE(cmn(r3, Operand(-1024)),
+          "e3530b01       cmp r3, #1024");
+
   // Miscellaneous instructions encoded as type 0.
   COMPARE(blx(ip),
           "e12fff3c       blx ip");
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index c8e0197..e51bfab 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -276,9 +276,11 @@
 
   __ jmp(&L1);
   __ jmp(Operand(ebx, ecx, times_4, 10000));
+#ifdef ENABLE_DEBUGGER_SUPPORT
   ExternalReference after_break_target =
       ExternalReference(Debug_Address::AfterBreakTarget());
   __ jmp(Operand::StaticVariable(after_break_target));
+#endif  // ENABLE_DEBUGGER_SUPPORT
   __ jmp(ic, RelocInfo::CODE_TARGET);
   __ nop();
 
@@ -375,7 +377,7 @@
       __ divsd(xmm1, xmm0);
       __ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
       __ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
-      __ comisd(xmm0, xmm1);
+      __ ucomisd(xmm0, xmm1);
 
       // 128 bit move instructions.
       __ movdqa(xmm0, Operand(ebx, ecx, times_4, 10000));
diff --git a/test/cctest/test-func-name-inference.cc b/test/cctest/test-func-name-inference.cc
index 67791fb..563cc4b 100644
--- a/test/cctest/test-func-name-inference.cc
+++ b/test/cctest/test-func-name-inference.cc
@@ -81,6 +81,7 @@
   int func_pos = Runtime::StringMatch(script_src, func_pos_str, 0);
   CHECK_NE(0, func_pos);
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
   // Obtain SharedFunctionInfo for the function.
   Object* shared_func_info_ptr =
       Runtime::FindSharedFunctionInfoInScript(i_script, func_pos);
@@ -92,6 +93,7 @@
   SmartPointer<char> inferred_name =
       shared_func_info->inferred_name()->ToCString();
   CHECK_EQ(ref_inferred_name, *inferred_name);
+#endif  // ENABLE_DEBUGGER_SUPPORT
 }
 
 
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 2e56894..7f1e3d8 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -6,9 +6,11 @@
 
 #include "v8.h"
 #include "heap-profiler.h"
+#include "snapshot.h"
 #include "string-stream.h"
 #include "cctest.h"
 #include "zone-inl.h"
+#include "../include/v8-profiler.h"
 
 namespace i = v8::internal;
 using i::ClustersCoarser;
@@ -390,4 +392,236 @@
   CHECK_EQ("(global property);1", printer.GetRetainers("C"));
 }
 
+
+namespace {
+
+class NamedEntriesDetector {
+ public:
+  NamedEntriesDetector()
+      : has_A1(false), has_B1(false), has_C1(false),
+        has_A2(false), has_B2(false), has_C2(false) {
+  }
+
+  void Apply(i::HeapEntry* entry) {
+    const char* node_name = entry->name();
+    if (strcmp("A1", node_name) == 0
+        && entry->GetRetainingPaths()->length() > 0) has_A1 = true;
+    if (strcmp("B1", node_name) == 0
+        && entry->GetRetainingPaths()->length() > 0) has_B1 = true;
+    if (strcmp("C1", node_name) == 0
+        && entry->GetRetainingPaths()->length() > 0) has_C1 = true;
+    if (strcmp("A2", node_name) == 0
+        && entry->GetRetainingPaths()->length() > 0) has_A2 = true;
+    if (strcmp("B2", node_name) == 0
+        && entry->GetRetainingPaths()->length() > 0) has_B2 = true;
+    if (strcmp("C2", node_name) == 0
+        && entry->GetRetainingPaths()->length() > 0) has_C2 = true;
+  }
+
+  bool has_A1;
+  bool has_B1;
+  bool has_C1;
+  bool has_A2;
+  bool has_B2;
+  bool has_C2;
+};
+
+}  // namespace
+
+
+static const v8::HeapGraphNode* GetGlobalObject(
+    const v8::HeapSnapshot* snapshot) {
+  CHECK_EQ(1, snapshot->GetHead()->GetChildrenCount());
+  return snapshot->GetHead()->GetChild(0)->GetToNode();
+}
+
+
+static const v8::HeapGraphNode* GetProperty(const v8::HeapGraphNode* node,
+                                            v8::HeapGraphEdge::Type type,
+                                            const char* name) {
+  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = node->GetChild(i);
+    v8::String::AsciiValue prop_name(prop->GetName());
+    if (prop->GetType() == type && strcmp(name, *prop_name) == 0)
+      return prop->GetToNode();
+  }
+  return NULL;
+}
+
+
+static bool HasString(const v8::HeapGraphNode* node, const char* contents) {
+  for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = node->GetChild(i);
+    const v8::HeapGraphNode* node = prop->GetToNode();
+    if (node->GetType() == v8::HeapGraphNode::STRING) {
+      v8::String::AsciiValue node_name(node->GetName());
+      if (strcmp(contents, *node_name) == 0) return true;
+    }
+  }
+  return false;
+}
+
+
+TEST(HeapSnapshot) {
+  v8::HandleScope scope;
+
+  v8::Handle<v8::String> token1 = v8::String::New("token1");
+  v8::Handle<v8::Context> env1 = v8::Context::New();
+  env1->SetSecurityToken(token1);
+  env1->Enter();
+
+  CompileAndRunScript(
+      "function A1() {}\n"
+      "function B1(x) { this.x = x; }\n"
+      "function C1(x) { this.x1 = x; this.x2 = x; }\n"
+      "var a1 = new A1();\n"
+      "var b1_1 = new B1(a1), b1_2 = new B1(a1);\n"
+      "var c1 = new C1(a1);");
+
+  v8::Handle<v8::String> token2 = v8::String::New("token2");
+  v8::Handle<v8::Context> env2 = v8::Context::New();
+  env2->SetSecurityToken(token2);
+  env2->Enter();
+
+  CompileAndRunScript(
+      "function A2() {}\n"
+      "function B2(x) { return function() { return typeof x; }; }\n"
+      "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n"
+      "var a2 = new A2();\n"
+      "var b2_1 = new B2(a2), b2_2 = new B2(a2);\n"
+      "var c2 = new C2(a2);");
+  const v8::HeapSnapshot* snapshot_env2 =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("env2"));
+  const v8::HeapGraphNode* global_env2 = GetGlobalObject(snapshot_env2);
+
+  // Verify, that JS global object of env2 doesn't have '..1'
+  // properties, but has '..2' properties.
+  CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a1"));
+  CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_1"));
+  CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b1_2"));
+  CHECK_EQ(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c1"));
+  const v8::HeapGraphNode* a2_node =
+      GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "a2");
+  CHECK_NE(NULL, a2_node);
+  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_1"));
+  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "b2_2"));
+  CHECK_NE(NULL, GetProperty(global_env2, v8::HeapGraphEdge::PROPERTY, "c2"));
+
+  // Verify that anything related to '[ABC]1' is not reachable.
+  NamedEntriesDetector det;
+  i::HeapSnapshot* i_snapshot_env2 =
+      const_cast<i::HeapSnapshot*>(
+          reinterpret_cast<const i::HeapSnapshot*>(snapshot_env2));
+  i_snapshot_env2->IterateEntries(&det);
+  CHECK(!det.has_A1);
+  CHECK(!det.has_B1);
+  CHECK(!det.has_C1);
+  CHECK(det.has_A2);
+  CHECK(det.has_B2);
+  CHECK(det.has_C2);
+
+  // Verify 'a2' object retainers. They are:
+  //  - (global object).a2
+  //  - c2.x1, c2.x2, c2[1]
+  //  - b2_1 and b2_2 closures: via 'x' variable
+  CHECK_EQ(6, a2_node->GetRetainingPathsCount());
+  bool has_global_obj_a2_ref = false;
+  bool has_c2_x1_ref = false, has_c2_x2_ref = false, has_c2_1_ref = false;
+  bool has_b2_1_x_ref = false, has_b2_2_x_ref = false;
+  for (int i = 0; i < a2_node->GetRetainingPathsCount(); ++i) {
+    const v8::HeapGraphPath* path = a2_node->GetRetainingPath(i);
+    const int edges_count = path->GetEdgesCount();
+    CHECK_GT(edges_count, 0);
+    const v8::HeapGraphEdge* last_edge = path->GetEdge(edges_count - 1);
+    v8::String::AsciiValue last_edge_name(last_edge->GetName());
+    if (strcmp("a2", *last_edge_name) == 0
+        && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY) {
+      has_global_obj_a2_ref = true;
+      continue;
+    }
+    CHECK_GT(edges_count, 1);
+    const v8::HeapGraphEdge* prev_edge = path->GetEdge(edges_count - 2);
+    v8::String::AsciiValue prev_edge_name(prev_edge->GetName());
+    if (strcmp("x1", *last_edge_name) == 0
+        && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY
+        && strcmp("c2", *prev_edge_name) == 0) has_c2_x1_ref = true;
+    if (strcmp("x2", *last_edge_name) == 0
+        && last_edge->GetType() == v8::HeapGraphEdge::PROPERTY
+        && strcmp("c2", *prev_edge_name) == 0) has_c2_x2_ref = true;
+    if (strcmp("1", *last_edge_name) == 0
+        && last_edge->GetType() == v8::HeapGraphEdge::ELEMENT
+        && strcmp("c2", *prev_edge_name) == 0) has_c2_1_ref = true;
+    if (strcmp("x", *last_edge_name) == 0
+        && last_edge->GetType() == v8::HeapGraphEdge::CONTEXT_VARIABLE
+        && strcmp("b2_1", *prev_edge_name) == 0) has_b2_1_x_ref = true;
+    if (strcmp("x", *last_edge_name) == 0
+        && last_edge->GetType() == v8::HeapGraphEdge::CONTEXT_VARIABLE
+        && strcmp("b2_2", *prev_edge_name) == 0) has_b2_2_x_ref = true;
+  }
+  CHECK(has_global_obj_a2_ref);
+  CHECK(has_c2_x1_ref);
+  CHECK(has_c2_x2_ref);
+  CHECK(has_c2_1_ref);
+  CHECK(has_b2_1_x_ref);
+  CHECK(has_b2_2_x_ref);
+}
+
+
+TEST(HeapSnapshotCodeObjects) {
+  v8::HandleScope scope;
+  v8::Handle<v8::Context> env = v8::Context::New();
+  env->Enter();
+
+  CompileAndRunScript(
+      "function lazy(x) { return x - 1; }\n"
+      "function compiled(x) { return x + 1; }\n"
+      "compiled(1)");
+  const v8::HeapSnapshot* snapshot =
+      v8::HeapProfiler::TakeSnapshot(v8::String::New("code"));
+
+  const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
+  const v8::HeapGraphNode* compiled =
+      GetProperty(global, v8::HeapGraphEdge::PROPERTY, "compiled");
+  CHECK_NE(NULL, compiled);
+  CHECK_EQ(v8::HeapGraphNode::CLOSURE, compiled->GetType());
+  const v8::HeapGraphNode* lazy =
+      GetProperty(global, v8::HeapGraphEdge::PROPERTY, "lazy");
+  CHECK_NE(NULL, lazy);
+  CHECK_EQ(v8::HeapGraphNode::CLOSURE, lazy->GetType());
+
+  // Find references to code.
+  const v8::HeapGraphNode* compiled_code =
+      GetProperty(compiled, v8::HeapGraphEdge::INTERNAL, "code");
+  CHECK_NE(NULL, compiled_code);
+  const v8::HeapGraphNode* lazy_code =
+      GetProperty(lazy, v8::HeapGraphEdge::INTERNAL, "code");
+  CHECK_NE(NULL, lazy_code);
+
+  // Verify that non-compiled code doesn't contain references to "x"
+  // literal, while compiled code does.
+  bool compiled_references_x = false, lazy_references_x = false;
+  for (int i = 0, count = compiled_code->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = compiled_code->GetChild(i);
+    const v8::HeapGraphNode* node = prop->GetToNode();
+    if (node->GetType() == v8::HeapGraphNode::CODE) {
+      if (HasString(node, "x")) {
+        compiled_references_x = true;
+        break;
+      }
+    }
+  }
+  for (int i = 0, count = lazy_code->GetChildrenCount(); i < count; ++i) {
+    const v8::HeapGraphEdge* prop = lazy_code->GetChild(i);
+    const v8::HeapGraphNode* node = prop->GetToNode();
+    if (node->GetType() == v8::HeapGraphNode::CODE) {
+      if (HasString(node, "x")) {
+        lazy_references_x = true;
+        break;
+      }
+    }
+  }
+  CHECK(compiled_references_x);
+  CHECK(!lazy_references_x);
+}
+
 #endif  // ENABLE_LOGGING_AND_PROFILING
diff --git a/test/cctest/test-liveedit.cc b/test/cctest/test-liveedit.cc
index ec1a7a6..244980a 100644
--- a/test/cctest/test-liveedit.cc
+++ b/test/cctest/test-liveedit.cc
@@ -25,6 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
+
 #include <stdlib.h>
 
 #include "v8.h"
@@ -172,3 +174,5 @@
   CompareStrings("abbabababababaaabbabababababbabbbbbbbababa",
                  "bbbbabababbbabababbbabababababbabbababa");
 }
+
+#endif  // ENABLE_DEBUGGER_SUPPORT
diff --git a/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index c4c8a45..3ec25c9 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -98,9 +98,11 @@
 }
 
 
+#ifdef ENABLE_DEBUGGER_SUPPORT
 static int register_code(int reg) {
   return Debug::k_register_address << kDebugIdShift | reg;
 }
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 
 TEST(ExternalReferenceEncoder) {
@@ -113,8 +115,10 @@
            Encode(encoder, Runtime::kAbort));
   CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
            Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
+#ifdef ENABLE_DEBUGGER_SUPPORT
   CHECK_EQ(make_code(DEBUG_ADDRESS, register_code(3)),
            Encode(encoder, Debug_Address(Debug::k_register_address, 3)));
+#endif  // ENABLE_DEBUGGER_SUPPORT
   ExternalReference keyed_load_function_prototype =
       ExternalReference(&Counters::keyed_load_function_prototype);
   CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
@@ -131,9 +135,11 @@
       ExternalReference::address_of_real_stack_limit();
   CHECK_EQ(make_code(UNCLASSIFIED, 5),
            encoder.Encode(real_stack_limit_address.address()));
-  CHECK_EQ(make_code(UNCLASSIFIED, 12),
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  CHECK_EQ(make_code(UNCLASSIFIED, 15),
            encoder.Encode(ExternalReference::debug_break().address()));
-  CHECK_EQ(make_code(UNCLASSIFIED, 7),
+#endif  // ENABLE_DEBUGGER_SUPPORT
+  CHECK_EQ(make_code(UNCLASSIFIED, 10),
            encoder.Encode(ExternalReference::new_space_start().address()));
   CHECK_EQ(make_code(UNCLASSIFIED, 3),
            encoder.Encode(ExternalReference::roots_address().address()));
@@ -150,8 +156,10 @@
            decoder.Decode(make_code(RUNTIME_FUNCTION, Runtime::kAbort)));
   CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
            decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
+#ifdef ENABLE_DEBUGGER_SUPPORT
   CHECK_EQ(AddressOf(Debug_Address(Debug::k_register_address, 3)),
            decoder.Decode(make_code(DEBUG_ADDRESS, register_code(3))));
+#endif  // ENABLE_DEBUGGER_SUPPORT
   ExternalReference keyed_load_function =
       ExternalReference(&Counters::keyed_load_function_prototype);
   CHECK_EQ(keyed_load_function.address(),
@@ -164,10 +172,12 @@
            decoder.Decode(make_code(UNCLASSIFIED, 4)));
   CHECK_EQ(ExternalReference::address_of_real_stack_limit().address(),
            decoder.Decode(make_code(UNCLASSIFIED, 5)));
+#ifdef ENABLE_DEBUGGER_SUPPORT
   CHECK_EQ(ExternalReference::debug_break().address(),
-           decoder.Decode(make_code(UNCLASSIFIED, 12)));
+           decoder.Decode(make_code(UNCLASSIFIED, 15)));
+#endif  // ENABLE_DEBUGGER_SUPPORT
   CHECK_EQ(ExternalReference::new_space_start().address(),
-           decoder.Decode(make_code(UNCLASSIFIED, 7)));
+           decoder.Decode(make_code(UNCLASSIFIED, 10)));
 }
 
 
diff --git a/test/mjsunit/apply.js b/test/mjsunit/apply.js
index a4b0fd7..cab7eb8 100644
--- a/test/mjsunit/apply.js
+++ b/test/mjsunit/apply.js
@@ -112,12 +112,25 @@
   return arguments.length + arguments[arguments.length - 1];
 }
 
+var stack_corner_case_failure = false;
+
 for (var j = 1; j < 0x40000000; j <<= 1) {
   try {
     var a = new Array(j);
     a[j - 1] = 42;
     assertEquals(42 + j, al.apply(345, a));
   } catch (e) {
+    if (e.toString().indexOf("Maximum call stack size exceeded") != -1) {
+      // For some combinations of build settings, it may be the case that the
+      // stack here is just tall enough to contain the array whose size is
+      // specified by j but is not tall enough to contain the activation
+      // record for the apply call. Allow one such corner case through,
+      // checking that the length check will do the right thing for an array
+      // the next size up.
+      assertEquals(false, stack_corner_case_failure);
+      stack_corner_case_failure = true;
+      continue;
+    }
     assertTrue(e.toString().indexOf("Function.prototype.apply") != -1,
               "exception does not contain Function.prototype.apply: " +
                   e.toString());
@@ -127,7 +140,7 @@
         a = new Array(j);
         a[j - 1] = 42;
         al.apply(345, a);
-        assertUnreachable("Apply of arrray with length " + a.length +
+        assertUnreachable("Apply of array with length " + a.length +
                           " should have thrown");
       } catch (e) {
         assertTrue(e.toString().indexOf("Function.prototype.apply") != -1,
diff --git a/test/mjsunit/debug-setbreakpoint.js b/test/mjsunit/debug-setbreakpoint.js
index 3981dc4..9661c95 100644
--- a/test/mjsunit/debug-setbreakpoint.js
+++ b/test/mjsunit/debug-setbreakpoint.js
@@ -116,7 +116,7 @@
     mirror = debug.MakeMirror(o.a);
     testArguments(dcp, '{"type":"handle","target":' + mirror.handle() + '}', true, false);
 
-    testArguments(dcp, '{"type":"script","target":"sourceUrlScript","line":1}', true, true);
+    testArguments(dcp, '{"type":"script","target":"sourceUrlScript","line":0}', true, true);
 
     // Indicate that all was processed.
     listenerComplete = true;
@@ -134,6 +134,7 @@
 };
 
 function g() {
+  // Comment.
   f();
 };
 
@@ -184,3 +185,8 @@
 sourceUrlFunc();
 
 assertTrue(breakListenerCalled, "Break listener not called on breakpoint set by sourceURL");
+
+// Set a break point on a line with the comment, and check that actual position
+// is the next line after the comment.
+var number = Debug.setScriptBreakPointById(g_script_id, g_line + 1);
+assertEquals(g_line + 2, Debug.findBreakPoint(number).actual_location.line);
diff --git a/test/mjsunit/keyed-call-generic.js b/test/mjsunit/keyed-call-generic.js
index 0b49b3e..0314698 100644
--- a/test/mjsunit/keyed-call-generic.js
+++ b/test/mjsunit/keyed-call-generic.js
@@ -94,3 +94,20 @@
 testMany(dict_array, first3num, first3num);
 testMany(fast_prop, first3str, first3num);
 testMany(normal_prop, first3str, first3num);
+
+
+function testException(receiver, keys, exceptions) {
+  for (var i = 0; i != 10; i++) {
+    for (var k = 0; k != keys.length; k++) {
+      var thrown = false;
+      try {
+        var result = receiver[keys[k]]();
+      } catch (e) {
+        thrown = true;
+      }
+      assertEquals(exceptions[k], thrown);
+    }
+  }
+}
+
+testException([zero, one, /* hole */ ], [0, 1, 2], [false, false, true]);
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index 514d345..ceb5e62 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -34,9 +34,6 @@
 # too long to run in debug mode on ARM.
 fuzz-natives: PASS, SKIP if ($mode == release || $arch == arm)
 
-# Issue 494: new snapshot code breaks mjsunit/apply on mac debug snapshot.
-apply: PASS, FAIL if ($system == macos && $mode == debug)
-
 big-object-literal: PASS, SKIP if ($arch == arm)
 
 # Issue 488: this test sometimes times out.
diff --git a/test/mjsunit/object-define-property.js b/test/mjsunit/object-define-property.js
index 46bfb34..b258aa7 100644
--- a/test/mjsunit/object-define-property.js
+++ b/test/mjsunit/object-define-property.js
@@ -714,3 +714,156 @@
 } catch (e) {
   assertTrue(/Cannot redefine property/.test(e));
 }
+
+
+var obj6 = {};
+obj6[1] = 'foo';
+obj6[2] = 'bar';
+obj6[3] = '42';
+obj6[4] = '43';
+obj6[5] = '44';
+
+var descElement = { value: 'foobar' };
+var descElementNonConfigurable = { value: 'barfoo', configurable: false };
+var descElementNonWritable = { value: 'foofoo', writable: false };
+var descElementNonEnumerable = { value: 'barbar', enumerable: false };
+var descElementAllFalse = { value: 'foofalse', 
+                            configurable: false,
+                            writable: false,
+                            enumerable: false };
+
+
+// Redefine existing property.
+Object.defineProperty(obj6, '1', descElement);
+desc = Object.getOwnPropertyDescriptor(obj6, '1');
+assertEquals(desc.value, 'foobar');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(obj6, '2', descElementNonConfigurable);
+desc = Object.getOwnPropertyDescriptor(obj6, '2');
+assertEquals(desc.value, 'barfoo');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Ensure that we can't overwrite the non configurable element.
+try {
+  Object.defineProperty(obj6, '2', descElement);
+  assertUnreachable();
+} catch (e) {
+  assertTrue(/Cannot redefine property/.test(e));
+}
+
+Object.defineProperty(obj6, '3', descElementNonWritable);
+desc = Object.getOwnPropertyDescriptor(obj6, '3');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(obj6, '4', descElementNonEnumerable);
+desc = Object.getOwnPropertyDescriptor(obj6, '4');
+assertEquals(desc.value, 'barbar');
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(obj6, '5', descElementAllFalse);
+desc = Object.getOwnPropertyDescriptor(obj6, '5');
+assertEquals(desc.value, 'foofalse');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Define non existing property - all attributes should default to false.
+Object.defineProperty(obj6, '15', descElement);
+desc = Object.getOwnPropertyDescriptor(obj6, '15');
+assertEquals(desc.value, 'foobar');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Make sure that we can't redefine using direct access.
+obj6[15] ='overwrite';
+assertEquals(obj6[15],'foobar'); 
+
+
+// Repeat the above tests on an array.
+var arr = new Array();
+arr[1] = 'foo';
+arr[2] = 'bar';
+arr[3] = '42';
+arr[4] = '43';
+arr[5] = '44';
+
+var descElement = { value: 'foobar' };
+var descElementNonConfigurable = { value: 'barfoo', configurable: false };
+var descElementNonWritable = { value: 'foofoo', writable: false };
+var descElementNonEnumerable = { value: 'barbar', enumerable: false };
+var descElementAllFalse = { value: 'foofalse', 
+                            configurable: false,
+                            writable: false,
+                            enumerable: false };
+
+
+// Redefine existing property.
+Object.defineProperty(arr, '1', descElement);
+desc = Object.getOwnPropertyDescriptor(arr, '1');
+assertEquals(desc.value, 'foobar');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(arr, '2', descElementNonConfigurable);
+desc = Object.getOwnPropertyDescriptor(arr, '2');
+assertEquals(desc.value, 'barfoo');
+assertTrue(desc.writable);
+assertTrue(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Ensure that we can't overwrite the non configurable element.
+try {
+  Object.defineProperty(arr, '2', descElement);
+  assertUnreachable();
+} catch (e) {
+  assertTrue(/Cannot redefine property/.test(e));
+}
+
+Object.defineProperty(arr, '3', descElementNonWritable);
+desc = Object.getOwnPropertyDescriptor(arr, '3');
+assertEquals(desc.value, 'foofoo');
+assertFalse(desc.writable);
+assertTrue(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(arr, '4', descElementNonEnumerable);
+desc = Object.getOwnPropertyDescriptor(arr, '4');
+assertEquals(desc.value, 'barbar');
+assertTrue(desc.writable);
+assertFalse(desc.enumerable);
+assertTrue(desc.configurable);
+
+// Redefine existing property with configurable: false.
+Object.defineProperty(arr, '5', descElementAllFalse);
+desc = Object.getOwnPropertyDescriptor(arr, '5');
+assertEquals(desc.value, 'foofalse');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+// Define non existing property - all attributes should default to false.
+Object.defineProperty(arr, '15', descElement);
+desc = Object.getOwnPropertyDescriptor(arr, '15');
+assertEquals(desc.value, 'foobar');
+assertFalse(desc.writable);
+assertFalse(desc.enumerable);
+assertFalse(desc.configurable);
+
+
diff --git a/test/mjsunit/bugs/bug-619.js b/test/mjsunit/regress/regress-619.js
similarity index 92%
rename from test/mjsunit/bugs/bug-619.js
rename to test/mjsunit/regress/regress-619.js
index ef8ba80..24bdbc1 100644
--- a/test/mjsunit/bugs/bug-619.js
+++ b/test/mjsunit/regress/regress-619.js
@@ -25,9 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// When this bug is corrected move to object-define-property and add
-// additional tests for configurable in the same manner as existing tests
-// there.
+// Tests that Object.defineProperty works correctly on array indices. 
+// Please see http://code.google.com/p/v8/issues/detail?id=619 for details.
 
 var obj = {};
 obj[1] = 42;
diff --git a/test/mjsunit/bugs/bug-619.js b/test/mjsunit/regress/regress-747.js
similarity index 68%
copy from test/mjsunit/bugs/bug-619.js
copy to test/mjsunit/regress/regress-747.js
index ef8ba80..6fcc000 100644
--- a/test/mjsunit/bugs/bug-619.js
+++ b/test/mjsunit/regress/regress-747.js
@@ -25,38 +25,32 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// When this bug is corrected move to object-define-property and add
-// additional tests for configurable in the same manner as existing tests
-// there.
+// Flags: --expose_gc
 
-var obj = {};
-obj[1] = 42;
-assertEquals(42, obj[1]);
-Object.defineProperty(obj, '1', {value:10, writable:false});
-assertEquals(10, obj[1]);
+// This test makes sure that we do flush code with heap allocated locals.
+// This can be a problem if eval is used within the scope.
+// See: http://code.google.com/p/v8/issues/detail?id=747
 
-// We should not be able to override obj[1].
-obj[1] = 5;
-assertEquals(10, obj[1]);
+(function() {
+  var x = 42;
+  this.callEval = function() {eval('x');};
+})();
 
-// Try on a range of numbers.
-for(var i = 0; i < 1024; i++) {
-  obj[i] = 42;
-}
+try {
+  callEval();
+} catch (e) {
+  assertUnreachable();
+} 
 
-for(var i = 0; i < 1024; i++) {
-  Object.defineProperty(obj, i, {value: i, writable:false});
-}
+gc();
+gc();
+gc();
+gc();
+gc();
+gc();
 
-for(var i = 0; i < 1024; i++) {
-  assertEquals(i, obj[i]);
-}
-
-for(var i = 0; i < 1024; i++) {
-  obj[1] = 5;
-}
-
-for(var i = 0; i < 1024; i++) {
-  assertEquals(i, obj[i]);
-}
-
+try {
+  callEval();
+} catch (e) {
+  assertUnreachable();
+} 
diff --git a/test/mjsunit/samevalue.js b/test/mjsunit/samevalue.js
index 2de677e..6cb35e6 100644
--- a/test/mjsunit/samevalue.js
+++ b/test/mjsunit/samevalue.js
@@ -1,102 +1,102 @@
-// 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.

-

-

-// Flags: --expose-natives_as natives

-// Test the SameValue internal method.

-

-var obj1 = {x: 10, y: 11, z: "test"};

-var obj2 = {x: 10, y: 11, z: "test"};

-

-assertTrue(natives.SameValue(0, 0));

-assertTrue(natives.SameValue(+0, +0));

-assertTrue(natives.SameValue(-0, -0));

-assertTrue(natives.SameValue(1, 1));

-assertTrue(natives.SameValue(2, 2));

-assertTrue(natives.SameValue(-1, -1));

-assertTrue(natives.SameValue(0.5, 0.5));

-assertTrue(natives.SameValue(true, true));

-assertTrue(natives.SameValue(false, false));

-assertTrue(natives.SameValue(NaN, NaN));

-assertTrue(natives.SameValue(null, null));

-assertTrue(natives.SameValue("foo", "foo"));

-assertTrue(natives.SameValue(obj1, obj1));

-// Undefined values.

-assertTrue(natives.SameValue());

-assertTrue(natives.SameValue(undefined, undefined));

-

-assertFalse(natives.SameValue(0,1));

-assertFalse(natives.SameValue("foo", "bar"));

-assertFalse(natives.SameValue(obj1, obj2));

-assertFalse(natives.SameValue(true, false));

-

-assertFalse(natives.SameValue(obj1, true));

-assertFalse(natives.SameValue(obj1, "foo"));

-assertFalse(natives.SameValue(obj1, 1));

-assertFalse(natives.SameValue(obj1, undefined));

-assertFalse(natives.SameValue(obj1, NaN));

-

-assertFalse(natives.SameValue(undefined, true));

-assertFalse(natives.SameValue(undefined, "foo"));

-assertFalse(natives.SameValue(undefined, 1));

-assertFalse(natives.SameValue(undefined, obj1));

-assertFalse(natives.SameValue(undefined, NaN));

-

-assertFalse(natives.SameValue(NaN, true));

-assertFalse(natives.SameValue(NaN, "foo"));

-assertFalse(natives.SameValue(NaN, 1));

-assertFalse(natives.SameValue(NaN, obj1));

-assertFalse(natives.SameValue(NaN, undefined));

-

-assertFalse(natives.SameValue("foo", true));

-assertFalse(natives.SameValue("foo", 1));

-assertFalse(natives.SameValue("foo", obj1));

-assertFalse(natives.SameValue("foo", undefined));

-assertFalse(natives.SameValue("foo", NaN));

-

-assertFalse(natives.SameValue(true, 1));

-assertFalse(natives.SameValue(true, obj1));

-assertFalse(natives.SameValue(true, undefined));

-assertFalse(natives.SameValue(true, NaN));

-assertFalse(natives.SameValue(true, "foo"));

-

-assertFalse(natives.SameValue(1, true));

-assertFalse(natives.SameValue(1, obj1));

-assertFalse(natives.SameValue(1, undefined));

-assertFalse(natives.SameValue(1, NaN));

-assertFalse(natives.SameValue(1, "foo"));

-

-// Special string cases.

-assertFalse(natives.SameValue("1", 1));

-assertFalse(natives.SameValue("true", true));

-assertFalse(natives.SameValue("false", false));

-assertFalse(natives.SameValue("undefined", undefined));

-assertFalse(natives.SameValue("NaN", NaN));

-

-// -0 and +0 are should be different

-assertFalse(natives.SameValue(+0, -0));

-assertFalse(natives.SameValue(-0, +0));

+// 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.
+
+
+// Flags: --expose-natives_as natives
+// Test the SameValue internal method.
+
+var obj1 = {x: 10, y: 11, z: "test"};
+var obj2 = {x: 10, y: 11, z: "test"};
+
+assertTrue(natives.SameValue(0, 0));
+assertTrue(natives.SameValue(+0, +0));
+assertTrue(natives.SameValue(-0, -0));
+assertTrue(natives.SameValue(1, 1));
+assertTrue(natives.SameValue(2, 2));
+assertTrue(natives.SameValue(-1, -1));
+assertTrue(natives.SameValue(0.5, 0.5));
+assertTrue(natives.SameValue(true, true));
+assertTrue(natives.SameValue(false, false));
+assertTrue(natives.SameValue(NaN, NaN));
+assertTrue(natives.SameValue(null, null));
+assertTrue(natives.SameValue("foo", "foo"));
+assertTrue(natives.SameValue(obj1, obj1));
+// Undefined values.
+assertTrue(natives.SameValue());
+assertTrue(natives.SameValue(undefined, undefined));
+
+assertFalse(natives.SameValue(0,1));
+assertFalse(natives.SameValue("foo", "bar"));
+assertFalse(natives.SameValue(obj1, obj2));
+assertFalse(natives.SameValue(true, false));
+
+assertFalse(natives.SameValue(obj1, true));
+assertFalse(natives.SameValue(obj1, "foo"));
+assertFalse(natives.SameValue(obj1, 1));
+assertFalse(natives.SameValue(obj1, undefined));
+assertFalse(natives.SameValue(obj1, NaN));
+
+assertFalse(natives.SameValue(undefined, true));
+assertFalse(natives.SameValue(undefined, "foo"));
+assertFalse(natives.SameValue(undefined, 1));
+assertFalse(natives.SameValue(undefined, obj1));
+assertFalse(natives.SameValue(undefined, NaN));
+
+assertFalse(natives.SameValue(NaN, true));
+assertFalse(natives.SameValue(NaN, "foo"));
+assertFalse(natives.SameValue(NaN, 1));
+assertFalse(natives.SameValue(NaN, obj1));
+assertFalse(natives.SameValue(NaN, undefined));
+
+assertFalse(natives.SameValue("foo", true));
+assertFalse(natives.SameValue("foo", 1));
+assertFalse(natives.SameValue("foo", obj1));
+assertFalse(natives.SameValue("foo", undefined));
+assertFalse(natives.SameValue("foo", NaN));
+
+assertFalse(natives.SameValue(true, 1));
+assertFalse(natives.SameValue(true, obj1));
+assertFalse(natives.SameValue(true, undefined));
+assertFalse(natives.SameValue(true, NaN));
+assertFalse(natives.SameValue(true, "foo"));
+
+assertFalse(natives.SameValue(1, true));
+assertFalse(natives.SameValue(1, obj1));
+assertFalse(natives.SameValue(1, undefined));
+assertFalse(natives.SameValue(1, NaN));
+assertFalse(natives.SameValue(1, "foo"));
+
+// Special string cases.
+assertFalse(natives.SameValue("1", 1));
+assertFalse(natives.SameValue("true", true));
+assertFalse(natives.SameValue("false", false));
+assertFalse(natives.SameValue("undefined", undefined));
+assertFalse(natives.SameValue("NaN", NaN));
+
+// -0 and +0 are should be different
+assertFalse(natives.SameValue(+0, -0));
+assertFalse(natives.SameValue(-0, +0));
diff --git a/test/mjsunit/string-externalize.js b/test/mjsunit/string-externalize.js
new file mode 100644
index 0000000..5b1f917
--- /dev/null
+++ b/test/mjsunit/string-externalize.js
@@ -0,0 +1,95 @@
+// 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.
+
+// Flags: --expose-externalize-string
+
+var size = 1024;
+
+function test() {
+  var str = "";
+
+  // Build an ascii cons string.
+  for (var i = 0; i < size; i++) {
+      str += String.fromCharCode(i & 0x7f);
+  }
+  assertTrue(isAsciiString(str));
+
+  var twoByteExternalWithAsciiData =
+      "AA" + (function() { return "A"; })();
+  externalizeString(twoByteExternalWithAsciiData, true /* force two-byte */);
+  assertFalse(isAsciiString(twoByteExternalWithAsciiData));
+
+  var realTwoByteExternalString =
+      "\u1234\u1234" + (function() { return "\u1234"; })();
+  externalizeString(realTwoByteExternalString);
+  assertFalse(isAsciiString(realTwoByteExternalString));
+
+  assertTrue(isAsciiString(["a", twoByteExternalWithAsciiData].join("")));
+
+  // Appending a two-byte string that contains only ascii chars should
+  // still produce an ascii cons.
+  var str1 = str + twoByteExternalWithAsciiData;
+  assertTrue(isAsciiString(str1));
+
+  // Force flattening of the string.
+  var old_length = str1.length - twoByteExternalWithAsciiData.length;
+  for (var i = 0; i < old_length; i++) {
+    assertEquals(String.fromCharCode(i & 0x7f), str1[i]);
+  }
+  for (var i = old_length; i < str1.length; i++) {
+    assertEquals("A", str1[i]);
+  }
+
+  // Flattened string should still be ascii.
+  assertTrue(isAsciiString(str1));
+
+  // Lower-casing an ascii string should produce ascii.
+  assertTrue(isAsciiString(str1.toLowerCase()));
+
+  assertFalse(isAsciiString(["a", realTwoByteExternalString].join("")));
+
+  // Appending a real two-byte string should produce a two-byte cons.
+  var str2 = str + realTwoByteExternalString;
+  assertFalse(isAsciiString(str2));
+
+  // Force flattening of the string.
+  old_length = str2.length - realTwoByteExternalString.length;
+  for (var i = 0; i < old_length; i++) {
+    assertEquals(String.fromCharCode(i & 0x7f), str2[i]);
+  }
+  for (var i = old_length; i < str.length; i++) {
+    assertEquals("\u1234", str2[i]);
+  }
+
+  // Flattened string should still be two-byte.
+  assertFalse(isAsciiString(str2));
+}
+
+// Run the test many times to ensure IC-s don't break things.
+for (var i = 0; i < 10; i++) {
+  test();
+}