Version 3.4.13

Improved debugger support to allow inspection of optimized frames (issue 1140).

Fixed a bug in prototype transitions cache clearing introduced by r8165.

Fixed shortcutting bug in HInferRepresentation. Patch by Andy Wingo.

Fixed a memory leak in sample/shell.cc (dispose semaphores).

Simplified HClampToUint8. Patch by Andy Wingo.

Exposed APIs for detecting boxed primitives, native errors. Patch by Luke Zarko.

Added map check for COW elements to crankshaft array handling code (issue 1560).

Sample shell and (a light version of) D8 links against a shared library now.

Fixed bug in array filter and reduce functions (issue 1559).

Avoid TLS load in AstNode constructor.

Introduced a random entropy source which can optionally be provided at initialization. (Chromium issue 89462).


git-svn-id: http://v8.googlecode.com/svn/trunk@8669 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 7e7df06..5c4b0a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2011-07-18: Version 3.4.13
+
+        Improved debugger support to allow inspection of optimized frames (issue
+        1140).
+
+        Fixed a bug in prototype transitions cache clearing introduced by r8165.
+
+        Fixed shortcutting bug in HInferRepresentation. Patch by Andy Wingo.
+
+        Fixed a memory leak in sample/shell.cc (dispose semaphores).
+
+        Simplified HClampToUint8. Patch by Andy Wingo.
+
+        Exposed APIs for detecting boxed primitives, native errors. Patch by
+        Luke Zarko.
+
+        Added map check for COW elements to crankshaft array handling code
+        (issue 1560).
+
+        Sample shell and (a light version of) D8 links against a shared library
+        now.
+
+        Fixed bug in array filter and reduce functions (issue 1559).
+
+        Avoid TLS load in AstNode constructor.
+
+        Introduced a random entropy source which can optionally be provided at
+        initialization. (Chromium issue 89462).
+
+
 2011-07-13: Version 3.4.12
 
         Added --prof profiling option to d8 shell.
diff --git a/SConstruct b/SConstruct
index 5276ce2..03a615c 100644
--- a/SConstruct
+++ b/SConstruct
@@ -773,6 +773,13 @@
 
 
 D8_FLAGS = {
+  'all': {
+    'library:shared': {
+      'CPPDEFINES': ['V8_SHARED'],
+      'LIBS': ['v8'],
+      'LIBPATH': ['.']
+    },
+  },
   'gcc': {
     'all': {
       'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
@@ -1370,7 +1377,11 @@
   d8_env = Environment(tools=tools)
   d8_env.Replace(**context.flags['d8'])
   context.ApplyEnvOverrides(d8_env)
-  shell = d8_env.Program('d8' + suffix, object_files + shell_files)
+  if context.options['library'] == 'static':
+    shell = d8_env.Program('d8' + suffix, object_files + shell_files)
+  else:
+    shell = d8_env.Program('d8' + suffix, shell_files)
+    d8_env.Depends(shell, library)
   context.d8_targets.append(shell)
 
   for sample in context.samples:
diff --git a/build/all.gyp b/build/all.gyp
index 544e2c2..38287e3 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -9,9 +9,15 @@
       'type': 'none',
       'dependencies': [
         '../samples/samples.gyp:*',
-        '../test/cctest/cctest.gyp:*',
-        '../src/d8.gyp:*',
-      ]
+        '../src/d8.gyp:d8',
+      ],
+      'conditions': [
+        [ 'component!="shared_library"', {
+          'dependencies': [
+            '../test/cctest/cctest.gyp:*',
+          ],
+        }]
+      ],
     }
   ]
 }
diff --git a/include/v8.h b/include/v8.h
index 0872411..ac26061 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -80,9 +80,11 @@
 
 class Context;
 class String;
+class StringObject;
 class Value;
 class Utils;
 class Number;
+class NumberObject;
 class Object;
 class Array;
 class Int32;
@@ -90,6 +92,7 @@
 class External;
 class Primitive;
 class Boolean;
+class BooleanObject;
 class Integer;
 class Function;
 class Date;
@@ -929,6 +932,26 @@
   V8EXPORT bool IsDate() const;
 
   /**
+   * Returns true if this value is a Boolean object.
+   */
+  V8EXPORT bool IsBooleanObject() const;
+
+  /**
+   * Returns true if this value is a Number object.
+   */
+  V8EXPORT bool IsNumberObject() const;
+
+  /**
+   * Returns true if this value is a String object.
+   */
+  V8EXPORT bool IsStringObject() const;
+
+  /**
+   * Returns true if this value is a NativeError.
+   */
+  V8EXPORT bool IsNativeError() const;
+
+  /**
    * Returns true if this value is a RegExp.
    */
   V8EXPORT bool IsRegExp() const;
@@ -1745,6 +1768,63 @@
 
 
 /**
+ * A Number object (ECMA-262, 4.3.21).
+ */
+class NumberObject : public Object {
+ public:
+  V8EXPORT static Local<Value> New(double value);
+
+  /**
+   * Returns the Number held by the object.
+   */
+  V8EXPORT double NumberValue() const;
+
+  static inline NumberObject* Cast(v8::Value* obj);
+
+ private:
+  V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
+ * A Boolean object (ECMA-262, 4.3.15).
+ */
+class BooleanObject : public Object {
+ public:
+  V8EXPORT static Local<Value> New(bool value);
+
+  /**
+   * Returns the Boolean held by the object.
+   */
+  V8EXPORT bool BooleanValue() const;
+
+  static inline BooleanObject* Cast(v8::Value* obj);
+
+ private:
+  V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
+ * A String object (ECMA-262, 4.3.18).
+ */
+class StringObject : public Object {
+ public:
+  V8EXPORT static Local<Value> New(Handle<String> value);
+
+  /**
+   * Returns the String held by the object.
+   */
+  V8EXPORT Local<String> StringValue() const;
+
+  static inline StringObject* Cast(v8::Value* obj);
+
+ private:
+  V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
  * An instance of the built-in RegExp constructor (ECMA-262, 15.10).
  */
 class RegExp : public Object {
@@ -2721,6 +2801,13 @@
   char** raw_data;
 };
 
+
+/**
+ * EntropySource is used as a callback function when v8 needs a source
+ * of entropy.
+ */
+typedef bool (*EntropySource)(unsigned char* buffer, size_t length);
+
 /**
  * Container class for static utility functions.
  */
@@ -2946,6 +3033,12 @@
   static bool Initialize();
 
   /**
+   * Allows the host application to provide a callback which can be used
+   * as a source of entropy for random number generators.
+   */
+  static void SetEntropySource(EntropySource source);
+
+  /**
    * Adjusts the amount of registered external memory.  Used to give
    * V8 an indication of the amount of externally allocated memory
    * that is kept alive by JavaScript objects.  V8 uses this to decide
@@ -4010,6 +4103,30 @@
 }
 
 
+StringObject* StringObject::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<StringObject*>(value);
+}
+
+
+NumberObject* NumberObject::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<NumberObject*>(value);
+}
+
+
+BooleanObject* BooleanObject::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+  CheckCast(value);
+#endif
+  return static_cast<BooleanObject*>(value);
+}
+
+
 RegExp* RegExp::Cast(v8::Value* value) {
 #ifdef V8_ENABLE_CHECKS
   CheckCast(value);
diff --git a/preparser/preparser-process.cc b/preparser/preparser-process.cc
index d7c96f0..e67851c 100644
--- a/preparser/preparser-process.cc
+++ b/preparser/preparser-process.cc
@@ -208,7 +208,7 @@
     fflush(stderr);
   }
   exit(EXIT_FAILURE);
-};
+}
 
 
 bool IsFlag(const char* arg) {
diff --git a/samples/shell.cc b/samples/shell.cc
index 7c30bec..f37e731 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -95,6 +95,13 @@
                   begin_offset_(0),
                   end_offset_(0) { }
 
+#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
+  ~SourceGroup() {
+    delete next_semaphore_;
+    delete done_semaphore_;
+  }
+#endif  // USING_V8_SHARED
+
   void Begin(char** argv, int offset) {
     argv_ = const_cast<const char**>(argv);
     begin_offset_ = offset;
diff --git a/src/SConscript b/src/SConscript
index 6b3059a..b45a567 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -243,7 +243,14 @@
 }
 
 
-D8_FILES = {
+D8_LIGHT_FILES = {
+  'all': [
+    'd8.cc'
+  ]
+}
+
+
+D8_FULL_FILES = {
   'all': [
     'd8.cc', 'd8-debug.cc'
   ],
@@ -323,11 +330,15 @@
 
   # Build the standard platform-independent source files.
   source_files = context.GetRelevantSources(SOURCES)
-
-  d8_files = context.GetRelevantSources(D8_FILES)
   d8_js = env.JS2C('d8-js.cc', 'd8.js', **{'TYPE': 'D8', 'COMPRESSION': 'off'})
   d8_js_obj = context.ConfigureObject(env, d8_js, CPPPATH=['.'])
-  d8_objs = [context.ConfigureObject(env, [d8_files]), d8_js_obj]
+  if context.options['library'] == 'shared':
+    d8_files = context.GetRelevantSources(D8_LIGHT_FILES)
+    d8_objs = []
+  else:
+    d8_files = context.GetRelevantSources(D8_FULL_FILES)
+    d8_objs = [d8_js_obj]
+  d8_objs.append(context.ConfigureObject(env, [d8_files]))
 
   # Combine the JavaScript library files into a single C++ file and
   # compile it.
diff --git a/src/api.cc b/src/api.cc
index dc1f90c..fca7fbf 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2167,6 +2167,65 @@
 }
 
 
+bool Value::IsStringObject() const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::IsStringObject()")) return false;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->HasSpecificClassOf(isolate->heap()->String_symbol());
+}
+
+
+bool Value::IsNumberObject() const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::IsNumberObject()")) return false;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->HasSpecificClassOf(isolate->heap()->Number_symbol());
+}
+
+
+static i::Object* LookupBuiltin(i::Isolate* isolate,
+                                const char* builtin_name) {
+  i::Handle<i::String> symbol =
+      isolate->factory()->LookupAsciiSymbol(builtin_name);
+  i::Handle<i::JSBuiltinsObject> builtins = isolate->js_builtins_object();
+  return builtins->GetPropertyNoExceptionThrown(*symbol);
+}
+
+
+static bool CheckConstructor(i::Isolate* isolate,
+                             i::Handle<i::JSObject> obj,
+                             const char* class_name) {
+  return obj->map()->constructor() == LookupBuiltin(isolate, class_name);
+}
+
+
+bool Value::IsNativeError() const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::IsNativeError()")) return false;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  if (obj->IsJSObject()) {
+    i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
+    return CheckConstructor(isolate, js_obj, "$Error") ||
+        CheckConstructor(isolate, js_obj, "$EvalError") ||
+        CheckConstructor(isolate, js_obj, "$RangeError") ||
+        CheckConstructor(isolate, js_obj, "$ReferenceError") ||
+        CheckConstructor(isolate, js_obj, "$SyntaxError") ||
+        CheckConstructor(isolate, js_obj, "$TypeError") ||
+        CheckConstructor(isolate, js_obj, "$URIError");
+  } else {
+    return false;
+  }
+}
+
+
+bool Value::IsBooleanObject() const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::Value::IsBooleanObject()")) return false;
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  return obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol());
+}
+
+
 bool Value::IsRegExp() const {
   if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsRegExp()")) return false;
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
@@ -2362,6 +2421,36 @@
 }
 
 
+void v8::StringObject::CheckCast(v8::Value* that) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::StringObject::Cast()")) return;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_symbol()),
+           "v8::StringObject::Cast()",
+           "Could not convert to StringObject");
+}
+
+
+void v8::NumberObject::CheckCast(v8::Value* that) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::NumberObject::Cast()")) return;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_symbol()),
+           "v8::NumberObject::Cast()",
+           "Could not convert to NumberObject");
+}
+
+
+void v8::BooleanObject::CheckCast(v8::Value* that) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::BooleanObject::Cast()")) return;
+  i::Handle<i::Object> obj = Utils::OpenHandle(that);
+  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol()),
+           "v8::BooleanObject::Cast()",
+           "Could not convert to BooleanObject");
+}
+
+
 void v8::RegExp::CheckCast(v8::Value* that) {
   if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::Cast()")) return;
   i::Handle<i::Object> obj = Utils::OpenHandle(that);
@@ -3844,6 +3933,11 @@
 }
 
 
+void v8::V8::SetEntropySource(EntropySource source) {
+  i::V8::SetEntropySource(source);
+}
+
+
 bool v8::V8::Dispose() {
   i::Isolate* isolate = i::Isolate::Current();
   if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
@@ -4427,6 +4521,73 @@
 }
 
 
+Local<v8::Value> v8::NumberObject::New(double value) {
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::NumberObject::New()");
+  LOG_API(isolate, "NumberObject::New");
+  ENTER_V8(isolate);
+  i::Handle<i::Object> number = isolate->factory()->NewNumber(value);
+  i::Handle<i::Object> obj = isolate->factory()->ToObject(number);
+  return Utils::ToLocal(obj);
+}
+
+
+double v8::NumberObject::NumberValue() const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::NumberObject::NumberValue()")) return 0;
+  LOG_API(isolate, "NumberObject::NumberValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+  return jsvalue->value()->Number();
+}
+
+
+Local<v8::Value> v8::BooleanObject::New(bool value) {
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()");
+  LOG_API(isolate, "BooleanObject::New");
+  ENTER_V8(isolate);
+  i::Handle<i::Object> boolean(value ? isolate->heap()->true_value()
+                                     : isolate->heap()->false_value());
+  i::Handle<i::Object> obj = isolate->factory()->ToObject(boolean);
+  return Utils::ToLocal(obj);
+}
+
+
+bool v8::BooleanObject::BooleanValue() const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::BooleanObject::BooleanValue()")) return 0;
+  LOG_API(isolate, "BooleanObject::BooleanValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+  return jsvalue->value()->IsTrue();
+}
+
+
+Local<v8::Value> v8::StringObject::New(Handle<String> value) {
+  i::Isolate* isolate = i::Isolate::Current();
+  EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
+  LOG_API(isolate, "StringObject::New");
+  ENTER_V8(isolate);
+  i::Handle<i::Object> obj =
+      isolate->factory()->ToObject(Utils::OpenHandle(*value));
+  return Utils::ToLocal(obj);
+}
+
+
+Local<v8::String> v8::StringObject::StringValue() const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::StringObject::StringValue()")) {
+    return Local<v8::String>();
+  }
+  LOG_API(isolate, "StringObject::StringValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
+  return Utils::ToLocal(
+      i::Handle<i::String>(i::String::cast(jsvalue->value())));
+}
+
+
 Local<v8::Value> v8::Date::New(double time) {
   i::Isolate* isolate = i::Isolate::Current();
   EnsureInitializedForIsolate(isolate, "v8::Date::New()");
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 320879a..1a995e9 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -2548,6 +2548,9 @@
     LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
     cmp(elements, ip);
     b(eq, &ok);
+    LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex);
+    cmp(elements, ip);
+    b(eq, &ok);
     LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
     cmp(elements, ip);
     b(eq, &ok);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 86e4971..c2665f8 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -4168,6 +4168,77 @@
 }
 
 
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+    MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- r0    : key
+  //  -- r1    : receiver
+  // -----------------------------------
+  Label miss_force_generic, slow_allocate_heapnumber;
+
+  Register key_reg = r0;
+  Register receiver_reg = r1;
+  Register elements_reg = r2;
+  Register heap_number_reg = r2;
+  Register indexed_double_offset = r3;
+  Register scratch = r4;
+  Register scratch2 = r5;
+  Register scratch3 = r6;
+  Register heap_number_map = r7;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(key_reg, &miss_force_generic);
+
+  // Get the elements array.
+  __ ldr(elements_reg,
+         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+  // Check that the key is within bounds.
+  __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+  __ cmp(key_reg, Operand(scratch));
+  __ b(hs, &miss_force_generic);
+
+  // Load the upper word of the double in the fixed array and test for NaN.
+  __ add(indexed_double_offset, elements_reg,
+         Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
+  uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
+  __ ldr(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
+  __ cmp(scratch, Operand(kHoleNanUpper32));
+  __ b(&miss_force_generic, eq);
+
+  // Non-NaN. Allocate a new heap number and copy the double value into it.
+  __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+  __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
+                        heap_number_map, &slow_allocate_heapnumber);
+
+  // Don't need to reload the upper 32 bits of the double, it's already in
+  // scratch.
+  __ str(scratch, FieldMemOperand(heap_number_reg,
+                                  HeapNumber::kExponentOffset));
+  __ ldr(scratch, FieldMemOperand(indexed_double_offset,
+                                  FixedArray::kHeaderSize));
+  __ str(scratch, FieldMemOperand(heap_number_reg,
+                                  HeapNumber::kMantissaOffset));
+
+  __ mov(r0, heap_number_reg);
+  __ Ret();
+
+  __ bind(&slow_allocate_heapnumber);
+  Handle<Code> slow_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_Slow();
+  __ Jump(slow_ic, RelocInfo::CODE_TARGET);
+
+  __ bind(&miss_force_generic);
+  Handle<Code> miss_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+  __ Jump(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
                                                       bool is_js_array) {
   // ----------- S t a t e -------------
@@ -4231,6 +4302,125 @@
 }
 
 
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+    MacroAssembler* masm,
+    bool is_js_array) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r1    : key
+  //  -- r2    : receiver
+  //  -- lr    : return address
+  //  -- r3    : scratch
+  //  -- r4    : scratch
+  //  -- r5    : scratch
+  // -----------------------------------
+  Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value;
+
+  Register value_reg = r0;
+  Register key_reg = r1;
+  Register receiver_reg = r2;
+  Register scratch = r3;
+  Register elements_reg = r4;
+  Register mantissa_reg = r5;
+  Register exponent_reg = r6;
+  Register scratch4 = r7;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+  __ JumpIfNotSmi(key_reg, &miss_force_generic);
+
+  __ ldr(elements_reg,
+         FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
+
+  // Check that the key is within bounds.
+  if (is_js_array) {
+    __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+  } else {
+    __ ldr(scratch,
+           FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
+  }
+  // Compare smis, unsigned compare catches both negative and out-of-bound
+  // indexes.
+  __ cmp(key_reg, scratch);
+  __ b(hs, &miss_force_generic);
+
+  // Handle smi values specially.
+  __ JumpIfSmi(value_reg, &smi_value);
+
+  // Ensure that the object is a heap number
+  __ CheckMap(value_reg,
+              scratch,
+              masm->isolate()->factory()->heap_number_map(),
+              &miss_force_generic,
+              DONT_DO_SMI_CHECK);
+
+  // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
+  // in the exponent.
+  __ mov(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
+  __ ldr(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
+  __ cmp(exponent_reg, scratch);
+  __ b(ge, &maybe_nan);
+
+  __ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+
+  __ bind(&have_double_value);
+  __ add(scratch, elements_reg,
+         Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
+  __ str(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize));
+  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+  __ str(exponent_reg, FieldMemOperand(scratch, offset));
+  __ Ret();
+
+  __ bind(&maybe_nan);
+  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+  // it's an Infinity, and the non-NaN code path applies.
+  __ b(gt, &is_nan);
+  __ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
+  __ cmp(mantissa_reg, Operand(0));
+  __ b(eq, &have_double_value);
+  __ bind(&is_nan);
+  // Load canonical NaN for storing into the double array.
+  uint64_t nan_int64 = BitCast<uint64_t>(
+      FixedDoubleArray::canonical_not_the_hole_nan_as_double());
+  __ mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
+  __ mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
+  __ jmp(&have_double_value);
+
+  __ bind(&smi_value);
+  __ add(scratch, elements_reg,
+         Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
+  __ add(scratch, scratch,
+         Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
+  // scratch is now effective address of the double element
+
+  FloatingPointHelper::Destination destination;
+  if (CpuFeatures::IsSupported(VFP3)) {
+    destination = FloatingPointHelper::kVFPRegisters;
+  } else {
+    destination = FloatingPointHelper::kCoreRegisters;
+  }
+  __ SmiUntag(value_reg, value_reg);
+  FloatingPointHelper::ConvertIntToDouble(
+      masm, value_reg, destination,
+      d0, mantissa_reg, exponent_reg,  // These are: double_dst, dst1, dst2.
+      scratch4, s2);  // These are: scratch2, single_scratch.
+  if (destination == FloatingPointHelper::kVFPRegisters) {
+    CpuFeatures::Scope scope(VFP3);
+    __ vstr(d0, scratch, 0);
+  } else {
+    __ str(mantissa_reg, MemOperand(scratch, 0));
+    __ str(exponent_reg, MemOperand(scratch, Register::kSizeInBytes));
+  }
+  __ Ret();
+
+  // Handle store cache miss, replacing the ic with the generic stub.
+  __ bind(&miss_force_generic);
+  Handle<Code> ic =
+      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/array.js b/src/array.js
index 60cf3f0..e6c13d9 100644
--- a/src/array.js
+++ b/src/array.js
@@ -999,7 +999,7 @@
   }
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping.
-  var length = this.length;
+  var length = ToUint32(this.length);
   var result = [];
   var result_length = 0;
   for (var i = 0; i < length; i++) {
@@ -1236,7 +1236,7 @@
   }
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping.
-  var length = this.length;
+  var length = ToUint32(this.length);
   var i = 0;
 
   find_initial: if (%_ArgumentsLength() < 2) {
@@ -1268,7 +1268,7 @@
   if (!IS_FUNCTION(callback)) {
     throw MakeTypeError('called_non_callable', [callback]);
   }
-  var i = this.length - 1;
+  var i = ToUint32(this.length) - 1;
 
   find_initial: if (%_ArgumentsLength() < 2) {
     for (; i >= 0; i--) {
diff --git a/src/assembler.cc b/src/assembler.cc
index 3c7fc1c..fbd8089 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 1994-2006 Sun Microsystems Inc.
+// Copyright (c) 2011 Sun Microsystems Inc.
 // All Rights Reserved.
 //
 // Redistribution and use in source and binary forms, with or without
@@ -71,7 +71,8 @@
 const double DoubleConstant::minus_zero = -0.0;
 const double DoubleConstant::uint8_max_value = 255;
 const double DoubleConstant::zero = 0.0;
-const double DoubleConstant::nan = OS::nan_value();
+const double DoubleConstant::canonical_non_hole_nan = OS::nan_value();
+const double DoubleConstant::the_hole_nan = BitCast<double>(kHoleNanInt64);
 const double DoubleConstant::negative_infinity = -V8_INFINITY;
 const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
 
@@ -921,9 +922,15 @@
 }
 
 
-ExternalReference ExternalReference::address_of_nan() {
+ExternalReference ExternalReference::address_of_canonical_non_hole_nan() {
   return ExternalReference(reinterpret_cast<void*>(
-      const_cast<double*>(&DoubleConstant::nan)));
+      const_cast<double*>(&DoubleConstant::canonical_non_hole_nan)));
+}
+
+
+ExternalReference ExternalReference::address_of_the_hole_nan() {
+  return ExternalReference(reinterpret_cast<void*>(
+      const_cast<double*>(&DoubleConstant::the_hole_nan)));
 }
 
 
diff --git a/src/assembler.h b/src/assembler.h
index bced11f..2d14f06 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -70,7 +70,8 @@
   static const double zero;
   static const double uint8_max_value;
   static const double negative_infinity;
-  static const double nan;
+  static const double canonical_non_hole_nan;
+  static const double the_hole_nan;
 };
 
 
@@ -629,7 +630,8 @@
   static ExternalReference address_of_zero();
   static ExternalReference address_of_uint8_max_value();
   static ExternalReference address_of_negative_infinity();
-  static ExternalReference address_of_nan();
+  static ExternalReference address_of_canonical_non_hole_nan();
+  static ExternalReference address_of_the_hole_nan();
 
   static ExternalReference math_sin_double_function(Isolate* isolate);
   static ExternalReference math_cos_double_function(Isolate* isolate);
diff --git a/src/ast.cc b/src/ast.cc
index 8b6cdce..9f8a6ee 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -138,7 +138,7 @@
   ASSERT(Token::IsAssignmentOp(op));
   if (is_compound()) {
     binary_operation_ =
-        new BinaryOperation(binary_op(), target, value, pos + 1);
+        new(ZONE) BinaryOperation(binary_op(), target, value, pos + 1);
     compound_load_id_ = GetNextId();
   }
 }
@@ -187,7 +187,7 @@
 
 ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
   emit_store_ = true;
-  key_ = new Literal(value->name());
+  key_ = new(ZONE) Literal(value->name());
   value_ = value;
   kind_ = is_getter ? GETTER : SETTER;
 }
diff --git a/src/ast.h b/src/ast.h
index 27d82cb..b92f2db 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -134,11 +134,15 @@
   static const int kNoNumber = -1;
   static const int kFunctionEntryId = 2;  // Using 0 could disguise errors.
 
-  AstNode() {
-    Isolate* isolate = Isolate::Current();
+  // Override ZoneObject's new to count allocated AST nodes.
+  void* operator new(size_t size, Zone* zone) {
+    Isolate* isolate = zone->isolate();
     isolate->set_ast_node_count(isolate->ast_node_count() + 1);
+    return zone->New(static_cast<int>(size));
   }
 
+  AstNode() {}
+
   virtual ~AstNode() { }
 
   virtual void Accept(AstVisitor* v) = 0;
@@ -173,6 +177,11 @@
     return tmp;
   }
 
+ private:
+  // Hidden to prevent accidental usage. It would have to load the
+  // current zone from the TLS.
+  void* operator new(size_t size);
+
   friend class CaseClause;  // Generates AST IDs.
 };
 
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 5c0ef5a..1d1128f 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -250,7 +250,7 @@
       KeyedLoadStubCompiler::GenerateLoadFastElement(masm);
       break;
     case JSObject::FAST_DOUBLE_ELEMENTS:
-      UNIMPLEMENTED();
+      KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(masm);
       break;
     case JSObject::EXTERNAL_BYTE_ELEMENTS:
     case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
@@ -279,7 +279,8 @@
       KeyedStoreStubCompiler::GenerateStoreFastElement(masm, is_js_array_);
       break;
     case JSObject::FAST_DOUBLE_ELEMENTS:
-      UNIMPLEMENTED();
+      KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
+                                                             is_js_array_);
       break;
     case JSObject::EXTERNAL_BYTE_ELEMENTS:
     case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
diff --git a/src/d8.cc b/src/d8.cc
index 5f57350..64c0d1f 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -26,33 +26,49 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
+#ifdef V8_SHARED
+#define USING_V8_SHARED
+#endif
+
 #ifdef COMPRESS_STARTUP_DATA_BZ2
 #include <bzlib.h>
 #endif
+
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
 
-#include "v8.h"
+#ifdef USING_V8_SHARED
+#include <assert.h>
+#include "../include/v8-testing.h"
+#endif  // USING_V8_SHARED
 
 #include "d8.h"
+
+#ifndef USING_V8_SHARED
+#include "api.h"
+#include "checks.h"
 #include "d8-debug.h"
 #include "debug.h"
-#include "api.h"
 #include "natives.h"
 #include "platform.h"
+#include "v8.h"
+#endif  // USING_V8_SHARED
 
 #if !defined(_WIN32) && !defined(_WIN64)
 #include <unistd.h>  // NOLINT
 #endif
 
+#ifdef USING_V8_SHARED
+#define ASSERT(condition) assert(condition)
+#endif  // USING_V8_SHARED
+
 namespace v8 {
 
 
-const char* Shell::kHistoryFileName = ".d8_history";
-const char* Shell::kPrompt = "d8> ";
-
-
+#ifndef USING_V8_SHARED
 LineEditor *LineEditor::first_ = NULL;
+const char* Shell::kHistoryFileName = ".d8_history";
 
 
 LineEditor::LineEditor(Type type, const char* name)
@@ -98,17 +114,22 @@
 i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
 CounterCollection Shell::local_counters_;
 CounterCollection* Shell::counters_ = &local_counters_;
-Persistent<Context> Shell::utility_context_;
-Persistent<Context> Shell::evaluation_context_;
 i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
+Persistent<Context> Shell::utility_context_;
+#endif  // USING_V8_SHARED
+
+Persistent<Context> Shell::evaluation_context_;
 ShellOptions Shell::options;
+const char* Shell::kPrompt = "d8> ";
 
 
+#ifndef USING_V8_SHARED
 bool CounterMap::Match(void* key1, void* key2) {
   const char* name1 = reinterpret_cast<const char*>(key1);
   const char* name2 = reinterpret_cast<const char*>(key2);
   return strcmp(name1, name2) == 0;
 }
+#endif  // USING_V8_SHARED
 
 
 // Converts a V8 value to a C string.
@@ -122,17 +143,22 @@
                           Handle<Value> name,
                           bool print_result,
                           bool report_exceptions) {
+#ifndef USING_V8_SHARED
+  bool FLAG_debugger = i::FLAG_debugger;
+#else
+  bool FLAG_debugger = false;
+#endif  // USING_V8_SHARED
   HandleScope handle_scope;
   TryCatch try_catch;
   options.script_executed = true;
-  if (i::FLAG_debugger) {
+  if (FLAG_debugger) {
     // When debugging make exceptions appear to be uncaught.
     try_catch.SetVerbose(true);
   }
   Handle<Script> script = Script::Compile(source, name);
   if (script.IsEmpty()) {
     // Print errors that happened during compilation.
-    if (report_exceptions && !i::FLAG_debugger)
+    if (report_exceptions && !FLAG_debugger)
       ReportException(&try_catch);
     return false;
   } else {
@@ -140,7 +166,7 @@
     if (result.IsEmpty()) {
       ASSERT(try_catch.HasCaught());
       // Print errors that happened during execution.
-      if (report_exceptions && !i::FLAG_debugger)
+      if (report_exceptions && !FLAG_debugger)
         ReportException(&try_catch);
       return false;
     } else {
@@ -196,15 +222,20 @@
 
 
 Handle<Value> Shell::ReadLine(const Arguments& args) {
-  i::SmartPointer<char> line(i::ReadLine(""));
-  if (*line == NULL) {
-    return Null();
-  }
-  size_t len = strlen(*line);
-  if (len > 0 && line[len - 1] == '\n') {
-    --len;
-  }
-  return String::New(*line, len);
+  static const int kBufferSize = 256;
+  char buffer[kBufferSize];
+  Handle<String> accumulator = String::New("");
+  bool linebreak;
+  int length;
+  do {  // Repeat if the line ends with an escape '\'.
+    // fgets got an error. Just give up.
+    if (fgets(buffer, kBufferSize, stdin) == NULL) return Null();
+    length = strlen(buffer);
+    linebreak = (length > 1 && buffer[length-2] == '\\');
+    if (linebreak) buffer[length-2] = '\n';
+    accumulator = String::Concat(accumulator, String::New(buffer, length-1));
+  } while (linebreak);
+  return accumulator;
 }
 
 
@@ -236,6 +267,10 @@
     return ThrowException(
         String::New("Array constructor needs one parameter."));
   }
+  static const int kMaxLength = 0x3fffffff;
+#ifndef USING_V8_SHARED
+  ASSERT(kMaxLength == i::ExternalArray::kMaxLength);
+#endif  // USING_V8_SHARED
   size_t length = 0;
   if (args[0]->IsUint32()) {
     length = args[0]->Uint32Value();
@@ -244,7 +279,7 @@
     if (raw_length < 0) {
       return ThrowException(String::New("Array length must not be negative."));
     }
-    if (raw_length > i::ExternalArray::kMaxLength) {
+    if (raw_length > kMaxLength) {
       return ThrowException(
           String::New("Array length exceeds maximum length."));
     }
@@ -252,7 +287,7 @@
   } else {
     return ThrowException(String::New("Array length must be a number."));
   }
-  if (length > static_cast<size_t>(i::ExternalArray::kMaxLength)) {
+  if (length > static_cast<size_t>(kMaxLength)) {
     return ThrowException(String::New("Array length exceeds maximum length."));
   }
   void* data = calloc(length, element_size);
@@ -332,7 +367,9 @@
 
 Handle<Value> Shell::Quit(const Arguments& args) {
   int exit_code = args[0]->Int32Value();
+#ifndef USING_V8_SHARED
   OnExit();
+#endif  // USING_V8_SHARED
   exit(exit_code);
   return Undefined();
 }
@@ -381,6 +418,7 @@
 }
 
 
+#ifndef USING_V8_SHARED
 Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
   HandleScope handle_scope;
   Context::Scope context_scope(utility_context_);
@@ -414,9 +452,11 @@
   Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
   return val;
 }
-#endif
+#endif  // ENABLE_DEBUGGER_SUPPORT
+#endif  // USING_V8_SHARED
 
 
+#ifndef USING_V8_SHARED
 int32_t* Counter::Bind(const char* name, bool is_histogram) {
   int i;
   for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
@@ -448,8 +488,8 @@
 
 
 void Shell::MapCounters(const char* name) {
-  counters_file_ = i::OS::MemoryMappedFile::create(name,
-    sizeof(CounterCollection), &local_counters_);
+  counters_file_ = i::OS::MemoryMappedFile::create(
+      name, sizeof(CounterCollection), &local_counters_);
   void* memory = (counters_file_ == NULL) ?
       NULL : counters_file_->memory();
   if (memory == NULL) {
@@ -514,6 +554,7 @@
   counter->AddSample(sample);
 }
 
+
 void Shell::InstallUtilityScript() {
   Locker lock;
   HandleScope scope;
@@ -532,7 +573,7 @@
   utility_context_->Global()->Set(String::New("$debug"),
                                   Utils::ToLocal(js_debug));
   debug->debug_context()->set_security_token(HEAP->undefined_value());
-#endif
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
   // Run the d8 shell utility script in the utility context
   int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
@@ -550,10 +591,10 @@
   // in the debugger.
   i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
   i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
-     ? i::Handle<i::Script>(i::Script::cast(
-         i::JSFunction::cast(*compiled_script)->shared()->script()))
-     : i::Handle<i::Script>(i::Script::cast(
-         i::SharedFunctionInfo::cast(*compiled_script)->script()));
+      ? i::Handle<i::Script>(i::Script::cast(
+          i::JSFunction::cast(*compiled_script)->shared()->script()))
+      : i::Handle<i::Script>(i::Script::cast(
+          i::SharedFunctionInfo::cast(*compiled_script)->script()));
   script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
@@ -561,8 +602,9 @@
   if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
     v8::Debug::SetDebugEventListener(HandleDebugEvent);
   }
-#endif
+#endif  // ENABLE_DEBUGGER_SUPPORT
 }
+#endif  // USING_V8_SHARED
 
 
 #ifdef COMPRESS_STARTUP_DATA_BZ2
@@ -629,9 +671,11 @@
   global_template->Set(String::New("lol_is_enabled"), Boolean::New(false));
 #endif
 
+#ifndef USING_V8_SHARED
   Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
   AddOSMethods(os_templ);
   global_template->Set(String::New("os"), os_templ);
+#endif  // USING_V8_SHARED
 
   return global_template;
 }
@@ -647,6 +691,7 @@
   }
 #endif
 
+#ifndef USING_V8_SHARED
   Shell::counter_map_ = new CounterMap();
   // Set up counters
   if (i::StrLength(i::FLAG_map_counters) != 0)
@@ -656,9 +701,10 @@
     V8::SetCreateHistogramFunction(CreateHistogram);
     V8::SetAddHistogramSampleFunction(AddHistogramSample);
   }
-
+#endif  // USING_V8_SHARED
   if (options.test_shell) return;
 
+#ifndef USING_V8_SHARED
   Locker lock;
   HandleScope scope;
   Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
@@ -669,18 +715,22 @@
   if (i::FLAG_debugger_agent) {
     v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
   }
-#endif
+#endif  // ENABLE_DEBUGGER_SUPPORT
+#endif  // USING_V8_SHARED
 }
 
 
 Persistent<Context> Shell::CreateEvaluationContext() {
+#ifndef USING_V8_SHARED
   // This needs to be a critical section since this is not thread-safe
   i::ScopedLock lock(context_mutex_);
+#endif  // USING_V8_SHARED
   // Initialize the global objects
   Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
   Persistent<Context> context = Context::New(NULL, global_template);
   Context::Scope scope(context);
 
+#ifndef USING_V8_SHARED
   i::JSArguments js_args = i::FLAG_js_arguments;
   i::Handle<i::FixedArray> arguments_array =
       FACTORY->NewFixedArray(js_args.argc());
@@ -692,11 +742,13 @@
   i::Handle<i::JSArray> arguments_jsarray =
       FACTORY->NewJSArrayWithElements(arguments_array);
   context->Global()->Set(String::New("arguments"),
-                                     Utils::ToLocal(arguments_jsarray));
+                         Utils::ToLocal(arguments_jsarray));
+#endif  // USING_V8_SHARED
   return context;
 }
 
 
+#ifndef USING_V8_SHARED
 void Shell::OnExit() {
   if (i::FLAG_dump_counters) {
     printf("+----------------------------------------+-------------+\n");
@@ -716,12 +768,18 @@
   if (counters_file_ != NULL)
     delete counters_file_;
 }
+#endif  // USING_V8_SHARED
 
 
 static char* ReadChars(const char* name, int* size_out) {
   // Release the V8 lock while reading files.
   v8::Unlocker unlocker(Isolate::GetCurrent());
+#ifndef USING_V8_SHARED
   FILE* file = i::OS::FOpen(name, "rb");
+#else
+  // TODO(yangguo@chromium.org): reading from a directory hangs!
+  FILE* file = fopen(name, "rb");
+#endif  // USING_V8_SHARED
   if (file == NULL) return NULL;
 
   fseek(file, 0, SEEK_END);
@@ -740,6 +798,7 @@
 }
 
 
+#ifndef USING_V8_SHARED
 static char* ReadToken(char* data, char token) {
   char* next = i::OS::StrChr(data, token);
   if (next != NULL) {
@@ -759,6 +818,7 @@
 static char* ReadWord(char* data) {
   return ReadToken(data, ' ');
 }
+#endif  // USING_V8_SHARED
 
 
 // Reads a file into a v8 string.
@@ -773,34 +833,44 @@
 
 
 void Shell::RunShell() {
+  Locker locker;
+  Context::Scope context_scope(evaluation_context_);
+  HandleScope handle_scope;
+  Handle<String> name = String::New("(d8)");
+#ifndef USING_V8_SHARED
   LineEditor* editor = LineEditor::Get();
   printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
   if (i::FLAG_debugger) {
     printf("JavaScript debugger enabled\n");
   }
-
   editor->Open();
   while (true) {
-    Locker locker;
-    HandleScope handle_scope;
-    Context::Scope context_scope(evaluation_context_);
     i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
-    if (input.is_empty())
-      break;
+    if (input.is_empty()) break;
     editor->AddHistory(*input);
-    Handle<String> name = String::New("(d8)");
     ExecuteString(String::New(*input), name, true, true);
   }
   editor->Close();
+#else
+  printf("V8 version %s [D8 light using shared library]\n", V8::GetVersion());
+  static const int kBufferSize = 256;
+  while (true) {
+    char buffer[kBufferSize];
+    printf("%s", Shell::kPrompt);
+    if (fgets(buffer, kBufferSize, stdin) == NULL) break;
+    ExecuteString(String::New(buffer), name, true, true);
+  }
+#endif  // USING_V8_SHARED
   printf("\n");
 }
 
 
+#ifndef USING_V8_SHARED
 class ShellThread : public i::Thread {
  public:
   ShellThread(int no, i::Vector<const char> files)
-    : Thread("d8:ShellThread"),
-      no_(no), files_(files) { }
+      : Thread("d8:ShellThread"),
+        no_(no), files_(files) { }
   virtual void Run();
  private:
   int no_;
@@ -848,6 +918,7 @@
     ptr = next_line;
   }
 }
+#endif  // USING_V8_SHARED
 
 
 void SourceGroup::ExitShell(int exit_code) {
@@ -894,7 +965,12 @@
 
 
 Handle<String> SourceGroup::ReadFile(const char* name) {
+#ifndef USING_V8_SHARED
+  FILE* file = i::OS::FOpen(name, "rb");
+#else
+  // TODO(yangguo@chromium.org): reading from a directory hangs!
   FILE* file = fopen(name, "rb");
+#endif  // USING_V8_SHARED
   if (file == NULL) return Handle<String>();
 
   fseek(file, 0, SEEK_END);
@@ -914,6 +990,7 @@
 }
 
 
+#ifndef USING_V8_SHARED
 i::Thread::Options SourceGroup::GetThreadOptions() {
   i::Thread::Options options;
   options.name = "IsolateThread";
@@ -965,6 +1042,7 @@
     done_semaphore_->Wait();
   }
 }
+#endif  // USING_V8_SHARED
 
 
 bool Shell::SetOptions(int argc, char* argv[]) {
@@ -986,12 +1064,26 @@
       options.test_shell = true;
       argv[i] = NULL;
     } else if (strcmp(argv[i], "--preemption") == 0) {
+#ifdef USING_V8_SHARED
+      printf("D8 with shared library does not support multi-threading\n");
+      return false;
+#else
       options.use_preemption = true;
       argv[i] = NULL;
+#endif  // USING_V8_SHARED
     } else if (strcmp(argv[i], "--no-preemption") == 0) {
+#ifdef USING_V8_SHARED
+      printf("D8 with shared library does not support multi-threading\n");
+      return false;
+#else
       options.use_preemption = false;
       argv[i] = NULL;
+#endif  // USING_V8_SHARED
     } else if (strcmp(argv[i], "--preemption-interval") == 0) {
+#ifdef USING_V8_SHARED
+      printf("D8 with shared library does not support multi-threading\n");
+      return false;
+#else
       if (++i < argc) {
         argv[i-1] = NULL;
         char* end = NULL;
@@ -1007,15 +1099,33 @@
         printf("Missing value for --preemption-interval\n");
         return false;
       }
+#endif  // USING_V8_SHARED
     } else if (strcmp(argv[i], "-f") == 0) {
       // Ignore any -f flags for compatibility with other stand-alone
       // JavaScript engines.
       continue;
     } else if (strcmp(argv[i], "--isolate") == 0) {
+#ifdef USING_V8_SHARED
+      printf("D8 with shared library does not support multi-threading\n");
+      return false;
+#endif  // USING_V8_SHARED
       options.num_isolates++;
     }
+#ifdef USING_V8_SHARED
+    else if (strcmp(argv[i], "--dump-counters") == 0) {
+      printf("D8 with shared library does not include counters\n");
+      return false;
+    } else if (strcmp(argv[i], "-p") == 0) {
+      printf("D8 with shared library does not support multi-threading\n");
+      return false;
+    } else if (strcmp(argv[i], "--debugger") == 0) {
+      printf("Javascript debugger not included\n");
+      return false;
+    }
+#endif  // USING_V8_SHARED
   }
 
+#ifndef USING_V8_SHARED
   // Run parallel threads if we are not using --isolate
   for (int i = 1; i < argc; i++) {
     if (argv[i] == NULL) continue;
@@ -1038,6 +1148,7 @@
       options.parallel_files->Add(i::Vector<const char>(files, size));
     }
   }
+#endif  // USING_V8_SHARED
 
   v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
 
@@ -1062,21 +1173,21 @@
 
 
 int Shell::RunMain(int argc, char* argv[]) {
+#ifndef USING_V8_SHARED
   i::List<i::Thread*> threads(1);
-
-  {
-    if (options.parallel_files != NULL)
-      for (int i = 0; i < options.parallel_files->length(); i++) {
-        i::Vector<const char> files = options.parallel_files->at(i);
-        ShellThread* thread = new ShellThread(threads.length(), files);
-        thread->Start();
-        threads.Add(thread);
-      }
-
-    for (int i = 1; i < options.num_isolates; ++i) {
-      options.isolate_sources[i].StartExecuteInThread();
+  if (options.parallel_files != NULL)
+    for (int i = 0; i < options.parallel_files->length(); i++) {
+      i::Vector<const char> files = options.parallel_files->at(i);
+      ShellThread* thread = new ShellThread(threads.length(), files);
+      thread->Start();
+      threads.Add(thread);
     }
 
+  for (int i = 1; i < options.num_isolates; ++i) {
+    options.isolate_sources[i].StartExecuteInThread();
+  }
+#endif  // USING_V8_SHARED
+  {  // NOLINT
     Locker lock;
     HandleScope scope;
     Persistent<Context> context = CreateEvaluationContext();
@@ -1090,14 +1201,18 @@
     } else {
       context.Dispose();
     }
+
+#ifndef USING_V8_SHARED
     // Start preemption if threads have been created and preemption is enabled.
     if (options.parallel_files != NULL
         && threads.length() > 0
         && options.use_preemption) {
       Locker::StartPreemption(options.preemption_interval);
     }
+#endif  // USING_V8_SHARED
   }
 
+#ifndef USING_V8_SHARED
   for (int i = 1; i < options.num_isolates; ++i) {
     options.isolate_sources[i].WaitForThread();
   }
@@ -1110,6 +1225,7 @@
     }
 
   OnExit();
+#endif  // USING_V8_SHARED
   return 0;
 }
 
@@ -1136,14 +1252,15 @@
     result = RunMain(argc, argv);
   }
 
-#ifdef ENABLE_DEBUGGER_SUPPORT
+
+#if !defined(USING_V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
   // Run remote debugger if requested, but never on --test
   if (i::FLAG_remote_debugger && !options.test_shell) {
     InstallUtilityScript();
     RunRemoteDebugger(i::FLAG_debugger_port);
     return 0;
   }
-#endif
+#endif  // !USING_V8_SHARED && ENABLE_DEBUGGER_SUPPORT
 
   // Run interactive shell if explicitly requested or if no script has been
   // executed, but never on --test
@@ -1151,7 +1268,9 @@
   if (( options.interactive_shell
       || !options.script_executed )
       && !options.test_shell ) {
+#ifndef USING_V8_SHARED
     InstallUtilityScript();
+#endif  // USING_V8_SHARED
     RunShell();
   }
 
diff --git a/src/d8.gyp b/src/d8.gyp
index 85914ec..d2b4254 100644
--- a/src/d8.gyp
+++ b/src/d8.gyp
@@ -26,12 +26,14 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 {
+  'variables': {
+    'console%': '',
+  },
   'targets': [
     {
       'target_name': 'd8',
       'type': 'executable',
       'dependencies': [
-        'd8_js2c#host',
         '../tools/gyp/v8.gyp:v8',
       ],
       'include_dirs+': [
@@ -42,15 +44,24 @@
       ],
       'sources': [
         'd8.cc',
-        'd8-debug.cc',
-        '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc',
       ],
       'conditions': [
-        [ 'OS=="linux" or OS=="mac" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
-          'sources': [ 'd8-posix.cc', ]
-        }],
-        [ 'OS=="win"', {
-          'sources': [ 'd8-windows.cc', ]
+        [ 'component!="shared_library"', {
+          'dependencies': [ 'd8_js2c#host', ], 
+          'sources': [ 'd8-debug.cc', '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc', ],
+          'conditions': [
+            [ 'console=="readline"', {
+              'libraries': [ '-lreadline', ],
+              'sources': [ 'd8-readline.cc' ],
+            }],
+            [ '(OS=="linux" or OS=="mac" or OS=="freebsd" \
+              or OS=="openbsd" or OS=="solaris")', {
+              'sources': [ 'd8-posix.cc', ]
+            }],
+            [ 'OS=="win"', {
+              'sources': [ 'd8-windows.cc', ]
+            }],
+          ],
         }],
       ],
     },
diff --git a/src/d8.h b/src/d8.h
index 7f02727..840ca1e 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -28,16 +28,23 @@
 #ifndef V8_D8_H_
 #define V8_D8_H_
 
-#include "allocation.h"
+
+#ifndef USING_V8_SHARED
 #include "v8.h"
+#include "allocation.h"
 #include "hashmap.h"
+#else
+#include "../include/v8.h"
+#endif  // USING_V8_SHARED
 
 namespace v8 {
 
-
+#ifndef USING_V8_SHARED
 namespace i = v8::internal;
+#endif  // USING_V8_SHARED
 
 
+#ifndef USING_V8_SHARED
 // A single counter in a counter collection.
 class Counter {
  public:
@@ -110,17 +117,20 @@
   static bool Match(void* key1, void* key2);
   i::HashMap hash_map_;
 };
+#endif  // USING_V8_SHARED
 
 
 class SourceGroup {
  public:
-  SourceGroup()
-      : next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
-        done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
-        thread_(NULL),
-        argv_(NULL),
-        begin_offset_(0),
-        end_offset_(0) { }
+  SourceGroup() :
+#ifndef USING_V8_SHARED
+      next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
+      done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
+      thread_(NULL),
+#endif  // USING_V8_SHARED
+      argv_(NULL),
+      begin_offset_(0),
+      end_offset_(0) { }
 
   void Begin(char** argv, int offset) {
     argv_ = const_cast<const char**>(argv);
@@ -131,6 +141,7 @@
 
   void Execute();
 
+#ifndef USING_V8_SHARED
   void StartExecuteInThread();
   void WaitForThread();
 
@@ -154,6 +165,7 @@
   i::Semaphore* next_semaphore_;
   i::Semaphore* done_semaphore_;
   i::Thread* thread_;
+#endif  // USING_V8_SHARED
 
   void ExitShell(int exit_code);
   Handle<String> ReadFile(const char* name);
@@ -166,34 +178,41 @@
 
 class ShellOptions {
  public:
-  ShellOptions()
-     : script_executed(false),
-       last_run(true),
-       stress_opt(false),
-       stress_deopt(false),
-       interactive_shell(false),
-       test_shell(false),
-       use_preemption(true),
-       preemption_interval(10),
-       num_isolates(1),
-       isolate_sources(NULL),
-       parallel_files(NULL) { }
+  ShellOptions() :
+#ifndef USING_V8_SHARED
+     use_preemption(true),
+     preemption_interval(10),
+     parallel_files(NULL),
+#endif  // USING_V8_SHARED
+     script_executed(false),
+     last_run(true),
+     stress_opt(false),
+     stress_deopt(false),
+     interactive_shell(false),
+     test_shell(false),
+     num_isolates(1),
+     isolate_sources(NULL) { }
 
+#ifndef USING_V8_SHARED
+  bool use_preemption;
+  int preemption_interval;
+  i::List< i::Vector<const char> >* parallel_files;
+#endif  // USING_V8_SHARED
   bool script_executed;
   bool last_run;
   bool stress_opt;
   bool stress_deopt;
   bool interactive_shell;
   bool test_shell;
-  bool use_preemption;
-  int preemption_interval;
   int num_isolates;
   SourceGroup* isolate_sources;
-  i::List< i::Vector<const char> >* parallel_files;
 };
 
-
-class Shell: public i::AllStatic {
+#ifdef USING_V8_SHARED
+class Shell {
+#else
+class Shell : public i::AllStatic {
+#endif  // USING_V8_SHARED
  public:
   static bool ExecuteString(Handle<String> source,
                             Handle<Value> name,
@@ -201,6 +220,14 @@
                             bool report_exceptions);
   static const char* ToCString(const v8::String::Utf8Value& value);
   static void ReportException(TryCatch* try_catch);
+  static Handle<String> ReadFile(const char* name);
+  static Persistent<Context> CreateEvaluationContext();
+  static int RunMain(int argc, char* argv[]);
+  static int Main(int argc, char* argv[]);
+
+#ifndef USING_V8_SHARED
+  static Handle<Array> GetCompletions(Handle<String> text,
+                                      Handle<String> full);
   static void OnExit();
   static int* LookupCounter(const char* name);
   static void* CreateHistogram(const char* name,
@@ -209,18 +236,8 @@
                                size_t buckets);
   static void AddHistogramSample(void* histogram, int sample);
   static void MapCounters(const char* name);
-  static Handle<String> ReadFile(const char* name);
-  static void Initialize();
-  static Persistent<Context> CreateEvaluationContext();
-  static void InstallUtilityScript();
-  static void RunShell();
-  static bool SetOptions(int argc, char* argv[]);
-  static int RunScript(char* filename);
-  static int RunMain(int argc, char* argv[]);
-  static int Main(int argc, char* argv[]);
-  static Handle<ObjectTemplate> CreateGlobalTemplate();
-  static Handle<Array> GetCompletions(Handle<String> text,
-                                      Handle<String> full);
+#endif  // USING_V8_SHARED
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
   static Handle<Object> DebugMessageDetails(Handle<String> message);
   static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
@@ -283,15 +300,16 @@
   static Handle<Value> RemoveDirectory(const Arguments& args);
 
   static void AddOSMethods(Handle<ObjectTemplate> os_template);
-
+#ifndef USING_V8_SHARED
   static const char* kHistoryFileName;
+#endif  // USING_V8_SHARED
   static const char* kPrompt;
-
   static ShellOptions options;
 
  private:
-  static Persistent<Context> utility_context_;
   static Persistent<Context> evaluation_context_;
+#ifndef USING_V8_SHARED
+  static Persistent<Context> utility_context_;
   static CounterMap* counter_map_;
   // We statically allocate a set of local counters to be used if we
   // don't want to store the stats in a memory-mapped file
@@ -299,7 +317,14 @@
   static CounterCollection* counters_;
   static i::OS::MemoryMappedFile* counters_file_;
   static i::Mutex* context_mutex_;
+
   static Counter* GetCounter(const char* name, bool is_histogram);
+  static void InstallUtilityScript();
+#endif  // USING_V8_SHARED
+  static void Initialize();
+  static void RunShell();
+  static bool SetOptions(int argc, char* argv[]);
+  static Handle<ObjectTemplate> CreateGlobalTemplate();
   static Handle<Value> CreateExternalArray(const Arguments& args,
                                            ExternalArrayType type,
                                            size_t element_size);
@@ -307,6 +332,7 @@
 };
 
 
+#ifndef USING_V8_SHARED
 class LineEditor {
  public:
   enum Type { DUMB = 0, READLINE = 1 };
@@ -326,6 +352,7 @@
   LineEditor* next_;
   static LineEditor* first_;
 };
+#endif  // USING_V8_SHARED
 
 
 }  // namespace v8
diff --git a/src/globals.h b/src/globals.h
index 5ab9806..bb9d0a8 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -199,6 +199,8 @@
 const int kIntptrSize   = sizeof(intptr_t);  // NOLINT
 const int kPointerSize  = sizeof(void*);     // NOLINT
 
+const int kDoubleSizeLog2 = 3;
+
 #if V8_HOST_ARCH_64_BIT
 const int kPointerSizeLog2 = 3;
 const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 401c2e4..93a7073 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -588,9 +588,9 @@
   // it would otherwise output what should be a minus zero as an int32 zero.
   // If the operation also exists in a form that takes int32 and outputs int32
   // then the operation should return its input value so that we can propagate
-  // back.  There are two operations that need to propagate back to more than
-  // one input.  They are phi and binary add.  They always return NULL and
-  // expect the caller to take care of things.
+  // back.  There are three operations that need to propagate back to more than
+  // one input.  They are phi and binary div and mul.  They always return NULL
+  // and expect the caller to take care of things.
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
     visited->Add(id());
     return NULL;
@@ -1123,40 +1123,19 @@
 class HClampToUint8: public HUnaryOperation {
  public:
   explicit HClampToUint8(HValue* value)
-      : HUnaryOperation(value),
-        input_rep_(Representation::None()) {
-    SetFlag(kFlexibleRepresentation);
-    set_representation(Representation::Tagged());
+      : HUnaryOperation(value) {
+    set_representation(Representation::Integer32());
     SetFlag(kUseGVN);
   }
 
   virtual Representation RequiredInputRepresentation(int index) const {
-    return input_rep_;
-  }
-
-  virtual Representation InferredRepresentation() {
-    // TODO(danno): Inference on input types should happen separately from
-    // return representation.
-    Representation new_rep = value()->representation();
-    if (input_rep_.IsNone()) {
-      if (!new_rep.IsNone()) {
-        input_rep_ = new_rep;
-        return Representation::Integer32();
-      } else {
-        return Representation::None();
-      }
-    } else {
-      return Representation::Integer32();
-    }
+    return Representation::None();
   }
 
   DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
 
  protected:
   virtual bool DataEquals(HValue* other) { return true; }
-
- private:
-  Representation input_rep_;
 };
 
 
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 887ba73..57329ba 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1666,8 +1666,8 @@
         HValue* use = it.value();
         if (use->IsPhi()) {
           int id = HPhi::cast(use)->phi_id();
-          change = change ||
-              connected_phis[i]->UnionIsChanged(*connected_phis[id]);
+          if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
+            change = true;
         }
       }
     }
@@ -3925,8 +3925,16 @@
     length = AddInstruction(new(zone()) HJSArrayLength(object));
     checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
     AddInstruction(elements);
+    if (is_store) {
+      AddInstruction(new(zone()) HCheckMap(
+          elements, isolate()->factory()->fixed_array_map()));
+    }
   } else {
     AddInstruction(elements);
+    if (is_store) {
+      AddInstruction(new(zone()) HCheckMap(
+          elements, isolate()->factory()->fixed_array_map()));
+    }
     length = AddInstruction(new(zone()) HFixedArrayLength(elements));
     checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
   }
@@ -4033,6 +4041,8 @@
         elements = AddInstruction(new(zone()) HLoadElements(object));
         elements->ClearFlag(HValue::kUseGVN);
         if (is_store) {
+          AddInstruction(new(zone()) HCheckMap(
+              elements, isolate()->factory()->fixed_array_map()));
           access = AddInstruction(
               new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
         } else {
@@ -4049,6 +4059,10 @@
         set_current_block(if_fastobject);
         elements = AddInstruction(new(zone()) HLoadElements(object));
         elements->ClearFlag(HValue::kUseGVN);
+        if (is_store) {
+          AddInstruction(new(zone()) HCheckMap(
+              elements, isolate()->factory()->fixed_array_map()));
+        }
         length = AddInstruction(new(zone()) HFixedArrayLength(elements));
         checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
         if (is_store) {
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 6293718..9532d94 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2790,7 +2790,8 @@
   __ ucomisd(input_reg, xmm0);
   __ j(above, &positive, Label::kNear);
   __ j(equal, &zero, Label::kNear);
-  ExternalReference nan = ExternalReference::address_of_nan();
+  ExternalReference nan =
+      ExternalReference::address_of_canonical_non_hole_nan();
   __ movdbl(input_reg, Operand::StaticVariable(nan));
   __ jmp(&done, Label::kNear);
   __ bind(&zero);
@@ -3451,7 +3452,8 @@
     DeoptimizeIf(not_equal, env);
 
     // Convert undefined to NaN.
-    ExternalReference nan = ExternalReference::address_of_nan();
+    ExternalReference nan =
+        ExternalReference::address_of_canonical_non_hole_nan();
     __ movdbl(result_reg, Operand::StaticVariable(nan));
     __ jmp(&done, Label::kNear);
 
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 136b24c..3e037d7 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -2044,6 +2044,9 @@
         Immediate(factory->fixed_array_map()));
     j(equal, &ok);
     cmp(FieldOperand(elements, HeapObject::kMapOffset),
+        Immediate(factory->fixed_double_array_map()));
+    j(equal, &ok);
+    cmp(FieldOperand(elements, HeapObject::kMapOffset),
         Immediate(factory->fixed_cow_array_map()));
     j(equal, &ok);
     Abort("JSObject with fast elements map has slow elements");
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 2660850..9a690d7 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -3790,6 +3790,71 @@
 }
 
 
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+    MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- eax    : key
+  //  -- edx    : receiver
+  //  -- esp[0] : return address
+  // -----------------------------------
+  Label miss_force_generic, slow_allocate_heapnumber;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(eax, &miss_force_generic);
+
+  // Get the elements array.
+  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
+  __ AssertFastElements(ecx);
+
+  // Check that the key is within bounds.
+  __ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset));
+  __ j(above_equal, &miss_force_generic);
+
+  // Check for the hole
+  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+  __ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32));
+  __ j(equal, &miss_force_generic);
+
+  // Always allocate a heap number for the result.
+  if (CpuFeatures::IsSupported(SSE2)) {
+    CpuFeatures::Scope use_sse2(SSE2);
+    __ movdbl(xmm0, FieldOperand(ecx, eax, times_4,
+                                 FixedDoubleArray::kHeaderSize));
+  } else {
+    __ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize));
+  }
+  __ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber);
+  // Set the value.
+  if (CpuFeatures::IsSupported(SSE2)) {
+    CpuFeatures::Scope use_sse2(SSE2);
+    __ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
+  } else {
+    __ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset));
+  }
+  __ mov(eax, ecx);
+  __ ret(0);
+
+  __ bind(&slow_allocate_heapnumber);
+  // A value was pushed on the floating point stack before the allocation, if
+  // the allocation fails it needs to be removed.
+  if (!CpuFeatures::IsSupported(SSE2)) {
+    __ ffree();
+    __ fincstp();
+  }
+  Handle<Code> slow_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_Slow();
+  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
+
+  __ bind(&miss_force_generic);
+  Handle<Code> miss_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
                                                       bool is_js_array) {
   // ----------- S t a t e -------------
@@ -3839,6 +3904,98 @@
 }
 
 
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+    MacroAssembler* masm,
+    bool is_js_array) {
+  // ----------- S t a t e -------------
+  //  -- eax    : value
+  //  -- ecx    : key
+  //  -- edx    : receiver
+  //  -- esp[0] : return address
+  // -----------------------------------
+  Label miss_force_generic, smi_value, is_nan, maybe_nan;
+  Label have_double_value, not_nan;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(ecx, &miss_force_generic);
+
+  // Get the elements array.
+  __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
+  __ AssertFastElements(edi);
+
+  if (is_js_array) {
+    // Check that the key is within bounds.
+    __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset));  // smis.
+  } else {
+    // Check that the key is within bounds.
+    __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));  // smis.
+  }
+  __ j(above_equal, &miss_force_generic);
+
+  __ JumpIfSmi(eax, &smi_value, Label::kNear);
+
+  __ CheckMap(eax,
+              masm->isolate()->factory()->heap_number_map(),
+              &miss_force_generic,
+              DONT_DO_SMI_CHECK);
+
+  // Double value, canonicalize NaN.
+  uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
+  __ cmp(FieldOperand(eax, offset), Immediate(kNaNOrInfinityLowerBoundUpper32));
+  __ j(greater_equal, &maybe_nan, Label::kNear);
+
+  __ bind(&not_nan);
+  ExternalReference canonical_nan_reference =
+      ExternalReference::address_of_canonical_non_hole_nan();
+  if (CpuFeatures::IsSupported(SSE2)) {
+    CpuFeatures::Scope use_sse2(SSE2);
+    __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
+    __ bind(&have_double_value);
+    __ movdbl(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize),
+              xmm0);
+    __ ret(0);
+  } else {
+    __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+    __ bind(&have_double_value);
+    __ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
+    __ ret(0);
+  }
+
+  __ bind(&maybe_nan);
+  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+  // it's an Infinity, and the non-NaN code path applies.
+  __ j(greater, &is_nan, Label::kNear);
+  __ cmp(FieldOperand(eax, HeapNumber::kValueOffset), Immediate(0));
+  __ j(zero, &not_nan);
+  __ bind(&is_nan);
+  if (CpuFeatures::IsSupported(SSE2)) {
+    CpuFeatures::Scope use_sse2(SSE2);
+    __ movdbl(xmm0, Operand::StaticVariable(canonical_nan_reference));
+  } else {
+    __ fld_d(Operand::StaticVariable(canonical_nan_reference));
+  }
+  __ jmp(&have_double_value, Label::kNear);
+
+  __ bind(&smi_value);
+  // Value is a smi. convert to a double and store.
+  __ SmiUntag(eax);
+  __ push(eax);
+  __ fild_s(Operand(esp, 0));
+  __ pop(eax);
+  __ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
+  __ ret(0);
+
+  // Handle store cache miss, replacing the ic with the generic stub.
+  __ bind(&miss_force_generic);
+  Handle<Code> ic_force_generic =
+      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 919bdc4..6c8e961 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -4229,6 +4229,12 @@
 }
 
 
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+    MacroAssembler* masm) {
+  UNIMPLEMENTED();
+}
+
+
 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
                                                       bool is_js_array) {
   // ----------- S t a t e -------------
@@ -4292,6 +4298,13 @@
 }
 
 
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+    MacroAssembler* masm,
+    bool is_js_array) {
+  UNIMPLEMENTED();
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index 57de6c6..0a32597 100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -1250,9 +1250,9 @@
 const kFrameDetailsValueIndex = 1;
 const kFrameDetailsNameValueSize = 2;
 
-const kFrameDetailsFlagDebuggerFrame = 1;
-const kFrameDetailsFlagOptimizedFrame = 2;
-const kFrameDetailsFlagInlinedFrame = 4;
+const kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
+const kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
+const kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
 
 /**
  * Wrapper for the frame details information retreived from the VM. The frame
@@ -1266,7 +1266,7 @@
  *     5: Source position
  *     6: Construct call
  *     7: Is at return
- *     8: Flags (debugger frame, optimized frame, inlined frame)
+ *     8: Flags (debugger frame, optimized frame, inlined frame index)
  *     Arguments name, value
  *     Locals name, value
  *     Return value if any
@@ -1312,22 +1312,27 @@
 
 FrameDetails.prototype.isDebuggerFrame = function() {
   %CheckExecutionState(this.break_id_);
-  var f = kFrameDetailsFlagDebuggerFrame;
+  var f = kFrameDetailsFlagDebuggerFrameMask;
   return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
 }
 
 
 FrameDetails.prototype.isOptimizedFrame = function() {
   %CheckExecutionState(this.break_id_);
-  var f = kFrameDetailsFlagOptimizedFrame;
+  var f = kFrameDetailsFlagOptimizedFrameMask;
   return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
 }
 
 
 FrameDetails.prototype.isInlinedFrame = function() {
+  return this.inlinedFrameIndex() > 0;
+}
+
+
+FrameDetails.prototype.inlinedFrameIndex = function() {
   %CheckExecutionState(this.break_id_);
-  var f = kFrameDetailsFlagInlinedFrame;
-  return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
+  var f = kFrameDetailsFlagInlinedFrameIndexMask;
+  return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2
 }
 
 
@@ -1476,6 +1481,11 @@
 };
 
 
+FrameMirror.prototype.inlinedFrameIndex = function() {
+  return this.details_.inlinedFrameIndex();
+};
+
+
 FrameMirror.prototype.argumentCount = function() {
   return this.details_.argumentCount();
 };
@@ -1565,8 +1575,12 @@
 
 
 FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
-  var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
-                              source, Boolean(disable_break), opt_context_object);
+  var result = %DebugEvaluate(this.break_id_,
+                              this.details_.frameId(),
+                              this.details_.inlinedFrameIndex(),
+                              source,
+                              Boolean(disable_break),
+                              opt_context_object);
   return MakeMirror(result);
 };
 
@@ -1719,6 +1733,7 @@
   this.break_id_ = frame.break_id_;
   this.details_ = %GetScopeDetails(frame.break_id_,
                                    frame.details_.frameId(),
+                                   frame.details_.inlinedFrameIndex(),
                                    index);
 }
 
diff --git a/src/natives.h b/src/natives.h
index a283186..5f34420 100644
--- a/src/natives.h
+++ b/src/natives.h
@@ -36,7 +36,7 @@
                                      int index);
 
 enum NativeType {
-  CORE, EXPERIMENTAL, D8
+  CORE, EXPERIMENTAL, D8, TEST
 };
 
 template <NativeType type>
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 3d325b8..2963231 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -315,7 +315,8 @@
     if (!is_the_hole(i)) {
       double value = get(i);
       ASSERT(!isnan(value) ||
-             BitCast<uint64_t>(value) == kCanonicalNonHoleNanInt64);
+             (BitCast<uint64_t>(value) ==
+              BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())));
     }
   }
 }
diff --git a/src/objects-inl.h b/src/objects-inl.h
index eb537c7..fdc5102 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1610,6 +1610,23 @@
 }
 
 
+inline bool FixedDoubleArray::is_the_hole_nan(double value) {
+  return BitCast<uint64_t, double>(value) == kHoleNanInt64;
+}
+
+
+inline double FixedDoubleArray::hole_nan_as_double() {
+  return BitCast<double, uint64_t>(kHoleNanInt64);
+}
+
+
+inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
+  ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
+  ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
+  return OS::nan_value();
+}
+
+
 double FixedDoubleArray::get(int index) {
   ASSERT(map() != HEAP->fixed_cow_array_map() &&
          map() != HEAP->fixed_array_map());
diff --git a/src/objects.cc b/src/objects.cc
index ca780db..26ab645 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -58,11 +58,6 @@
 const int kGetterIndex = 0;
 const int kSetterIndex = 1;
 
-uint64_t FixedDoubleArray::kHoleNanInt64 = -1;
-uint64_t FixedDoubleArray::kCanonicalNonHoleNanLower32 = 0x7FF00000;
-uint64_t FixedDoubleArray::kCanonicalNonHoleNanInt64 =
-    kCanonicalNonHoleNanLower32 << 32;
-
 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
                                                   Object* value) {
   Object* result;
@@ -194,7 +189,7 @@
     AccessorInfo* data = AccessorInfo::cast(structure);
     Object* fun_obj = data->getter();
     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
-    HandleScope scope;
+    HandleScope scope(isolate);
     JSObject* self = JSObject::cast(receiver);
     JSObject* holder_handle = JSObject::cast(holder);
     Handle<String> key(name);
@@ -234,7 +229,7 @@
                                             String* name_raw,
                                             Object* handler_raw) {
   Isolate* isolate = name_raw->GetIsolate();
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<Object> receiver(receiver_raw);
   Handle<Object> name(name_raw);
   Handle<Object> handler(handler_raw);
@@ -2178,9 +2173,9 @@
     }
   }
 
-  HandleScope scope;
-  Handle<Object> value_handle(value);
   Heap* heap = GetHeap();
+  HandleScope scope(heap->isolate());
+  Handle<Object> value_handle(value);
   heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   return *value_handle;
 }
@@ -2207,7 +2202,7 @@
     PropertyAttributes attributes,
     StrictModeFlag strict_mode) {
   Isolate* isolate = GetIsolate();
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<Object> receiver(this);
   Handle<Object> name(name_raw);
   Handle<Object> value(value_raw);
@@ -2233,12 +2228,50 @@
 }
 
 
+MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
+    String* name_raw, DeleteMode mode) {
+  Isolate* isolate = GetIsolate();
+  HandleScope scope(isolate);
+  Handle<Object> receiver(this);
+  Handle<Object> name(name_raw);
+  Handle<Object> handler(this->handler());
+
+  // Extract trap function.
+  Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
+  Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
+  if (trap->IsUndefined()) {
+    Handle<Object> args[] = { handler, trap_name };
+    Handle<Object> error = isolate->factory()->NewTypeError(
+        "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
+    isolate->Throw(*error);
+    return Failure::Exception();
+  }
+
+  // Call trap function.
+  Object** args[] = { name.location() };
+  bool has_exception;
+  Handle<Object> result =
+      Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
+  if (has_exception) return Failure::Exception();
+
+  Object* bool_result = result->ToBoolean();
+  if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
+    Handle<Object> args[] = { handler, trap_name };
+    Handle<Object> error = isolate->factory()->NewTypeError(
+        "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
+    isolate->Throw(*error);
+    return Failure::Exception();
+  }
+  return bool_result;
+}
+
+
 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
     JSReceiver* receiver_raw,
     String* name_raw,
     bool* has_exception) {
   Isolate* isolate = GetIsolate();
-  HandleScope scope;
+  HandleScope scope(isolate);
   Handle<JSReceiver> receiver(receiver_raw);
   Handle<Object> name(name_raw);
   Handle<Object> handler(this->handler());
@@ -2327,7 +2360,7 @@
   }
   if (result->IsReadOnly() && result->IsProperty()) {
     if (strict_mode == kStrictMode) {
-      HandleScope scope;
+      HandleScope scope(heap->isolate());
       Handle<String> key(name);
       Handle<Object> holder(this);
       Handle<Object> args[2] = { key, holder };
@@ -2811,16 +2844,18 @@
   ASSERT(!HasExternalArrayElements());
 
   // Find the backing store.
-  FixedArray* array = FixedArray::cast(elements());
+  FixedArrayBase* array = FixedArrayBase::cast(elements());
   Map* old_map = array->map();
   bool is_arguments =
       (old_map == old_map->heap()->non_strict_arguments_elements_map());
   if (is_arguments) {
-    array = FixedArray::cast(array->get(1));
+    array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
   }
   if (array->IsDictionary()) return array;
 
-  ASSERT(HasFastElements() || HasFastArgumentsElements());
+  ASSERT(HasFastElements() ||
+         HasFastDoubleElements() ||
+         HasFastArgumentsElements());
   // Compute the effective length and allocate a new backing store.
   int length = IsJSArray()
       ? Smi::cast(JSArray::cast(this)->length())->value()
@@ -2833,7 +2868,7 @@
   }
 
   // Copy the elements to the new backing store.
-  bool has_double_elements = old_map->has_fast_double_elements();
+  bool has_double_elements = array->IsFixedDoubleArray();
   for (int i = 0; i < length; i++) {
     Object* value = NULL;
     if (has_double_elements) {
@@ -2851,7 +2886,7 @@
       }
     } else {
       ASSERT(old_map->has_fast_elements());
-      value = array->get(i);
+      value = FixedArray::cast(array)->get(i);
     }
     PropertyDetails details = PropertyDetails(NONE, NORMAL);
     if (!value->IsTheHole()) {
@@ -3179,6 +3214,15 @@
 }
 
 
+MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
+  if (IsJSProxy()) {
+    return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
+  } else {
+    return JSObject::cast(this)->DeleteProperty(name, mode);
+  }
+}
+
+
 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
   Isolate* isolate = GetIsolate();
   // ECMA-262, 3rd, 8.6.2.5
@@ -7317,22 +7361,28 @@
     new_map = Map::cast(object);
   }
 
-  AssertNoAllocation no_gc;
-  WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
   switch (GetElementsKind()) {
-    case FAST_ELEMENTS:
+    case FAST_ELEMENTS: {
+      AssertNoAllocation no_gc;
+      WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
       CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode);
       set_map(new_map);
       set_elements(new_elements);
       break;
-    case DICTIONARY_ELEMENTS:
+    }
+    case DICTIONARY_ELEMENTS: {
+      AssertNoAllocation no_gc;
+      WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
       CopySlowElementsToFast(NumberDictionary::cast(elements()),
                              new_elements,
                              mode);
       set_map(new_map);
       set_elements(new_elements);
       break;
+    }
     case NON_STRICT_ARGUMENTS_ELEMENTS: {
+      AssertNoAllocation no_gc;
+      WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
       // The object's map and the parameter map are unchanged, the unaliased
       // arguments are copied to the new backing store.
       FixedArray* parameter_map = FixedArray::cast(elements());
@@ -7368,6 +7418,8 @@
           new_elements->set(i, obj, UPDATE_WRITE_BARRIER);
         }
       }
+      set_map(new_map);
+      set_elements(new_elements);
       break;
     }
     case EXTERNAL_BYTE_ELEMENTS:
@@ -7430,7 +7482,9 @@
       break;
   }
 
+  ASSERT(new_map->has_fast_double_elements());
   set_map(new_map);
+  ASSERT(elems->IsFixedDoubleArray());
   set_elements(elems);
 
   if (IsJSArray()) {
@@ -7520,7 +7574,7 @@
 
 
 static Failure* ArrayLengthRangeError(Heap* heap) {
-  HandleScope scope;
+  HandleScope scope(heap->isolate());
   return heap->isolate()->Throw(
       *FACTORY->NewRangeError("invalid_array_length",
           HandleVector<Object>(NULL, 0)));
@@ -7718,7 +7772,7 @@
   // or [[Extensible]] must not violate the invariants defined in the preceding
   // paragraph.
   if (!this->map()->is_extensible()) {
-    HandleScope scope;
+    HandleScope scope(heap->isolate());
     Handle<Object> handle(this, heap->isolate());
     return heap->isolate()->Throw(
         *FACTORY->NewTypeError("non_extensible_proto",
@@ -7732,7 +7786,7 @@
   for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
     if (JSObject::cast(pt) == this) {
       // Cycle detected.
-      HandleScope scope;
+      HandleScope scope(heap->isolate());
       return heap->isolate()->Throw(
           *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
     }
@@ -8407,8 +8461,9 @@
     } else {
       new_length = dictionary->max_number_key() + 1;
     }
-    MaybeObject* result =
-        SetFastElementsCapacityAndLength(new_length, new_length);
+    MaybeObject* result = ShouldConvertToFastDoubleElements()
+        ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
+        : SetFastElementsCapacityAndLength(new_length, new_length);
     if (result->IsFailure()) return result;
 #ifdef DEBUG
     if (FLAG_trace_normalization) {
@@ -8495,6 +8550,9 @@
   }
 
   // Otherwise default to slow case.
+  ASSERT(HasFastDoubleElements());
+  ASSERT(map()->has_fast_double_elements());
+  ASSERT(elements()->IsFixedDoubleArray());
   Object* obj;
   { MaybeObject* maybe_obj = NormalizeElements();
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
@@ -8512,7 +8570,7 @@
   if (IsAccessCheckNeeded()) {
     Heap* heap = GetHeap();
     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
-      HandleScope scope;
+      HandleScope scope(heap->isolate());
       Handle<Object> value_handle(value);
       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
       return *value_handle;
@@ -8948,10 +9006,13 @@
   int capacity = 0;
   int number_of_elements = 0;
 
-  FixedArray* backing_store = FixedArray::cast(elements());
+  FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
+  FixedArray* backing_store = NULL;
   switch (GetElementsKind()) {
     case NON_STRICT_ARGUMENTS_ELEMENTS:
-      backing_store = FixedArray::cast(backing_store->get(1));
+      backing_store_base =
+          FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
+      backing_store = FixedArray::cast(backing_store_base);
       if (backing_store->IsDictionary()) {
         NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
         capacity = dictionary->Capacity();
@@ -8960,13 +9021,15 @@
       }
       // Fall through.
     case FAST_ELEMENTS:
+      backing_store = FixedArray::cast(backing_store_base);
       capacity = backing_store->length();
       for (int i = 0; i < capacity; ++i) {
         if (!backing_store->get(i)->IsTheHole()) ++number_of_elements;
       }
       break;
     case DICTIONARY_ELEMENTS: {
-      NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
+      NumberDictionary* dictionary =
+          NumberDictionary::cast(FixedArray::cast(elements()));
       capacity = dictionary->Capacity();
       number_of_elements = dictionary->NumberOfElements();
       break;
@@ -11053,11 +11116,11 @@
 
 template<typename Shape, typename Key>
 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
-                                               JSObject::DeleteMode mode) {
+                                               JSReceiver::DeleteMode mode) {
   Heap* heap = Dictionary<Shape, Key>::GetHeap();
   PropertyDetails details = DetailsAt(entry);
   // Ignore attributes if forcing a deletion.
-  if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
+  if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
     return heap->false_value();
   }
   SetEntry(entry, heap->null_value(), heap->null_value());
diff --git a/src/objects.h b/src/objects.h
index 9765fe2..0eaeb36 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1359,6 +1359,12 @@
 // JSObject and JSProxy.
 class JSReceiver: public HeapObject {
  public:
+  enum DeleteMode {
+    NORMAL_DELETION,
+    STRICT_DELETION,
+    FORCE_DELETION
+  };
+
   // Casting.
   static inline JSReceiver* cast(Object* obj);
 
@@ -1373,6 +1379,8 @@
                                            PropertyAttributes attributes,
                                            StrictModeFlag strict_mode);
 
+  MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
+
   // Returns the class name ([[Class]] property in the specification).
   String* class_name();
 
@@ -1422,12 +1430,6 @@
 // caching.
 class JSObject: public JSReceiver {
  public:
-  enum DeleteMode {
-    NORMAL_DELETION,
-    STRICT_DELETION,
-    FORCE_DELETION
-  };
-
   enum ElementsKind {
     // The "fast" kind for tagged values. Must be first to make it possible
     // to efficiently check maps if they have fast elements.
@@ -2173,23 +2175,9 @@
     return kHeaderSize + length * kDoubleSize;
   }
 
-  // The following can't be declared inline as const static
-  // because they're 64-bit.
-  static uint64_t kCanonicalNonHoleNanLower32;
-  static uint64_t kCanonicalNonHoleNanInt64;
-  static uint64_t kHoleNanInt64;
-
-  inline static bool is_the_hole_nan(double value) {
-    return BitCast<uint64_t, double>(value) == kHoleNanInt64;
-  }
-
-  inline static double hole_nan_as_double() {
-    return BitCast<double, uint64_t>(kHoleNanInt64);
-  }
-
-  inline static double canonical_not_the_hole_nan_as_double() {
-    return BitCast<double, uint64_t>(kCanonicalNonHoleNanInt64);
-  }
+  inline static bool is_the_hole_nan(double value);
+  inline static double hole_nan_as_double();
+  inline static double canonical_not_the_hole_nan_as_double();
 
   // Casting.
   static inline FixedDoubleArray* cast(Object* obj);
@@ -6491,14 +6479,18 @@
   static inline JSProxy* cast(Object* obj);
 
   MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
-      String* name_raw,
-      Object* value_raw,
+      String* name,
+      Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode);
 
+  MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
+      String* name,
+      DeleteMode mode);
+
   MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
       JSReceiver* receiver,
-      String* name_raw,
+      String* name,
       bool* has_exception);
 
   // Dispatched behavior.
diff --git a/src/parser.cc b/src/parser.cc
index 3085ef8..949ff76 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2868,7 +2868,7 @@
         // Consume one of the new prefixes (already parsed).
         ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
         int last = stack->pop();
-        result = new CallNew(result, args, last);
+        result = new(zone()) CallNew(result, args, last);
         break;
       }
       default:
diff --git a/src/parser.h b/src/parser.h
index 9ce1026..71f5d39 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -668,7 +668,7 @@
   Expression* NewCall(Expression* expression,
                       ZoneList<Expression*>* arguments,
                       int pos) {
-    return new Call(expression, arguments, pos);
+    return new(zone()) Call(expression, arguments, pos);
   }
 
 
diff --git a/src/rewriter.cc b/src/rewriter.cc
index 64d7b36..1ac2bb8 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -66,9 +66,10 @@
 
   Expression* SetResult(Expression* value) {
     result_assigned_ = true;
-    VariableProxy* result_proxy = new VariableProxy(result_);
-    return new Assignment(Token::ASSIGN, result_proxy, value,
-                          RelocInfo::kNoPosition);
+    Zone* zone = isolate()->zone();
+    VariableProxy* result_proxy = new(zone) VariableProxy(result_);
+    return new(zone) Assignment(Token::ASSIGN, result_proxy, value,
+                                RelocInfo::kNoPosition);
   }
 
   // Node visitors.
@@ -229,8 +230,9 @@
     if (processor.HasStackOverflow()) return false;
 
     if (processor.result_assigned()) {
-      VariableProxy* result_proxy = new VariableProxy(result);
-      body->Add(new ReturnStatement(result_proxy));
+      Zone* zone = info->isolate()->zone();
+      VariableProxy* result_proxy = new(zone) VariableProxy(result);
+      body->Add(new(zone) ReturnStatement(result_proxy));
     }
   }
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 56507ae..0ce5836 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -3872,7 +3872,7 @@
        || result.type() == CONSTANT_FUNCTION)) {
     Object* ok;
     { MaybeObject* maybe_ok =
-          obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
+          obj->DeleteProperty(name, JSReceiver::NORMAL_DELETION);
       if (!maybe_ok->ToObject(&ok)) return maybe_ok;
     }
   }
@@ -4126,24 +4126,25 @@
 
 
 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
-                                                Handle<JSObject> js_object,
+                                                Handle<JSReceiver> receiver,
                                                 Handle<Object> key) {
   HandleScope scope(isolate);
 
   // Check if the given key is an array index.
   uint32_t index;
-  if (key->ToArrayIndex(&index)) {
+  if (receiver->IsJSObject() && key->ToArrayIndex(&index)) {
     // In Firefox/SpiderMonkey, Safari and Opera you can access the
     // characters of a string using [] notation.  In the case of a
     // String object we just need to redirect the deletion to the
     // underlying string if the index is in range.  Since the
     // underlying string does nothing with the deletion, we can ignore
     // such deletions.
-    if (js_object->IsStringObjectWithCharacterAt(index)) {
+    if (receiver->IsStringObjectWithCharacterAt(index)) {
       return isolate->heap()->true_value();
     }
 
-    return js_object->DeleteElement(index, JSObject::FORCE_DELETION);
+    return JSObject::cast(*receiver)->DeleteElement(
+        index, JSReceiver::FORCE_DELETION);
   }
 
   Handle<String> key_string;
@@ -4158,7 +4159,7 @@
   }
 
   key_string->TryFlatten();
-  return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
+  return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
 }
 
 
@@ -4237,12 +4238,12 @@
   NoHandleAllocation ha;
   ASSERT(args.length() == 3);
 
-  CONVERT_CHECKED(JSObject, object, args[0]);
+  CONVERT_CHECKED(JSReceiver, object, args[0]);
   CONVERT_CHECKED(String, key, args[1]);
   CONVERT_SMI_ARG_CHECKED(strict, 2);
   return object->DeleteProperty(key, (strict == kStrictMode)
-                                      ? JSObject::STRICT_DELETION
-                                      : JSObject::NORMAL_DELETION);
+                                      ? JSReceiver::STRICT_DELETION
+                                      : JSReceiver::NORMAL_DELETION);
 }
 
 
@@ -8198,9 +8199,9 @@
   // index is non-negative.
   Handle<JSObject> object = Handle<JSObject>::cast(holder);
   if (index >= 0) {
-    return object->DeleteElement(index, JSObject::NORMAL_DELETION);
+    return object->DeleteElement(index, JSReceiver::NORMAL_DELETION);
   } else {
-    return object->DeleteProperty(*name, JSObject::NORMAL_DELETION);
+    return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
   }
 }
 
@@ -9976,6 +9977,71 @@
 }
 
 
+class FrameInspector {
+ public:
+  FrameInspector(JavaScriptFrame* frame,
+                 int inlined_frame_index,
+                 Isolate* isolate)
+      : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
+    // Calculate the deoptimized frame.
+    if (frame->is_optimized()) {
+      deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
+          frame, inlined_frame_index, isolate);
+    }
+    has_adapted_arguments_ = frame_->has_adapted_arguments();
+    is_optimized_ = frame_->is_optimized();
+  }
+
+  ~FrameInspector() {
+    // Get rid of the calculated deoptimized frame if any.
+    if (deoptimized_frame_ != NULL) {
+      Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
+                                                  isolate_);
+    }
+  }
+
+  int GetParametersCount() {
+    return is_optimized_
+        ? deoptimized_frame_->parameters_count()
+        : frame_->ComputeParametersCount();
+  }
+  int expression_count() { return deoptimized_frame_->expression_count(); }
+  Object* GetFunction() {
+    return is_optimized_
+        ? deoptimized_frame_->GetFunction()
+        : frame_->function();
+  }
+  Object* GetParameter(int index) {
+    return is_optimized_
+        ? deoptimized_frame_->GetParameter(index)
+        : frame_->GetParameter(index);
+  }
+  Object* GetExpression(int index) {
+    return is_optimized_
+        ? deoptimized_frame_->GetExpression(index)
+        : frame_->GetExpression(index);
+  }
+
+  // To inspect all the provided arguments the frame might need to be
+  // replaced with the arguments frame.
+  void SetArgumentsFrame(JavaScriptFrame* frame) {
+    ASSERT(has_adapted_arguments_);
+    frame_ = frame;
+    is_optimized_ = frame_->is_optimized();
+    ASSERT(!is_optimized_);
+  }
+
+ private:
+  JavaScriptFrame* frame_;
+  DeoptimizedFrameInfo* deoptimized_frame_;
+  Isolate* isolate_;
+  bool is_optimized_;
+  bool has_adapted_arguments_;
+
+  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
+};
+
+
 static const int kFrameDetailsFrameIdIndex = 0;
 static const int kFrameDetailsReceiverIndex = 1;
 static const int kFrameDetailsFunctionIndex = 2;
@@ -10024,8 +10090,7 @@
     return heap->undefined_value();
   }
 
-  int deoptimized_frame_index = -1;  // Frame index in optimized frame.
-  DeoptimizedFrameInfo* deoptimized_frame = NULL;
+  int inlined_frame_index = 0;  // Inlined frame index in optimized frame.
 
   int count = 0;
   JavaScriptFrameIterator it(isolate, id);
@@ -10036,13 +10101,10 @@
   if (it.done()) return heap->undefined_value();
 
   if (it.frame()->is_optimized()) {
-    deoptimized_frame_index =
+    inlined_frame_index =
         it.frame()->GetInlineCount() - (index - count) - 1;
-    deoptimized_frame = Deoptimizer::DebuggerInspectableFrame(
-        it.frame(),
-        deoptimized_frame_index,
-        isolate);
   }
+  FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
 
   // Traverse the saved contexts chain to find the active context for the
   // selected frame.
@@ -10061,7 +10123,7 @@
 
   // Check for constructor frame. Inlined frames cannot be construct calls.
   bool inlined_frame =
-      it.frame()->is_optimized() && deoptimized_frame_index != 0;
+      it.frame()->is_optimized() && inlined_frame_index != 0;
   bool constructor = !inlined_frame && it.frame()->IsConstructor();
 
   // Get scope info and read from it for local variable information.
@@ -10083,14 +10145,7 @@
   for (; i < info.number_of_stack_slots(); ++i) {
     // Use the value from the stack.
     locals->set(i * 2, *info.LocalName(i));
-    if (it.frame()->is_optimized()) {
-      // Get the value from the deoptimized frame.
-      locals->set(i * 2 + 1,
-                  deoptimized_frame->GetExpression(i));
-    } else {
-      // Get the value from the stack.
-      locals->set(i * 2 + 1, it.frame()->GetExpression(i));
-    }
+    locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
   }
   if (i < info.NumberOfLocals()) {
     // Get the context containing declarations.
@@ -10147,18 +10202,22 @@
   // the provided parameters whereas the function frame always have the number
   // of arguments matching the functions parameters. The rest of the
   // information (except for what is collected above) is the same.
-  it.AdvanceToArgumentsFrame();
+  if (it.frame()->has_adapted_arguments()) {
+    it.AdvanceToArgumentsFrame();
+    frame_inspector.SetArgumentsFrame(it.frame());
+  }
 
   // Find the number of arguments to fill. At least fill the number of
   // parameters for the function and fill more if more parameters are provided.
   int argument_count = info.number_of_parameters();
-  if (it.frame()->is_optimized()) {
-    ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
-  } else {
-    if (argument_count < it.frame()->ComputeParametersCount()) {
-      argument_count = it.frame()->ComputeParametersCount();
-    }
+  if (argument_count < frame_inspector.GetParametersCount()) {
+    argument_count = frame_inspector.GetParametersCount();
   }
+#ifdef DEBUG
+  if (it.frame()->is_optimized()) {
+    ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
+  }
+#endif
 
   // Calculate the size of the result.
   int details_size = kFrameDetailsFirstDynamicIndex +
@@ -10170,13 +10229,7 @@
   details->set(kFrameDetailsFrameIdIndex, *frame_id);
 
   // Add the function (same as in function frame).
-  if (it.frame()->is_optimized()) {
-    // Get the function from the deoptimized frame.
-    details->set(kFrameDetailsFunctionIndex, deoptimized_frame->GetFunction());
-  } else {
-    // Get the function from the stack.
-    details->set(kFrameDetailsFunctionIndex, it.frame()->function());
-  }
+  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
 
   // Add the arguments count.
   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
@@ -10208,9 +10261,7 @@
   }
   if (it.frame()->is_optimized()) {
     flags |= 1 << 1;
-    if (deoptimized_frame_index > 0) {
-      flags |= 1 << 2;
-    }
+    flags |= inlined_frame_index << 2;
   }
   details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
 
@@ -10227,16 +10278,11 @@
     }
 
     // Parameter value.
-    if (it.frame()->is_optimized()) {
-      // Get the value from the deoptimized frame.
-      details->set(details_index++, deoptimized_frame->GetParameter(i));
+    if (i < it.frame()->ComputeParametersCount()) {
+      // Get the value from the stack.
+      details->set(details_index++, frame_inspector.GetParameter(i));
     } else {
-      if (i < it.frame()->ComputeParametersCount()) {
-        // Get the value from the stack.
-        details->set(details_index++, it.frame()->GetParameter(i));
-      } else {
-        details->set(details_index++, heap->undefined_value());
-      }
+      details->set(details_index++, heap->undefined_value());
     }
   }
 
@@ -10268,12 +10314,6 @@
   }
   details->set(kFrameDetailsReceiverIndex, *receiver);
 
-  // Get rid of the calculated deoptimized frame if any.
-  if (deoptimized_frame != NULL) {
-    Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame,
-                                                isolate);
-  }
-
   ASSERT_EQ(details_size, details_index);
   return *isolate->factory()->NewJSArrayWithElements(details);
 }
@@ -10309,12 +10349,15 @@
 
 // Create a plain JSObject which materializes the local scope for the specified
 // frame.
-static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
-                                              JavaScriptFrame* frame) {
+static Handle<JSObject> MaterializeLocalScope(
+    Isolate* isolate,
+    JavaScriptFrame* frame,
+    int inlined_frame_index) {
   Handle<JSFunction> function(JSFunction::cast(frame->function()));
   Handle<SharedFunctionInfo> shared(function->shared());
   Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
   ScopeInfo<> scope_info(*serialized_scope_info);
+  FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
 
   // Allocate and initialize a JSObject with all the arguments, stack locals
   // heap locals and extension properties of the debugged function.
@@ -10327,7 +10370,7 @@
         isolate,
         SetProperty(local_scope,
                     scope_info.parameter_name(i),
-                    Handle<Object>(frame->GetParameter(i), isolate),
+                    Handle<Object>(frame_inspector.GetParameter(i)),
                     NONE,
                     kNonStrictMode),
         Handle<JSObject>());
@@ -10339,7 +10382,7 @@
         isolate,
         SetProperty(local_scope,
                     scope_info.stack_slot_name(i),
-                    Handle<Object>(frame->GetExpression(i), isolate),
+                    Handle<Object>(frame_inspector.GetExpression(i)),
                     NONE,
                     kNonStrictMode),
         Handle<JSObject>());
@@ -10459,9 +10502,12 @@
     ScopeTypeCatch
   };
 
-  ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
+  ScopeIterator(Isolate* isolate,
+                JavaScriptFrame* frame,
+                int inlined_frame_index)
     : isolate_(isolate),
       frame_(frame),
+      inlined_frame_index_(inlined_frame_index),
       function_(JSFunction::cast(frame->function())),
       context_(Context::cast(frame->context())),
       local_done_(false),
@@ -10546,7 +10592,7 @@
         return Handle<JSObject>(CurrentContext()->global());
       case ScopeIterator::ScopeTypeLocal:
         // Materialize the content of the local scope into a JSObject.
-        return MaterializeLocalScope(isolate_, frame_);
+        return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
       case ScopeIterator::ScopeTypeWith:
         // Return the with object.
         return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
@@ -10626,6 +10672,7 @@
  private:
   Isolate* isolate_;
   JavaScriptFrame* frame_;
+  int inlined_frame_index_;
   Handle<JSFunction> function_;
   Handle<Context> context_;
   bool local_done_;
@@ -10654,7 +10701,9 @@
 
   // Count the visible scopes.
   int n = 0;
-  for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
+  for (ScopeIterator it(isolate, frame, 0);
+       !it.Done();
+       it.Next()) {
     n++;
   }
 
@@ -10669,14 +10718,15 @@
 // Return an array with scope details
 // args[0]: number: break id
 // args[1]: number: frame index
-// args[2]: number: scope index
+// args[2]: number: inlined frame index
+// args[3]: number: scope index
 //
 // The array returned contains the following information:
 // 0: Scope type
 // 1: Scope object
 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
   HandleScope scope(isolate);
-  ASSERT(args.length() == 3);
+  ASSERT(args.length() == 4);
 
   // Check arguments.
   Object* check;
@@ -10685,7 +10735,8 @@
     if (!maybe_check->ToObject(&check)) return maybe_check;
   }
   CONVERT_CHECKED(Smi, wrapped_id, args[1]);
-  CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
+  CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
+  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
 
   // Get the frame where the debugging is performed.
   StackFrame::Id id = UnwrapFrameId(wrapped_id);
@@ -10694,7 +10745,7 @@
 
   // Find the requested scope.
   int n = 0;
-  ScopeIterator it(isolate, frame);
+  ScopeIterator it(isolate, frame, inlined_frame_index);
   for (; !it.Done() && n < index; it.Next()) {
     n++;
   }
@@ -10724,7 +10775,9 @@
   // Print the scopes for the top frame.
   StackFrameLocator locator;
   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
-  for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
+  for (ScopeIterator it(isolate, frame, 0);
+       !it.Done();
+       it.Next()) {
     it.DebugPrint();
   }
 #endif
@@ -11117,6 +11170,7 @@
 // Runtime_DebugEvaluate.
 static Handle<Object> GetArgumentsObject(Isolate* isolate,
                                          JavaScriptFrame* frame,
+                                         int inlined_frame_index,
                                          Handle<JSFunction> function,
                                          Handle<SerializedScopeInfo> scope_info,
                                          const ScopeInfo<>* sinfo,
@@ -11128,6 +11182,7 @@
   if (sinfo->number_of_stack_slots() > 0) {
     index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
     if (index != -1) {
+      CHECK(false);
       return Handle<Object>(frame->GetExpression(index), isolate);
     }
   }
@@ -11140,7 +11195,9 @@
     }
   }
 
-  const int length = frame->ComputeParametersCount();
+  FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
+
+  int length = frame_inspector.GetParametersCount();
   Handle<JSObject> arguments =
       isolate->factory()->NewArgumentsObject(function, length);
   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
@@ -11148,7 +11205,7 @@
   AssertNoAllocation no_gc;
   WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
   for (int i = 0; i < length; i++) {
-    array->set(i, frame->GetParameter(i), mode);
+    array->set(i, frame_inspector.GetParameter(i), mode);
   }
   arguments->set_elements(*array);
   return arguments;
@@ -11175,7 +11232,7 @@
 
   // Check the execution state and decode arguments frame and source to be
   // evaluated.
-  ASSERT(args.length() == 5);
+  ASSERT(args.length() == 6);
   Object* check_result;
   { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
       RUNTIME_ARGUMENTS(isolate, args));
@@ -11184,9 +11241,10 @@
     }
   }
   CONVERT_CHECKED(Smi, wrapped_id, args[1]);
-  CONVERT_ARG_CHECKED(String, source, 2);
-  CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
-  Handle<Object> additional_context(args[4]);
+  CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
+  CONVERT_ARG_CHECKED(String, source, 3);
+  CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
+  Handle<Object> additional_context(args[5]);
 
   // Handle the processing of break.
   DisableBreak disable_break_save(disable_break);
@@ -11226,7 +11284,8 @@
 #endif
 
   // Materialize the content of the local scope into a JSObject.
-  Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
+  Handle<JSObject> local_scope = MaterializeLocalScope(
+      isolate, frame, inlined_frame_index);
   RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
 
   // Allocate a new context for the debug evaluation and set the extension
@@ -11275,7 +11334,8 @@
                       &has_pending_exception);
   if (has_pending_exception) return Failure::Exception();
 
-  Handle<Object> arguments = GetArgumentsObject(isolate, frame,
+  Handle<Object> arguments = GetArgumentsObject(isolate,
+                                                frame, inlined_frame_index,
                                                 function, scope_info,
                                                 &sinfo, function_context);
 
diff --git a/src/runtime.h b/src/runtime.h
index e59c82c..7bd58c8 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -372,7 +372,7 @@
   F(GetFrameCount, 1, 1) \
   F(GetFrameDetails, 2, 1) \
   F(GetScopeCount, 2, 1) \
-  F(GetScopeDetails, 3, 1) \
+  F(GetScopeDetails, 4, 1) \
   F(DebugPrintScopes, 0, 1) \
   F(GetThreadCount, 1, 1) \
   F(GetThreadDetails, 2, 1) \
@@ -385,7 +385,7 @@
   F(IsBreakOnException, 1, 1) \
   F(PrepareStep, 3, 1) \
   F(ClearStepping, 0, 1) \
-  F(DebugEvaluate, 5, 1) \
+  F(DebugEvaluate, 6, 1) \
   F(DebugEvaluateGlobal, 4, 1) \
   F(DebugGetLoadedScripts, 0, 1) \
   F(DebugReferencedBy, 3, 1) \
@@ -636,7 +636,7 @@
 
   MUST_USE_RESULT static MaybeObject* ForceDeleteObjectProperty(
       Isolate* isolate,
-      Handle<JSObject> object,
+      Handle<JSReceiver> object,
       Handle<Object> key);
 
   MUST_USE_RESULT static MaybeObject* GetObjectProperty(
diff --git a/src/scopes.cc b/src/scopes.cc
index c6e2a46..f25f5a3 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -116,25 +116,27 @@
 
 // Dummy constructor
 Scope::Scope(Type type)
-  : inner_scopes_(0),
-    variables_(false),
-    temps_(0),
-    params_(0),
-    unresolved_(0),
-    decls_(0),
-    already_resolved_(false) {
+    : isolate_(Isolate::Current()),
+      inner_scopes_(0),
+      variables_(false),
+      temps_(0),
+      params_(0),
+      unresolved_(0),
+      decls_(0),
+      already_resolved_(false) {
   SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null());
 }
 
 
 Scope::Scope(Scope* outer_scope, Type type)
-  : inner_scopes_(4),
-    variables_(),
-    temps_(4),
-    params_(4),
-    unresolved_(16),
-    decls_(4),
-    already_resolved_(false) {
+    : isolate_(Isolate::Current()),
+      inner_scopes_(4),
+      variables_(),
+      temps_(4),
+      params_(4),
+      unresolved_(16),
+      decls_(4),
+      already_resolved_(false) {
   SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
   // At some point we might want to provide outer scopes to
   // eval scopes (by walking the stack and reading the scope info).
@@ -145,13 +147,14 @@
 
 
 Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
-  : inner_scopes_(4),
-    variables_(),
-    temps_(4),
-    params_(4),
-    unresolved_(16),
-    decls_(4),
-    already_resolved_(true) {
+    : isolate_(Isolate::Current()),
+      inner_scopes_(4),
+      variables_(),
+      temps_(4),
+      params_(4),
+      unresolved_(16),
+      decls_(4),
+      already_resolved_(true) {
   ASSERT(!scope_info.is_null());
   SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
   if (scope_info->HasHeapAllocatedLocals()) {
@@ -162,7 +165,8 @@
 
 
 Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
-    : inner_scopes_(1),
+    : isolate_(Isolate::Current()),
+      inner_scopes_(1),
       variables_(),
       temps_(0),
       params_(0),
@@ -186,7 +190,7 @@
                         Handle<SerializedScopeInfo> scope_info) {
   outer_scope_ = outer_scope;
   type_ = type;
-  scope_name_ = FACTORY->empty_symbol();
+  scope_name_ = isolate_->factory()->empty_symbol();
   dynamics_ = NULL;
   receiver_ = NULL;
   function_ = NULL;
@@ -295,9 +299,12 @@
     receiver_ = outer_scope()->receiver();
   } else {
     Variable* var =
-        variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
-                           false, Variable::THIS);
-    var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
+        variables_.Declare(this,
+                           isolate_->factory()->this_symbol(),
+                           Variable::VAR,
+                           false,
+                           Variable::THIS);
+    var->set_rewrite(new(isolate_->zone()) Slot(var, Slot::PARAMETER, -1));
     receiver_ = var;
   }
 
@@ -305,8 +312,11 @@
     // Declare 'arguments' variable which exists in all functions.
     // Note that it might never be accessed, in which case it won't be
     // allocated during variable allocation.
-    variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR,
-                       true, Variable::ARGUMENTS);
+    variables_.Declare(this,
+                       isolate_->factory()->arguments_symbol(),
+                       Variable::VAR,
+                       true,
+                       Variable::ARGUMENTS);
   }
 }
 
@@ -320,7 +330,7 @@
   //
   // We should never lookup 'arguments' in this scope as it is implicitly
   // present in every scope.
-  ASSERT(*name != *FACTORY->arguments_symbol());
+  ASSERT(*name != *isolate_->factory()->arguments_symbol());
   // There should be no local slot with the given name.
   ASSERT(scope_info_->StackSlotIndex(*name) < 0);
 
@@ -340,7 +350,7 @@
 
   Variable* var =
       variables_.Declare(this, name, mode, true, Variable::NORMAL);
-  var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
+  var->set_rewrite(new(isolate_->zone()) Slot(var, Slot::CONTEXT, index));
   return var;
 }
 
@@ -397,7 +407,8 @@
   // the same name because they may be removed selectively via
   // RemoveUnresolved().
   ASSERT(!already_resolved());
-  VariableProxy* proxy = new VariableProxy(name, false, inside_with, position);
+  VariableProxy* proxy =
+      new(isolate_->zone()) VariableProxy(name, false, inside_with, position);
   unresolved_.Add(proxy);
   return proxy;
 }
@@ -697,7 +708,7 @@
     // Declare a new non-local.
     var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
     // Allocate it by giving it a dynamic lookup.
-    var->set_rewrite(new Slot(var, Slot::LOOKUP, -1));
+    var->set_rewrite(new(isolate_->zone()) Slot(var, Slot::LOOKUP, -1));
   }
   return var;
 }
@@ -943,26 +954,30 @@
 
 bool Scope::HasArgumentsParameter() {
   for (int i = 0; i < params_.length(); i++) {
-    if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol()))
+    if (params_[i]->name().is_identical_to(
+            isolate_->factory()->arguments_symbol())) {
       return true;
+    }
   }
   return false;
 }
 
 
 void Scope::AllocateStackSlot(Variable* var) {
-  var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++));
+  var->set_rewrite(
+      new(isolate_->zone()) Slot(var, Slot::LOCAL, num_stack_slots_++));
 }
 
 
 void Scope::AllocateHeapSlot(Variable* var) {
-  var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++));
+  var->set_rewrite(
+      new(isolate_->zone()) Slot(var, Slot::CONTEXT, num_heap_slots_++));
 }
 
 
 void Scope::AllocateParameterLocals() {
   ASSERT(is_function_scope());
-  Variable* arguments = LocalLookup(FACTORY->arguments_symbol());
+  Variable* arguments = LocalLookup(isolate_->factory()->arguments_symbol());
   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
 
   bool uses_nonstrict_arguments = false;
@@ -1009,7 +1024,7 @@
       } else {
         ASSERT(var->rewrite() == NULL || var->IsParameter());
         if (var->rewrite() == NULL) {
-          var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
+          var->set_rewrite(new(isolate_->zone()) Slot(var, Slot::PARAMETER, i));
         }
       }
     }
@@ -1020,7 +1035,7 @@
 void Scope::AllocateNonParameterLocal(Variable* var) {
   ASSERT(var->scope() == this);
   ASSERT(var->rewrite() == NULL ||
-         !var->IsVariable(FACTORY->result_symbol()) ||
+         !var->IsVariable(isolate_->factory()->result_symbol()) ||
          var->AsSlot() == NULL ||
          var->AsSlot()->type() != Slot::LOCAL);
   if (var->rewrite() == NULL && MustAllocate(var)) {
diff --git a/src/scopes.h b/src/scopes.h
index a493d57..031ea3d 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -319,6 +319,8 @@
 
   explicit Scope(Type type);
 
+  Isolate* const isolate_;
+
   // Scope tree.
   Scope* outer_scope_;  // the immediately enclosing outer scope, or NULL
   ZoneList<Scope*> inner_scopes_;  // the immediately enclosed inner scopes
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 93c50fa..ffe4241 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -662,6 +662,8 @@
 
   static void GenerateLoadFastElement(MacroAssembler* masm);
 
+  static void GenerateLoadFastDoubleElement(MacroAssembler* masm);
+
   static void GenerateLoadDictionaryElement(MacroAssembler* masm);
 
  private:
@@ -717,6 +719,9 @@
   static void GenerateStoreFastElement(MacroAssembler* masm,
                                        bool is_js_array);
 
+  static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
+                                             bool is_js_array);
+
   static void GenerateStoreExternalArray(MacroAssembler* masm,
                                          JSObject::ElementsKind elements_kind);
 
diff --git a/src/v8.cc b/src/v8.cc
index 11af057..36f835f 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -50,6 +50,9 @@
 bool V8::has_fatal_error_ = false;
 bool V8::use_crankshaft_ = true;
 
+static Mutex* entropy_mutex = OS::CreateMutex();
+static EntropySource entropy_source;
+
 
 bool V8::Initialize(Deserializer* des) {
   InitializeOncePerProcess();
@@ -102,8 +105,14 @@
 
 static void seed_random(uint32_t* state) {
   for (int i = 0; i < 2; ++i) {
-    state[i] = FLAG_random_seed;
-    while (state[i] == 0) {
+    if (FLAG_random_seed != 0) {
+      state[i] = FLAG_random_seed;
+    } else if (entropy_source != NULL) {
+      uint32_t val;
+      ScopedLock lock(entropy_mutex);
+      entropy_source(reinterpret_cast<unsigned char*>(&val), sizeof(uint32_t));
+      state[i] = val;
+    } else {
       state[i] = random();
     }
   }
@@ -124,6 +133,11 @@
 }
 
 
+void V8::SetEntropySource(EntropySource source) {
+  entropy_source = source;
+}
+
+
 // Used by JavaScript APIs
 uint32_t V8::Random(Isolate* isolate) {
   ASSERT(isolate == Isolate::Current());
diff --git a/src/v8.h b/src/v8.h
index e74a60c..e565ca5 100644
--- a/src/v8.h
+++ b/src/v8.h
@@ -91,6 +91,9 @@
   static void FatalProcessOutOfMemory(const char* location,
                                       bool take_snapshot = false);
 
+  // Allows an entropy source to be provided for use in random number
+  // generation.
+  static void SetEntropySource(EntropySource source);
   // Random number generation support. Not cryptographically safe.
   static uint32_t Random(Isolate* isolate);
   // We use random numbers internally in memory allocation and in the
diff --git a/src/v8globals.h b/src/v8globals.h
index d86f299..aff2757 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -506,6 +506,16 @@
   CALL_AS_FUNCTION
 };
 
+
+static const uint32_t kHoleNanUpper32 = 0x7FFFFFFF;
+static const uint32_t kHoleNanLower32 = 0xFFFFFFFF;
+static const uint32_t kNaNOrInfinityLowerBoundUpper32 = 0x7FF00000;
+
+const uint64_t kHoleNanInt64 =
+    (static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
+const uint64_t kLastNonNaNInt64 =
+    (static_cast<uint64_t>(kNaNOrInfinityLowerBoundUpper32) << 32);
+
 } }  // namespace v8::internal
 
 #endif  // V8_V8GLOBALS_H_
diff --git a/src/version.cc b/src/version.cc
index ee5411d..b0a346d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     4
-#define BUILD_NUMBER      12
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      13
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index 4c12904..c23eb16 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -125,7 +125,7 @@
     return names[index];
   }
 
-  static Register toRegister(int code) {
+  static Register from_code(int code) {
     Register r = { code };
     return r;
   }
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index 7eb08f7..6f48320 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -643,7 +643,7 @@
   // We push all registers onto the stack, even though we do not need
   // to restore all later.
   for (int i = 0; i < kNumberOfRegisters; i++) {
-    Register r = Register::toRegister(i);
+    Register r = Register::from_code(i);
     __ push(r);
   }
 
@@ -801,12 +801,12 @@
 
   // Restore the registers from the stack.
   for (int i = kNumberOfRegisters - 1; i >= 0 ; i--) {
-    Register r = Register::toRegister(i);
+    Register r = Register::from_code(i);
     // Do not restore rsp, simply pop the value into the next register
     // and overwrite this afterwards.
     if (r.is(rsp)) {
       ASSERT(i > 0);
-      r = Register::toRegister(i - 1);
+      r = Register::from_code(i - 1);
     }
     __ pop(r);
   }
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 1df0228..2b15553 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -385,6 +385,9 @@
                 Heap::kFixedArrayMapRootIndex);
     j(equal, &ok, Label::kNear);
     CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
+                Heap::kFixedDoubleArrayMapRootIndex);
+    j(equal, &ok, Label::kNear);
+    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
                 Heap::kFixedCOWArrayMapRootIndex);
     j(equal, &ok, Label::kNear);
     Abort("JSObject with fast elements map has slow elements");
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 71ce856..d4f9d7c 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -3584,6 +3584,57 @@
 }
 
 
+void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
+    MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- rax    : key
+  //  -- rdx    : receiver
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  Label miss_force_generic, slow_allocate_heapnumber;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(rax, &miss_force_generic);
+
+  // Get the elements array.
+  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ AssertFastElements(rcx);
+
+  // Check that the key is within bounds.
+  __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
+  __ j(above_equal, &miss_force_generic);
+
+  // Check for the hole
+  __ SmiToInteger32(kScratchRegister, rax);
+  uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
+  __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset),
+          Immediate(kHoleNanUpper32));
+  __ j(equal, &miss_force_generic);
+
+  // Always allocate a heap number for the result.
+  __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8,
+                              FixedDoubleArray::kHeaderSize));
+  __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
+  // Set the value.
+  __ movq(rax, rcx);
+  __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
+  __ ret(0);
+
+  __ bind(&slow_allocate_heapnumber);
+  Handle<Code> slow_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_Slow();
+  __ jmp(slow_ic, RelocInfo::CODE_TARGET);
+
+  __ bind(&miss_force_generic);
+  Handle<Code> miss_ic =
+      masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
+  __ jmp(miss_ic, RelocInfo::CODE_TARGET);
+}
+
+
 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
                                                       bool is_js_array) {
   // ----------- S t a t e -------------
@@ -3634,6 +3685,92 @@
 }
 
 
+void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
+    MacroAssembler* masm,
+    bool is_js_array) {
+  // ----------- S t a t e -------------
+  //  -- rax    : value
+  //  -- rcx    : key
+  //  -- rdx    : receiver
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  Label miss_force_generic, smi_value, is_nan, maybe_nan;
+  Label have_double_value, not_nan;
+
+  // This stub is meant to be tail-jumped to, the receiver must already
+  // have been verified by the caller to not be a smi.
+
+  // Check that the key is a smi.
+  __ JumpIfNotSmi(rcx, &miss_force_generic);
+
+  // Get the elements array.
+  __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ AssertFastElements(rdi);
+
+  // Check that the key is within bounds.
+  if (is_js_array) {
+    __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
+  } else {
+    __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
+  }
+  __ j(above_equal, &miss_force_generic);
+
+  // Handle smi values specially
+  __ JumpIfSmi(rax, &smi_value, Label::kNear);
+
+  __ CheckMap(rax,
+              masm->isolate()->factory()->heap_number_map(),
+              &miss_force_generic,
+              DONT_DO_SMI_CHECK);
+
+  // Double value, canonicalize NaN.
+  uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
+  __ cmpl(FieldOperand(rax, offset),
+          Immediate(kNaNOrInfinityLowerBoundUpper32));
+  __ j(greater_equal, &maybe_nan, Label::kNear);
+
+  __ bind(&not_nan);
+  __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
+  __ bind(&have_double_value);
+  __ SmiToInteger32(rcx, rcx);
+  __ movsd(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize),
+           xmm0);
+  __ ret(0);
+
+  __ bind(&maybe_nan);
+  // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
+  // it's an Infinity, and the non-NaN code path applies.
+  __ j(greater, &is_nan, Label::kNear);
+  __ cmpl(FieldOperand(rax, HeapNumber::kValueOffset), Immediate(0));
+  __ j(zero, &not_nan);
+  __ bind(&is_nan);
+  // Convert all NaNs to the same canonical NaN value when they are stored in
+  // the double array.
+  ExternalReference canonical_nan_reference =
+      ExternalReference::address_of_canonical_non_hole_nan();
+  __ Set(kScratchRegister, BitCast<uint64_t>(
+      FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
+  __ movq(xmm0, kScratchRegister);
+  __ jmp(&have_double_value, Label::kNear);
+
+  __ bind(&smi_value);
+  // Value is a smi. convert to a double and store.
+  __ SmiToInteger32(rax, rax);
+  __ push(rax);
+  __ fild_s(Operand(rsp, 0));
+  __ pop(rax);
+  __ SmiToInteger32(rcx, rcx);
+  __ fstp_d(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize));
+  __ ret(0);
+
+  // Handle store cache miss, replacing the ic with the generic stub.
+  __ bind(&miss_force_generic);
+  Handle<Code> ic_force_generic =
+      masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
+  __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
diff --git a/src/zone.h b/src/zone.h
index af9c916..abb53ad 100644
--- a/src/zone.h
+++ b/src/zone.h
@@ -74,6 +74,8 @@
 
   inline void adjust_segment_bytes_allocated(int delta);
 
+  inline Isolate* isolate() { return isolate_; }
+
   static unsigned allocation_size_;
 
  private:
diff --git a/test/cctest/SConscript b/test/cctest/SConscript
index 0ef5667..b0a7166 100644
--- a/test/cctest/SConscript
+++ b/test/cctest/SConscript
@@ -29,9 +29,23 @@
 from os.path import join, dirname, abspath
 root_dir = dirname(File('SConstruct').rfile().abspath)
 sys.path.append(join(root_dir, 'tools'))
+import js2c
 Import('context object_files tools')
 
 
+# Needed for test-log. Paths are relative to the cctest dir.
+JS_FILES_FOR_TESTS = [
+  '../../../tools/splaytree.js',
+  '../../../tools/codemap.js',
+  '../../../tools/csvparser.js',
+  '../../../tools/consarray.js',
+  '../../../tools/profile.js',
+  '../../../tools/profile_view.js',
+  '../../../tools/logreader.js',
+  'log-eq-of-logging-and-traversal.js',
+]
+
+
 SOURCES = {
   'all': [
     'gay-fixed.cc',
@@ -109,9 +123,19 @@
   env = Environment(tools=tools)
   env.Replace(**context.flags['cctest'])
   context.ApplyEnvOverrides(env)
+  env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
+
+  # Combine the JavaScript library files into a single C++ file and
+  # compile it.
+  js_files = [s for s in JS_FILES_FOR_TESTS]
+  js_files_src = env.JS2C(
+    ['js-files-for-cctest.cc'], js_files, **{'TYPE': 'TEST', 'COMPRESSION': 'off'})
+  js_files_obj = context.ConfigureObject(env, js_files_src, CPPPATH=['.'])
+
   # There seems to be a glitch in the way scons decides where to put
   # PDB files when compiling using MSVC so we specify it manually.
   # This should not affect any other platforms.
+  object_files.append(js_files_obj)
   return env.Program('cctest', ['cctest.cc', cctest_files, object_files],
       PDB='cctest.exe.pdb')
 
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 0a74ce3..9cbcb9c 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -26,6 +26,9 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 {
+  'variables': {
+    'generated_file': '<(SHARED_INTERMEDIATE_DIR)/resources.cc',
+  },
   'includes': [ '../../build/v8-features.gypi' ],
   'targets': [
     {
@@ -33,11 +36,13 @@
       'type': 'executable',
       'dependencies': [
         '../../tools/gyp/v8.gyp:v8',
+        'resources',
       ],
       'include_dirs': [
         '../../src',
       ],
       'sources': [
+        '<(generated_file)',
         'cctest.cc',
         'gay-fixed.cc',
         'gay-precision.cc',
@@ -131,5 +136,41 @@
         }],
       ],
     },
+    {
+      'target_name': 'resources',
+      'type': 'none',
+      'variables': {
+        'file_list': [
+           '../../tools/splaytree.js',
+           '../../tools/codemap.js',
+           '../../tools/csvparser.js',
+           '../../tools/consarray.js',
+           '../../tools/profile.js',
+           '../../tools/profile_view.js',
+           '../../tools/logreader.js',
+           'log-eq-of-logging-and-traversal.js',
+        ],
+      },
+      'actions': [
+        {
+          'action_name': 'js2c',
+          'inputs': [
+            '../../tools/js2c.py',
+            '<@(file_list)',
+          ],
+          'outputs': [
+            '<(generated_file)',
+          ],
+          'action': [
+            'python',
+            '../../tools/js2c.py',
+            '<@(_outputs)',
+            'TEST',  # type
+            'off',  # compression
+            '<@(file_list)',
+          ],
+        }
+      ],
+    },
   ],
 }
diff --git a/test/cctest/log-eq-of-logging-and-traversal.js b/test/cctest/log-eq-of-logging-and-traversal.js
index e661efe..cd52da5 100644
--- a/test/cctest/log-eq-of-logging-and-traversal.js
+++ b/test/cctest/log-eq-of-logging-and-traversal.js
@@ -137,36 +137,38 @@
     return entityA.size === entityB.size && entityNamesEqual(entityA, entityB);
   }
 
-  var i = 0, j = 0, k = logging_entries.length, l = traversal_entries.length;
+  var l_pos = 0, t_pos = 0;
+  var l_len = logging_entries.length, t_len = traversal_entries.length;
   var comparison = [];
   var equal = true;
   // Do a merge-like comparison of entries. At the same address we expect to
   // find the same entries. We skip builtins during log parsing, but compiled
   // functions traversal may erroneously recognize them as functions, so we are
   // expecting more functions in traversal vs. logging.
-  while (i < k && j < l) {
-    var entryA = logging_entries[i], entryB = traversal_entries[j];
+  while (l_pos < l_len && t_pos < t_len) {
+    var entryA = logging_entries[l_pos];
+    var entryB = traversal_entries[t_pos];
     var cmp = addressComparator(entryA, entryB);
     var entityA = entryA[1], entityB = entryB[1];
     var address = entryA[0];
     if (cmp < 0) {
-      ++i;
+      ++l_pos;
       entityB = null;
     } else if (cmp > 0) {
-      ++j;
+      ++t_pos;
       entityA = null;
       address = entryB[0];
     } else {
-      ++i;
-      ++j;
+      ++l_pos;
+      ++t_pos;
     }
     var entities_equal = entitiesEqual(entityA, entityB);
     if (!entities_equal) equal = false;
     comparison.push([entities_equal, address, entityA, entityB]);
   }
-  if (i < k) equal = false;
-  while (i < k) {
-    var entryA = logging_entries[i++];
+  if (l_pos < l_len) equal = false;
+  while (l_pos < l_len) {
+    var entryA = logging_entries[l_pos++];
     comparison.push([false, entryA[0], entryA[1], null]);
   }
   return [equal, comparison];
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 8d8770f..9769fb7 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1026,6 +1026,90 @@
 }
 
 
+THREADED_TEST(IsNativeError) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<Value> syntax_error = CompileRun(
+      "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
+  CHECK(syntax_error->IsNativeError());
+  v8::Handle<Value> not_error = CompileRun("{a:42}");
+  CHECK(!not_error->IsNativeError());
+  v8::Handle<Value> not_object = CompileRun("42");
+  CHECK(!not_object->IsNativeError());
+}
+
+
+THREADED_TEST(StringObject) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
+  CHECK(boxed_string->IsStringObject());
+  v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
+  CHECK(!unboxed_string->IsStringObject());
+  v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
+  CHECK(!boxed_not_string->IsStringObject());
+  v8::Handle<Value> not_object = CompileRun("0");
+  CHECK(!not_object->IsStringObject());
+  v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
+  CHECK(!as_boxed.IsEmpty());
+  Local<v8::String> the_string = as_boxed->StringValue();
+  CHECK(!the_string.IsEmpty());
+  ExpectObject("\"test\"", the_string);
+  v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
+  CHECK(new_boxed_string->IsStringObject());
+  as_boxed = new_boxed_string.As<v8::StringObject>();
+  the_string = as_boxed->StringValue();
+  CHECK(!the_string.IsEmpty());
+  ExpectObject("\"test\"", the_string);
+}
+
+
+THREADED_TEST(NumberObject) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
+  CHECK(boxed_number->IsNumberObject());
+  v8::Handle<Value> unboxed_number = CompileRun("42");
+  CHECK(!unboxed_number->IsNumberObject());
+  v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
+  CHECK(!boxed_not_number->IsNumberObject());
+  v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
+  CHECK(!as_boxed.IsEmpty());
+  double the_number = as_boxed->NumberValue();
+  CHECK_EQ(42.0, the_number);
+  v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
+  CHECK(new_boxed_number->IsNumberObject());
+  as_boxed = new_boxed_number.As<v8::NumberObject>();
+  the_number = as_boxed->NumberValue();
+  CHECK_EQ(43.0, the_number);
+}
+
+
+THREADED_TEST(BooleanObject) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
+  CHECK(boxed_boolean->IsBooleanObject());
+  v8::Handle<Value> unboxed_boolean = CompileRun("true");
+  CHECK(!unboxed_boolean->IsBooleanObject());
+  v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
+  CHECK(!boxed_not_boolean->IsBooleanObject());
+  v8::Handle<v8::BooleanObject> as_boxed =
+      boxed_boolean.As<v8::BooleanObject>();
+  CHECK(!as_boxed.IsEmpty());
+  bool the_boolean = as_boxed->BooleanValue();
+  CHECK_EQ(true, the_boolean);
+  v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
+  v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
+  CHECK(boxed_true->IsBooleanObject());
+  CHECK(boxed_false->IsBooleanObject());
+  as_boxed = boxed_true.As<v8::BooleanObject>();
+  CHECK_EQ(true, as_boxed->BooleanValue());
+  as_boxed = boxed_false.As<v8::BooleanObject>();
+  CHECK_EQ(false, as_boxed->BooleanValue());
+}
+
+
 THREADED_TEST(Number) {
   v8::HandleScope scope;
   LocalContext env;
diff --git a/test/cctest/test-ast.cc b/test/cctest/test-ast.cc
index d1e537d..786a54a 100644
--- a/test/cctest/test-ast.cc
+++ b/test/cctest/test-ast.cc
@@ -40,7 +40,7 @@
   CHECK_EQ(0, list->length());
 
   ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
-  AstNode* node = new EmptyStatement();
+  AstNode* node = new(ZONE) EmptyStatement();
   list->Add(node);
   CHECK_EQ(1, list->length());
   CHECK_EQ(node, list->at(0));
diff --git a/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 5704b07..262e7bb 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -12,6 +12,7 @@
 #include "v8.h"
 #include "log.h"
 #include "cpu-profiler.h"
+#include "natives.h"
 #include "v8threads.h"
 #include "v8utils.h"
 #include "cctest.h"
@@ -469,6 +470,8 @@
 }
 
 
+typedef i::NativesCollection<i::TEST> TestSources;
+
 // Test that logging of code create / move / delete events
 // is equivalent to traversal of a resulting heap.
 TEST(EquivalenceOfLoggingAndTraversal) {
@@ -505,38 +508,25 @@
   v8::Handle<v8::String> log_str = v8::String::New(log.start(), log.length());
   initialize_logger.env()->Global()->Set(v8_str("_log"), log_str);
 
-  const char* scripts[] = {
-    "tools/splaytree.js", "tools/codemap.js", "tools/csvparser.js",
-    "tools/consarray.js", "tools/profile.js", "tools/profile_view.js",
-    "tools/logreader.js", "test/cctest/log-eq-of-logging-and-traversal.js"
-  };
-  int scripts_count = sizeof(scripts) / sizeof(scripts[0]);
-  v8::Handle<v8::Value> last_result;
-  for (int i = 0; i < scripts_count; ++i) {
-    bool exists = true;
-    i::Vector<const char> source(i::ReadFile(scripts[i], &exists, true));
-    CHECK(exists);
-    CHECK_GT(source.length(), 0);
-    v8::Handle<v8::String> source_str =
-        v8::String::New(source.start(), source.length());
-    v8::TryCatch try_catch;
-    v8::Handle<v8::Script> script =
-        v8::Script::Compile(source_str, v8_str(scripts[i]));
-    if (script.IsEmpty()) {
-      v8::String::Utf8Value exception(try_catch.Exception());
-      printf("compile %s: %s\n", scripts[i], *exception);
-      CHECK(false);
-    }
-    last_result = script->Run();
-    if (last_result.IsEmpty()) {
-      v8::String::Utf8Value exception(try_catch.Exception());
-      printf("run %s: %s\n", scripts[i], *exception);
-      CHECK(false);
-    }
+  i::Vector<const unsigned char> source = TestSources::GetScriptsSource();
+  v8::Handle<v8::String> source_str = v8::String::New(
+      reinterpret_cast<const char*>(source.start()), source.length());
+  v8::TryCatch try_catch;
+  v8::Handle<v8::Script> script = v8::Script::Compile(source_str, v8_str(""));
+  if (script.IsEmpty()) {
+    v8::String::Utf8Value exception(try_catch.Exception());
+    printf("compile: %s\n", *exception);
+    CHECK(false);
+  }
+  v8::Handle<v8::Value> result = script->Run();
+  if (result.IsEmpty()) {
+    v8::String::Utf8Value exception(try_catch.Exception());
+    printf("run: %s\n", *exception);
+    CHECK(false);
   }
   // The result either be a "true" literal or problem description.
-  if (!last_result->IsTrue()) {
-    v8::Local<v8::String> s = last_result->ToString();
+  if (!result->IsTrue()) {
+    v8::Local<v8::String> s = result->ToString();
     i::ScopedVector<char> data(s->Length() + 1);
     CHECK_NE(NULL, data.start());
     s->WriteAscii(data.start());
diff --git a/test/mjsunit/debug-evaluate-locals-optimized-double.js b/test/mjsunit/debug-evaluate-locals-optimized-double.js
index 584d1af..9ed1dbb 100644
--- a/test/mjsunit/debug-evaluate-locals-optimized-double.js
+++ b/test/mjsunit/debug-evaluate-locals-optimized-double.js
@@ -44,21 +44,44 @@
       for (var i = 0; i < exec_state.frameCount(); i++) {
         var frame = exec_state.frame(i);
         if (i < exec_state.frameCount() - 1) {
-        // All frames except the bottom one has normal variables a and b.
+          var expected_a = i * 2 + 1 + (i * 2 + 1) / 100;
+          var expected_b = i * 2 + 2 + (i * 2 + 2) / 100;
+          var expected_x = (i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100;
+          var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100;
+
+          // All frames except the bottom one has normal variables a and b.
           assertEquals('a', frame.localName(0));
           assertEquals('b', frame.localName(1));
-          assertEquals(i * 2 + 1 + (i * 2 + 1) / 100,
-                       frame.localValue(0).value());
-          assertEquals(i * 2 + 2 + (i * 2 + 2) / 100,
-                       frame.localValue(1).value());
+          assertEquals(expected_a, frame.localValue(0).value());
+          assertEquals(expected_b, frame.localValue(1).value());
 
           // All frames except the bottom one has arguments variables x and y.
           assertEquals('x', frame.argumentName(0));
           assertEquals('y', frame.argumentName(1));
-          assertEquals((i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100,
-                       frame.argumentValue(0).value());
-          assertEquals((i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100,
-                       frame.argumentValue(1).value());
+          assertEquals(expected_x, frame.argumentValue(0).value());
+          assertEquals(expected_y, frame.argumentValue(1).value());
+
+          // All frames except the bottom one have two scopes.
+          assertEquals(2, frame.scopeCount());
+          assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
+          assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
+          assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
+          assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']);
+          assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']);
+          assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']);
+
+          // Evaluate in the inlined frame.
+          assertEquals(expected_a, frame.evaluate('a').value());
+          assertEquals(expected_x, frame.evaluate('x').value());
+          assertEquals(expected_x, frame.evaluate('arguments[0]').value());
+          assertEquals(expected_a + expected_b + expected_x + expected_y,
+                       frame.evaluate('a + b + x + y').value());
+          assertEquals(expected_x + expected_y,
+                       frame.evaluate('arguments[0] + arguments[1]').value());
+        } else {
+          // The bottom frame only have the global scope.
+          assertEquals(1, frame.scopeCount());
+          assertEquals(debug.ScopeType.Global, frame.scope(0).scopeType());
         }
 
         // Check the frame function.
@@ -75,12 +98,13 @@
         // Check for construct call.
         assertEquals(testingConstructCall && i == 4, frame.isConstructCall());
 
-        // When function f is optimized (2 means YES, see runtime.cc) we
+        // When function f is optimized (1 means YES, see runtime.cc) we
         // expect an optimized frame for f with g1, g2 and g3 inlined.
-        if (%GetOptimizationStatus(f) == 2) {
+        if (%GetOptimizationStatus(f) == 1) {
           if (i == 1 || i == 2 || i == 3) {
             assertTrue(frame.isOptimizedFrame());
             assertTrue(frame.isInlinedFrame());
+            assertEquals(4 - i, frame.inlinedFrameIndex());
           } else if (i == 4) {
             assertTrue(frame.isOptimizedFrame());
             assertFalse(frame.isInlinedFrame());
diff --git a/test/mjsunit/debug-evaluate-locals-optimized.js b/test/mjsunit/debug-evaluate-locals-optimized.js
index 1aaf296..683c139 100644
--- a/test/mjsunit/debug-evaluate-locals-optimized.js
+++ b/test/mjsunit/debug-evaluate-locals-optimized.js
@@ -44,17 +44,44 @@
       for (var i = 0; i < exec_state.frameCount(); i++) {
         var frame = exec_state.frame(i);
         if (i < exec_state.frameCount() - 1) {
+          var expected_a = i * 2 + 1;
+          var expected_b = i * 2 + 2;
+          var expected_x = (i + 1) * 2 + 1;
+          var expected_y = (i + 1) * 2 + 2;
+
           // All frames except the bottom one has normal variables a and b.
           assertEquals('a', frame.localName(0));
           assertEquals('b', frame.localName(1));
-          assertEquals(i * 2 + 1, frame.localValue(0).value());
-          assertEquals(i * 2 + 2, frame.localValue(1).value());
+          assertEquals(expected_a, frame.localValue(0).value());
+          assertEquals(expected_b, frame.localValue(1).value());
 
           // All frames except the bottom one has arguments variables x and y.
           assertEquals('x', frame.argumentName(0));
           assertEquals('y', frame.argumentName(1));
-          assertEquals((i + 1) * 2 + 1, frame.argumentValue(0).value());
-          assertEquals((i + 1) * 2 + 2, frame.argumentValue(1).value());
+          assertEquals(expected_x, frame.argumentValue(0).value());
+          assertEquals(expected_y, frame.argumentValue(1).value());
+
+          // All frames except the bottom one have two scopes.
+          assertEquals(2, frame.scopeCount());
+          assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
+          assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
+          assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
+          assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']);
+          assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']);
+          assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']);
+
+          // Evaluate in the inlined frame.
+          assertEquals(expected_a, frame.evaluate('a').value());
+          assertEquals(expected_x, frame.evaluate('x').value());
+          assertEquals(expected_x, frame.evaluate('arguments[0]').value());
+          assertEquals(expected_a + expected_b + expected_x + expected_y,
+                       frame.evaluate('a + b + x + y').value());
+          assertEquals(expected_x + expected_y,
+                       frame.evaluate('arguments[0] + arguments[1]').value());
+        } else {
+          // The bottom frame only have the global scope.
+          assertEquals(1, frame.scopeCount());
+          assertEquals(debug.ScopeType.Global, frame.scope(0).scopeType());
         }
 
         // Check the frame function.
@@ -71,12 +98,13 @@
         // Check for construct call.
         assertEquals(testingConstructCall && i == 4, frame.isConstructCall());
 
-        // When function f is optimized (2 means YES, see runtime.cc) we
+        // When function f is optimized (1 means YES, see runtime.cc) we
         // expect an optimized frame for f with g1, g2 and g3 inlined.
-        if (%GetOptimizationStatus(f) == 2) {
+        if (%GetOptimizationStatus(f) == 1) {
           if (i == 1 || i == 2 || i == 3) {
             assertTrue(frame.isOptimizedFrame());
             assertTrue(frame.isInlinedFrame());
+            assertEquals(4 - i, frame.inlinedFrameIndex());
           } else if (i == 4) {
             assertTrue(frame.isOptimizedFrame());
             assertFalse(frame.isInlinedFrame());
diff --git a/test/mjsunit/harmony/proxies.js b/test/mjsunit/harmony/proxies.js
index 37f3513..f87d756 100644
--- a/test/mjsunit/harmony/proxies.js
+++ b/test/mjsunit/harmony/proxies.js
@@ -289,6 +289,50 @@
 
 
 
+// Property deletion (delete).
+
+var key
+function TestDelete(handler) {
+  var o = Proxy.create(handler)
+  assertEquals(true, delete o.a)
+  assertEquals("a", key)
+  assertEquals(true, delete o["b"])
+  assertEquals("b", key)
+
+  assertEquals(false, delete o.z1)
+  assertEquals("z1", key)
+  assertEquals(false, delete o["z2"])
+  assertEquals("z2", key);
+
+  (function() {
+    "use strict"
+    assertEquals(true, delete o.c)
+    assertEquals("c", key)
+    assertEquals(true, delete o["d"])
+    assertEquals("d", key)
+
+    assertThrows(function() { delete o.z3 }, TypeError)
+    assertEquals("z3", key)
+    assertThrows(function() { delete o["z4"] }, TypeError)
+    assertEquals("z4", key)
+  })()
+}
+
+TestDelete({
+  'delete': function(k) { key = k; return k < "z" }
+})
+TestDelete({
+  'delete': function(k) { return this.delete2(k) },
+  delete2: function(k) { key = k; return k < "z" }
+})
+TestDelete(Proxy.create({
+  get: function(pr, pk) {
+    return function(k) { key = k; return k < "z" }
+  }
+}))
+
+
+
 // Property descriptors (Object.getOwnPropertyDescriptor).
 
 function TestDescriptor(handler) {
diff --git a/test/mjsunit/regress/regress-1560.js b/test/mjsunit/regress/regress-1560.js
new file mode 100644
index 0000000..a0aa7e6
--- /dev/null
+++ b/test/mjsunit/regress/regress-1560.js
@@ -0,0 +1,68 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --expose-gc
+
+function mkCOWArray() {
+  var a = [''];
+  assertEquals('', a[0]);
+  return a;
+}
+
+function mkArray() {
+  var a = [];
+  a[0] = '';
+  return a;
+}
+
+function mkNumberDictionary() {
+  var a = new Array();
+  a[0] = '';
+  a[100000] = '';
+  return a;
+}
+
+function write(a, i) { a[i] = "bazinga!"; }
+
+function test(factories, w) {
+  factories.forEach(function(f) { w(f(), 0); });
+  factories.forEach(function(f) { w(f(), 0); });
+      %OptimizeFunctionOnNextCall(w);
+  factories.forEach(function(f) { w(f(), 0); });
+}
+
+// Monomorphic case.
+for (var i = 0; i < 5; i++) write(mkArray(), 0);
+%OptimizeFunctionOnNextCall(write);
+write(mkCOWArray(), 0);
+var failure = mkCOWArray();
+
+// Cleanup, then polymorphic case.
+%DeoptimizeFunction(write);
+gc();
+test([mkArray, mkNumberDictionary], write);
+test([mkArray, mkNumberDictionary, mkCOWArray], write);
diff --git a/test/mjsunit/unbox-double-arrays.js b/test/mjsunit/unbox-double-arrays.js
index 31918b3..53d6b87 100644
--- a/test/mjsunit/unbox-double-arrays.js
+++ b/test/mjsunit/unbox-double-arrays.js
@@ -27,52 +27,255 @@
 
 // Test dictionary -> double elements -> dictionary elements round trip
 
-var foo = new Array(500000);
+// Flags: --allow-natives-syntax --unbox-double-arrays
+var large_array_size = 500000;
+var approx_dict_to_elements_threshold = 69000;
 
-function func(a) {
-  for (var i= 0; i < 100000; ++i ) {
-    a[i] = i+0.5;
+function expected_array_value(i) {
+  if ((i % 2) == 0) {
+    return i;
+  } else {
+    return i + 0.5;
   }
 }
 
-func(foo);
-
-for (var i= 0; i < 100000; i += 500 ) {
-  assertEquals(i+0.5, foo[i]);
-}
-
-delete foo[5];
-// Don't use assertEquals for comparison to undefined due to
-assertTrue(undefined === foo[5]);
-assertTrue(undefined === foo[500000-1]);
-assertTrue(undefined === foo[-1]);
-assertEquals(500000, foo.length);
-
-// Cause the array to grow beyond it's JSArray length. This will double the
-// size of the capacity and force the array into "slow" dictionary case.
-foo[500001] = 50;
-assertEquals(50, foo[500001]);
-assertEquals(500002, foo.length);
-assertTrue(undefined === foo[5])
-assertTrue(undefined === foo[500000-1])
-assertTrue(undefined === foo[-1])
-assertEquals(500002, foo.length);
-
-// Test dictionary -> double elements -> fast elements.
-
-var foo2 = new Array(500000);
-func(foo2);
-delete foo2[5];
-
-// Convert back to fast elements and make sure the contents of the array are
-// unchanged.
-foo2[25] = new Object();
-for (var i= 0; i < 100000; i += 500 ) {
-  if (i != 25 && i != 5) {
-    assertEquals(i+0.5, foo2[i]);
+function force_to_fast_double_array(a) {
+  for (var i= 0; i < approx_dict_to_elements_threshold; ++i ) {
+    a[i] = expected_array_value(i);
   }
+  assertTrue(%HasFastDoubleElements(a));
 }
-assertTrue(undefined === foo2[5])
-assertTrue(undefined === foo2[500000-1])
-assertTrue(undefined === foo2[-1])
-assertEquals(500000, foo2.length);
+
+function testOneArrayType(allocator) {
+  var large_array = new allocator(500000);
+  force_to_fast_double_array(large_array);
+
+  for (var i= 0; i < approx_dict_to_elements_threshold; i += 501 ) {
+    assertEquals(expected_array_value(i), large_array[i]);
+  }
+
+  function get_test_various_loads() {
+    return function test_various_loads(a, value_5, value_6, value_7) {
+      assertTrue(%HasFastDoubleElements(a));
+      assertEquals(value_5, a[5]);
+      assertEquals(value_6, a[6]);
+      assertEquals(value_7, a[7]);
+      assertEquals(undefined, a[large_array_size-1]);
+      assertEquals(undefined, a[-1]);
+      assertEquals(large_array_size, a.length);
+      assertTrue(%HasFastDoubleElements(a));
+    }
+  }
+
+  function get_test_various_stores() {
+    return function test_various_stores(a, value_5, value_6, value_7) {
+      assertTrue(%HasFastDoubleElements(a));
+      a[5] = value_5;
+      a[6] = value_6;
+      a[7] = value_7;
+      assertTrue(%HasFastDoubleElements(a));
+    }
+  }
+
+  // Run tests up to three times to make sure both runtime and IC implementation
+  // (premonomorphic and monomorphic) of KeyedLoad access works in various
+  // cases.
+
+  // Test double and integer values
+  test_various_loads = get_test_various_loads();
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+
+  // Test NaN values
+  test_various_stores = get_test_various_stores();
+  test_various_stores(large_array, NaN, -NaN, expected_array_value(7));
+
+  test_various_loads(large_array,
+                     NaN,
+                     -NaN,
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     NaN,
+                     -NaN,
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     NaN,
+                     -NaN,
+                     expected_array_value(7));
+
+  // Test Infinity values
+  test_various_stores = get_test_various_stores();
+  test_various_stores(large_array,
+                      Infinity,
+                      -Infinity,
+                      expected_array_value(7));
+
+  test_various_loads(large_array,
+                     Infinity,
+                     -Infinity,
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     Infinity,
+                     -Infinity,
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     Infinity,
+                     -Infinity,
+                     expected_array_value(7));
+
+  // Test the hole for the default runtime implementation.
+  delete large_array[5];
+  delete large_array[6];
+  test_various_loads = get_test_various_loads();
+  test_various_loads(large_array,
+                     undefined,
+                     undefined,
+                     expected_array_value(7));
+
+  // Test the keyed load IC implementation when the value is the hole.
+  test_various_loads = get_test_various_loads();
+  test_various_stores(large_array,
+                      expected_array_value(5),
+                      expected_array_value(6),
+                      expected_array_value(7));
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+  delete large_array[5];
+  delete large_array[6];
+  test_various_loads(large_array,
+                     undefined,
+                     undefined,
+                     expected_array_value(7));
+  test_various_loads(large_array,
+                     undefined,
+                     undefined,
+                     expected_array_value(7));
+
+  // Test both runtime and IC variants of double array stores for normal
+  // values (double and integer).
+  test_various_stores = get_test_various_stores();
+  test_various_stores(large_array,
+                      expected_array_value(4),
+                      expected_array_value(5),
+                      expected_array_value(6));
+  test_various_loads(large_array,
+                     expected_array_value(4),
+                     expected_array_value(5),
+                     expected_array_value(6));
+  test_various_stores(large_array,
+                      expected_array_value(5),
+                      expected_array_value(6),
+                      expected_array_value(7));
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+
+  // Test stores of NaN to make sure they don't get mistaken for the
+  // hole. Test both runtime and IC implementation.
+  test_various_stores = get_test_various_stores();
+  test_various_stores(large_array,
+                      NaN,
+                      -NaN,
+                      expected_array_value(6));
+  test_various_loads(large_array,
+                      NaN,
+                      -NaN,
+                     expected_array_value(6));
+  test_various_stores(large_array,
+                      expected_array_value(5),
+                      expected_array_value(6),
+                      expected_array_value(7));
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+  test_various_stores(large_array,
+                      NaN,
+                      -NaN,
+                      expected_array_value(7));
+  test_various_loads(large_array,
+                      NaN,
+                      -NaN,
+                     expected_array_value(7));
+
+  // Test stores of Infinity to make sure they don't get mistaken for the
+  // hole. Test both runtime and IC implementation.
+  test_various_stores = get_test_various_stores();
+  test_various_stores(large_array,
+                      Infinity,
+                      -Infinity,
+                      expected_array_value(6));
+  test_various_loads(large_array,
+                      Infinity,
+                      -Infinity,
+                     expected_array_value(6));
+  test_various_stores(large_array,
+                      expected_array_value(5),
+                      expected_array_value(6),
+                      expected_array_value(7));
+  test_various_loads(large_array,
+                     expected_array_value(5),
+                     expected_array_value(6),
+                     expected_array_value(7));
+  test_various_stores(large_array,
+                      Infinity,
+                      -Infinity,
+                      expected_array_value(7));
+  test_various_loads(large_array,
+                      Infinity,
+                      -Infinity,
+                     expected_array_value(7));
+
+  delete large_array[5];
+
+  // Make sure that we haven't converted from fast double.
+  assertTrue(%HasFastDoubleElements(large_array));
+  // Cause the array to grow beyond it's JSArray length. This will double the
+  // size of the capacity and force the array into "slow" dictionary case.
+  large_array[large_array_size+1] = 50;
+  assertTrue(%HasDictionaryElements(large_array));
+  assertEquals(50, large_array[large_array_size+1]);
+  assertEquals(large_array_size+2, large_array.length);
+  assertEquals(undefined, large_array[5]);
+  assertEquals(undefined, large_array[large_array_size-1]);
+  assertEquals(undefined, large_array[-1]);
+  assertEquals(large_array_size+2, large_array.length);
+
+  // Test dictionary -> double elements -> fast elements.
+  var large_array2 = new allocator(large_array_size);
+  force_to_fast_double_array(large_array2);
+  delete large_array2[5];
+
+  // Convert back to fast elements and make sure the contents of the array are
+  // unchanged.
+  large_array2[25] = new Object();
+  assertTrue(%HasFastElements(large_array2));
+  for (var i= 0; i < approx_dict_to_elements_threshold; i += 500 ) {
+    if (i != 25 && i != 5) {
+      assertEquals(expected_array_value(i), large_array2[i]);
+    }
+  }
+  assertEquals(undefined, large_array2[5])
+      assertEquals(undefined, large_array2[large_array_size-1])
+      assertEquals(undefined, large_array2[-1])
+      assertEquals(large_array_size, large_array2.length);
+}
+
+testOneArrayType(Array);
diff --git a/test/test262/test262.status b/test/test262/test262.status
index f68b85d..8cee210 100644
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -1138,33 +1138,6 @@
 15.4.4.20-1-5: FAIL
 # Bug? Array.prototype.filter applied to string primitive
 15.4.4.20-1-7: FAIL
-# Bug? Array.prototype.filter - value of 'length' is a number (value is
-#      negative)
-15.4.4.20-3-7: FAIL
-# Bug? Array.prototype.filter - value of 'length' is a number (value is
-#      Infinity)
-# V8 timeout
-15.4.4.20-3-8: SKIP
-# Bug? Array.prototype.filter - 'length' is a string containing a negative
-#      number
-15.4.4.20-3-12: FAIL
-# Bug? Array.prototype.filter - 'length' is a string containing a decimal number
-15.4.4.20-3-13: FAIL
-# Bug? Array.prototype.filter - 'length' is a string containing +/-Infinity
-15.4.4.20-3-14: SKIP
-# Bug? Array.prototype.filter - value of 'length' is a positive non-integer,
-#      ensure truncation occurs in the proper direction
-# V8 timeout
-15.4.4.20-3-24: FAIL
-# Bug? Array.prototype.filter - value of 'length' is a negative non-integer,
-#      ensure truncation occurs in the proper direction
-15.4.4.20-3-25: FAIL
-# Bug? Array.prototype.filter - value of 'length' is boundary value (2^32)
-# V8 timeout
-15.4.4.20-3-28: SKIP
-# Bug? Array.prototype.filter - value of 'length' is boundary value (2^32 + 1)
-# V8 timeout
-15.4.4.20-3-29: SKIP
 # Bug? Array.prototype.filter - side effects produced by step 2 are visible when
 #      an exception occurs
 15.4.4.20-4-8: FAIL
@@ -1220,33 +1193,6 @@
 15.4.4.21-1-5: FAIL
 # Bug? Array.prototype.reduce applied to string primitive
 15.4.4.21-1-7: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is a number (value is
-#      negative)
-15.4.4.21-3-7: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is a number (value is
-#      Infinity)
-# V8 timeout.
-15.4.4.21-3-8: SKIP
-# Bug? Array.prototype.reduce - 'length' is a string containing a negative
-#      number
-15.4.4.21-3-12: FAIL
-# Bug? Array.prototype.reduce - 'length' is a string containing a decimal number
-15.4.4.21-3-13: FAIL
-# Bug? Array.prototype.reduce - 'length' is a string containing +/-Infinity
-# V8 timeout.
-15.4.4.21-3-14: SKIP
-# Bug? Array.prototype.reduce - value of 'length' is a positive non-integer,
-#      ensure truncation occurs in the proper direction
-15.4.4.21-3-24: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is a negative non-integer,
-#      ensure truncation occurs in the proper direction
-15.4.4.21-3-25: FAIL
-# Bug? Array.prototype.reduce - value of 'length' is boundary value (2^32)
-# V8 timeout.
-15.4.4.21-3-28: SKIP
-# Bug? Array.prototype.reduce - value of 'length' is boundary value (2^32 + 1)
-# V8 timeout.
-15.4.4.21-3-29: SKIP
 # Bug? Array.prototype.reduce - side effects produced by step 2 are visible when
 #      an exception occurs
 15.4.4.21-4-8: FAIL
@@ -1274,36 +1220,6 @@
 15.4.4.22-1-5: FAIL
 # Bug? Array.prototype.reduceRight applied to string primitive
 15.4.4.22-1-7: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a number (value is
-#      negative)
-15.4.4.22-3-7: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a number (value is
-#      Infinity)
-# V8 timeout.
-15.4.4.22-3-8: SKIP
-# Bug? Array.prototype.reduceRight - value of 'length' is a string containing a
-#      negative number
-15.4.4.22-3-12: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a string containing a
-#      decimal number
-15.4.4.22-3-13: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a string containing
-#      +/-Infinity
-# V8 timeout.
-15.4.4.22-3-14: SKIP
-# Bug? Array.prototype.reduceRight - value of 'length' is a positive
-#      non-integer, ensure truncation occurs in the proper direction
-15.4.4.22-3-24: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is a negative
-#      non-integer, ensure truncation occurs in the proper direction
-15.4.4.22-3-25: FAIL
-# Bug? Array.prototype.reduceRight - value of 'length' is boundary value (2^32)
-# V8 timeout.
-15.4.4.22-3-28: SKIP
-# Bug? Array.prototype.reduceRight - value of 'length' is boundary value (2^32 +
-#      1)
-# V8 timeout.
-15.4.4.22-3-29: SKIP
 # Bug? Array.prototype.reduceRight - side effects produced by step 2 are visible
 #      when an exception occurs
 15.4.4.22-4-8: FAIL