Version 3.22.1

Sped up creating typed arrays from array-like objects. (Chromium issue 270507)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@16931 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/.gitignore b/.gitignore
index ee4e02f..d554ec6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,25 +37,16 @@
 /out
 /perf.data
 /perf.data.old
-/test/benchmarks/benchmarks.status2
 /test/benchmarks/CHECKED_OUT_*
 /test/benchmarks/downloaded_*
 /test/benchmarks/kraken
 /test/benchmarks/octane
 /test/benchmarks/sunspider
-/test/cctest/cctest.status2
-/test/intl/intl.status2
-/test/message/message.status2
-/test/mjsunit/mjsunit.status2
 /test/mozilla/CHECKED_OUT_VERSION
 /test/mozilla/data
 /test/mozilla/downloaded_*
-/test/mozilla/mozilla.status2
-/test/preparser/preparser.status2
 /test/test262/data
 /test/test262/test262-*
-/test/test262/test262.status2
-/test/webkit/webkit.status2
 /third_party
 /tools/jsfunfuzz
 /tools/jsfunfuzz.zip
diff --git a/ChangeLog b/ChangeLog
index c2c3a3d..f3e6ea7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2013-09-25: Version 3.22.1
+
+        Sped up creating typed arrays from array-like objects.
+        (Chromium issue 270507)
+
+        Performance and stability improvements on all platforms.
+
+
 2013-09-23: Version 3.22.0
 
         LiveEdit to mark more closure functions for re-instantiation when scope
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 819331f..75e16e3 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -58,6 +58,17 @@
   return results
 
 
+def _SkipTreeCheck(input_api, output_api):
+  """Check the env var whether we want to skip tree check.
+     Only skip if src/version.cc has been updated."""
+  src_version = 'src/version.cc'
+  FilterFile = lambda file: file.LocalPath() == src_version
+  if not input_api.AffectedSourceFiles(
+      lambda file: file.LocalPath() == src_version):
+    return False
+  return input_api.environ.get('PRESUBMIT_TREE_CHECK') == 'skip'
+
+
 def CheckChangeOnUpload(input_api, output_api):
   results = []
   results.extend(_CommonChecks(input_api, output_api))
@@ -69,7 +80,8 @@
   results.extend(_CommonChecks(input_api, output_api))
   results.extend(input_api.canned_checks.CheckChangeHasDescription(
       input_api, output_api))
-  results.extend(input_api.canned_checks.CheckTreeIsOpen(
-      input_api, output_api,
-      json_url='http://v8-status.appspot.com/current?format=json'))
+  if not _SkipTreeCheck(input_api, output_api):
+    results.extend(input_api.canned_checks.CheckTreeIsOpen(
+        input_api, output_api,
+        json_url='http://v8-status.appspot.com/current?format=json'))
   return results
diff --git a/include/v8.h b/include/v8.h
index 4206105..62a1cb3 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1479,6 +1479,7 @@
   /** JS == */
   bool Equals(Handle<Value> that) const;
   bool StrictEquals(Handle<Value> that) const;
+  bool SameValue(Handle<Value> that) const;
 
   template <class T> V8_INLINE static Value* Cast(T* value);
 
diff --git a/src/api.cc b/src/api.cc
index 6d53d91..6eb3789 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3055,6 +3055,19 @@
 }
 
 
+bool Value::SameValue(Handle<Value> that) const {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (EmptyCheck("v8::Value::SameValue()", this) ||
+      EmptyCheck("v8::Value::SameValue()", that)) {
+    return false;
+  }
+  LOG_API(isolate, "SameValue");
+  i::Handle<i::Object> obj = Utils::OpenHandle(this);
+  i::Handle<i::Object> other = Utils::OpenHandle(*that);
+  return obj->SameValue(*other);
+}
+
+
 uint32_t Value::Uint32Value() const {
   i::Handle<i::Object> obj = Utils::OpenHandle(this);
   if (obj->IsSmi()) {
@@ -7427,9 +7440,11 @@
     v->VisitPointers(blocks()->last(), handle_scope_data_.next);
   }
 
-  if (!saved_contexts_.is_empty()) {
-    Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
-    v->VisitPointers(start, start + saved_contexts_.length());
+  List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_};
+  for (unsigned i = 0; i < ARRAY_SIZE(context_lists); i++) {
+    if (context_lists[i]->is_empty()) continue;
+    Object** start = reinterpret_cast<Object**>(&context_lists[i]->first());
+    v->VisitPointers(start, start + context_lists[i]->length());
   }
 }
 
diff --git a/src/api.h b/src/api.h
index 7dfa36d..8fb17a0 100644
--- a/src/api.h
+++ b/src/api.h
@@ -542,12 +542,12 @@
   inline void DecrementCallDepth() {call_depth_--;}
   inline bool CallDepthIsZero() { return call_depth_ == 0; }
 
-  inline void EnterContext(Handle<Object> context);
-  inline bool LeaveContext(Handle<Object> context);
+  inline void EnterContext(Handle<Context> context);
+  inline bool LeaveContext(Handle<Context> context);
 
   // Returns the last entered context or an empty handle if no
   // contexts have been entered.
-  inline Handle<Object> LastEnteredContext();
+  inline Handle<Context> LastEnteredContext();
 
   inline void SaveContext(Context* context);
   inline Context* RestoreContext();
@@ -592,7 +592,7 @@
   Isolate* isolate_;
   List<internal::Object**> blocks_;
   // Used as a stack to keep track of entered contexts.
-  List<Handle<Object> > entered_contexts_;
+  List<Context*> entered_contexts_;
   // Used as a stack to keep track of saved contexts.
   List<Context*> saved_contexts_;
   Object** spare_;
@@ -630,23 +630,23 @@
 }
 
 
-void HandleScopeImplementer::EnterContext(Handle<Object> context) {
-  entered_contexts_.Add(context);
+void HandleScopeImplementer::EnterContext(Handle<Context> context) {
+  entered_contexts_.Add(*context);
 }
 
 
-bool HandleScopeImplementer::LeaveContext(Handle<Object> context) {
+bool HandleScopeImplementer::LeaveContext(Handle<Context> context) {
   if (entered_contexts_.is_empty()) return false;
   // TODO(dcarney): figure out what's wrong here
-  // if (*entered_contexts_.last() != *context) return false;
+  // if (entered_contexts_.last() != *context) return false;
   entered_contexts_.RemoveLast();
   return true;
 }
 
 
-Handle<Object> HandleScopeImplementer::LastEnteredContext() {
-  if (entered_contexts_.is_empty()) return Handle<Object>::null();
-  return entered_contexts_.last();
+Handle<Context> HandleScopeImplementer::LastEnteredContext() {
+  if (entered_contexts_.is_empty()) return Handle<Context>::null();
+  return Handle<Context>(entered_contexts_.last());
 }
 
 
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 1399021..d7b8f02 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -118,7 +118,8 @@
 // Core register
 struct Register {
   static const int kNumRegisters = 16;
-  static const int kMaxNumAllocatableRegisters = 8;
+  static const int kMaxNumAllocatableRegisters =
+      FLAG_enable_ool_constant_pool ? 7 : 8;
   static const int kSizeInBytes = 4;
 
   inline static int NumAllocatableRegisters();
@@ -201,6 +202,7 @@
 const Register r4  = { kRegister_r4_Code };
 const Register r5  = { kRegister_r5_Code };
 const Register r6  = { kRegister_r6_Code };
+// Used as constant pool pointer register if FLAGS_enable_ool_constant_pool.
 const Register r7  = { kRegister_r7_Code };
 // Used as context register.
 const Register r8  = { kRegister_r8_Code };
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index ec1b227..530c1d2 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -445,9 +445,8 @@
       // r3: object size (in words)
       // r4: JSObject (not tagged)
       // r5: First in-object property of JSObject (not tagged)
-      __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
       ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
-      __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
+      __ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
       if (count_constructions) {
         __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
         __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
@@ -455,14 +454,16 @@
         __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
         // r0: offset of first field after pre-allocated fields
         if (FLAG_debug_code) {
-          __ cmp(r0, r6);
+          __ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
+          __ cmp(r0, ip);
           __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
         }
-        __ InitializeFieldsWithFiller(r5, r0, r7);
+        __ InitializeFieldsWithFiller(r5, r0, r6);
         // To allow for truncation.
-        __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
+        __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
       }
-      __ InitializeFieldsWithFiller(r5, r6, r7);
+      __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
+      __ InitializeFieldsWithFiller(r5, r0, r6);
 
       // Add the object tag to make the JSObject real, so that we can continue
       // and jump into the continuation code at any time from now on. Any
@@ -527,16 +528,10 @@
       __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2));  // End of object.
       ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
       { Label loop, entry;
-        if (count_constructions) {
-          __ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
-        } else if (FLAG_debug_code) {
-          __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
-          __ cmp(r7, r8);
-          __ Assert(eq, kUndefinedValueNotLoaded);
-        }
+        __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
         __ b(&entry);
         __ bind(&loop);
-        __ str(r7, MemOperand(r2, kPointerSize, PostIndex));
+        __ str(r0, MemOperand(r2, kPointerSize, PostIndex));
         __ bind(&entry);
         __ cmp(r2, r6);
         __ b(lt, &loop);
@@ -700,7 +695,7 @@
   // r2: receiver
   // r3: argc
   // r4: argv
-  // r5-r7, cp may be clobbered
+  // r5-r6, r7 (if not FLAG_enable_ool_constant_pool) and cp may be clobbered
   ProfileEntryHookStub::MaybeCallEntryHook(masm);
 
   // Clear the context before we push it when entering the internal frame.
@@ -740,7 +735,9 @@
     __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
     __ mov(r5, Operand(r4));
     __ mov(r6, Operand(r4));
-    __ mov(r7, Operand(r4));
+    if (!FLAG_enable_ool_constant_pool) {
+      __ mov(r7, Operand(r4));
+    }
     if (kR9Available == 1) {
       __ mov(r9, Operand(r4));
     }
@@ -894,21 +891,6 @@
 }
 
 
-void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
-  // For now, we are relying on the fact that Runtime::NotifyOSR
-  // doesn't do any garbage collection which allows us to save/restore
-  // the registers without worrying about which of them contain
-  // pointers. This seems a bit fragile.
-  __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ CallRuntime(Runtime::kNotifyOSR, 0);
-  }
-  __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit());
-  __ Ret();
-}
-
-
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
   // Lookup the function in the JavaScript frame.
   __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 0335607..2c7fb78 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -59,6 +59,16 @@
 }
 
 
+void NumberToStringStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { r0 };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ = NULL;
+}
+
+
 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
@@ -825,8 +835,7 @@
   // Convert lhs to a double in d7.
   __ SmiToDouble(d7, lhs);
   // Load the double from rhs, tagged HeapNumber r0, to d6.
-  __ sub(r7, rhs, Operand(kHeapObjectTag));
-  __ vldr(d6, r7, HeapNumber::kValueOffset);
+  __ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag);
 
   // We now have both loaded as doubles but we can skip the lhs nan check
   // since it's a smi.
@@ -851,8 +860,7 @@
 
   // Rhs is a smi, lhs is a heap number.
   // Load the double from lhs, tagged HeapNumber r1, to d7.
-  __ sub(r7, lhs, Operand(kHeapObjectTag));
-  __ vldr(d7, r7, HeapNumber::kValueOffset);
+  __ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag);
   // Convert rhs to a double in d6              .
   __ SmiToDouble(d6, rhs);
   // Fall through to both_loaded_as_doubles.
@@ -920,10 +928,8 @@
 
   // Both are heap numbers.  Load them up then jump to the code we have
   // for that.
-  __ sub(r7, rhs, Operand(kHeapObjectTag));
-  __ vldr(d6, r7, HeapNumber::kValueOffset);
-  __ sub(r7, lhs, Operand(kHeapObjectTag));
-  __ vldr(d7, r7, HeapNumber::kValueOffset);
+  __ vldr(d6, rhs, HeapNumber::kValueOffset - kHeapObjectTag);
+  __ vldr(d7, lhs, HeapNumber::kValueOffset - kHeapObjectTag);
   __ jmp(both_loaded_as_doubles);
 }
 
@@ -972,22 +978,6 @@
 }
 
 
-void NumberToStringStub::Generate(MacroAssembler* masm) {
-  Label runtime;
-
-  __ ldr(r1, MemOperand(sp, 0));
-
-  // Generate code to lookup number in the number string cache.
-  __ LookupNumberStringCache(r1, r0, r2, r3, r4, &runtime);
-  __ add(sp, sp, Operand(1 * kPointerSize));
-  __ Ret();
-
-  __ bind(&runtime);
-  // Handle number to string in the runtime system if not found in the cache.
-  __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
-}
-
-
 static void ICCompareStub_CheckInputType(MacroAssembler* masm,
                                          Register input,
                                          Register scratch,
@@ -1267,13 +1257,14 @@
 
 
 void BinaryOpStub_GenerateSmiSmiOperation(MacroAssembler* masm,
-                                          Token::Value op) {
+                                          Token::Value op,
+                                          Register scratch1,
+                                          Register scratch2) {
   Register left = r1;
   Register right = r0;
-  Register scratch1 = r7;
-  Register scratch2 = r9;
 
   ASSERT(right.is(r0));
+  ASSERT(!AreAliased(left, right, scratch1, scratch2, ip));
   STATIC_ASSERT(kSmiTag == 0);
 
   Label not_smi_result;
@@ -1488,11 +1479,15 @@
                                       Label* gc_required,
                                       Label* miss,
                                       Token::Value op,
-                                      OverwriteMode mode) {
+                                      OverwriteMode mode,
+                                      Register scratch1,
+                                      Register scratch2,
+                                      Register scratch3,
+                                      Register scratch4) {
   Register left = r1;
   Register right = r0;
-  Register scratch1 = r6;
-  Register scratch2 = r7;
+  Register result = scratch3;
+  ASSERT(!AreAliased(left, right, scratch1, scratch2, scratch3, scratch4));
 
   ASSERT(smi_operands || (not_numbers != NULL));
   if (smi_operands) {
@@ -1506,7 +1501,7 @@
     __ JumpIfNotSmi(right, miss);
   }
 
-  Register heap_number_map = r9;
+  Register heap_number_map = scratch4;
   __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
 
   switch (op) {
@@ -1516,7 +1511,6 @@
     case Token::DIV:
     case Token::MOD: {
       // Allocate new heap number for result.
-      Register result = r5;
       BinaryOpStub_GenerateHeapResultAllocation(
           masm, result, heap_number_map, scratch1, scratch2, gc_required, mode);
 
@@ -1635,7 +1629,6 @@
 
       // Allocate new heap number for result.
       __ bind(&result_not_a_smi);
-      Register result = r5;
       if (smi_operands) {
         __ AllocateHeapNumber(
             result, scratch1, scratch2, heap_number_map, gc_required);
@@ -1646,11 +1639,11 @@
       }
 
       // r2: Answer as signed int32.
-      // r5: Heap number to write answer into.
+      // result: Heap number to write answer into.
 
       // Nothing can go wrong now, so move the heap number to r0, which is the
       // result.
-      __ mov(r0, Operand(r5));
+      __ mov(r0, Operand(result));
 
       // Convert the int32 in r2 to the heap number in r0. r3 is corrupted. As
       // mentioned above SHR needs to always produce a positive result.
@@ -1681,26 +1674,31 @@
     Label* gc_required,
     Token::Value op,
     BinaryOpStub::SmiCodeGenerateHeapNumberResults allow_heapnumber_results,
-    OverwriteMode mode) {
+    OverwriteMode mode,
+    Register scratch1,
+    Register scratch2,
+    Register scratch3,
+    Register scratch4) {
   Label not_smis;
 
   Register left = r1;
   Register right = r0;
-  Register scratch1 = r7;
+  ASSERT(!AreAliased(left, right, scratch1, scratch2, scratch3, scratch4));
 
   // Perform combined smi check on both operands.
   __ orr(scratch1, left, Operand(right));
   __ JumpIfNotSmi(scratch1, &not_smis);
 
   // If the smi-smi operation results in a smi return is generated.
-  BinaryOpStub_GenerateSmiSmiOperation(masm, op);
+  BinaryOpStub_GenerateSmiSmiOperation(masm, op, scratch1, scratch2);
 
   // If heap number results are possible generate the result in an allocated
   // heap number.
   if (allow_heapnumber_results == BinaryOpStub::ALLOW_HEAPNUMBER_RESULTS) {
     BinaryOpStub_GenerateFPOperation(
         masm, BinaryOpIC::UNINITIALIZED, BinaryOpIC::UNINITIALIZED, true,
-        use_runtime, gc_required, &not_smis, op, mode);
+        use_runtime, gc_required, &not_smis, op, mode, scratch2, scratch3,
+        scratch1, scratch4);
   }
   __ bind(&not_smis);
 }
@@ -1719,14 +1717,13 @@
   if (result_type_ == BinaryOpIC::UNINITIALIZED ||
       result_type_ == BinaryOpIC::SMI) {
     // Only allow smi results.
-    BinaryOpStub_GenerateSmiCode(
-        masm, &call_runtime, NULL, op_, NO_HEAPNUMBER_RESULTS, mode_);
+    BinaryOpStub_GenerateSmiCode(masm, &call_runtime, NULL, op_,
+        NO_HEAPNUMBER_RESULTS, mode_, r5, r6, r4, r9);
   } else {
     // Allow heap number result and don't make a transition if a heap number
     // cannot be allocated.
-    BinaryOpStub_GenerateSmiCode(
-        masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS,
-        mode_);
+    BinaryOpStub_GenerateSmiCode(masm, &call_runtime, &call_runtime, op_,
+      ALLOW_HEAPNUMBER_RESULTS, mode_, r5, r6, r4, r9);
   }
 
   // Code falls through if the result is not returned as either a smi or heap
@@ -1780,8 +1777,9 @@
 
   Register left = r1;
   Register right = r0;
-  Register scratch1 = r7;
+  Register scratch1 = r4;
   Register scratch2 = r9;
+  Register scratch3 = r5;
   LowDwVfpRegister double_scratch = d0;
 
   Register heap_number_result = no_reg;
@@ -1798,7 +1796,7 @@
   Label skip;
   __ orr(scratch1, left, right);
   __ JumpIfNotSmi(scratch1, &skip);
-  BinaryOpStub_GenerateSmiSmiOperation(masm, op_);
+  BinaryOpStub_GenerateSmiSmiOperation(masm, op_, scratch2, scratch3);
   // Fall through if the result is not a smi.
   __ bind(&skip);
 
@@ -1892,12 +1890,6 @@
           __ b(ne, &transition);
         }
 
-        // We preserved r0 and r1 to be able to call runtime.
-        // Save the left value on the stack.
-        __ Push(r5, r4);
-
-        Label pop_and_call_runtime;
-
         // Allocate a heap number to store the result.
         heap_number_result = r5;
         BinaryOpStub_GenerateHeapResultAllocation(masm,
@@ -1905,20 +1897,15 @@
                                                   heap_number_map,
                                                   scratch1,
                                                   scratch2,
-                                                  &pop_and_call_runtime,
+                                                  &call_runtime,
                                                   mode_);
 
-        // Load the left value from the value saved on the stack.
-        __ Pop(r1, r0);
-
         // Call the C function to handle the double operation.
         CallCCodeForDoubleOperation(masm, op_, heap_number_result, scratch1);
         if (FLAG_debug_code) {
           __ stop("Unreachable code.");
         }
 
-        __ bind(&pop_and_call_runtime);
-        __ Drop(2);
         __ b(&call_runtime);
       }
 
@@ -2069,7 +2056,7 @@
   Label call_runtime, transition;
   BinaryOpStub_GenerateFPOperation(
       masm, left_type_, right_type_, false,
-      &transition, &call_runtime, &transition, op_, mode_);
+      &transition, &call_runtime, &transition, op_, mode_, r6, r4, r5, r9);
 
   __ bind(&transition);
   GenerateTypeTransition(masm);
@@ -2088,11 +2075,13 @@
   Label call_runtime, call_string_add_or_runtime, transition;
 
   BinaryOpStub_GenerateSmiCode(
-      masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_);
+      masm, &call_runtime, &call_runtime, op_, ALLOW_HEAPNUMBER_RESULTS, mode_,
+      r5, r6, r4, r9);
 
   BinaryOpStub_GenerateFPOperation(
       masm, left_type_, right_type_, false,
-      &call_string_add_or_runtime, &call_runtime, &transition, op_, mode_);
+      &call_string_add_or_runtime, &call_runtime, &transition, op_, mode_, r6,
+      r4, r5, r9);
 
   __ bind(&transition);
   GenerateTypeTransition(masm);
@@ -2194,7 +2183,7 @@
   Label calculate;
   Label invalid_cache;
   const Register scratch0 = r9;
-  const Register scratch1 = r7;
+  Register scratch1 = no_reg;  // will be r4
   const Register cache_entry = r0;
   const bool tagged = (argument_type_ == TAGGED);
 
@@ -2274,6 +2263,9 @@
   __ cmp(r2, r4);
   __ cmp(r3, r5, eq);
   __ b(ne, &calculate);
+
+  scratch1 = r4;  // Start of scratch1 range.
+
   // Cache hit. Load result, cleanup and return.
   Counters* counters = masm->isolate()->counters();
   __ IncrementCounter(
@@ -2416,7 +2408,7 @@
   const DwVfpRegister double_scratch = d0;
   const SwVfpRegister single_scratch = s0;
   const Register scratch = r9;
-  const Register scratch2 = r7;
+  const Register scratch2 = r4;
 
   Label call_runtime, done, int_exponent;
   if (exponent_type_ == ON_STACK) {
@@ -2926,14 +2918,14 @@
   // r3: argc
   // r4: argv
   Isolate* isolate = masm->isolate();
-  __ mov(r8, Operand(-1));  // Push a bad frame pointer to fail if it is used.
   int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
-  __ mov(r7, Operand(Smi::FromInt(marker)));
+  __ mov(r8, Operand(Smi::FromInt(marker)));
   __ mov(r6, Operand(Smi::FromInt(marker)));
   __ mov(r5,
          Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
   __ ldr(r5, MemOperand(r5));
-  __ Push(r8, r7, r6, r5);
+  __ mov(ip, Operand(-1));  // Push a bad frame pointer to fail if it is used.
+  __ Push(ip, r8, r6, r5);
 
   // Set up frame pointer for the frame to be pushed.
   __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
@@ -2979,7 +2971,7 @@
   // Invoke: Link this frame into the handler chain.  There's only one
   // handler block in this code object, so its index is 0.
   __ bind(&invoke);
-  // Must preserve r0-r4, r5-r7 are available.
+  // Must preserve r0-r4, r5-r6 are available.
   __ PushTryHandler(StackHandler::JS_ENTRY, 0);
   // If an exception not caught by another handler occurs, this handler
   // returns control to the code after the bl(&invoke) above, which
@@ -3586,31 +3578,36 @@
   __ ldr(r9, MemOperand(sp, 0 * kPointerSize));
   __ add(r9, r9, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS)));
   __ sub(r9, r9, Operand(r1));
-  __ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
+  __ LoadRoot(r5, Heap::kTheHoleValueRootIndex);
   __ add(r3, r4, Operand(r6, LSL, 1));
   __ add(r3, r3, Operand(kParameterMapHeaderSize));
 
   // r6 = loop variable (tagged)
   // r1 = mapping index (tagged)
   // r3 = address of backing store (tagged)
-  // r4 = address of parameter map (tagged)
-  // r5 = temporary scratch (a.o., for address calculation)
-  // r7 = the hole value
+  // r4 = address of parameter map (tagged), which is also the address of new
+  //      object + Heap::kArgumentsObjectSize (tagged)
+  // r0 = temporary scratch (a.o., for address calculation)
+  // r5 = the hole value
   __ jmp(&parameters_test);
 
   __ bind(&parameters_loop);
   __ sub(r6, r6, Operand(Smi::FromInt(1)));
-  __ mov(r5, Operand(r6, LSL, 1));
-  __ add(r5, r5, Operand(kParameterMapHeaderSize - kHeapObjectTag));
-  __ str(r9, MemOperand(r4, r5));
-  __ sub(r5, r5, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
-  __ str(r7, MemOperand(r3, r5));
+  __ mov(r0, Operand(r6, LSL, 1));
+  __ add(r0, r0, Operand(kParameterMapHeaderSize - kHeapObjectTag));
+  __ str(r9, MemOperand(r4, r0));
+  __ sub(r0, r0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize));
+  __ str(r5, MemOperand(r3, r0));
   __ add(r9, r9, Operand(Smi::FromInt(1)));
   __ bind(&parameters_test);
   __ cmp(r6, Operand(Smi::FromInt(0)));
   __ b(ne, &parameters_loop);
 
+  // Restore r0 = new object (tagged)
+  __ sub(r0, r4, Operand(Heap::kArgumentsObjectSize));
+
   __ bind(&skip_parameter_map);
+  // r0 = address of new object (tagged)
   // r2 = argument count (tagged)
   // r3 = address of backing store (tagged)
   // r5 = scratch
@@ -3641,6 +3638,7 @@
   __ Ret();
 
   // Do the runtime call to allocate the arguments object.
+  // r0 = address of new object (tagged)
   // r2 = argument count (tagged)
   __ bind(&runtime);
   __ str(r2, MemOperand(sp, 0 * kPointerSize));  // Patch argument count.
@@ -3769,7 +3767,7 @@
   // therefore the content of these registers are safe to use after the call.
   Register subject = r4;
   Register regexp_data = r5;
-  Register last_match_info_elements = r6;
+  Register last_match_info_elements = no_reg;  // will be r6;
 
   // Ensure that a RegExp stack is allocated.
   Isolate* isolate = masm->isolate();
@@ -3902,19 +3900,19 @@
   STATIC_ASSERT(kTwoByteStringTag == 0);
   __ and_(r0, r0, Operand(kStringEncodingMask));
   __ mov(r3, Operand(r0, ASR, 2), SetCC);
-  __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
-  __ ldr(r7, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
+  __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataAsciiCodeOffset), ne);
+  __ ldr(r6, FieldMemOperand(regexp_data, JSRegExp::kDataUC16CodeOffset), eq);
 
   // (E) Carry on.  String handling is done.
-  // r7: irregexp code
+  // r6: irregexp code
   // Check that the irregexp code has been generated for the actual string
   // encoding. If it has, the field contains a code object otherwise it contains
   // a smi (code flushing support).
-  __ JumpIfSmi(r7, &runtime);
+  __ JumpIfSmi(r6, &runtime);
 
   // r1: previous index
   // r3: encoding of subject string (1 if ASCII, 0 if two_byte);
-  // r7: code
+  // r6: code
   // subject: Subject string
   // regexp_data: RegExp data (FixedArray)
   // All checks done. Now push arguments for native regexp code.
@@ -3981,12 +3979,14 @@
   __ mov(r0, subject);
 
   // Locate the code entry and call it.
-  __ add(r7, r7, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ add(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag));
   DirectCEntryStub stub;
-  stub.GenerateCall(masm, r7);
+  stub.GenerateCall(masm, r6);
 
   __ LeaveExitFrame(false, no_reg, true);
 
+  last_match_info_elements = r6;
+
   // r0: result
   // subject: subject string (callee saved)
   // regexp_data: RegExp data (callee saved)
@@ -4075,7 +4075,7 @@
   __ RecordWriteField(last_match_info_elements,
                       RegExpImpl::kLastSubjectOffset,
                       subject,
-                      r7,
+                      r3,
                       kLRHasNotBeenSaved,
                       kDontSaveFPRegs);
   __ mov(subject, r2);
@@ -4085,7 +4085,7 @@
   __ RecordWriteField(last_match_info_elements,
                       RegExpImpl::kLastInputOffset,
                       subject,
-                      r7,
+                      r3,
                       kLRHasNotBeenSaved,
                       kDontSaveFPRegs);
 
@@ -4652,7 +4652,6 @@
                                               Register scratch2,
                                               Register scratch3,
                                               Register scratch4,
-                                              Register scratch5,
                                               int flags) {
   bool ascii = (flags & COPY_ASCII) != 0;
   bool dest_always_aligned = (flags & DEST_ALWAYS_ALIGNED) != 0;
@@ -4727,30 +4726,29 @@
 
     __ bind(&loop);
     __ ldr(scratch3, MemOperand(src, 4, PostIndex));
-    __ sub(scratch5, limit, Operand(dest));
     __ orr(scratch1, scratch1, Operand(scratch3, LSL, left_shift));
     __ str(scratch1, MemOperand(dest, 4, PostIndex));
     __ mov(scratch1, Operand(scratch3, LSR, right_shift));
     // Loop if four or more bytes left to copy.
-    // Compare to eight, because we did the subtract before increasing dst.
-    __ sub(scratch5, scratch5, Operand(8), SetCC);
+    __ sub(scratch3, limit, Operand(dest));
+    __ sub(scratch3, scratch3, Operand(4), SetCC);
     __ b(ge, &loop);
   }
   // There is now between zero and three bytes left to copy (negative that
-  // number is in scratch5), and between one and three bytes already read into
+  // number is in scratch3), and between one and three bytes already read into
   // scratch1 (eight times that number in scratch4). We may have read past
   // the end of the string, but because objects are aligned, we have not read
   // past the end of the object.
   // Find the minimum of remaining characters to move and preloaded characters
   // and write those as bytes.
-  __ add(scratch5, scratch5, Operand(4), SetCC);
+  __ add(scratch3, scratch3, Operand(4), SetCC);
   __ b(eq, &done);
-  __ cmp(scratch4, Operand(scratch5, LSL, 3), ne);
+  __ cmp(scratch4, Operand(scratch3, LSL, 3), ne);
   // Move minimum of bytes read and bytes left to copy to scratch4.
-  __ mov(scratch5, Operand(scratch4, LSR, 3), LeaveCC, lt);
-  // Between one and three (value in scratch5) characters already read into
+  __ mov(scratch3, Operand(scratch4, LSR, 3), LeaveCC, lt);
+  // Between one and three (value in scratch3) characters already read into
   // scratch ready to write.
-  __ cmp(scratch5, Operand(2));
+  __ cmp(scratch3, Operand(2));
   __ strb(scratch1, MemOperand(dest, 1, PostIndex));
   __ mov(scratch1, Operand(scratch1, LSR, 8), LeaveCC, ge);
   __ strb(scratch1, MemOperand(dest, 1, PostIndex), ge);
@@ -5090,10 +5088,10 @@
     STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
     __ tst(r1, Operand(kStringEncodingMask));
     __ b(eq, &two_byte_slice);
-    __ AllocateAsciiSlicedString(r0, r2, r6, r7, &runtime);
+    __ AllocateAsciiSlicedString(r0, r2, r6, r4, &runtime);
     __ jmp(&set_slice_header);
     __ bind(&two_byte_slice);
-    __ AllocateTwoByteSlicedString(r0, r2, r6, r7, &runtime);
+    __ AllocateTwoByteSlicedString(r0, r2, r6, r4, &runtime);
     __ bind(&set_slice_header);
     __ mov(r3, Operand(r3, LSL, 1));
     __ str(r5, FieldMemOperand(r0, SlicedString::kParentOffset));
@@ -5134,7 +5132,7 @@
   __ b(eq, &two_byte_sequential);
 
   // Allocate and copy the resulting ASCII string.
-  __ AllocateAsciiString(r0, r2, r4, r6, r7, &runtime);
+  __ AllocateAsciiString(r0, r2, r4, r6, r1, &runtime);
 
   // Locate first character of substring to copy.
   __ add(r5, r5, r3);
@@ -5146,13 +5144,13 @@
   // r2: result string length
   // r5: first character of substring to copy
   STATIC_ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0);
-  StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
+  StringHelper::GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r9,
                                            COPY_ASCII | DEST_ALWAYS_ALIGNED);
   __ jmp(&return_r0);
 
   // Allocate and copy the resulting two-byte string.
   __ bind(&two_byte_sequential);
-  __ AllocateTwoByteString(r0, r2, r4, r6, r7, &runtime);
+  __ AllocateTwoByteString(r0, r2, r4, r6, r1, &runtime);
 
   // Locate first character of substring to copy.
   STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
@@ -5166,7 +5164,7 @@
   // r5: first character of substring to copy.
   STATIC_ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0);
   StringHelper::GenerateCopyCharactersLong(
-      masm, r1, r5, r2, r3, r4, r6, r7, r9, DEST_ALWAYS_ALIGNED);
+      masm, r1, r5, r2, r3, r4, r6, r9, DEST_ALWAYS_ALIGNED);
 
   __ bind(&return_r0);
   Counters* counters = masm->isolate()->counters();
@@ -5432,7 +5430,7 @@
     __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
     __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
   }
-  __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7,
+  __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r3,
                                                   &call_runtime);
 
   // Get the two characters forming the sub string.
@@ -5443,7 +5441,7 @@
   // just allocate a new one.
   Label make_two_character_string;
   StringHelper::GenerateTwoCharacterStringTableProbe(
-      masm, r2, r3, r6, r7, r4, r5, r9, &make_two_character_string);
+      masm, r2, r3, r6, r0, r4, r5, r9, &make_two_character_string);
   __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
@@ -5488,7 +5486,7 @@
 
   // Allocate an ASCII cons string.
   __ bind(&ascii_data);
-  __ AllocateAsciiConsString(r7, r6, r4, r5, &call_runtime);
+  __ AllocateAsciiConsString(r3, r6, r4, r5, &call_runtime);
   __ bind(&allocated);
   // Fill the fields of the cons string.
   Label skip_write_barrier, after_writing;
@@ -5499,15 +5497,15 @@
   __ cmp(r4, Operand::Zero());
   __ b(eq, &skip_write_barrier);
 
-  __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
-  __ RecordWriteField(r7,
+  __ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
+  __ RecordWriteField(r3,
                       ConsString::kFirstOffset,
                       r0,
                       r4,
                       kLRHasNotBeenSaved,
                       kDontSaveFPRegs);
-  __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
-  __ RecordWriteField(r7,
+  __ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
+  __ RecordWriteField(r3,
                       ConsString::kSecondOffset,
                       r1,
                       r4,
@@ -5516,12 +5514,12 @@
   __ jmp(&after_writing);
 
   __ bind(&skip_write_barrier);
-  __ str(r0, FieldMemOperand(r7, ConsString::kFirstOffset));
-  __ str(r1, FieldMemOperand(r7, ConsString::kSecondOffset));
+  __ str(r0, FieldMemOperand(r3, ConsString::kFirstOffset));
+  __ str(r1, FieldMemOperand(r3, ConsString::kSecondOffset));
 
   __ bind(&after_writing);
 
-  __ mov(r0, Operand(r7));
+  __ mov(r0, Operand(r3));
   __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
@@ -5541,7 +5539,7 @@
   __ b(eq, &ascii_data);
 
   // Allocate a two byte cons string.
-  __ AllocateTwoByteConsString(r7, r6, r4, r5, &call_runtime);
+  __ AllocateTwoByteConsString(r3, r6, r4, r5, &call_runtime);
   __ jmp(&allocated);
 
   // We cannot encounter sliced strings or cons strings here since:
@@ -5565,14 +5563,15 @@
   }
 
   // Check whether both strings have same encoding
-  __ eor(r7, r4, Operand(r5));
-  __ tst(r7, Operand(kStringEncodingMask));
+  __ eor(ip, r4, Operand(r5));
+  ASSERT(__ ImmediateFitsAddrMode1Instruction(kStringEncodingMask));
+  __ tst(ip, Operand(kStringEncodingMask));
   __ b(ne, &call_runtime);
 
   STATIC_ASSERT(kSeqStringTag == 0);
   __ tst(r4, Operand(kStringRepresentationMask));
   STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
-  __ add(r7,
+  __ add(r6,
          r0,
          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag),
          LeaveCC,
@@ -5582,7 +5581,7 @@
   STATIC_ASSERT(kShortExternalStringTag != 0);
   __ tst(r4, Operand(kShortExternalStringMask));
   __ b(ne, &call_runtime);
-  __ ldr(r7, FieldMemOperand(r0, ExternalString::kResourceDataOffset));
+  __ ldr(r6, FieldMemOperand(r0, ExternalString::kResourceDataOffset));
   __ bind(&first_prepared);
 
   STATIC_ASSERT(kSeqStringTag == 0);
@@ -5602,43 +5601,46 @@
   __ bind(&second_prepared);
 
   Label non_ascii_string_add_flat_result;
-  // r7: first character of first string
+  // r6: first character of first string
   // r1: first character of second string
   // r2: length of first string.
   // r3: length of second string.
-  // r6: sum of lengths.
   // Both strings have the same encoding.
   STATIC_ASSERT(kTwoByteStringTag == 0);
   __ tst(r5, Operand(kStringEncodingMask));
   __ b(eq, &non_ascii_string_add_flat_result);
 
-  __ AllocateAsciiString(r0, r6, r4, r5, r9, &call_runtime);
-  __ add(r6, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r2, Operand(r3));
+  __ AllocateAsciiString(r0, r2, r4, r5, r9, &call_runtime);
+  __ sub(r2, r2, Operand(r3));
+  __ add(r5, r0, Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
   // r0: result string.
-  // r7: first character of first string.
+  // r6: first character of first string.
   // r1: first character of second string.
   // r2: length of first string.
   // r3: length of second string.
-  // r6: first character of result.
-  StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, true);
-  // r6: next character of result.
-  StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, true);
+  // r5: first character of result.
+  StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, true);
+  // r5: next character of result.
+  StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, true);
   __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
 
   __ bind(&non_ascii_string_add_flat_result);
-  __ AllocateTwoByteString(r0, r6, r4, r5, r9, &call_runtime);
-  __ add(r6, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r2, Operand(r3));
+  __ AllocateTwoByteString(r0, r2, r4, r5, r9, &call_runtime);
+  __ sub(r2, r2, Operand(r3));
+  __ add(r5, r0, Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
   // r0: result string.
-  // r7: first character of first string.
+  // r6: first character of first string.
   // r1: first character of second string.
   // r2: length of first string.
   // r3: length of second string.
-  // r6: first character of result.
-  StringHelper::GenerateCopyCharacters(masm, r6, r7, r2, r4, false);
-  // r6: next character of result.
-  StringHelper::GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
+  // r5: first character of result.
+  StringHelper::GenerateCopyCharacters(masm, r5, r6, r2, r4, false);
+  // r5: next character of result.
+  StringHelper::GenerateCopyCharacters(masm, r5, r1, r3, r4, false);
   __ IncrementCounter(counters->string_add_native(), 1, r2, r3);
   __ add(sp, sp, Operand(2 * kPointerSize));
   __ Ret();
@@ -6308,7 +6310,7 @@
 
 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
   // Used in RegExpExecStub.
-  { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET },
+  { REG(r6), REG(r4), REG(r3), EMIT_REMEMBERED_SET },
   // Used in CompileArrayPushCall.
   // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore.
   // Also used in KeyedStoreIC::GenerateGeneric.
@@ -6335,8 +6337,8 @@
   // FastNewClosureStub::Generate
   { REG(r2), REG(r4), REG(r1), EMIT_REMEMBERED_SET },
   // StringAddStub::Generate
-  { REG(r7), REG(r1), REG(r4), EMIT_REMEMBERED_SET },
-  { REG(r7), REG(r0), REG(r4), EMIT_REMEMBERED_SET },
+  { REG(r3), REG(r1), REG(r4), EMIT_REMEMBERED_SET },
+  { REG(r3), REG(r0), REG(r4), EMIT_REMEMBERED_SET },
   // Null termination.
   { REG(no_reg), REG(no_reg), REG(no_reg), EMIT_REMEMBERED_SET}
 };
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index a404f01..c03d8f2 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -106,7 +106,6 @@
                                          Register scratch2,
                                          Register scratch3,
                                          Register scratch4,
-                                         Register scratch5,
                                          int flags);
 
 
@@ -257,18 +256,6 @@
 };
 
 
-class NumberToStringStub: public PlatformCodeStub {
- public:
-  NumberToStringStub() { }
-
- private:
-  Major MajorKey() { return NumberToString; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
-};
-
-
 class RecordWriteStub: public PlatformCodeStub {
  public:
   RecordWriteStub(Register object,
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 5b80d6f..e19c5ab 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -444,15 +444,16 @@
 
   __ push(lr);
   __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
-  // r4: source FixedArray
   // r5: number of elements (smi-tagged)
 
   // Allocate new FixedDoubleArray.
   // Use lr as a temporary register.
   __ mov(lr, Operand(r5, LSL, 2));
   __ add(lr, lr, Operand(FixedDoubleArray::kHeaderSize));
-  __ Allocate(lr, r6, r7, r9, &gc_required, DOUBLE_ALIGNMENT);
+  __ Allocate(lr, r6, r4, r9, &gc_required, DOUBLE_ALIGNMENT);
   // r6: destination FixedDoubleArray, not tagged as heap object.
+  __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
+  // r4: source FixedArray.
 
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
@@ -483,15 +484,15 @@
 
   // Prepare for conversion loop.
   __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
-  __ add(r7, r6, Operand(FixedDoubleArray::kHeaderSize));
-  __ add(r6, r7, Operand(r5, LSL, 2));
+  __ add(r9, r6, Operand(FixedDoubleArray::kHeaderSize));
+  __ add(r6, r9, Operand(r5, LSL, 2));
   __ mov(r4, Operand(kHoleNanLower32));
   __ mov(r5, Operand(kHoleNanUpper32));
   // r3: begin of source FixedArray element fields, not tagged
   // r4: kHoleNanLower32
   // r5: kHoleNanUpper32
   // r6: end of destination FixedDoubleArray, not tagged
-  // r7: begin of FixedDoubleArray element fields, not tagged
+  // r9: begin of FixedDoubleArray element fields, not tagged
 
   __ b(&entry);
 
@@ -514,30 +515,30 @@
 
   // Convert and copy elements.
   __ bind(&loop);
-  __ ldr(r9, MemOperand(r3, 4, PostIndex));
-  // r9: current element
-  __ UntagAndJumpIfNotSmi(r9, r9, &convert_hole);
+  __ ldr(lr, MemOperand(r3, 4, PostIndex));
+  // lr: current element
+  __ UntagAndJumpIfNotSmi(lr, lr, &convert_hole);
 
   // Normal smi, convert to double and store.
-  __ vmov(s0, r9);
+  __ vmov(s0, lr);
   __ vcvt_f64_s32(d0, s0);
-  __ vstr(d0, r7, 0);
-  __ add(r7, r7, Operand(8));
+  __ vstr(d0, r9, 0);
+  __ add(r9, r9, Operand(8));
   __ b(&entry);
 
   // Hole found, store the-hole NaN.
   __ bind(&convert_hole);
   if (FLAG_debug_code) {
     // Restore a "smi-untagged" heap object.
-    __ SmiTag(r9);
-    __ orr(r9, r9, Operand(1));
-    __ CompareRoot(r9, Heap::kTheHoleValueRootIndex);
+    __ SmiTag(lr);
+    __ orr(lr, lr, Operand(1));
+    __ CompareRoot(lr, Heap::kTheHoleValueRootIndex);
     __ Assert(eq, kObjectFoundInSmiOnlyArray);
   }
-  __ Strd(r4, r5, MemOperand(r7, 8, PostIndex));
+  __ Strd(r4, r5, MemOperand(r9, 8, PostIndex));
 
   __ bind(&entry);
-  __ cmp(r7, r6);
+  __ cmp(r9, r6);
   __ b(lt, &loop);
 
   __ pop(lr);
@@ -577,7 +578,7 @@
   // Allocate new FixedArray.
   __ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
   __ add(r0, r0, Operand(r5, LSL, 1));
-  __ Allocate(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
+  __ Allocate(r0, r6, r3, r9, &gc_required, NO_ALLOCATION_FLAGS);
   // r6: destination FixedArray, not tagged as heap object
   // Set destination FixedDoubleArray's length and map.
   __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
@@ -589,14 +590,12 @@
   __ add(r3, r6, Operand(FixedArray::kHeaderSize));
   __ add(r6, r6, Operand(kHeapObjectTag));
   __ add(r5, r3, Operand(r5, LSL, 1));
-  __ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
   __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
   // Using offsetted addresses in r4 to fully take advantage of post-indexing.
   // r3: begin of destination FixedArray element fields, not tagged
   // r4: begin of source FixedDoubleArray element fields, not tagged, +4
   // r5: end of destination FixedArray, not tagged
   // r6: destination FixedArray
-  // r7: the-hole pointer
   // r9: heap number map
   __ b(&entry);
 
@@ -608,7 +607,7 @@
 
   __ bind(&loop);
   __ ldr(r1, MemOperand(r4, 8, PostIndex));
-  // lr: current element's upper 32 bit
+  // r1: current element's upper 32 bit
   // r4: address of next element's upper 32 bit
   __ cmp(r1, Operand(kHoleNanUpper32));
   __ b(eq, &convert_hole);
@@ -631,7 +630,8 @@
 
   // Replace the-hole NaN with the-hole pointer.
   __ bind(&convert_hole);
-  __ str(r7, MemOperand(r3, 4, PostIndex));
+  __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
+  __ str(r0, MemOperand(r3, 4, PostIndex));
 
   __ bind(&entry);
   __ cmp(r3, r5);
@@ -775,50 +775,65 @@
   ASSERT(!temp2.is(temp3));
   ASSERT(ExternalReference::math_exp_constants(0).address() != NULL);
 
-  Label done;
+  Label zero, infinity, done;
 
   __ mov(temp3, Operand(ExternalReference::math_exp_constants(0)));
 
   __ vldr(double_scratch1, ExpConstant(0, temp3));
-  __ vmov(result, kDoubleRegZero);
   __ VFPCompareAndSetFlags(double_scratch1, input);
-  __ b(ge, &done);
+  __ b(ge, &zero);
+
   __ vldr(double_scratch2, ExpConstant(1, temp3));
   __ VFPCompareAndSetFlags(input, double_scratch2);
-  __ vldr(result, ExpConstant(2, temp3));
-  __ b(ge, &done);
+  __ b(ge, &infinity);
+
   __ vldr(double_scratch1, ExpConstant(3, temp3));
   __ vldr(result, ExpConstant(4, temp3));
   __ vmul(double_scratch1, double_scratch1, input);
   __ vadd(double_scratch1, double_scratch1, result);
-  __ vmov(temp2, temp1, double_scratch1);
+  __ VmovLow(temp2, double_scratch1);
   __ vsub(double_scratch1, double_scratch1, result);
   __ vldr(result, ExpConstant(6, temp3));
   __ vldr(double_scratch2, ExpConstant(5, temp3));
   __ vmul(double_scratch1, double_scratch1, double_scratch2);
   __ vsub(double_scratch1, double_scratch1, input);
   __ vsub(result, result, double_scratch1);
-  __ vmul(input, double_scratch1, double_scratch1);
-  __ vmul(result, result, input);
-  __ mov(temp1, Operand(temp2, LSR, 11));
+  __ vmul(double_scratch2, double_scratch1, double_scratch1);
+  __ vmul(result, result, double_scratch2);
   __ vldr(double_scratch2, ExpConstant(7, temp3));
   __ vmul(result, result, double_scratch2);
   __ vsub(result, result, double_scratch1);
-  __ vldr(double_scratch2, ExpConstant(8, temp3));
+  // Mov 1 in double_scratch2 as math_exp_constants_array[8] == 1.
+  ASSERT(*reinterpret_cast<double*>
+         (ExternalReference::math_exp_constants(8).address()) == 1);
+  __ vmov(double_scratch2, 1);
   __ vadd(result, result, double_scratch2);
-  __ movw(ip, 0x7ff);
-  __ and_(temp2, temp2, Operand(ip));
+  __ mov(temp1, Operand(temp2, LSR, 11));
+  __ Ubfx(temp2, temp2, 0, 11);
   __ add(temp1, temp1, Operand(0x3ff));
-  __ mov(temp1, Operand(temp1, LSL, 20));
 
   // Must not call ExpConstant() after overwriting temp3!
   __ mov(temp3, Operand(ExternalReference::math_exp_log_table()));
-  __ ldr(ip, MemOperand(temp3, temp2, LSL, 3));
-  __ add(temp3, temp3, Operand(kPointerSize));
-  __ ldr(temp2, MemOperand(temp3, temp2, LSL, 3));
-  __ orr(temp1, temp1, temp2);
-  __ vmov(input, ip, temp1);
-  __ vmul(result, result, input);
+  __ add(temp3, temp3, Operand(temp2, LSL, 3));
+  __ ldm(ia, temp3, temp2.bit() | temp3.bit());
+  // The first word is loaded is the lower number register.
+  if (temp2.code() < temp3.code()) {
+    __ orr(temp1, temp3, Operand(temp1, LSL, 20));
+    __ vmov(double_scratch1, temp2, temp1);
+  } else {
+    __ orr(temp1, temp2, Operand(temp1, LSL, 20));
+    __ vmov(double_scratch1, temp3, temp1);
+  }
+  __ vmul(result, result, double_scratch1);
+  __ b(&done);
+
+  __ bind(&zero);
+  __ vmov(result, kDoubleRegZero);
+  __ b(&done);
+
+  __ bind(&infinity);
+  __ vldr(result, ExpConstant(2, temp3));
+
   __ bind(&done);
 }
 
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 54530d8..ecbe64c 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -97,6 +97,7 @@
 
 class MathExpGenerator : public AllStatic {
  public:
+  // Register input isn't modified. All other registers are clobbered.
   static void EmitMathExp(MacroAssembler* masm,
                           DwVfpRegister input,
                           DwVfpRegister result,
diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc
index 9f8da50..0ed84ff 100644
--- a/src/arm/deoptimizer-arm.cc
+++ b/src/arm/deoptimizer-arm.cc
@@ -268,8 +268,8 @@
   __ bind(&inner_push_loop);
   __ sub(r3, r3, Operand(sizeof(uint32_t)));
   __ add(r6, r2, Operand(r3));
-  __ ldr(r7, MemOperand(r6, FrameDescription::frame_content_offset()));
-  __ push(r7);
+  __ ldr(r6, MemOperand(r6, FrameDescription::frame_content_offset()));
+  __ push(r6);
   __ bind(&inner_loop_header);
   __ cmp(r3, Operand::Zero());
   __ b(ne, &inner_push_loop);  // test for gt?
@@ -315,9 +315,9 @@
   __ InitializeRootRegister();
 
   __ pop(ip);  // remove pc
-  __ pop(r7);  // get continuation, leave pc on stack
+  __ pop(ip);  // get continuation, leave pc on stack
   __ pop(lr);
-  __ Jump(r7);
+  __ Jump(ip);
   __ stop("Unreachable.");
 }
 
diff --git a/src/arm/frames-arm.h b/src/arm/frames-arm.h
index d022b41..64a718e 100644
--- a/src/arm/frames-arm.h
+++ b/src/arm/frames-arm.h
@@ -64,7 +64,7 @@
   1 <<  4 |  //  r4 v1
   1 <<  5 |  //  r5 v2
   1 <<  6 |  //  r6 v3
-  1 <<  7 |  //  r7 v4
+  1 <<  7 |  //  r7 v4 (pp in JavaScript code)
   1 <<  8 |  //  r8 v5 (cp in JavaScript code)
   kR9Available <<  9 |  //  r9 v6
   1 << 10 |  // r10 v7
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 195fc8c..d49f842 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -3590,8 +3590,8 @@
 void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(args->length(), 1);
-  // Load the argument on the stack and call the stub.
-  VisitForStackValue(args->at(0));
+  // Load the argument into r0 and call the stub.
+  VisitForAccumulatorValue(args->at(0));
 
   NumberToStringStub stub;
   __ CallStub(&stub);
@@ -3962,9 +3962,8 @@
 
 
 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
-  Label bailout, done, one_char_separator, long_separator,
-      non_trivial_array, not_size_one_array, loop,
-      empty_separator_loop, one_char_separator_loop,
+  Label bailout, done, one_char_separator, long_separator, non_trivial_array,
+      not_size_one_array, loop, empty_separator_loop, one_char_separator_loop,
       one_char_separator_loop_entry, long_separator_loop;
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT(args->length() == 2);
@@ -3982,19 +3981,18 @@
   Register string = r4;
   Register element = r5;
   Register elements_end = r6;
-  Register scratch1 = r7;
-  Register scratch2 = r9;
+  Register scratch = r9;
 
   // Separator operand is on the stack.
   __ pop(separator);
 
   // Check that the array is a JSArray.
   __ JumpIfSmi(array, &bailout);
-  __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE);
+  __ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE);
   __ b(ne, &bailout);
 
   // Check that the array has fast elements.
-  __ CheckFastElements(scratch1, scratch2, &bailout);
+  __ CheckFastElements(scratch, array_length, &bailout);
 
   // If the array has length zero, return the empty string.
   __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
@@ -4031,11 +4029,11 @@
   __ bind(&loop);
   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
   __ JumpIfSmi(string, &bailout);
-  __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
-  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
-  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
-  __ ldr(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
-  __ add(string_length, string_length, Operand(scratch1), SetCC);
+  __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
+  __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
+  __ add(string_length, string_length, Operand(scratch), SetCC);
   __ b(vs, &bailout);
   __ cmp(element, elements_end);
   __ b(lt, &loop);
@@ -4056,23 +4054,23 @@
 
   // Check that the separator is a flat ASCII string.
   __ JumpIfSmi(separator, &bailout);
-  __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
-  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
-  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
+  __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset));
+  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
 
   // Add (separator length times array_length) - separator length to the
   // string_length to get the length of the result string. array_length is not
   // smi but the other values are, so the result is a smi
-  __ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
-  __ sub(string_length, string_length, Operand(scratch1));
-  __ smull(scratch2, ip, array_length, scratch1);
+  __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
+  __ sub(string_length, string_length, Operand(scratch));
+  __ smull(scratch, ip, array_length, scratch);
   // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
   // zero.
   __ cmp(ip, Operand::Zero());
   __ b(ne, &bailout);
-  __ tst(scratch2, Operand(0x80000000));
+  __ tst(scratch, Operand(0x80000000));
   __ b(ne, &bailout);
-  __ add(string_length, string_length, Operand(scratch2), SetCC);
+  __ add(string_length, string_length, Operand(scratch), SetCC);
   __ b(vs, &bailout);
   __ SmiUntag(string_length);
 
@@ -4089,9 +4087,9 @@
   //   array_length: Length of the array.
   __ AllocateAsciiString(result,
                          string_length,
-                         scratch1,
-                         scratch2,
-                         elements_end,
+                         scratch,
+                         string,  // used as scratch
+                         elements_end,  // used as scratch
                          &bailout);
   // Prepare for looping. Set up elements_end to end of the array. Set
   // result_pos to the position of the result where to write the first
@@ -4104,8 +4102,8 @@
          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
 
   // Check the length of the separator.
-  __ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
-  __ cmp(scratch1, Operand(Smi::FromInt(1)));
+  __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
+  __ cmp(scratch, Operand(Smi::FromInt(1)));
   __ b(eq, &one_char_separator);
   __ b(gt, &long_separator);
 
@@ -4123,7 +4121,7 @@
   __ add(string,
          string,
          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ CopyBytes(string, result_pos, string_length, scratch);
   __ cmp(element, elements_end);
   __ b(lt, &empty_separator_loop);  // End while (element < elements_end).
   ASSERT(result.is(r0));
@@ -4155,7 +4153,7 @@
   __ add(string,
          string,
          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ CopyBytes(string, result_pos, string_length, scratch);
   __ cmp(element, elements_end);
   __ b(lt, &one_char_separator_loop);  // End while (element < elements_end).
   ASSERT(result.is(r0));
@@ -4176,7 +4174,7 @@
   __ add(string,
          separator,
          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ CopyBytes(string, result_pos, string_length, scratch);
 
   __ bind(&long_separator);
   __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
@@ -4185,7 +4183,7 @@
   __ add(string,
          string,
          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
-  __ CopyBytes(string, result_pos, string_length, scratch1);
+  __ CopyBytes(string, result_pos, string_length, scratch);
   __ cmp(element, elements_end);
   __ b(lt, &long_separator_loop);  // End while (element < elements_end).
   ASSERT(result.is(r0));
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index f15d4b1..b39a0ed 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -1394,7 +1394,7 @@
   Register receiver = r2;
   Register receiver_map = r3;
   Register elements_map = r6;
-  Register elements = r7;  // Elements array of the receiver.
+  Register elements = r9;  // Elements array of the receiver.
   // r4 and r5 are used as general scratch registers.
 
   // Check that the key is a smi.
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index f216a8e..6fdbbb5 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1240,7 +1240,7 @@
 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) {
   ASSERT(instr->representation().IsDouble());
   ASSERT(instr->value()->representation().IsDouble());
-  LOperand* input = UseTempRegister(instr->value());
+  LOperand* input = UseRegister(instr->value());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
   LOperand* double_temp = FixedTemp(d3);  // Chosen by fair dice roll.
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 3902b4c..76867c8 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -1360,8 +1360,8 @@
   LOperand* temp() { return temps_[0]; }
   Smi* index() const { return index_; }
 
-  DECLARE_CONCRETE_INSTRUCTION(ValueOf, "date-field")
-  DECLARE_HYDROGEN_ACCESSOR(ValueOf)
+  DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
+  DECLARE_HYDROGEN_ACCESSOR(DateField)
 
  private:
   Smi* index_;
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 2680c34..ca38743 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -1090,11 +1090,6 @@
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
       break;
     }
-    case CodeStub::NumberToString: {
-      NumberToStringStub stub;
-      CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
     case CodeStub::StringCompare: {
       StringCompareStub stub;
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -3879,9 +3874,9 @@
   } else if (exponent_type.IsTagged()) {
     Label no_deopt;
     __ JumpIfSmi(r2, &no_deopt);
-    __ ldr(r7, FieldMemOperand(r2, HeapObject::kMapOffset));
+    __ ldr(r6, FieldMemOperand(r2, HeapObject::kMapOffset));
     __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
-    __ cmp(r7, Operand(ip));
+    __ cmp(r6, Operand(ip));
     DeoptimizeIf(ne, instr->environment());
     __ bind(&no_deopt);
     MathPowStub stub(MathPowStub::TAGGED);
@@ -5386,24 +5381,24 @@
 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
   Label materialized;
   // Registers will be used as follows:
-  // r7 = literals array.
+  // r6 = literals array.
   // r1 = regexp literal.
   // r0 = regexp literal clone.
-  // r2 and r4-r6 are used as temporaries.
+  // r2-5 are used as temporaries.
   int literal_offset =
       FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
-  __ LoadHeapObject(r7, instr->hydrogen()->literals());
-  __ ldr(r1, FieldMemOperand(r7, literal_offset));
+  __ LoadHeapObject(r6, instr->hydrogen()->literals());
+  __ ldr(r1, FieldMemOperand(r6, literal_offset));
   __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
   __ cmp(r1, ip);
   __ b(ne, &materialized);
 
   // Create regexp literal using runtime function
   // Result will be in r0.
-  __ mov(r6, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
-  __ mov(r5, Operand(instr->hydrogen()->pattern()));
-  __ mov(r4, Operand(instr->hydrogen()->flags()));
-  __ Push(r7, r6, r5, r4);
+  __ mov(r5, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
+  __ mov(r4, Operand(instr->hydrogen()->pattern()));
+  __ mov(r3, Operand(instr->hydrogen()->flags()));
+  __ Push(r6, r5, r4, r3);
   CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
   __ mov(r1, r0);
 
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index eeabc05..fd51521 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1337,7 +1337,7 @@
   STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
 
-  // For the JSEntry handler, we must preserve r0-r4, r5-r7 are available.
+  // For the JSEntry handler, we must preserve r0-r4, r5-r6 are available.
   // We will build up the handler from the bottom by pushing on the stack.
   // Set up the code object (r5) and the state (r6) for pushing.
   unsigned state =
@@ -1348,9 +1348,9 @@
 
   // Push the frame pointer, context, state, and code object.
   if (kind == StackHandler::JS_ENTRY) {
-    mov(r7, Operand(Smi::FromInt(0)));  // Indicates no context.
+    mov(cp, Operand(Smi::FromInt(0)));  // Indicates no context.
     mov(ip, Operand::Zero());  // NULL frame pointer.
-    stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | ip.bit());
+    stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | ip.bit());
   } else {
     stm(db_w, sp, r5.bit() | r6.bit() | cp.bit() | fp.bit());
   }
@@ -2305,13 +2305,15 @@
       ExternalReference::handle_scope_level_address(isolate()),
       next_address);
 
+  ASSERT(!thunk_last_arg.is(r3));
+
   // Allocate HandleScope in callee-save registers.
-  mov(r7, Operand(next_address));
-  ldr(r4, MemOperand(r7, kNextOffset));
-  ldr(r5, MemOperand(r7, kLimitOffset));
-  ldr(r6, MemOperand(r7, kLevelOffset));
+  mov(r9, Operand(next_address));
+  ldr(r4, MemOperand(r9, kNextOffset));
+  ldr(r5, MemOperand(r9, kLimitOffset));
+  ldr(r6, MemOperand(r9, kLevelOffset));
   add(r6, r6, Operand(1));
-  str(r6, MemOperand(r7, kLevelOffset));
+  str(r6, MemOperand(r9, kLevelOffset));
 
   if (FLAG_log_timer_events) {
     FrameScope frame(this, StackFrame::MANUAL);
@@ -2322,7 +2324,6 @@
     PopSafepointRegisters();
   }
 
-  ASSERT(!thunk_last_arg.is(r3));
   Label profiler_disabled;
   Label end_profiler_check;
   bool* is_profiling_flag =
@@ -2368,15 +2369,15 @@
   bind(&return_value_loaded);
   // No more valid handles (the result handle was the last one). Restore
   // previous handle scope.
-  str(r4, MemOperand(r7, kNextOffset));
+  str(r4, MemOperand(r9, kNextOffset));
   if (emit_debug_code()) {
-    ldr(r1, MemOperand(r7, kLevelOffset));
+    ldr(r1, MemOperand(r9, kLevelOffset));
     cmp(r1, r6);
     Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
   }
   sub(r6, r6, Operand(1));
-  str(r6, MemOperand(r7, kLevelOffset));
-  ldr(ip, MemOperand(r7, kLimitOffset));
+  str(r6, MemOperand(r9, kLevelOffset));
+  ldr(ip, MemOperand(r9, kLimitOffset));
   cmp(r5, ip);
   b(ne, &delete_allocated_handles);
 
@@ -2409,7 +2410,7 @@
 
   // HandleScope limit has changed. Delete allocated extensions.
   bind(&delete_allocated_handles);
-  str(r5, MemOperand(r7, kLimitOffset));
+  str(r5, MemOperand(r9, kLimitOffset));
   mov(r4, r0);
   PrepareCallCFunction(1, r5);
   mov(r0, Operand(ExternalReference::isolate_address(isolate())));
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 6d08ab9..6d5ba51 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -45,8 +45,9 @@
 
 
 // Give alias names to registers
-const Register cp = { 8 };  // JavaScript context pointer
-const Register kRootRegister = { 10 };  // Roots array pointer.
+const Register pp = { kRegister_r7_Code };  // Constant pool pointer.
+const Register cp = { kRegister_r8_Code };  // JavaScript context pointer.
+const Register kRootRegister = { kRegister_r10_Code };  // Roots array pointer.
 
 // Flags used for AllocateHeapNumber
 enum TaggingMode {
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 567eb63..6308b34 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -874,8 +874,8 @@
   // Store call data.
   __ str(r6, MemOperand(sp, 3 * kPointerSize));
   // Store isolate.
-  __ mov(r7, Operand(ExternalReference::isolate_address(masm->isolate())));
-  __ str(r7, MemOperand(sp, 4 * kPointerSize));
+  __ mov(r5, Operand(ExternalReference::isolate_address(masm->isolate())));
+  __ str(r5, MemOperand(sp, 4 * kPointerSize));
   // Store ReturnValue default and ReturnValue.
   __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
   __ str(r5, MemOperand(sp, 5 * kPointerSize));
@@ -1855,15 +1855,15 @@
 
       if (FLAG_smi_only_arrays  && !FLAG_trace_elements_transitions) {
         Label fast_object, not_fast_object;
-        __ CheckFastObjectElements(r3, r7, &not_fast_object);
+        __ CheckFastObjectElements(r3, r9, &not_fast_object);
         __ jmp(&fast_object);
         // In case of fast smi-only, convert to fast object, otherwise bail out.
         __ bind(&not_fast_object);
-        __ CheckFastSmiElements(r3, r7, &call_builtin);
+        __ CheckFastSmiElements(r3, r9, &call_builtin);
 
-        __ ldr(r7, FieldMemOperand(r4, HeapObject::kMapOffset));
+        __ ldr(r9, FieldMemOperand(r4, HeapObject::kMapOffset));
         __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
-        __ cmp(r7, ip);
+        __ cmp(r9, ip);
         __ b(eq, &call_builtin);
         // edx: receiver
         // r3: map
@@ -1871,7 +1871,7 @@
         __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
                                                FAST_ELEMENTS,
                                                r3,
-                                               r7,
+                                               r9,
                                                &try_holey_map);
         __ mov(r2, receiver);
         ElementsTransitionGenerator::
@@ -1884,7 +1884,7 @@
         __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
                                                FAST_HOLEY_ELEMENTS,
                                                r3,
-                                               r7,
+                                               r9,
                                                &call_builtin);
         __ mov(r2, receiver);
         ElementsTransitionGenerator::
@@ -1917,7 +1917,6 @@
 
       __ bind(&attempt_to_grow_elements);
       // r0: array's length + 1.
-      // r4: elements' length.
 
       if (!FLAG_inline_new) {
         __ b(&call_builtin);
@@ -1928,8 +1927,8 @@
       // the new element is non-Smi. For now, delegate to the builtin.
       Label no_fast_elements_check;
       __ JumpIfSmi(r2, &no_fast_elements_check);
-      __ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset));
-      __ CheckFastObjectElements(r7, r7, &call_builtin);
+      __ ldr(r9, FieldMemOperand(receiver, HeapObject::kMapOffset));
+      __ CheckFastObjectElements(r9, r9, &call_builtin);
       __ bind(&no_fast_elements_check);
 
       ExternalReference new_space_allocation_top =
@@ -1941,8 +1940,8 @@
       // Load top and check if it is the end of elements.
       __ add(end_elements, elements, Operand::PointerOffsetFromSmiKey(r0));
       __ add(end_elements, end_elements, Operand(kEndElementsOffset));
-      __ mov(r7, Operand(new_space_allocation_top));
-      __ ldr(r3, MemOperand(r7));
+      __ mov(r4, Operand(new_space_allocation_top));
+      __ ldr(r3, MemOperand(r4));
       __ cmp(end_elements, r3);
       __ b(ne, &call_builtin);
 
@@ -1954,7 +1953,7 @@
 
       // We fit and could grow elements.
       // Update new_space_allocation_top.
-      __ str(r3, MemOperand(r7));
+      __ str(r3, MemOperand(r4));
       // Push the argument.
       __ str(r2, MemOperand(end_elements));
       // Fill the rest with holes.
@@ -1965,6 +1964,7 @@
 
       // Update elements' and array's sizes.
       __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+      __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
       __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta)));
       __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset));
 
diff --git a/src/builtins.h b/src/builtins.h
index 01061b6..54787f7 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -108,8 +108,6 @@
                                     Code::kNoExtraICState)              \
   V(NotifyStubFailure,              BUILTIN, UNINITIALIZED,             \
                                     Code::kNoExtraICState)              \
-  V(NotifyOSR,                      BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
                                                                         \
   V(LoadIC_Miss,                    BUILTIN, UNINITIALIZED,             \
                                     Code::kNoExtraICState)              \
@@ -388,7 +386,6 @@
   static void Generate_NotifyDeoptimized(MacroAssembler* masm);
   static void Generate_NotifySoftDeoptimized(MacroAssembler* masm);
   static void Generate_NotifyLazyDeoptimized(MacroAssembler* masm);
-  static void Generate_NotifyOSR(MacroAssembler* masm);
   static void Generate_NotifyStubFailure(MacroAssembler* masm);
   static void Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm);
 
diff --git a/src/checks.cc b/src/checks.cc
index 7108d18..d2a107c 100644
--- a/src/checks.cc
+++ b/src/checks.cc
@@ -25,11 +25,48 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <stdarg.h>
+#include "checks.h"
 
-#include "v8.h"
+#if V8_LIBC_GLIBC || V8_OS_BSD
+# include <cxxabi.h>
+# include <execinfo.h>
+#endif  // V8_LIBC_GLIBC || V8_OS_BSD
+#include <stdio.h>
 
 #include "platform.h"
+#include "v8.h"
+
+
+// Attempts to dump a backtrace (if supported).
+static V8_INLINE void DumpBacktrace() {
+#if V8_LIBC_GLIBC || V8_OS_BSD
+  void* trace[100];
+  int size = backtrace(trace, ARRAY_SIZE(trace));
+  char** symbols = backtrace_symbols(trace, size);
+  i::OS::PrintError("\n==== C stack trace ===============================\n\n");
+  if (size == 0) {
+    i::OS::PrintError("(empty)\n");
+  } else if (symbols == NULL) {
+    i::OS::PrintError("(no symbols)\n");
+  } else {
+    for (int i = 1; i < size; ++i) {
+      i::OS::PrintError("%2d: ", i);
+      char mangled[201];
+      if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) {  // NOLINT
+        int status;
+        size_t length;
+        char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
+        i::OS::PrintError("%s\n", demangled != NULL ? demangled : mangled);
+        free(demangled);
+      } else {
+        i::OS::PrintError("??\n");
+      }
+    }
+  }
+  free(symbols);
+#endif  // V8_LIBC_GLIBC || V8_OS_BSD
+}
+
 
 // Contains protection against recursive calls (faults while handling faults).
 extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
@@ -43,7 +80,8 @@
   i::OS::VPrintError(format, arguments);
   va_end(arguments);
   i::OS::PrintError("\n#\n");
-  i::OS::DumpBacktrace();
+  DumpBacktrace();
+  fflush(stderr);
   i::OS::Abort();
 }
 
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 0d06209..2700dbb 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -339,6 +339,19 @@
 
 
 template <>
+HValue* CodeStubGraphBuilder<NumberToStringStub>::BuildCodeStub() {
+  info()->MarkAsSavesCallerDoubles();
+  HValue* number = GetParameter(NumberToStringStub::kNumber);
+  return BuildNumberToString(number);
+}
+
+
+Handle<Code> NumberToStringStub::GenerateCode(Isolate* isolate) {
+  return DoGenerateCode(isolate, this);
+}
+
+
+template <>
 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
   Factory* factory = isolate()->factory();
   HValue* undefined = graph()->GetConstantUndefined();
@@ -473,6 +486,11 @@
                         HObjectAccess::ForAllocationSiteTransitionInfo(),
                         initial_elements_kind);
 
+  // Unlike literals, constructed arrays don't have nested sites
+  Add<HStoreNamedField>(object,
+                        HObjectAccess::ForAllocationSiteNestedSite(),
+                        graph()->GetConstant0());
+
   // Store an empty fixed array for the code dependency.
   HConstant* empty_fixed_array =
     Add<HConstant>(isolate()->factory()->empty_fixed_array());
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 30ec1c7..a5c2f88 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -464,6 +464,25 @@
 };
 
 
+class NumberToStringStub V8_FINAL : public HydrogenCodeStub {
+ public:
+  NumberToStringStub() {}
+
+  virtual Handle<Code> GenerateCode(Isolate* isolate) V8_OVERRIDE;
+
+  virtual void InitializeInterfaceDescriptor(
+      Isolate* isolate,
+      CodeStubInterfaceDescriptor* descriptor) V8_OVERRIDE;
+
+  // Parameters accessed via CodeStubGraphBuilder::GetParameter()
+  static const int kNumber = 0;
+
+ private:
+  virtual Major MajorKey() V8_OVERRIDE { return NumberToString; }
+  virtual int NotMissMinorKey() V8_OVERRIDE { return 0; }
+};
+
+
 class FastNewClosureStub : public HydrogenCodeStub {
  public:
   explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 2c01251..a8229ea 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -176,11 +176,6 @@
             "enable harmony collections (sets, maps, and weak maps)")
 DEFINE_bool(harmony_observation, false,
             "enable harmony object observation (implies harmony collections")
-DEFINE_bool(harmony_typed_arrays, true,
-            "enable harmony typed arrays")
-DEFINE_bool(harmony_array_buffer, true,
-            "enable harmony array buffer")
-DEFINE_implication(harmony_typed_arrays, harmony_array_buffer)
 DEFINE_bool(harmony_generators, false, "enable harmony generators")
 DEFINE_bool(harmony_iteration, false, "enable harmony iteration (for-of)")
 DEFINE_bool(harmony_numeric_literals, false,
@@ -201,7 +196,6 @@
 DEFINE_implication(harmony, harmony_arrays)
 DEFINE_implication(harmony_modules, harmony_scoping)
 DEFINE_implication(harmony_observation, harmony_collections)
-// TODO[dslomov] add harmony => harmony_typed_arrays
 
 // Flags for experimental implementation features.
 DEFINE_bool(packed_arrays, true, "optimizes arrays that have no holes")
@@ -826,6 +820,16 @@
 #endif
 #endif
 
+//
+// Read-only flags
+//
+#undef FLAG
+#define FLAG FLAG_READONLY
+
+// assembler-arm.h
+DEFINE_bool(enable_ool_constant_pool, false,
+            "enable use of out-of-line constant pools (ARM only)")
+
 // Cleanup...
 #undef FLAG_FULL
 #undef FLAG_READONLY
diff --git a/src/heap-inl.h b/src/heap-inl.h
index e11dec8..a0762a3 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -140,12 +140,11 @@
   // Compute map and object size.
   Map* map = ascii_internalized_string_map();
   int size = SeqOneByteString::SizeFor(str.length());
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, TENURED);
 
   // Allocate string.
   Object* result;
-  { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize)
-                   ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE)
-                   : old_data_space_->AllocateRaw(size);
+  { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -174,12 +173,11 @@
   // Compute map and object size.
   Map* map = internalized_string_map();
   int size = SeqTwoByteString::SizeFor(str.length());
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, TENURED);
 
   // Allocate string.
   Object* result;
-  { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize)
-                   ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE)
-                   : old_data_space_->AllocateRaw(size);
+  { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -211,7 +209,9 @@
 MaybeObject* Heap::AllocateRaw(int size_in_bytes,
                                AllocationSpace space,
                                AllocationSpace retry_space) {
-  ASSERT(AllowHandleAllocation::IsAllowed() && gc_state_ == NOT_IN_GC);
+  ASSERT(AllowHandleAllocation::IsAllowed());
+  ASSERT(AllowHeapAllocation::IsAllowed());
+  ASSERT(gc_state_ == NOT_IN_GC);
   ASSERT(space != NEW_SPACE ||
          retry_space == OLD_POINTER_SPACE ||
          retry_space == OLD_DATA_SPACE ||
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 5799132..5570362 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1301,6 +1301,8 @@
                                                      AllocationSite* site) {
   SetInternalReference(site, entry, "transition_info", site->transition_info(),
                        AllocationSite::kTransitionInfoOffset);
+  SetInternalReference(site, entry, "nested_site", site->nested_site(),
+                       AllocationSite::kNestedSiteOffset);
   SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
                        AllocationSite::kDependentCodeOffset);
 }
diff --git a/src/heap.cc b/src/heap.cc
index e81a0e3..7b9f0d5 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -608,6 +608,11 @@
   // Note: as weak callbacks can execute arbitrary code, we cannot
   // hope that eventually there will be no weak callbacks invocations.
   // Therefore stop recollecting after several attempts.
+  if (FLAG_concurrent_recompilation) {
+    // The optimizing compiler may be unnecessarily holding on to memory.
+    DisallowHeapAllocation no_recursive_gc;
+    isolate()->optimizing_compiler_thread()->Flush();
+  }
   mark_compact_collector()->SetFlags(kMakeHeapIterableMask |
                                      kReduceMemoryFootprintMask);
   isolate_->compilation_cache()->Clear();
@@ -2896,12 +2901,12 @@
 MaybeObject* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) {
   // Statically ensure that it is safe to allocate heap numbers in paged
   // spaces.
+  int size = HeapNumber::kSize;
   STATIC_ASSERT(HeapNumber::kSize <= Page::kNonCodeObjectAreaSize);
-  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
 
   Object* result;
-  { MaybeObject* maybe_result =
-        AllocateRaw(HeapNumber::kSize, space, OLD_DATA_SPACE);
+  { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -2911,23 +2916,6 @@
 }
 
 
-MaybeObject* Heap::AllocateHeapNumber(double value) {
-  // Use general version, if we're forced to always allocate.
-  if (always_allocate()) return AllocateHeapNumber(value, TENURED);
-
-  // This version of AllocateHeapNumber is optimized for
-  // allocation in new space.
-  STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxNonCodeHeapObjectSize);
-  Object* result;
-  { MaybeObject* maybe_result = new_space_.AllocateRaw(HeapNumber::kSize);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
-  HeapObject::cast(result)->set_map_no_write_barrier(heap_number_map());
-  HeapNumber::cast(result)->set_value(value);
-  return result;
-}
-
-
 MaybeObject* Heap::AllocateCell(Object* value) {
   Object* result;
   { MaybeObject* maybe_result = AllocateRawCell();
@@ -4065,31 +4053,8 @@
   if (length < 0 || length > ByteArray::kMaxLength) {
     return Failure::OutOfMemoryException(0x7);
   }
-  if (pretenure == NOT_TENURED) {
-    return AllocateByteArray(length);
-  }
   int size = ByteArray::SizeFor(length);
-  AllocationSpace space =
-      (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : OLD_DATA_SPACE;
-  Object* result;
-  { MaybeObject* maybe_result = AllocateRaw(size, space, space);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
-
-  reinterpret_cast<ByteArray*>(result)->set_map_no_write_barrier(
-      byte_array_map());
-  reinterpret_cast<ByteArray*>(result)->set_length(length);
-  return result;
-}
-
-
-MaybeObject* Heap::AllocateByteArray(int length) {
-  if (length < 0 || length > ByteArray::kMaxLength) {
-    return Failure::OutOfMemoryException(0x8);
-  }
-  int size = ByteArray::SizeFor(length);
-  AllocationSpace space =
-      (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : NEW_SPACE;
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
   Object* result;
   { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
@@ -4120,11 +4085,10 @@
                                          ExternalArrayType array_type,
                                          void* external_pointer,
                                          PretenureFlag pretenure) {
-  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
+  int size = ExternalArray::kAlignedSize;
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
   Object* result;
-  { MaybeObject* maybe_result = AllocateRaw(ExternalArray::kAlignedSize,
-                                            space,
-                                            OLD_DATA_SPACE);
+  { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -4423,10 +4387,6 @@
     arguments_object_size = kArgumentsObjectSize;
   }
 
-  // This calls Copy directly rather than using Heap::AllocateRaw so we
-  // duplicate the check here.
-  ASSERT(AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC);
-
   // Check that the size of the boilerplate matches our
   // expectations. The ArgumentsAccessStub::GenerateNewObject relies
   // on the size being a known constant.
@@ -4562,9 +4522,8 @@
   }
 
   // Allocate the JSObject.
-  AllocationSpace space =
-      (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
-  if (map->instance_size() > Page::kMaxNonCodeHeapObjectSize) space = LO_SPACE;
+  int size = map->instance_size();
+  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, pretenure);
   Object* obj;
   MaybeObject* maybe_obj = Allocate(map, space);
   if (!maybe_obj->To(&obj)) return maybe_obj;
@@ -4597,8 +4556,8 @@
   }
 
   // Allocate the JSObject.
-  AllocationSpace space = NEW_SPACE;
-  if (map->instance_size() > Page::kMaxNonCodeHeapObjectSize) space = LO_SPACE;
+  int size = map->instance_size();
+  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, NOT_TENURED);
   Object* obj;
   MaybeObject* maybe_obj =
       AllocateWithAllocationSite(map, space, allocation_site);
@@ -5266,12 +5225,11 @@
     map = internalized_string_map();
     size = SeqTwoByteString::SizeFor(chars);
   }
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, TENURED);
 
   // Allocate string.
   Object* result;
-  { MaybeObject* maybe_result = (size > Page::kMaxNonCodeHeapObjectSize)
-                   ? lo_space_->AllocateRaw(size, NOT_EXECUTABLE)
-                   : old_data_space_->AllocateRaw(size);
+  { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -5310,16 +5268,10 @@
   }
   int size = SeqOneByteString::SizeFor(length);
   ASSERT(size <= SeqOneByteString::kMaxSize);
-  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
-  AllocationSpace retry_space = OLD_DATA_SPACE;
-
-  if (size > Page::kMaxNonCodeHeapObjectSize) {
-    // Allocate in large object space, retry space will be ignored.
-    space = LO_SPACE;
-  }
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
 
   Object* result;
-  { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
+  { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -5340,16 +5292,10 @@
   }
   int size = SeqTwoByteString::SizeFor(length);
   ASSERT(size <= SeqTwoByteString::kMaxSize);
-  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
-  AllocationSpace retry_space = OLD_DATA_SPACE;
-
-  if (size > Page::kMaxNonCodeHeapObjectSize) {
-    // Allocate in large object space, retry space will be ignored.
-    space = LO_SPACE;
-  }
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
 
   Object* result;
-  { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space);
+  { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_result->ToObject(&result)) return maybe_result;
   }
 
@@ -5452,39 +5398,14 @@
 }
 
 
-MaybeObject* Heap::AllocateFixedArray(int length) {
-  ASSERT(length >= 0);
-  if (length == 0) return empty_fixed_array();
-  Object* result;
-  { MaybeObject* maybe_result = AllocateRawFixedArray(length);
-    if (!maybe_result->ToObject(&result)) return maybe_result;
-  }
-  // Initialize header.
-  FixedArray* array = reinterpret_cast<FixedArray*>(result);
-  array->set_map_no_write_barrier(fixed_array_map());
-  array->set_length(length);
-  // Initialize body.
-  ASSERT(!InNewSpace(undefined_value()));
-  MemsetPointer(array->data_start(), undefined_value(), length);
-  return result;
-}
-
-
 MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) {
   if (length < 0 || length > FixedArray::kMaxLength) {
     return Failure::OutOfMemoryException(0xe);
   }
   int size = FixedArray::SizeFor(length);
-  AllocationSpace space =
-      (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE;
-  AllocationSpace retry_space = OLD_POINTER_SPACE;
+  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, pretenure);
 
-  if (size > Page::kMaxNonCodeHeapObjectSize) {
-    // Allocate in large object space, retry space will be ignored.
-    space = LO_SPACE;
-  }
-
-  return AllocateRaw(size, space, retry_space);
+  return AllocateRaw(size, space, OLD_POINTER_SPACE);
 }
 
 
@@ -5602,20 +5523,13 @@
     return Failure::OutOfMemoryException(0xf);
   }
   int size = FixedDoubleArray::SizeFor(length);
-  AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
-  AllocationSpace retry_space = OLD_DATA_SPACE;
-
 #ifndef V8_HOST_ARCH_64_BIT
   size += kPointerSize;
 #endif
-
-  if (size > Page::kMaxNonCodeHeapObjectSize) {
-    // Allocate in large object space, retry space will be ignored.
-    space = LO_SPACE;
-  }
+  AllocationSpace space = SelectSpace(size, OLD_DATA_SPACE, pretenure);
 
   HeapObject* object;
-  { MaybeObject* maybe_object = AllocateRaw(size, space, retry_space);
+  { MaybeObject* maybe_object = AllocateRaw(size, space, OLD_DATA_SPACE);
     if (!maybe_object->To<HeapObject>(&object)) return maybe_object;
   }
 
@@ -5819,8 +5733,7 @@
       return Failure::InternalError();
   }
   int size = map->instance_size();
-  AllocationSpace space =
-      (size > Page::kMaxNonCodeHeapObjectSize) ? LO_SPACE : OLD_POINTER_SPACE;
+  AllocationSpace space = SelectSpace(size, OLD_POINTER_SPACE, TENURED);
   Object* result;
   { MaybeObject* maybe_result = Allocate(map, space);
     if (!maybe_result->ToObject(&result)) return maybe_result;
diff --git a/src/heap.h b/src/heap.h
index 573c512..cb979a6 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -864,14 +864,9 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT MaybeObject* AllocateByteArray(int length,
-                                                 PretenureFlag pretenure);
-
-  // Allocate a non-tenured byte array of the specified length
-  // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
-  // failed.
-  // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT MaybeObject* AllocateByteArray(int length);
+  MUST_USE_RESULT MaybeObject* AllocateByteArray(
+      int length,
+      PretenureFlag pretenure = NOT_TENURED);
 
   // Allocates an external array of the specified length and type.
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
@@ -912,10 +907,9 @@
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
   // Please note this does not perform a garbage collection.
-  MUST_USE_RESULT MaybeObject* AllocateFixedArray(int length,
-                                                  PretenureFlag pretenure);
-  // Allocates a fixed array initialized with undefined values
-  MUST_USE_RESULT MaybeObject* AllocateFixedArray(int length);
+  MUST_USE_RESULT MaybeObject* AllocateFixedArray(
+      int length,
+      PretenureFlag pretenure = NOT_TENURED);
 
   // Allocates an uninitialized fixed array. It must be filled by the caller.
   //
@@ -1044,10 +1038,7 @@
 
   // Allocated a HeapNumber from value.
   MUST_USE_RESULT MaybeObject* AllocateHeapNumber(
-      double value,
-      PretenureFlag pretenure);
-  // pretenure = NOT_TENURED
-  MUST_USE_RESULT MaybeObject* AllocateHeapNumber(double value);
+      double value, PretenureFlag pretenure = NOT_TENURED);
 
   // Converts an int into either a Smi or a HeapNumber object.
   // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
@@ -2066,6 +2057,17 @@
 
   inline void UpdateOldSpaceLimits();
 
+  // Selects the proper allocation space depending on the given object
+  // size, pretenuring decision, and preferred old-space.
+  static AllocationSpace SelectSpace(int object_size,
+                                     AllocationSpace preferred_old_space,
+                                     PretenureFlag pretenure) {
+    ASSERT(preferred_old_space == OLD_POINTER_SPACE ||
+           preferred_old_space == OLD_DATA_SPACE);
+    if (object_size > Page::kMaxNonCodeHeapObjectSize) return LO_SPACE;
+    return (pretenure == TENURED) ? preferred_old_space : NEW_SPACE;
+  }
+
   // Allocate an uninitialized object in map space.  The behavior is identical
   // to Heap::AllocateRaw(size_in_bytes, MAP_SPACE), except that (a) it doesn't
   // have to test the allocation space argument and (b) can reduce code size
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index a685198..d301036 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -2363,8 +2363,7 @@
 
 HConstant::HConstant(Handle<Object> handle, Representation r)
   : HTemplateInstruction<0>(HType::TypeFromValue(handle)),
-    handle_(handle),
-    unique_id_(),
+    object_(Unique<Object>::CreateUninitialized(handle)),
     has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
@@ -2373,29 +2372,28 @@
     is_not_in_new_space_(true),
     is_cell_(false),
     boolean_value_(handle->BooleanValue()) {
-  if (handle_->IsHeapObject()) {
+  if (handle->IsHeapObject()) {
     Heap* heap = Handle<HeapObject>::cast(handle)->GetHeap();
     is_not_in_new_space_ = !heap->InNewSpace(*handle);
   }
-  if (handle_->IsNumber()) {
-    double n = handle_->Number();
+  if (handle->IsNumber()) {
+    double n = handle->Number();
     has_int32_value_ = IsInteger32(n);
     int32_value_ = DoubleToInt32(n);
     has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
     double_value_ = n;
     has_double_value_ = true;
   } else {
-    is_internalized_string_ = handle_->IsInternalizedString();
+    is_internalized_string_ = handle->IsInternalizedString();
   }
 
-  is_cell_ = !handle_.is_null() &&
-      (handle_->IsCell() || handle_->IsPropertyCell());
+  is_cell_ = !handle.is_null() &&
+      (handle->IsCell() || handle->IsPropertyCell());
   Initialize(r);
 }
 
 
-HConstant::HConstant(Handle<Object> handle,
-                     UniqueValueId unique_id,
+HConstant::HConstant(Unique<Object> unique,
                      Representation r,
                      HType type,
                      bool is_internalize_string,
@@ -2403,8 +2401,7 @@
                      bool is_cell,
                      bool boolean_value)
   : HTemplateInstruction<0>(type),
-    handle_(handle),
-    unique_id_(unique_id),
+    object_(unique),
     has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
@@ -2413,36 +2410,17 @@
     is_not_in_new_space_(is_not_in_new_space),
     is_cell_(is_cell),
     boolean_value_(boolean_value) {
-  ASSERT(!handle.is_null());
+  ASSERT(!unique.handle().is_null());
   ASSERT(!type.IsTaggedNumber());
   Initialize(r);
 }
 
 
-HConstant::HConstant(Handle<Map> handle,
-                     UniqueValueId unique_id)
-  : HTemplateInstruction<0>(HType::Tagged()),
-    handle_(handle),
-    unique_id_(unique_id),
-    has_smi_value_(false),
-    has_int32_value_(false),
-    has_double_value_(false),
-    has_external_reference_value_(false),
-    is_internalized_string_(false),
-    is_not_in_new_space_(true),
-    is_cell_(false),
-    boolean_value_(false) {
-  ASSERT(!handle.is_null());
-  Initialize(Representation::Tagged());
-}
-
-
 HConstant::HConstant(int32_t integer_value,
                      Representation r,
                      bool is_not_in_new_space,
-                     Handle<Object> optional_handle)
-  : handle_(optional_handle),
-    unique_id_(),
+                     Unique<Object> object)
+  : object_(object),
     has_smi_value_(Smi::IsValid(integer_value)),
     has_int32_value_(true),
     has_double_value_(true),
@@ -2461,9 +2439,8 @@
 HConstant::HConstant(double double_value,
                      Representation r,
                      bool is_not_in_new_space,
-                     Handle<Object> optional_handle)
-  : handle_(optional_handle),
-    unique_id_(),
+                     Unique<Object> object)
+  : object_(object),
     has_int32_value_(IsInteger32(double_value)),
     has_double_value_(true),
     has_external_reference_value_(false),
@@ -2481,6 +2458,7 @@
 
 HConstant::HConstant(ExternalReference reference)
   : HTemplateInstruction<0>(HType::None()),
+    object_(Unique<Object>(Handle<Object>::null())),
     has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
@@ -2494,14 +2472,6 @@
 }
 
 
-static void PrepareConstant(Handle<Object> object) {
-  if (!object->IsJSObject()) return;
-  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
-  if (!js_object->map()->is_deprecated()) return;
-  JSObject::TryMigrateInstance(js_object);
-}
-
-
 void HConstant::Initialize(Representation r) {
   if (r.IsNone()) {
     if (has_smi_value_ && SmiValuesAre31Bits()) {
@@ -2513,7 +2483,14 @@
     } else if (has_external_reference_value_) {
       r = Representation::External();
     } else {
-      PrepareConstant(handle_);
+      Handle<Object> object = object_.handle();
+      if (object->IsJSObject()) {
+        // Try to eagerly migrate JSObjects that have deprecated maps.
+        Handle<JSObject> js_object = Handle<JSObject>::cast(object);
+        if (js_object->map()->is_deprecated()) {
+          JSObject::TryMigrateInstance(js_object);
+        }
+      }
       r = Representation::Tagged();
     }
   }
@@ -2541,17 +2518,16 @@
   if (r.IsDouble() && !has_double_value_) return NULL;
   if (r.IsExternal() && !has_external_reference_value_) return NULL;
   if (has_int32_value_) {
-    return new(zone) HConstant(int32_value_, r, is_not_in_new_space_, handle_);
+    return new(zone) HConstant(int32_value_, r, is_not_in_new_space_, object_);
   }
   if (has_double_value_) {
-    return new(zone) HConstant(double_value_, r, is_not_in_new_space_, handle_);
+    return new(zone) HConstant(double_value_, r, is_not_in_new_space_, object_);
   }
   if (has_external_reference_value_) {
     return new(zone) HConstant(external_reference_value_);
   }
-  ASSERT(!handle_.is_null());
-  return new(zone) HConstant(handle_,
-                             unique_id_,
+  ASSERT(!object_.handle().is_null());
+  return new(zone) HConstant(object_,
                              r,
                              type_,
                              is_internalized_string_,
@@ -2567,12 +2543,12 @@
     res = new(zone) HConstant(int32_value_,
                               Representation::Integer32(),
                               is_not_in_new_space_,
-                              handle_);
+                              object_);
   } else if (has_double_value_) {
     res = new(zone) HConstant(DoubleToInt32(double_value_),
                               Representation::Integer32(),
                               is_not_in_new_space_,
-                              handle_);
+                              object_);
   }
   return Maybe<HConstant*>(res != NULL, res);
 }
@@ -3439,8 +3415,8 @@
   HConstant* filler_map = HConstant::New(
       zone,
       context(),
-      isolate()->factory()->free_space_map(),
-      UniqueValueId::free_space_map(isolate()->heap()));
+      isolate()->factory()->free_space_map());
+  filler_map->FinalizeUniqueness();  // TODO(titzer): should be init'd a'ready
   filler_map->InsertAfter(free_space_instr);
   HInstruction* store_map = HStoreNamedField::New(zone, context(),
       free_space_instr, HObjectAccess::ForMap(), filler_map);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 8cb2f59..71bdb33 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -306,65 +306,6 @@
 };
 
 
-class UniqueValueId V8_FINAL {
- public:
-  UniqueValueId() : raw_address_(NULL) { }
-
-  explicit UniqueValueId(Handle<Object> handle) {
-    ASSERT(!AllowHeapAllocation::IsAllowed());
-    static const Address kEmptyHandleSentinel = reinterpret_cast<Address>(1);
-    if (handle.is_null()) {
-      raw_address_ = kEmptyHandleSentinel;
-    } else {
-      raw_address_ = reinterpret_cast<Address>(*handle);
-      ASSERT_NE(kEmptyHandleSentinel, raw_address_);
-    }
-    ASSERT(IsInitialized());
-  }
-
-  bool IsInitialized() const { return raw_address_ != NULL; }
-
-  bool operator==(const UniqueValueId& other) const {
-    ASSERT(IsInitialized() && other.IsInitialized());
-    return raw_address_ == other.raw_address_;
-  }
-
-  bool operator!=(const UniqueValueId& other) const {
-    ASSERT(IsInitialized() && other.IsInitialized());
-    return raw_address_ != other.raw_address_;
-  }
-
-  intptr_t Hashcode() const {
-    ASSERT(IsInitialized());
-    return reinterpret_cast<intptr_t>(raw_address_);
-  }
-
-#define IMMOVABLE_UNIQUE_VALUE_ID(name)   \
-  static UniqueValueId name(Heap* heap) { return UniqueValueId(heap->name()); }
-
-  IMMOVABLE_UNIQUE_VALUE_ID(free_space_map)
-  IMMOVABLE_UNIQUE_VALUE_ID(minus_zero_value)
-  IMMOVABLE_UNIQUE_VALUE_ID(nan_value)
-  IMMOVABLE_UNIQUE_VALUE_ID(undefined_value)
-  IMMOVABLE_UNIQUE_VALUE_ID(null_value)
-  IMMOVABLE_UNIQUE_VALUE_ID(true_value)
-  IMMOVABLE_UNIQUE_VALUE_ID(false_value)
-  IMMOVABLE_UNIQUE_VALUE_ID(the_hole_value)
-  IMMOVABLE_UNIQUE_VALUE_ID(empty_string)
-  IMMOVABLE_UNIQUE_VALUE_ID(empty_fixed_array)
-
-#undef IMMOVABLE_UNIQUE_VALUE_ID
-
- private:
-  Address raw_address_;
-
-  explicit UniqueValueId(Object* object) {
-    raw_address_ = reinterpret_cast<Address>(object);
-    ASSERT(IsInitialized());
-  }
-};
-
-
 class HType V8_FINAL {
  public:
   static HType None() { return HType(kNone); }
@@ -904,7 +845,7 @@
   virtual intptr_t Hashcode();
 
   // Compute unique ids upfront that is safe wrt GC and concurrent compilation.
-  virtual void FinalizeUniqueValueId() { }
+  virtual void FinalizeUniqueness() { }
 
   // Printing support.
   virtual void PrintTo(StringStream* stream) = 0;
@@ -2691,7 +2632,7 @@
     return new(zone) HCheckValue(value, target, object_in_new_space);
   }
 
-  virtual void FinalizeUniqueValueId() V8_OVERRIDE {
+  virtual void FinalizeUniqueness() V8_OVERRIDE {
     object_ = Unique<HeapObject>(object_.handle());
   }
 
@@ -3297,7 +3238,6 @@
   DECLARE_INSTRUCTION_FACTORY_P2(HConstant, int32_t, Representation);
   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, double);
   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, Handle<Object>);
-  DECLARE_INSTRUCTION_FACTORY_P2(HConstant, Handle<Map>, UniqueValueId);
   DECLARE_INSTRUCTION_FACTORY_P1(HConstant, ExternalReference);
 
   static HConstant* CreateAndInsertAfter(Zone* zone,
@@ -3323,15 +3263,15 @@
   }
 
   Handle<Object> handle(Isolate* isolate) {
-    if (handle_.is_null()) {
-      Factory* factory = isolate->factory();
+    if (object_.handle().is_null()) {
       // Default arguments to is_not_in_new_space depend on this heap number
-      // to be tenured so that it's guaranteed not be be located in new space.
-      handle_ = factory->NewNumber(double_value_, TENURED);
+      // to be tenured so that it's guaranteed not to be located in new space.
+      object_ = Unique<Object>::CreateUninitialized(
+          isolate->factory()->NewNumber(double_value_, TENURED));
     }
     AllowDeferredHandleDereference smi_check;
-    ASSERT(has_int32_value_ || !handle_->IsSmi());
-    return handle_;
+    ASSERT(has_int32_value_ || !object_.handle()->IsSmi());
+    return object_.handle();
   }
 
   bool HasMap(Handle<Map> map) {
@@ -3365,17 +3305,18 @@
       return false;
     }
 
-    ASSERT(!handle_.is_null());
+    ASSERT(!object_.handle().is_null());
     Heap* heap = isolate()->heap();
-    ASSERT(unique_id_ != UniqueValueId::minus_zero_value(heap));
-    ASSERT(unique_id_ != UniqueValueId::nan_value(heap));
-    return unique_id_ == UniqueValueId::undefined_value(heap) ||
-           unique_id_ == UniqueValueId::null_value(heap) ||
-           unique_id_ == UniqueValueId::true_value(heap) ||
-           unique_id_ == UniqueValueId::false_value(heap) ||
-           unique_id_ == UniqueValueId::the_hole_value(heap) ||
-           unique_id_ == UniqueValueId::empty_string(heap) ||
-           unique_id_ == UniqueValueId::empty_fixed_array(heap);
+    ASSERT(!object_.IsKnownGlobal(heap->minus_zero_value()));
+    ASSERT(!object_.IsKnownGlobal(heap->nan_value()));
+    return
+        object_.IsKnownGlobal(heap->undefined_value()) ||
+        object_.IsKnownGlobal(heap->null_value()) ||
+        object_.IsKnownGlobal(heap->true_value()) ||
+        object_.IsKnownGlobal(heap->false_value()) ||
+        object_.IsKnownGlobal(heap->the_hole_value()) ||
+        object_.IsKnownGlobal(heap->empty_string()) ||
+        object_.IsKnownGlobal(heap->empty_fixed_array());
   }
 
   bool IsCell() const {
@@ -3414,11 +3355,7 @@
     if (HasDoubleValue() && FixedDoubleArray::is_the_hole_nan(double_value_)) {
       return true;
     }
-    Heap* heap = isolate()->heap();
-    if (!handle_.is_null() && *handle_ == heap->the_hole_value()) {
-      return true;
-    }
-    return false;
+    return object_.IsKnownGlobal(isolate()->heap()->the_hole_value());
   }
   bool HasNumberValue() const { return has_double_value_; }
   int32_t NumberValueAsInteger32() const {
@@ -3430,12 +3367,12 @@
   }
   bool HasStringValue() const {
     if (has_double_value_ || has_int32_value_) return false;
-    ASSERT(!handle_.is_null());
+    ASSERT(!object_.handle().is_null());
     return type_.IsString();
   }
   Handle<String> StringValue() const {
     ASSERT(HasStringValue());
-    return Handle<String>::cast(handle_);
+    return Handle<String>::cast(object_.handle());
   }
   bool HasInternalizedStringValue() const {
     return HasStringValue() && is_internalized_string_;
@@ -3459,27 +3396,20 @@
     } else if (has_external_reference_value_) {
       return reinterpret_cast<intptr_t>(external_reference_value_.address());
     } else {
-      ASSERT(!handle_.is_null());
-      return unique_id_.Hashcode();
+      ASSERT(!object_.handle().is_null());
+      return object_.Hashcode();
     }
   }
 
-  virtual void FinalizeUniqueValueId() V8_OVERRIDE {
+  virtual void FinalizeUniqueness() V8_OVERRIDE {
     if (!has_double_value_ && !has_external_reference_value_) {
-      ASSERT(!handle_.is_null());
-      unique_id_ = UniqueValueId(handle_);
+      ASSERT(!object_.handle().is_null());
+      object_ = Unique<Object>(object_.handle());
     }
   }
 
-  bool UniqueValueIdsMatch(UniqueValueId other) {
-    return !has_double_value_ && !has_external_reference_value_ &&
-        unique_id_ == other;
-  }
-
   Unique<Object> GetUnique() const {
-    // TODO(titzer): store a Unique<HeapObject> inside the HConstant.
-    Address raw_address = reinterpret_cast<Address>(unique_id_.Hashcode());
-    return Unique<Object>(raw_address, handle_);
+    return object_;
   }
 
 #ifdef DEBUG
@@ -3505,9 +3435,8 @@
           external_reference_value_ ==
           other_constant->external_reference_value_;
     } else {
-      ASSERT(!handle_.is_null());
-      return !other_constant->handle_.is_null() &&
-             unique_id_ == other_constant->unique_id_;
+      ASSERT(!object_.handle().is_null());
+      return other_constant->object_ == object_;
     }
   }
 
@@ -3517,33 +3446,30 @@
   HConstant(int32_t value,
             Representation r = Representation::None(),
             bool is_not_in_new_space = true,
-            Handle<Object> optional_handle = Handle<Object>::null());
+            Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
   HConstant(double value,
             Representation r = Representation::None(),
             bool is_not_in_new_space = true,
-            Handle<Object> optional_handle = Handle<Object>::null());
-  HConstant(Handle<Object> handle,
-            UniqueValueId unique_id,
+            Unique<Object> optional = Unique<Object>(Handle<Object>::null()));
+  HConstant(Unique<Object> unique,
             Representation r,
             HType type,
             bool is_internalized_string,
             bool is_not_in_new_space,
             bool is_cell,
             bool boolean_value);
-  HConstant(Handle<Map> handle,
-            UniqueValueId unique_id);
+
   explicit HConstant(ExternalReference reference);
 
   void Initialize(Representation r);
 
   virtual bool IsDeletable() const V8_OVERRIDE { return true; }
 
-  // If this is a numerical constant, handle_ either points to to the
+  // If this is a numerical constant, object_ either points to the
   // HeapObject the constant originated from or is null.  If the
-  // constant is non-numeric, handle_ always points to a valid
+  // constant is non-numeric, object_ always points to a valid
   // constant HeapObject.
-  Handle<Object> handle_;
-  UniqueValueId unique_id_;
+  Unique<Object> object_;
 
   // We store the HConstant in the most specific form safely possible.
   // The two flags, has_int32_value_ and has_double_value_ tell us if
@@ -5137,7 +5063,7 @@
     return cell_.Hashcode();
   }
 
-  virtual void FinalizeUniqueValueId() V8_OVERRIDE {
+  virtual void FinalizeUniqueness() V8_OVERRIDE {
     cell_ = Unique<Cell>(cell_.handle());
   }
 
@@ -5435,7 +5361,7 @@
     return StoringValueNeedsWriteBarrier(value());
   }
 
-  virtual void FinalizeUniqueValueId() V8_OVERRIDE {
+  virtual void FinalizeUniqueness() V8_OVERRIDE {
     cell_ = Unique<PropertyCell>(cell_.handle());
   }
 
@@ -5667,6 +5593,18 @@
         kDouble, HeapNumber::kValueOffset, Representation::Double());
   }
 
+  static HObjectAccess ForHeapNumberValueLowestBits() {
+    return HObjectAccess(kDouble,
+                         HeapNumber::kValueOffset,
+                         Representation::Integer32());
+  }
+
+  static HObjectAccess ForHeapNumberValueHighestBits() {
+    return HObjectAccess(kDouble,
+                         HeapNumber::kValueOffset + kIntSize,
+                         Representation::Integer32());
+  }
+
   static HObjectAccess ForElementsPointer() {
     return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
   }
@@ -5699,6 +5637,10 @@
     return HObjectAccess(kInobject, AllocationSite::kTransitionInfoOffset);
   }
 
+  static HObjectAccess ForAllocationSiteNestedSite() {
+    return HObjectAccess(kInobject, AllocationSite::kNestedSiteOffset);
+  }
+
   static HObjectAccess ForAllocationSiteDependentCode() {
     return HObjectAccess(kInobject, AllocationSite::kDependentCodeOffset);
   }
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 50882a8..0a7e9f0 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -649,8 +649,7 @@
 HConstant* HGraph::GetConstant##Name() {                                       \
   if (!constant_##name##_.is_set()) {                                          \
     HConstant* constant = new(zone()) HConstant(                               \
-        isolate()->factory()->name##_value(),                                  \
-        UniqueValueId::name##_value(isolate()->heap()),                        \
+        Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
         Representation::Tagged(),                                              \
         htype,                                                                 \
         false,                                                                 \
@@ -1039,7 +1038,7 @@
   CompilationPhase phase("H_Block building", info_);
   set_current_block(graph()->entry_block());
   if (!BuildGraph()) return NULL;
-  graph()->FinalizeUniqueValueIds();
+  graph()->FinalizeUniqueness();
   return graph_;
 }
 
@@ -1273,6 +1272,142 @@
 }
 
 
+HValue* HGraphBuilder::BuildLookupNumberStringCache(
+    HValue* object,
+    HIfContinuation* continuation) {
+  // Create a joinable continuation.
+  HIfContinuation found(graph()->CreateBasicBlock(),
+                        graph()->CreateBasicBlock());
+
+  // Load the number string cache.
+  HValue* number_string_cache =
+      Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
+
+  // Make the hash maks from the length of the number string cache. It
+  // contains two elements (number and string) for each cache entry.
+  HValue* mask = AddLoadFixedArrayLength(number_string_cache);
+  mask->set_type(HType::Smi());
+  mask = Add<HSar>(mask, graph()->GetConstant1());
+  mask = Add<HSub>(mask, graph()->GetConstant1());
+
+  // Check whether object is a smi.
+  IfBuilder if_objectissmi(this);
+  if_objectissmi.If<HIsSmiAndBranch>(object);
+  if_objectissmi.Then();
+  {
+    // Compute hash for smi similar to smi_get_hash().
+    HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask);
+
+    // Load the key.
+    HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
+    HValue* key = AddFastElementAccess(number_string_cache, key_index,
+                                       NULL, NULL, FAST_ELEMENTS, false,
+                                       ALLOW_RETURN_HOLE, STANDARD_STORE);
+
+    // Check if object == key.
+    IfBuilder if_objectiskey(this);
+    if_objectiskey.If<HCompareObjectEqAndBranch>(key, object);
+    if_objectiskey.Then();
+    {
+      // Make the key_index available.
+      Push(key_index);
+    }
+    if_objectiskey.JoinContinuation(&found);
+  }
+  if_objectissmi.Else();
+  {
+    // Check if object is a heap number.
+    IfBuilder if_objectisnumber(this);
+    if_objectisnumber.If<HCompareMap>(
+        object, isolate()->factory()->heap_number_map());
+    if_objectisnumber.Then();
+    {
+      // Compute hash for heap number similar to double_get_hash().
+      HValue* low = Add<HLoadNamedField>(
+          object, HObjectAccess::ForHeapNumberValueLowestBits());
+      HValue* high = Add<HLoadNamedField>(
+          object, HObjectAccess::ForHeapNumberValueHighestBits());
+      HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high);
+      hash = Add<HBitwise>(Token::BIT_AND, hash, mask);
+
+      // Load the key.
+      HValue* key_index = Add<HShl>(hash, graph()->GetConstant1());
+      HValue* key = AddFastElementAccess(number_string_cache, key_index,
+                                        NULL, NULL, FAST_ELEMENTS, false,
+                                        ALLOW_RETURN_HOLE, STANDARD_STORE);
+
+      // Check if key is a heap number.
+      IfBuilder if_keyisnumber(this);
+      if_keyisnumber.IfNot<HIsSmiAndBranch>(key);
+      if_keyisnumber.AndIf<HCompareMap>(
+          key, isolate()->factory()->heap_number_map());
+      if_keyisnumber.Then();
+      {
+        // Check if values of key and object match.
+        IfBuilder if_keyeqobject(this);
+        if_keyeqobject.If<HCompareNumericAndBranch>(
+            Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()),
+            Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()),
+            Token::EQ);
+        if_keyeqobject.Then();
+        {
+          // Make the key_index available.
+          Push(key_index);
+        }
+        if_keyeqobject.JoinContinuation(&found);
+      }
+      if_keyisnumber.JoinContinuation(&found);
+    }
+    if_objectisnumber.JoinContinuation(&found);
+  }
+  if_objectissmi.End();
+
+  // Check for cache hit.
+  IfBuilder if_found(this, &found);
+  if_found.Then();
+
+  // Load the value in case of cache hit.
+  HValue* key_index = Pop();
+  HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1());
+  HValue* value = AddFastElementAccess(number_string_cache, value_index,
+                                      NULL, NULL, FAST_ELEMENTS, false,
+                                      ALLOW_RETURN_HOLE, STANDARD_STORE);
+  AddIncrementCounter(isolate()->counters()->number_to_string_native());
+
+  if_found.CaptureContinuation(continuation);
+
+  // The value is only available in true branch of continuation.
+  return value;
+}
+
+
+HValue* HGraphBuilder::BuildNumberToString(HValue* number) {
+  NoObservableSideEffectsScope scope(this);
+
+  // Lookup the number in the number string cache.
+  HIfContinuation continuation;
+  HValue* value = BuildLookupNumberStringCache(number, &continuation);
+  IfBuilder if_found(this, &continuation);
+  if_found.Then();
+
+  // Cache hit.
+  Push(value);
+
+  if_found.Else();
+
+  // Cache miss, fallback to runtime.
+  Add<HPushArgument>(number);
+  Push(Add<HCallRuntime>(
+          isolate()->factory()->empty_string(),
+          Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
+          1));
+
+  if_found.End();
+
+  return Pop();
+}
+
+
 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
     HValue* checked_object,
     HValue* key,
@@ -2157,12 +2292,12 @@
 }
 
 
-void HGraph::FinalizeUniqueValueIds() {
+void HGraph::FinalizeUniqueness() {
   DisallowHeapAllocation no_gc;
   ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
   for (int i = 0; i < blocks()->length(); ++i) {
     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
-      it.Current()->FinalizeUniqueValueId();
+      it.Current()->FinalizeUniqueness();
     }
   }
 }
@@ -4106,7 +4241,7 @@
                           int* max_properties) {
   if (boilerplate->map()->is_deprecated()) {
     Handle<Object> result = JSObject::TryMigrateInstance(boilerplate);
-    if (result->IsSmi()) return false;
+    if (result.is_null()) return false;
   }
 
   ASSERT(max_depth >= 0 && *max_properties >= 0);
@@ -9009,12 +9144,10 @@
 // Fast support for number to string.
 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
   ASSERT_EQ(1, call->arguments()->length());
-  CHECK_ALIVE(VisitArgumentList(call->arguments()));
-  HValue* context = environment()->context();
-  HCallStub* result =
-      new(zone()) HCallStub(context, CodeStub::NumberToString, 1);
-  Drop(1);
-  return ast_context()->ReturnInstruction(result, call->id());
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  HValue* number = Pop();
+  HValue* result = BuildNumberToString(number);
+  return ast_context()->ReturnValue(result);
 }
 
 
diff --git a/src/hydrogen.h b/src/hydrogen.h
index a371fa5..6aa8217 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -316,7 +316,7 @@
   HBasicBlock* entry_block() const { return entry_block_; }
   HEnvironment* start_environment() const { return start_environment_; }
 
-  void FinalizeUniqueValueIds();
+  void FinalizeUniqueness();
   bool ProcessArgumentsObject();
   void OrderBlocks();
   void AssignDominators();
@@ -1237,6 +1237,15 @@
                                    ElementsKind to_kind,
                                    bool is_jsarray);
 
+  // Do lookup in the number string cache. If the object is not found
+  // in the cache, the false branch of the continuation is taken;
+  // otherwise the true branch is taken and the returned value contains
+  // the cache value for the object. The returned value must NOT be used
+  // on the false branch.
+  HValue* BuildLookupNumberStringCache(HValue* object,
+                                       HIfContinuation* continuation);
+  HValue* BuildNumberToString(HValue* number);
+
   HInstruction* BuildUncheckedMonomorphicElementAccess(
       HValue* checked_object,
       HValue* key,
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index e5456da..c2e8431 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -1131,30 +1131,21 @@
 
 
 void Assembler::test(Register reg, const Immediate& imm) {
-  EnsureSpace ensure_space(this);
-  // Only use test against byte for registers that have a byte
-  // variant: eax, ebx, ecx, and edx.
-  if (RelocInfo::IsNone(imm.rmode_) &&
-      is_uint8(imm.x_) &&
-      reg.is_byte_register()) {
-    uint8_t imm8 = imm.x_;
-    if (reg.is(eax)) {
-      EMIT(0xA8);
-      EMIT(imm8);
-    } else {
-      emit_arith_b(0xF6, 0xC0, reg, imm8);
-    }
-  } else {
-    // This is not using emit_arith because test doesn't support
-    // sign-extension of 8-bit operands.
-    if (reg.is(eax)) {
-      EMIT(0xA9);
-    } else {
-      EMIT(0xF7);
-      EMIT(0xC0 | reg.code());
-    }
-    emit(imm);
+  if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
+    test_b(reg, imm.x_);
+    return;
   }
+
+  EnsureSpace ensure_space(this);
+  // This is not using emit_arith because test doesn't support
+  // sign-extension of 8-bit operands.
+  if (reg.is(eax)) {
+    EMIT(0xA9);
+  } else {
+    EMIT(0xF7);
+    EMIT(0xC0 | reg.code());
+  }
+  emit(imm);
 }
 
 
@@ -1178,6 +1169,9 @@
     test(op.reg(), imm);
     return;
   }
+  if (RelocInfo::IsNone(imm.rmode_) && is_uint8(imm.x_)) {
+    return test_b(op, imm.x_);
+  }
   EnsureSpace ensure_space(this);
   EMIT(0xF7);
   emit_operand(eax, op);
@@ -1185,9 +1179,26 @@
 }
 
 
+void Assembler::test_b(Register reg, uint8_t imm8) {
+  EnsureSpace ensure_space(this);
+  // Only use test against byte for registers that have a byte
+  // variant: eax, ebx, ecx, and edx.
+  if (reg.is(eax)) {
+    EMIT(0xA8);
+    EMIT(imm8);
+  } else if (reg.is_byte_register()) {
+    emit_arith_b(0xF6, 0xC0, reg, imm8);
+  } else {
+    EMIT(0xF7);
+    EMIT(0xC0 | reg.code());
+    emit(imm8);
+  }
+}
+
+
 void Assembler::test_b(const Operand& op, uint8_t imm8) {
-  if (op.is_reg_only() && !op.reg().is_byte_register()) {
-    test(op, Immediate(imm8));
+  if (op.is_reg_only()) {
+    test_b(op.reg(), imm8);
     return;
   }
   EnsureSpace ensure_space(this);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 736dd3b..7c3999b 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -853,7 +853,7 @@
   void test(Register reg, const Operand& op);
   void test_b(Register reg, const Operand& op);
   void test(const Operand& op, const Immediate& imm);
-  void test_b(Register reg, uint8_t imm8) { test_b(Operand(reg), imm8); }
+  void test_b(Register reg, uint8_t imm8);
   void test_b(const Operand& op, uint8_t imm8);
 
   void xor_(Register dst, int32_t imm32);
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 5169627..91ff72c 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -630,25 +630,6 @@
 }
 
 
-void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
-  // TODO(kasperl): Do we need to save/restore the XMM registers too?
-  // TODO(mvstanton): We should save these regs, do this in a future
-  // checkin.
-
-  // For now, we are relying on the fact that Runtime::NotifyOSR
-  // doesn't do any garbage collection which allows us to save/restore
-  // the registers without worrying about which of them contain
-  // pointers. This seems a bit fragile.
-  __ pushad();
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ CallRuntime(Runtime::kNotifyOSR, 0);
-  }
-  __ popad();
-  __ ret(0);
-}
-
-
 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
   Factory* factory = masm->isolate()->factory();
 
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 6128633..83613cc 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -64,6 +64,16 @@
 }
 
 
+void NumberToStringStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { eax };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ = NULL;
+}
+
+
 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
@@ -3767,21 +3777,6 @@
 }
 
 
-void NumberToStringStub::Generate(MacroAssembler* masm) {
-  Label runtime;
-
-  __ mov(ebx, Operand(esp, kPointerSize));
-
-  // Generate code to lookup number in the number string cache.
-  __ LookupNumberStringCache(ebx, eax, ecx, edx, &runtime);
-  __ ret(1 * kPointerSize);
-
-  __ bind(&runtime);
-  // Handle number to string in the runtime system if not found in the cache.
-  __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
-}
-
-
 static int NegativeComparisonResult(Condition cc) {
   ASSERT(cc != equal);
   ASSERT((cc == less) || (cc == less_equal)
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index f36cd61..dc536e7 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -217,18 +217,6 @@
 };
 
 
-class NumberToStringStub: public PlatformCodeStub {
- public:
-  NumberToStringStub() { }
-
- private:
-  Major MajorKey() { return NumberToString; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
-};
-
-
 class NameDictionaryLookupStub: public PlatformCodeStub {
  public:
   enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 9a2c3ce..5250f4b 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -3549,8 +3549,8 @@
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(args->length(), 1);
 
-  // Load the argument on the stack and call the stub.
-  VisitForStackValue(args->at(0));
+  // Load the argument into eax and call the stub.
+  VisitForAccumulatorValue(args->at(0));
 
   NumberToStringStub stub;
   __ CallStub(&stub);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 98a049b..86ac466 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -416,6 +416,13 @@
         x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr));
       } else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
                  !instr->IsGap() && !instr->IsReturn()) {
+        if (instr->ClobbersDoubleRegisters()) {
+          if (instr->HasDoubleRegisterResult()) {
+            ASSERT_EQ(1, x87_stack_.depth());
+          } else {
+            ASSERT_EQ(0, x87_stack_.depth());
+          }
+        }
         __ VerifyX87StackDepth(x87_stack_.depth());
       }
     }
@@ -561,6 +568,16 @@
 }
 
 
+void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
+  ASSERT(x87_stack_.Contains(reg1));
+  ASSERT(x87_stack_.Contains(reg2));
+  x87_stack_.Fxch(reg1, 1);
+  x87_stack_.Fxch(reg2);
+  x87_stack_.pop();
+  x87_stack_.pop();
+}
+
+
 void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
   ASSERT(is_mutable_);
   ASSERT(Contains(reg) && stack_depth_ > other_slot);
@@ -1365,11 +1382,6 @@
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
       break;
     }
-    case CodeStub::NumberToString: {
-      NumberToStringStub stub;
-      CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
     case CodeStub::StringCompare: {
       StringCompareStub stub;
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -2572,10 +2584,7 @@
         CpuFeatureScope scope(masm(), SSE2);
         __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
       } else {
-        X87Fxch(ToX87Register(right));
-        X87Fxch(ToX87Register(left), 1);
-        __ fld(0);
-        __ fld(2);
+        X87LoadForUsage(ToX87Register(right), ToX87Register(left));
         __ FCmp();
       }
       // Don't base result on EFLAGS when a NaN is involved. Instead
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index a2280f8..a813b3c 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -129,6 +129,7 @@
       X87Register left, X87Register right, X87Register result);
 
   void X87LoadForUsage(X87Register reg);
+  void X87LoadForUsage(X87Register reg1, X87Register reg2);
   void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); }
   void X87CommitWrite(X87Register reg) { x87_stack_.CommitWrite(reg); }
 
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index e528dd7..1b18140 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -924,23 +924,6 @@
 }
 
 
-void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
-  // For now, we are relying on the fact that Runtime::NotifyOSR
-  // doesn't do any garbage collection which allows us to save/restore
-  // the registers without worrying about which of them contain
-  // pointers. This seems a bit fragile.
-  RegList saved_regs =
-      (kJSCallerSaved | kCalleeSaved | ra.bit() | fp.bit()) & ~sp.bit();
-  __ MultiPush(saved_regs);
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ CallRuntime(Runtime::kNotifyOSR, 0);
-  }
-  __ MultiPop(saved_regs);
-  __ Ret();
-}
-
-
 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
   // Lookup the function in the JavaScript frame.
   __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index ea104fb..5cdfecc 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -60,6 +60,16 @@
 }
 
 
+void NumberToStringStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { a0 };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ = NULL;
+}
+
+
 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
@@ -994,21 +1004,6 @@
 }
 
 
-void NumberToStringStub::Generate(MacroAssembler* masm) {
-  Label runtime;
-
-  __ lw(a1, MemOperand(sp, 0));
-
-  // Generate code to lookup number in the number string cache.
-  __ LookupNumberStringCache(a1, v0, a2, a3, t0, &runtime);
-  __ DropAndRet(1);
-
-  __ bind(&runtime);
-  // Handle number to string in the runtime system if not found in the cache.
-  __ TailCallRuntime(Runtime::kNumberToString, 1, 1);
-}
-
-
 static void ICCompareStub_CheckInputType(MacroAssembler* masm,
                                          Register input,
                                          Register scratch,
@@ -6131,9 +6126,16 @@
 
 
 void DirectCEntryStub::Generate(MacroAssembler* masm) {
-  // No need to pop or drop anything, LeaveExitFrame will restore the old
-  // stack, thus dropping the allocated space for the return value.
-  // The saved ra is after the reserved stack space for the 4 args.
+  // Make place for arguments to fit C calling convention. Most of the callers
+  // of DirectCEntryStub::GenerateCall are using EnterExitFrame/LeaveExitFrame
+  // so they handle stack restoring and we don't have to do that here.
+  // Any caller of DirectCEntryStub::GenerateCall must take care of dropping
+  // kCArgsSlotsSize stack space after the call.
+  __ Subu(sp, sp, Operand(kCArgsSlotsSize));
+  // Place the return address on the stack, making the call
+  // GC safe. The RegExp backend also relies on this.
+  __ sw(ra, MemOperand(sp, kCArgsSlotsSize));
+  __ Call(t9);  // Call the C++ function.
   __ lw(t9, MemOperand(sp, kCArgsSlotsSize));
 
   if (FLAG_debug_code && FLAG_enable_slow_asserts) {
@@ -6150,33 +6152,11 @@
 
 void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
                                     Register target) {
-  __ Move(t9, target);
-  __ AssertStackIsAligned();
-  // Allocate space for arg slots.
-  __ Subu(sp, sp, kCArgsSlotsSize);
-
-  // Block the trampoline pool through the whole function to make sure the
-  // number of generated instructions is constant.
-  Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
-
-  // We need to get the current 'pc' value, which is not available on MIPS.
-  Label find_ra;
-  masm->bal(&find_ra);  // ra = pc + 8.
-  masm->nop();  // Branch delay slot nop.
-  masm->bind(&find_ra);
-
-  const int kNumInstructionsToJump = 6;
-  masm->addiu(ra, ra, kNumInstructionsToJump * kPointerSize);
-  // Push return address (accessible to GC through exit frame pc).
-  // This spot for ra was reserved in EnterExitFrame.
-  masm->sw(ra, MemOperand(sp, kCArgsSlotsSize));
   intptr_t loc =
       reinterpret_cast<intptr_t>(GetCode(masm->isolate()).location());
-  masm->li(ra, Operand(loc, RelocInfo::CODE_TARGET), CONSTANT_SIZE);
-  // Call the function.
-  masm->Jump(t9);
-  // Make sure the stored 'ra' points to this position.
-  ASSERT_EQ(kNumInstructionsToJump, masm->InstructionsGeneratedSince(&find_ra));
+  __ Move(t9, target);
+  __ li(ra, Operand(loc, RelocInfo::CODE_TARGET), CONSTANT_SIZE);
+  __ Call(ra);
 }
 
 
diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h
index 627244c..10531a8 100644
--- a/src/mips/code-stubs-mips.h
+++ b/src/mips/code-stubs-mips.h
@@ -268,18 +268,6 @@
 };
 
 
-class NumberToStringStub: public PlatformCodeStub {
- public:
-  NumberToStringStub() { }
-
- private:
-  Major MajorKey() { return NumberToString; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
-};
-
-
 class RecordWriteStub: public PlatformCodeStub {
  public:
   RecordWriteStub(Register object,
@@ -467,22 +455,6 @@
 };
 
 
-// Enter C code from generated RegExp code in a way that allows
-// the C code to fix the return address in case of a GC.
-// Currently only needed on ARM and MIPS.
-class RegExpCEntryStub: public PlatformCodeStub {
- public:
-  RegExpCEntryStub() {}
-  virtual ~RegExpCEntryStub() {}
-  void Generate(MacroAssembler* masm);
-
- private:
-  Major MajorKey() { return RegExpCEntry; }
-  int MinorKey() { return 0; }
-
-  bool NeedsImmovableCode() { return true; }
-};
-
 // Trampoline stub to call into native code. To call safely into native code
 // in the presence of compacting GC (which can move code objects) we need to
 // keep the code which called into native pinned in the memory. Currently the
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 853ee08..f889470 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -3611,8 +3611,9 @@
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(args->length(), 1);
 
-  // Load the argument on the stack and call the stub.
-  VisitForStackValue(args->at(0));
+  // Load the argument into a0 and call the stub.
+  VisitForAccumulatorValue(args->at(0));
+  __ mov(a0, result_register());
 
   NumberToStringStub stub;
   __ CallStub(&stub);
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 69a3c89..c869184 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1063,11 +1063,6 @@
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
       break;
     }
-    case CodeStub::NumberToString: {
-      NumberToStringStub stub;
-      CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
     case CodeStub::StringCompare: {
       StringCompareStub stub;
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index 7c22ae8..a8ca620 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -1342,8 +1342,8 @@
   LOperand* temp() { return temps_[0]; }
   Smi* index() const { return index_; }
 
-  DECLARE_CONCRETE_INSTRUCTION(ValueOf, "date-field")
-  DECLARE_HYDROGEN_ACCESSOR(ValueOf)
+  DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
+  DECLARE_HYDROGEN_ACCESSOR(DateField)
 
  private:
   Smi* index_;
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 159c924..cbb538f 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -3220,11 +3220,10 @@
                                Register dst,
                                Register length,
                                Register scratch) {
-  Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done;
+  Label align_loop_1, word_loop, byte_loop, byte_loop_1, done;
 
   // Align src before copying in word size chunks.
-  bind(&align_loop);
-  Branch(&done, eq, length, Operand(zero_reg));
+  Branch(&byte_loop, le, length, Operand(kPointerSize));
   bind(&align_loop_1);
   And(scratch, src, kPointerSize - 1);
   Branch(&word_loop, eq, scratch, Operand(zero_reg));
@@ -3233,7 +3232,7 @@
   sb(scratch, MemOperand(dst));
   Addu(dst, dst, 1);
   Subu(length, length, Operand(1));
-  Branch(&byte_loop_1, ne, length, Operand(zero_reg));
+  Branch(&align_loop_1, ne, length, Operand(zero_reg));
 
   // Copy bytes in word size chunks.
   bind(&word_loop);
diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc
index 1a04fd1..49dec3c 100644
--- a/src/mips/regexp-macro-assembler-mips.cc
+++ b/src/mips/regexp-macro-assembler-mips.cc
@@ -1063,15 +1063,56 @@
 // Private methods:
 
 void RegExpMacroAssemblerMIPS::CallCheckStackGuardState(Register scratch) {
-  static const int num_arguments = 3;
-  __ PrepareCallCFunction(num_arguments, scratch);
+  int stack_alignment = OS::ActivationFrameAlignment();
+
+  // Align the stack pointer and save the original sp value on the stack.
+  __ mov(scratch, sp);
+  __ Subu(sp, sp, Operand(kPointerSize));
+  ASSERT(IsPowerOf2(stack_alignment));
+  __ And(sp, sp, Operand(-stack_alignment));
+  __ sw(scratch, MemOperand(sp));
+
   __ mov(a2, frame_pointer());
   // Code* of self.
   __ li(a1, Operand(masm_->CodeObject()), CONSTANT_SIZE);
-  // a0 becomes return address pointer.
+
+  // We need to make room for the return address on the stack.
+  ASSERT(IsAligned(stack_alignment, kPointerSize));
+  __ Subu(sp, sp, Operand(stack_alignment));
+
+  // Stack pointer now points to cell where return address is to be written.
+  // Arguments are in registers, meaning we teat the return address as
+  // argument 5. Since DirectCEntryStub will handleallocating space for the C
+  // argument slots, we don't need to care about that here. This is how the
+  // stack will look (sp meaning the value of sp at this moment):
+  // [sp + 3] - empty slot if needed for alignment.
+  // [sp + 2] - saved sp.
+  // [sp + 1] - second word reserved for return value.
+  // [sp + 0] - first word reserved for return value.
+
+  // a0 will point to the return address, placed by DirectCEntry.
+  __ mov(a0, sp);
+
   ExternalReference stack_guard_check =
       ExternalReference::re_check_stack_guard_state(masm_->isolate());
-  CallCFunctionUsingStub(stack_guard_check, num_arguments);
+  __ li(t9, Operand(stack_guard_check));
+  DirectCEntryStub stub;
+  stub.GenerateCall(masm_, t9);
+
+  // DirectCEntryStub allocated space for the C argument slots so we have to
+  // drop them with the return address from the stack with loading saved sp.
+  // At this point stack must look:
+  // [sp + 7] - empty slot if needed for alignment.
+  // [sp + 6] - saved sp.
+  // [sp + 5] - second word reserved for return value.
+  // [sp + 4] - first word reserved for return value.
+  // [sp + 3] - C argument slot.
+  // [sp + 2] - C argument slot.
+  // [sp + 1] - C argument slot.
+  // [sp + 0] - C argument slot.
+  __ lw(sp, MemOperand(sp, stack_alignment + kCArgsSlotsSize));
+
+  __ li(code_pointer(), Operand(masm_->CodeObject()));
 }
 
 
@@ -1276,21 +1317,6 @@
 }
 
 
-void RegExpMacroAssemblerMIPS::CallCFunctionUsingStub(
-    ExternalReference function,
-    int num_arguments) {
-  // Must pass all arguments in registers. The stub pushes on the stack.
-  ASSERT(num_arguments <= 4);
-  __ li(code_pointer(), Operand(function));
-  RegExpCEntryStub stub;
-  __ CallStub(&stub);
-  if (OS::ActivationFrameAlignment() != 0) {
-    __ lw(sp, MemOperand(sp, 16));
-  }
-  __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
-}
-
-
 void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
                                                              int characters) {
   Register offset = current_input_offset();
@@ -1312,23 +1338,6 @@
 }
 
 
-void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
-  int stack_alignment = OS::ActivationFrameAlignment();
-  if (stack_alignment < kPointerSize) stack_alignment = kPointerSize;
-  // Stack is already aligned for call, so decrement by alignment
-  // to make room for storing the return address.
-  __ Subu(sp, sp, Operand(stack_alignment + kCArgsSlotsSize));
-  const int return_address_offset = kCArgsSlotsSize;
-  __ Addu(a0, sp, return_address_offset);
-  __ sw(ra, MemOperand(a0, 0));
-  __ mov(t9, t1);
-  __ Call(t9);
-  __ lw(ra, MemOperand(sp, return_address_offset));
-  __ Addu(sp, sp, Operand(stack_alignment + kCArgsSlotsSize));
-  __ Jump(ra);
-}
-
-
 #undef __
 
 #endif  // V8_INTERPRETED_REGEXP
diff --git a/src/mips/regexp-macro-assembler-mips.h b/src/mips/regexp-macro-assembler-mips.h
index 86ae4d4..063582c 100644
--- a/src/mips/regexp-macro-assembler-mips.h
+++ b/src/mips/regexp-macro-assembler-mips.h
@@ -217,14 +217,6 @@
   // and increments it by a word size.
   inline void Pop(Register target);
 
-  // Calls a C function and cleans up the frame alignment done by
-  // by FrameAlign. The called function *is* allowed to trigger a garbage
-  // collection, but may not take more than four arguments (no arguments
-  // passed on the stack), and the first argument will be a pointer to the
-  // return address.
-  inline void CallCFunctionUsingStub(ExternalReference function,
-                                     int num_arguments);
-
   Isolate* isolate() const { return masm_->isolate(); }
 
   MacroAssembler* masm_;
diff --git a/src/objects-inl.h b/src/objects-inl.h
index dcce931..8c20c7a 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -285,14 +285,13 @@
 
 
 MaybeObject* Object::AllocateNewStorageFor(Heap* heap,
-                                           Representation representation,
-                                           PretenureFlag tenure) {
+                                           Representation representation) {
   if (!FLAG_track_double_fields) return this;
   if (!representation.IsDouble()) return this;
   if (IsUninitialized()) {
-    return heap->AllocateHeapNumber(0, tenure);
+    return heap->AllocateHeapNumber(0);
   }
-  return heap->AllocateHeapNumber(Number(), tenure);
+  return heap->AllocateHeapNumber(Number());
 }
 
 
@@ -1325,6 +1324,7 @@
 
 void AllocationSite::Initialize() {
   SetElementsKind(GetInitialFastElementsKind());
+  set_nested_site(Smi::FromInt(0));
   set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
                      SKIP_WRITE_BARRIER);
 }
@@ -1542,19 +1542,6 @@
 }
 
 
-MaybeObject* JSObject::TryMigrateInstance() {
-  Map* new_map = map()->CurrentMapForDeprecated();
-  if (new_map == NULL) return Smi::FromInt(0);
-  Map* original_map = map();
-  MaybeObject* maybe_result = MigrateToMap(new_map);
-  JSObject* result;
-  if (FLAG_trace_migration && maybe_result->To(&result)) {
-    PrintInstanceMigration(stdout, original_map, result->map());
-  }
-  return maybe_result;
-}
-
-
 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) {
   DisallowHeapAllocation no_gc;
   if (!map->HasTransitionArray()) return Handle<String>::null();
@@ -4456,6 +4443,7 @@
 ACCESSORS(TypeSwitchInfo, types, Object, kTypesOffset)
 
 ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
+ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
 ACCESSORS(AllocationSite, dependent_code, DependentCode,
           kDependentCodeOffset)
 ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 26a7098..f4b4a4f 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -1102,7 +1102,8 @@
   weak_next()->ShortPrint(out);
   PrintF(out, "\n - dependent code: ");
   dependent_code()->ShortPrint(out);
-
+  PrintF(out, "\n - nested site: ");
+  nested_site()->ShortPrint(out);
   PrintF(out, "\n - transition_info: ");
   if (transition_info()->IsCell()) {
     Cell* cell = Cell::cast(transition_info());
diff --git a/src/objects.cc b/src/objects.cc
index 67f26f0..169307f 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1005,8 +1005,11 @@
   if (IsNumber() && other->IsNumber()) {
     double this_value = Number();
     double other_value = other->Number();
-    return (this_value == other_value) ||
-        (std::isnan(this_value) && std::isnan(other_value));
+    bool equal = this_value == other_value;
+    // SameValue(NaN, NaN) is true.
+    if (!equal) return std::isnan(this_value) && std::isnan(other_value);
+    // SameValue(0.0, -0.0) is false.
+    return (this_value != 0) || ((1 / this_value) == (1 / other_value));
   }
   if (IsString() && other->IsString()) {
     return String::cast(this)->Equals(String::cast(other));
@@ -2270,11 +2273,6 @@
 }
 
 
-void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
-  CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map));
-}
-
-
 // To migrate an instance to a map:
 // - First check whether the instance needs to be rewritten. If not, simply
 //   change the map.
@@ -2290,28 +2288,27 @@
 //     to temporarily store the inobject properties.
 //   * If there are properties left in the backing store, install the backing
 //     store.
-MaybeObject* JSObject::MigrateToMap(Map* new_map) {
-  Heap* heap = GetHeap();
-  Map* old_map = map();
+void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
+  Isolate* isolate = object->GetIsolate();
+  Handle<Map> old_map(object->map());
   int number_of_fields = new_map->NumberOfFields();
   int inobject = new_map->inobject_properties();
   int unused = new_map->unused_property_fields();
 
-  // Nothing to do if no functions were converted to fields.
+  // Nothing to do if no functions were converted to fields and no smis were
+  // converted to doubles.
   if (!old_map->InstancesNeedRewriting(
-          new_map, number_of_fields, inobject, unused)) {
-    set_map(new_map);
-    return this;
+          *new_map, number_of_fields, inobject, unused)) {
+    object->set_map(*new_map);
+    return;
   }
 
   int total_size = number_of_fields + unused;
   int external = total_size - inobject;
-  FixedArray* array;
-  MaybeObject* maybe_array = heap->AllocateFixedArray(total_size);
-  if (!maybe_array->To(&array)) return maybe_array;
+  Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
 
-  DescriptorArray* old_descriptors = old_map->instance_descriptors();
-  DescriptorArray* new_descriptors = new_map->instance_descriptors();
+  Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
+  Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
   int descriptors = new_map->NumberOfOwnDescriptors();
 
   for (int i = 0; i < descriptors; i++) {
@@ -2324,55 +2321,51 @@
     }
     ASSERT(old_details.type() == CONSTANT ||
            old_details.type() == FIELD);
-    Object* value = old_details.type() == CONSTANT
+    Object* raw_value = old_details.type() == CONSTANT
         ? old_descriptors->GetValue(i)
-        : RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
+        : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
+    Handle<Object> value(raw_value, isolate);
     if (FLAG_track_double_fields &&
         !old_details.representation().IsDouble() &&
         details.representation().IsDouble()) {
-      if (old_details.representation().IsNone()) value = Smi::FromInt(0);
-      // Objects must be allocated in the old object space, since the
-      // overall number of HeapNumbers needed for the conversion might
-      // exceed the capacity of new space, and we would fail repeatedly
-      // trying to migrate the instance.
-      MaybeObject* maybe_storage =
-          value->AllocateNewStorageFor(heap, details.representation(), TENURED);
-      if (!maybe_storage->To(&value)) return maybe_storage;
+      if (old_details.representation().IsNone()) {
+        value = handle(Smi::FromInt(0), isolate);
+      }
+      value = NewStorageFor(isolate, value, details.representation());
     }
     ASSERT(!(FLAG_track_double_fields &&
              details.representation().IsDouble() &&
              value->IsSmi()));
     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
     if (target_index < 0) target_index += total_size;
-    array->set(target_index, value);
+    array->set(target_index, *value);
   }
 
-  // From here on we cannot fail anymore.
+  // From here on we cannot fail and we shouldn't GC anymore.
+  DisallowHeapAllocation no_allocation;
 
   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
   // avoid overwriting |one_pointer_filler_map|.
   int limit = Min(inobject, number_of_fields);
   for (int i = 0; i < limit; i++) {
-    FastPropertyAtPut(i, array->get(external + i));
+    object->FastPropertyAtPut(i, array->get(external + i));
   }
 
   // Create filler object past the new instance size.
   int new_instance_size = new_map->instance_size();
   int instance_size_delta = old_map->instance_size() - new_instance_size;
   ASSERT(instance_size_delta >= 0);
-  Address address = this->address() + new_instance_size;
-  heap->CreateFillerObjectAt(address, instance_size_delta);
+  Address address = object->address() + new_instance_size;
+  isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
 
   // If there are properties in the new backing store, trim it to the correct
   // size and install the backing store into the object.
   if (external > 0) {
-    RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
-    set_properties(array);
+    RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject);
+    object->set_properties(*array);
   }
 
-  set_map(new_map);
-
-  return this;
+  object->set_map(*new_map);
 }
 
 
@@ -3758,7 +3751,13 @@
 
 
 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
-  MigrateInstance(object);
+  Map* new_map = object->map()->CurrentMapForDeprecated();
+  if (new_map == NULL) return Handle<Object>();
+  Handle<Map> original_map(object->map());
+  JSObject::MigrateToMap(object, handle(new_map));
+  if (FLAG_trace_migration) {
+    object->PrintInstanceMigration(stdout, *original_map, object->map());
+  }
   return object;
 }
 
diff --git a/src/objects.h b/src/objects.h
index c894915..437e61a 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1440,8 +1440,7 @@
   }
 
   inline MaybeObject* AllocateNewStorageFor(Heap* heap,
-                                            Representation representation,
-                                            PretenureFlag tenure = NOT_TENURED);
+                                            Representation representation);
 
   // Returns true if the object is of the correct type to be used as a
   // implementation of a JSObject's elements.
@@ -2173,10 +2172,13 @@
   // passed map. This also extends the property backing store if necessary.
   static void AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map);
 
+  // Migrates the given object to a map whose field representations are the
+  // lowest upper bound of all known representations for that field.
   static void MigrateInstance(Handle<JSObject> instance);
 
+  // Migrates the given object only if the target map is already available,
+  // or returns an empty handle if such a map is not yet available.
   static Handle<Object> TryMigrateInstance(Handle<JSObject> instance);
-  inline MUST_USE_RESULT MaybeObject* TryMigrateInstance();
 
   // Can cause GC.
   MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributesTrampoline(
@@ -2470,8 +2472,8 @@
   MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind);
   MUST_USE_RESULT MaybeObject* UpdateAllocationSite(ElementsKind to_kind);
 
+  // TODO(mstarzinger): Both public because of ConvertAnsSetLocalProperty().
   static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map);
-  MUST_USE_RESULT MaybeObject* MigrateToMap(Map* new_map);
   static void GeneralizeFieldRepresentation(Handle<JSObject> object,
                                             int modify_index,
                                             Representation new_representation,
@@ -7825,6 +7827,10 @@
   static const uint32_t kMaximumArrayBytesToPretransition = 8 * 1024;
 
   DECL_ACCESSORS(transition_info, Object)
+  // nested_site threads a list of sites that represent nested literals
+  // walked in a particular order. So [[1, 2], 1, 2] will have one
+  // nested_site, but [[1, 2], 3, [4]] will have a list of two.
+  DECL_ACCESSORS(nested_site, Object)
   DECL_ACCESSORS(dependent_code, DependentCode)
   DECL_ACCESSORS(weak_next, Object)
 
@@ -7856,7 +7862,8 @@
   static inline bool CanTrack(InstanceType type);
 
   static const int kTransitionInfoOffset = HeapObject::kHeaderSize;
-  static const int kDependentCodeOffset = kTransitionInfoOffset + kPointerSize;
+  static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize;
+  static const int kDependentCodeOffset = kNestedSiteOffset + kPointerSize;
   static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize;
   static const int kSize = kWeakNextOffset + kPointerSize;
 
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index 5903438..0076d56 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -41,7 +41,6 @@
 
 #include "v8.h"
 
-#include "platform-posix.h"
 #include "platform.h"
 #include "simulator.h"
 #include "v8threads.h"
@@ -88,11 +87,6 @@
 }
 
 
-void OS::DumpBacktrace() {
-  // Currently unsupported.
-}
-
-
 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
  public:
   PosixMemoryMappedFile(FILE* file, void* memory, int size)
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 518ad31..103fd6c 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -43,7 +43,6 @@
 #include <sys/fcntl.h>  // open
 #include <unistd.h>     // getpagesize
 // If you don't have execinfo.h then you need devel/libexecinfo from ports.
-#include <execinfo.h>   // backtrace, backtrace_symbols
 #include <strings.h>    // index
 #include <errno.h>
 #include <stdarg.h>
@@ -54,7 +53,6 @@
 #include "v8.h"
 #include "v8threads.h"
 
-#include "platform-posix.h"
 #include "platform.h"
 #include "vm-state-inl.h"
 
@@ -97,11 +95,6 @@
 }
 
 
-void OS::DumpBacktrace() {
-  POSIXBacktraceHelper<backtrace, backtrace_symbols>::DumpBacktrace();
-}
-
-
 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
  public:
   PosixMemoryMappedFile(FILE* file, void* memory, int size)
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 74d473f..eb2d10b 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -38,11 +38,6 @@
 #include <sys/types.h>
 #include <stdlib.h>
 
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
-#include <execinfo.h>
-#include <cxxabi.h>
-#endif
-
 // Ubuntu Dapper requires memory pages to be marked as
 // executable. Otherwise, OS raises an exception when executing code
 // in that page.
@@ -66,7 +61,6 @@
 
 #include "v8.h"
 
-#include "platform-posix.h"
 #include "platform.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
@@ -154,14 +148,6 @@
 }
 
 
-void OS::DumpBacktrace() {
-  // backtrace is a glibc extension.
-#if defined(__GLIBC__) && !defined(__UCLIBC__)
-  POSIXBacktraceHelper<backtrace, backtrace_symbols>::DumpBacktrace();
-#endif
-}
-
-
 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
  public:
   PosixMemoryMappedFile(FILE* file, void* memory, int size)
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index a58bc1a..5ffc3fc 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -53,27 +53,15 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <cxxabi.h>
 
 #undef MAP_TYPE
 
 #include "v8.h"
 
-#include "platform-posix.h"
 #include "platform.h"
 #include "simulator.h"
 #include "vm-state-inl.h"
 
-// Manually define these here as weak imports, rather than including execinfo.h.
-// This lets us launch on 10.4 which does not have these calls.
-extern "C" {
-  extern int backtrace(void**, int) __attribute__((weak_import));
-  extern char** backtrace_symbols(void* const*, int)
-      __attribute__((weak_import));
-  extern void backtrace_symbols_fd(void* const*, int, int)
-      __attribute__((weak_import));
-}
-
 
 namespace v8 {
 namespace internal {
@@ -107,14 +95,6 @@
 }
 
 
-void OS::DumpBacktrace() {
-  // If weak link to execinfo lib has failed, ie because we are on 10.4, abort.
-  if (backtrace == NULL) return;
-
-  POSIXBacktraceHelper<backtrace, backtrace_symbols>::DumpBacktrace();
-}
-
-
 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
  public:
   PosixMemoryMappedFile(FILE* file, void* memory, int size)
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index 4f5420e..710c390 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -42,7 +42,6 @@
 #include <sys/stat.h>   // open
 #include <fcntl.h>      // open
 #include <unistd.h>     // sysconf
-#include <execinfo.h>   // backtrace, backtrace_symbols
 #include <strings.h>    // index
 #include <errno.h>
 #include <stdarg.h>
@@ -51,7 +50,6 @@
 
 #include "v8.h"
 
-#include "platform-posix.h"
 #include "platform.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
@@ -96,11 +94,6 @@
 }
 
 
-void OS::DumpBacktrace() {
-  // Currently unsupported.
-}
-
-
 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
  public:
   PosixMemoryMappedFile(FILE* file, void* memory, int size)
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index fe27eaf..df15ee2 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -29,8 +29,6 @@
 // own but contains the parts which are the same across POSIX platforms Linux,
 // Mac OS, FreeBSD and OpenBSD.
 
-#include "platform-posix.h"
-
 #include <dlfcn.h>
 #include <pthread.h>
 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
diff --git a/src/platform-posix.h b/src/platform-posix.h
deleted file mode 100644
index e0fbc0c..0000000
--- a/src/platform-posix.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_PLATFORM_POSIX_H_
-#define V8_PLATFORM_POSIX_H_
-
-#if !defined(ANDROID)
-#include <cxxabi.h>
-#endif
-#include <stdio.h>
-
-#include "platform.h"
-
-namespace v8 {
-namespace internal {
-
-// Used by platform implementation files during OS::DumpBacktrace()
-template<int (*backtrace)(void**, int),
-         char** (*backtrace_symbols)(void* const*, int)>
-struct POSIXBacktraceHelper {
-  static void DumpBacktrace() {
-    void* trace[100];
-    int size = backtrace(trace, ARRAY_SIZE(trace));
-    char** symbols = backtrace_symbols(trace, size);
-    fprintf(stderr, "\n==== C stack trace ===============================\n\n");
-    if (size == 0) {
-      fprintf(stderr, "(empty)\n");
-    } else if (symbols == NULL) {
-      fprintf(stderr, "(no symbols)\n");
-    } else {
-      for (int i = 1; i < size; ++i) {
-        fprintf(stderr, "%2d: ", i);
-        char mangled[201];
-        if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) {// NOLINT
-          char* demangled = NULL;
-#if !defined(ANDROID)
-          int status;
-          size_t length;
-          demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
-#endif
-          fprintf(stderr, "%s\n", demangled != NULL ? demangled : mangled);
-          free(demangled);
-        } else {
-          fprintf(stderr, "??\n");
-        }
-      }
-    }
-    fflush(stderr);
-    free(symbols);
-  }
-};
-
-} }  // namespace v8::internal
-
-#endif  // V8_PLATFORM_POSIX_H_
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index df81c3a..a0590cb 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -51,7 +51,6 @@
 
 #include "v8.h"
 
-#include "platform-posix.h"
 #include "platform.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
@@ -112,11 +111,6 @@
 }
 
 
-void OS::DumpBacktrace() {
-  // Currently unsupported.
-}
-
-
 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
  public:
   PosixMemoryMappedFile(FILE* file, void* memory, int size)
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 073b21a..7b26dfb 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -891,11 +891,6 @@
 }
 
 
-void OS::DumpBacktrace() {
-  // Currently unsupported.
-}
-
-
 class Win32MemoryMappedFile : public OS::MemoryMappedFile {
  public:
   Win32MemoryMappedFile(HANDLE file,
diff --git a/src/platform.h b/src/platform.h
index e0e62fa..527de16 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -256,9 +256,6 @@
   // Debug break.
   static void DebugBreak();
 
-  // Dump C++ current stack trace (only functional on Linux).
-  static void DumpBacktrace();
-
   // Walk the stack.
   static const int kStackWalkError = -1;
   static const int kStackWalkMaxNameLen = 256;
diff --git a/src/runtime.cc b/src/runtime.cc
index dbc8f11..30763c1 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -933,17 +933,24 @@
             HandleVector<Object>(NULL, 0)));
   }
 
+  // NOTE: not initializing backing store.
   // We assume that the caller of this function will initialize holder
   // with the loop
   //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
+  // We assume that the caller of this function is always a typed array
+  // constructor.
   // If source is a typed array, this loop will always run to completion,
   // so we are sure that the backing store will be initialized.
-  // Otherwise, we do not know (the indexing operation might throw).
-  // Hence we require zero initialization unless our source is a typed array.
-  bool should_zero_initialize = !source->IsJSTypedArray();
+  // Otherwise, the indexing operation might throw, so the loop will not
+  // run to completion and the typed array might remain partly initialized.
+  // However we further assume that the caller of this function is a typed array
+  // constructor, and the exception will propagate out of the constructor,
+  // therefore uninitialized memory will not be accessible by a user program.
+  //
+  // TODO(dslomov): revise this once we support subclassing.
 
   if (!Runtime::SetupArrayBufferAllocatingData(
-        isolate, buffer, byte_length, should_zero_initialize)) {
+        isolate, buffer, byte_length, false)) {
     return isolate->Throw(*isolate->factory()->
           NewRangeError("invalid_array_buffer_length",
             HandleVector<Object>(NULL, 0)));
@@ -8436,14 +8443,6 @@
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
-  SealHandleScope shs(isolate);
-  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
-  delete deoptimizer;
-  return isolate->heap()->undefined_value();
-}
-
-
 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 1);
diff --git a/src/runtime.h b/src/runtime.h
index 64fade4..1b68863 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -91,7 +91,6 @@
   F(TryInstallRecompiledCode, 1, 1) \
   F(NotifyDeoptimized, 1, 1) \
   F(NotifyStubFailure, 0, 1) \
-  F(NotifyOSR, 0, 1) \
   F(DeoptimizeFunction, 1, 1) \
   F(ClearFunctionTypeFeedback, 1, 1) \
   F(RunningInSimulator, 0, 1) \
diff --git a/src/typedarray.js b/src/typedarray.js
index 7bd16f6..da12ccf 100644
--- a/src/typedarray.js
+++ b/src/typedarray.js
@@ -76,9 +76,11 @@
 
   function ConstructByArrayLike(obj, arrayLike) {
     var length = arrayLike.length;
-    var l =  ToPositiveInteger(length, "invalid_typed_array_length");
+    var l = ToPositiveInteger(length, "invalid_typed_array_length");
     if(!%TypedArrayInitializeFromArrayLike(obj, arrayId, arrayLike, l)) {
       for (var i = 0; i < l; i++) {
+        // It is crucial that we let any execptions from arrayLike[i]
+        // propagate outside the function.
         obj[i] = arrayLike[i];
       }
     }
diff --git a/src/unique.h b/src/unique.h
index 6816654..fdb7016 100644
--- a/src/unique.h
+++ b/src/unique.h
@@ -54,7 +54,7 @@
 template <typename T>
 class Unique V8_FINAL {
  public:
-  // TODO(titzer): make private and introduce a factory.
+  // TODO(titzer): make private and introduce a uniqueness scope.
   explicit Unique(Handle<T> handle) {
     if (handle.is_null()) {
       raw_address_ = NULL;
@@ -111,8 +111,11 @@
     return raw_address_ == NULL;
   }
 
-  // Extract the handle from this Unique in order to dereference it.
-  // WARNING: Only do this if you have access to the heap.
+  inline bool IsKnownGlobal(void* global) const {
+    ASSERT(IsInitialized());
+    return raw_address_ == reinterpret_cast<Address>(global);
+  }
+
   inline Handle<T> handle() const {
     return handle_;
   }
@@ -123,7 +126,11 @@
 
   // TODO(titzer): this is a hack to migrate to Unique<T> incrementally.
   static Unique<T> CreateUninitialized(Handle<T> handle) {
-    return Unique<T>(static_cast<Address>(NULL), handle);
+    return Unique<T>(reinterpret_cast<Address>(NULL), handle);
+  }
+
+  static Unique<T> CreateImmovable(Handle<T> handle) {
+    return Unique<T>(reinterpret_cast<Address>(*handle), handle);
   }
 
   friend class UniqueSet<T>;  // Uses internal details for speed.
@@ -171,9 +178,10 @@
     return true;
   }
 
+  // Check whether this set contains the given element. O(|this|)
+  // TODO(titzer): use binary search for large sets to make this O(log|this|)
   template <typename U>
   bool Contains(Unique<U> elem) const {
-    // TODO(titzer): use binary search for larger sets.
     for (int i = 0; i < size_; i++) {
       if (this->array_[i] == elem) return true;
     }
diff --git a/src/utils/random-number-generator.cc b/src/utils/random-number-generator.cc
index 1e03ee2..3f657fb 100644
--- a/src/utils/random-number-generator.cc
+++ b/src/utils/random-number-generator.cc
@@ -28,6 +28,7 @@
 #include "utils/random-number-generator.h"
 
 #include <cstdio>
+#include <cstdlib>
 
 #include "flags.h"
 #include "platform/mutex.h"
@@ -67,6 +68,16 @@
     }
   }
 
+#if V8_OS_CYGWIN || V8_OS_WIN
+  // Use rand_s() to gather entropy on Windows. See:
+  // https://code.google.com/p/v8/issues/detail?id=2905
+  unsigned first_half, second_half;
+  errno_t result = rand_s(&first_half);
+  ASSERT_EQ(0, result);
+  result = rand_s(&second_half);
+  ASSERT_EQ(0, result);
+  SetSeed((static_cast<int64_t>(first_half) << 32) + second_half);
+#else
   // Gather entropy from /dev/urandom if available.
   FILE* fp = fopen("/dev/urandom", "rb");
   if (fp != NULL) {
@@ -82,10 +93,16 @@
   // We cannot assume that random() or rand() were seeded
   // properly, so instead of relying on random() or rand(),
   // we just seed our PRNG using timing data as fallback.
+  // This is weak entropy, but it's sufficient, because
+  // it is the responsibility of the embedder to install
+  // an entropy source using v8::V8::SetEntropySource(),
+  // which provides reasonable entropy, see:
+  // https://code.google.com/p/v8/issues/detail?id=2905
   int64_t seed = Time::NowFromSystemTime().ToInternalValue() << 24;
   seed ^= TimeTicks::HighResNow().ToInternalValue() << 16;
   seed ^= TimeTicks::Now().ToInternalValue() << 8;
   SetSeed(seed);
+#endif  // V8_OS_CYGWIN || V8_OS_WIN
 }
 
 
diff --git a/src/utils/random-number-generator.h b/src/utils/random-number-generator.h
index bd7dca7..cc7d739 100644
--- a/src/utils/random-number-generator.h
+++ b/src/utils/random-number-generator.h
@@ -42,6 +42,10 @@
 // If two instances of RandomNumberGenerator are created with the same seed, and
 // the same sequence of method calls is made for each, they will generate and
 // return identical sequences of numbers.
+// This class uses (probably) weak entropy by default, but it's sufficient,
+// because it is the responsibility of the embedder to install an entropy source
+// using v8::V8::SetEntropySource(), which provides reasonable entropy, see:
+// https://code.google.com/p/v8/issues/detail?id=2905
 // This class is neither reentrant nor threadsafe.
 
 class RandomNumberGenerator V8_FINAL {
diff --git a/src/version.cc b/src/version.cc
index 02f61e4..02ffa65 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     22
-#define BUILD_NUMBER      0
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      1
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 41bf297..b6a28fc 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -2058,6 +2058,10 @@
 
 
 void Assembler::testq(Register dst, Immediate mask) {
+  if (is_uint8(mask.value_)) {
+    testb(dst, mask);
+    return;
+  }
   EnsureSpace ensure_space(this);
   if (dst.is(rax)) {
     emit_rex_64();
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index a6dc003..947f687 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -694,21 +694,6 @@
 }
 
 
-void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
-  // For now, we are relying on the fact that Runtime::NotifyOSR
-  // doesn't do any garbage collection which allows us to save/restore
-  // the registers without worrying about which of them contain
-  // pointers. This seems a bit fragile.
-  __ Pushad();
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-    __ CallRuntime(Runtime::kNotifyOSR, 0);
-  }
-  __ Popad();
-  __ ret(0);
-}
-
-
 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
   // Stack Layout:
   // rsp[0]           : Return address
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 8f27374..1896c00 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -60,6 +60,16 @@
 }
 
 
+void NumberToStringStub::InitializeInterfaceDescriptor(
+    Isolate* isolate,
+    CodeStubInterfaceDescriptor* descriptor) {
+  static Register registers[] = { rax };
+  descriptor->register_param_count_ = 1;
+  descriptor->register_params_ = registers;
+  descriptor->deoptimization_handler_ = NULL;
+}
+
+
 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor(
     Isolate* isolate,
     CodeStubInterfaceDescriptor* descriptor) {
@@ -2909,22 +2919,6 @@
 }
 
 
-void NumberToStringStub::Generate(MacroAssembler* masm) {
-  Label runtime;
-
-  StackArgumentsAccessor args(rsp, 1, ARGUMENTS_DONT_CONTAIN_RECEIVER);
-  __ movq(rbx, args.GetArgumentOperand(0));
-
-  // Generate code to lookup number in the number string cache.
-  __ LookupNumberStringCache(rbx, rax, r8, r9, &runtime);
-  __ ret(1 * kPointerSize);
-
-  __ bind(&runtime);
-  // Handle number to string in the runtime system if not found in the cache.
-  __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
-}
-
-
 static int NegativeComparisonResult(Condition cc) {
   ASSERT(cc != equal);
   ASSERT((cc == less) || (cc == less_equal)
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index c3eac81..c76abcf 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -208,18 +208,6 @@
 };
 
 
-class NumberToStringStub: public PlatformCodeStub {
- public:
-  NumberToStringStub() { }
-
- private:
-  Major MajorKey() { return NumberToString; }
-  int MinorKey() { return 0; }
-
-  void Generate(MacroAssembler* masm);
-};
-
-
 class NameDictionaryLookupStub: public PlatformCodeStub {
  public:
   enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index f9d1ffa..55feb4c 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -3507,8 +3507,8 @@
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(args->length(), 1);
 
-  // Load the argument on the stack and call the stub.
-  VisitForStackValue(args->at(0));
+  // Load the argument into rax and call the stub.
+  VisitForAccumulatorValue(args->at(0));
 
   NumberToStringStub stub;
   __ CallStub(&stub);
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 83a8cb2..27d064d 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -973,11 +973,6 @@
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
       break;
     }
-    case CodeStub::NumberToString: {
-      NumberToStringStub stub;
-      CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
-      break;
-    }
     case CodeStub::StringCompare: {
       StringCompareStub stub;
       CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 9f45f97..0ccbeb8 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -1297,8 +1297,8 @@
   LOperand* date() { return inputs_[0]; }
   Smi* index() const { return index_; }
 
-  DECLARE_CONCRETE_INSTRUCTION(ValueOf, "date-field")
-  DECLARE_HYDROGEN_ACCESSOR(ValueOf)
+  DECLARE_CONCRETE_INSTRUCTION(DateField, "date-field")
+  DECLARE_HYDROGEN_ACCESSOR(DateField)
 
  private:
   Smi* index_;
diff --git a/test/benchmarks/benchmarks.status b/test/benchmarks/benchmarks.status
index 651b8d7..103eaeb 100644
--- a/test/benchmarks/benchmarks.status
+++ b/test/benchmarks/benchmarks.status
@@ -25,5 +25,9 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-# Too slow in Debug mode.
-octane/mandreel: PASS, SKIP if $mode == debug
+[
+['mode == debug', {
+  # Too slow in Debug mode.
+  'octane/mandreel': [SKIP],
+}],  # 'mode == debug'
+]
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 8c6bf95..c8f6e57 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -147,6 +147,7 @@
           'sources': [
             'test-assembler-mips.cc',
             'test-disasm-mips.cc',
+            'test-macro-assembler-mips.cc'
           ],
         }],
         [ 'OS=="linux"', {
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 8566109..5480f4c 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -25,107 +25,118 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-prefix cctest
+[
+[ALWAYS, {
+  # All tests prefixed with 'Bug' are expected to fail.
+  'test-api/Bug*': [FAIL],
 
-# All tests prefixed with 'Bug' are expected to fail.
-test-api/Bug*: FAIL
+  ##############################################################################
+  # BUG(382): Weird test. Can't guarantee that it never times out.
+  'test-api/ApplyInterruption': [PASS, TIMEOUT],
+
+  # BUG(2907): Allocation while in DisallowHeapAllocation scope.
+  'test-object-observe/NamedAccessCheck': [SKIP],
+  'test-object-observe/DisallowAllForAccessKeys': [SKIP],
+  'test-object-observe/AccessCheckDisallowApiModifications': [SKIP],
+
+  # TODO(mstarzinger): Fail gracefully on multiple V8::Dispose calls.
+  'test-api/InitializeAndDisposeOnce': [SKIP],
+  'test-api/InitializeAndDisposeMultiple': [SKIP],
+
+  # These tests always fail.  They are here to test test.py.  If
+  # they don't fail then test.py has failed.
+  'test-serialize/TestThatAlwaysFails': [FAIL],
+  'test-serialize/DependentTestThatAlwaysFails': [FAIL],
+
+  # This test always fails.  It tests that LiveEdit causes abort when turned off.
+  'test-debug/LiveEditDisabled': [FAIL],
+
+  # TODO(gc): Temporarily disabled in the GC branch.
+  'test-log/EquivalenceOfLoggingAndTraversal': [PASS, FAIL],
+
+  # We do not yet shrink weak maps after they have been emptied by the GC
+  'test-weakmaps/Shrinking': [FAIL],
+  'test-weaksets/WeakSet_Shrinking': [FAIL],
+
+  # Boot up memory use is bloated in debug mode.
+  'test-mark-compact/BootUpMemoryUse': [PASS, PASS, ['mode == debug', FAIL]],
+
+  # Some CPU profiler tests are flaky.
+  'test-cpu-profiler/*': [PASS, FLAKY],
+}],  # ALWAYS
 
 ##############################################################################
-# BUG(382): Weird test. Can't guarantee that it never times out.
-test-api/ApplyInterruption: PASS || TIMEOUT
+['arch == arm', {
 
-# TODO(mstarzinger): Fail gracefully on multiple V8::Dispose calls.
-test-api/InitializeAndDisposeOnce: SKIP
-test-api/InitializeAndDisposeMultiple: SKIP
+  # We cannot assume that we can throw OutOfMemory exceptions in all situations.
+  # Apparently our ARM box is in such a state. Skip the test as it also runs for
+  # a long time.
+  'test-api/OutOfMemory': [SKIP],
+  'test-api/OutOfMemoryNested': [SKIP],
 
-# These tests always fail.  They are here to test test.py.  If
-# they don't fail then test.py has failed.
-test-serialize/TestThatAlwaysFails: FAIL
-test-serialize/DependentTestThatAlwaysFails: FAIL
+  # BUG(355): Test crashes on ARM.
+  'test-log/ProfLazyMode': [SKIP],
 
-# This test always fails.  It tests that LiveEdit causes abort when turned off.
-test-debug/LiveEditDisabled: FAIL
+  # BUG(1075): Unresolved crashes.
+  'test-serialize/Deserialize': [SKIP],
+  'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [SKIP],
+  'test-serialize/DeserializeAndRunScript2': [SKIP],
+  'test-serialize/DeserializeFromSecondSerialization': [SKIP],
 
-# TODO(gc): Temporarily disabled in the GC branch.
-test-log/EquivalenceOfLoggingAndTraversal: PASS || FAIL
+  # BUG(2874): Threading problems.
+  'test-api/*': [PASS, FLAKY],
+}],  # 'arch == arm'
+##############################################################################
+['arch == mipsel', {
 
-# We do not yet shrink weak maps after they have been emptied by the GC
-test-weakmaps/Shrinking: FAIL
-test-weaksets/WeakSet_Shrinking: FAIL
+  # BUG(2657): Test sometimes times out on MIPS simulator.
+  'test-thread-termination/TerminateMultipleV8ThreadsDefaultIsolate': [PASS, TIMEOUT],
 
-# Boot up memory use is bloated in debug mode.
-test-mark-compact/BootUpMemoryUse: PASS, PASS || FAIL if $mode == debug
-
-# Some CPU profiler tests are flaky.
-test-cpu-profiler/*: PASS || FLAKY
+  # BUG(1075): Unresolved crashes on MIPS also.
+  'test-serialize/Deserialize': [SKIP],
+  'test-serialize/DeserializeFromSecondSerializationAndRunScript2': [SKIP],
+  'test-serialize/DeserializeAndRunScript2': [SKIP],
+  'test-serialize/DeserializeFromSecondSerialization': [SKIP],
+}],  # 'arch == mipsel'
 
 ##############################################################################
-[ $arch == arm ]
+['arch == android_arm or arch == android_ia32', {
 
-# We cannot assume that we can throw OutOfMemory exceptions in all situations.
-# Apparently our ARM box is in such a state. Skip the test as it also runs for
-# a long time.
-test-api/OutOfMemory: SKIP
-test-api/OutOfMemoryNested: SKIP
+  # Tests crash as there is no /tmp directory in Android.
+  'test-log/LogAccessorCallbacks': [SKIP],
+  'test-log/LogCallbacks': [SKIP],
+  'test-log/ProfLazyMode': [SKIP],
 
-# BUG(355): Test crashes on ARM.
-test-log/ProfLazyMode: SKIP
+  # platform-tls.h does not contain an ANDROID-related header.
+  'test-platform-tls/FastTLS': [SKIP],
 
-# BUG(1075): Unresolved crashes.
-test-serialize/Deserialize: SKIP
-test-serialize/DeserializeFromSecondSerializationAndRunScript2: SKIP
-test-serialize/DeserializeAndRunScript2: SKIP
-test-serialize/DeserializeFromSecondSerialization: SKIP
-
-# BUG(2874): Threading problems.
-test-api/*: PASS || FLAKY
-##############################################################################
-[ $arch == mipsel ]
-
-# BUG(2657): Test sometimes times out on MIPS simulator.
-test-thread-termination/TerminateMultipleV8ThreadsDefaultIsolate: PASS || TIMEOUT
-
-# BUG(1075): Unresolved crashes on MIPS also.
-test-serialize/Deserialize: SKIP
-test-serialize/DeserializeFromSecondSerializationAndRunScript2: SKIP
-test-serialize/DeserializeAndRunScript2: SKIP
-test-serialize/DeserializeFromSecondSerialization: SKIP
+  # This test times out.
+  'test-threads/ThreadJoinSelf': [SKIP],
+}],  # 'arch == android_arm or arch == android_ia32'
 
 ##############################################################################
-[ $arch == android_arm || $arch == android_ia32 ]
+['arch == nacl_ia32 or arch == nacl_x64', {
 
-# Tests crash as there is no /tmp directory in Android.
-test-log/LogAccessorCallbacks: SKIP
-test-log/LogCallbacks: SKIP
-test-log/ProfLazyMode: SKIP
+  # NaCl builds have problems with threaded tests since Pepper_28.
+  # V8 Issue 2786
+  'test-api/Threading1': [SKIP],
+  'test-lockers/MultithreadedParallelIsolates': [SKIP],
+  'test-lockers/ExtensionsRegistration': [SKIP],
 
-# platform-tls.h does not contain an ANDROID-related header.
-test-platform-tls/FastTLS: SKIP
+  # These tests fail as there is no /tmp directory in Native Client.
+  'test-log/LogAccessorCallbacks': [SKIP],
+  'test-log/LogCallbacks': [SKIP],
+  'test-log/ProfLazyMode': [SKIP],
 
-# This test times out.
-test-threads/ThreadJoinSelf: SKIP
+  # Native Client doesn't support sockets.
+  'test-debug/DebuggerAgent': [SKIP],
+  'test-debug/DebuggerAgentProtocolOverflowHeader': [SKIP],
+  'test-socket/Socket': [SKIP],
 
-##############################################################################
-[ $arch == nacl_ia32 || $arch == nacl_x64 ]
+  # Profiling doesn't work on Native Client.
+  'test-cpu-profiler/*': [SKIP],
 
-# NaCl builds have problems with threaded tests since Pepper_28.
-# V8 Issue 2786
-test-api/Threading1: SKIP
-test-lockers/MultithreadedParallelIsolates: SKIP
-test-lockers/ExtensionsRegistration: SKIP
-
-# These tests fail as there is no /tmp directory in Native Client.
-test-log/LogAccessorCallbacks: SKIP
-test-log/LogCallbacks: SKIP
-test-log/ProfLazyMode: SKIP
-
-# Native Client doesn't support sockets.
-test-debug/DebuggerAgent: SKIP
-test-debug/DebuggerAgentProtocolOverflowHeader: SKIP
-test-socket/Socket: SKIP
-
-# Profiling doesn't work on Native Client.
-test-cpu-profiler/*: SKIP
-
-# Fails since 16322 (new test).
-test-code-stubs-arm/ConvertDToI: SKIP
+  # Fails since 16322 (new test).
+  'test-code-stubs-arm/ConvertDToI': [SKIP],
+}],  # 'arch == nacl_ia32 or arch == nacl_x64'
+]
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 070c377..cfebeff 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -4973,7 +4973,7 @@
   CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
   CHECK(v8_num(1)->StrictEquals(v8_num(1)));
   CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
-  CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
+  CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
   Local<Value> not_a_number = v8_num(i::OS::nan_value());
   CHECK(!not_a_number->StrictEquals(not_a_number));
   CHECK(v8::False()->StrictEquals(v8::False()));
@@ -4983,6 +4983,16 @@
   v8::Persistent<v8::Object> alias(isolate, obj);
   CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
   alias.Dispose();
+
+  CHECK(v8_str("a")->SameValue(v8_str("a")));
+  CHECK(!v8_str("a")->SameValue(v8_str("b")));
+  CHECK(!v8_str("5")->SameValue(v8_num(5)));
+  CHECK(v8_num(1)->SameValue(v8_num(1)));
+  CHECK(!v8_num(1)->SameValue(v8_num(2)));
+  CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
+  CHECK(not_a_number->SameValue(not_a_number));
+  CHECK(v8::False()->SameValue(v8::False()));
+  CHECK(!v8::False()->SameValue(v8::Undefined()));
 }
 
 
diff --git a/test/cctest/test-macro-assembler-mips.cc b/test/cctest/test-macro-assembler-mips.cc
new file mode 100644
index 0000000..b200949
--- /dev/null
+++ b/test/cctest/test-macro-assembler-mips.cc
@@ -0,0 +1,136 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <stdlib.h>
+
+#include "v8.h"
+#include "macro-assembler.h"
+#include "mips/macro-assembler-mips.h"
+#include "mips/simulator-mips.h"
+#include "cctest.h"
+
+
+using namespace v8::internal;
+
+typedef void* (*F)(int x, int y, int p2, int p3, int p4);
+
+#define __ masm->
+
+
+static byte to_non_zero(int n) {
+  return static_cast<unsigned>(n) % 255 + 1;
+}
+
+
+static bool all_zeroes(const byte* beg, const byte* end) {
+  CHECK(beg);
+  CHECK(beg <= end);
+  while (beg < end) {
+    if (*beg++ != 0)
+      return false;
+  }
+  return true;
+}
+
+
+TEST(CopyBytes) {
+  CcTest::InitializeVM();
+  Isolate* isolate = Isolate::Current();
+  HandleScope handles(isolate);
+
+  const int data_size = 1 * KB;
+  size_t act_size;
+
+  // Allocate two blocks to copy data between.
+  byte* src_buffer = static_cast<byte*>(OS::Allocate(data_size, &act_size, 0));
+  CHECK(src_buffer);
+  CHECK(act_size >= static_cast<size_t>(data_size));
+  byte* dest_buffer = static_cast<byte*>(OS::Allocate(data_size, &act_size, 0));
+  CHECK(dest_buffer);
+  CHECK(act_size >= static_cast<size_t>(data_size));
+
+  // Storage for a0 and a1.
+  byte* a0_;
+  byte* a1_;
+
+  MacroAssembler assembler(isolate, NULL, 0);
+  MacroAssembler* masm = &assembler;
+
+  // Code to be generated: The stuff in CopyBytes followed by a store of a0 and
+  // a1, respectively.
+  __ CopyBytes(a0, a1, a2, a3);
+  __ li(a2, Operand(reinterpret_cast<int>(&a0_)));
+  __ li(a3, Operand(reinterpret_cast<int>(&a1_)));
+  __ sw(a0, MemOperand(a2));
+  __ jr(ra);
+  __ sw(a1, MemOperand(a3));
+
+  CodeDesc desc;
+  masm->GetCode(&desc);
+  Object* code = isolate->heap()->CreateCode(
+      desc,
+      Code::ComputeFlags(Code::STUB),
+      Handle<Code>())->ToObjectChecked();
+  CHECK(code->IsCode());
+
+  ::F f = FUNCTION_CAST< ::F>(Code::cast(code)->entry());
+
+  // Initialise source data with non-zero bytes.
+  for (int i = 0; i < data_size; i++) {
+    src_buffer[i] = to_non_zero(i);
+  }
+
+  const int fuzz = 11;
+
+  for (int size = 0; size < 600; size++) {
+    for (const byte* src = src_buffer; src < src_buffer + fuzz; src++) {
+      for (byte* dest = dest_buffer; dest < dest_buffer + fuzz; dest++) {
+        memset(dest_buffer, 0, data_size);
+        CHECK(dest + size < dest_buffer + data_size);
+        (void) CALL_GENERATED_CODE(f, reinterpret_cast<int>(src),
+                                      reinterpret_cast<int>(dest), size, 0, 0);
+        // a0 and a1 should point at the first byte after the copied data.
+        CHECK_EQ(src + size, a0_);
+        CHECK_EQ(dest + size, a1_);
+        // Check that we haven't written outside the target area.
+        CHECK(all_zeroes(dest_buffer, dest));
+        CHECK(all_zeroes(dest + size, dest_buffer + data_size));
+        // Check the target area.
+        CHECK_EQ(0, memcmp(src, dest, size));
+      }
+    }
+  }
+
+  // Check that the source data hasn't been clobbered.
+  for (int i = 0; i < data_size; i++) {
+    CHECK(src_buffer[i] == to_non_zero(i));
+  }
+}
+
+
+
+#undef __
diff --git a/test/intl/intl.status b/test/intl/intl.status
index ad23784..fc3c66b 100644
--- a/test/intl/intl.status
+++ b/test/intl/intl.status
@@ -25,15 +25,17 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-prefix intl
+[
+[ALWAYS, {
+  # The following tests use getDefaultTimeZone().
+  'date-format/resolved-options': [FAIL],
+  'date-format/timezone': [FAIL],
+  'general/v8Intl-exists': [FAIL],
 
-# The following tests use getDefaultTimeZone().
-date-format/resolved-options: FAIL
-date-format/timezone: FAIL
-general/v8Intl-exists: FAIL
+  # TODO(jochen): The following test is flaky.
+  'overrides/caching': [PASS, FAIL],
 
-# TODO(jochen): The following test is flaky.
-overrides/caching: PASS || FAIL
-
-# BUG(2899): default locale for search fails on mac.
-collator/default-locale: FAIL if $system == macos
+  # BUG(2899): default locale for search fails on mac and on android.
+  'collator/default-locale': [['system == macos or arch == android_arm or arch == android_ia32', FAIL]],
+}],  # ALWAYS
+]
diff --git a/test/message/message.status b/test/message/message.status
index 441f8ed..234bf0f 100644
--- a/test/message/message.status
+++ b/test/message/message.status
@@ -25,7 +25,9 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-prefix message
-
-# All tests in the bug directory are expected to fail.
-bugs/*: FAIL
+[
+[ALWAYS, {
+  # All tests in the bug directory are expected to fail.
+  'bugs/*': [FAIL],
+}],  # ALWAYS
+]
diff --git a/test/mjsunit/lithium/MathExp.js b/test/mjsunit/lithium/MathExp.js
new file mode 100644
index 0000000..854ff5f
--- /dev/null
+++ b/test/mjsunit/lithium/MathExp.js
@@ -0,0 +1,39 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function foo(x) {
+  return Math.exp(x);
+}
+
+foo(12.3);
+var r1 = foo(12.3);
+%OptimizeFunctionOnNextCall(foo);
+var r2 = foo(12.3);
+
+assertEquals(r1, r2);
diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status
index ee35af5..ec780e5 100644
--- a/test/mjsunit/mjsunit.status
+++ b/test/mjsunit/mjsunit.status
@@ -25,184 +25,187 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-prefix mjsunit
+[
+[ALWAYS, {
+  # All tests in the bug directory are expected to fail.
+  'bugs/*': [FAIL],
 
-# All tests in the bug directory are expected to fail.
-bugs/*: FAIL
+  ##############################################################################
+  # Fails.
+  'regress/regress-1119': [FAIL],
+
+  # Issue 1719: Slow to collect arrays over several contexts.
+  'regress/regress-524': [SKIP],
+  # When that bug is fixed, revert the expectation to:
+  # Skip long running test in debug and allow it to timeout in release mode.
+  # regress/regress-524: [PASS, TIMEOUT, ['mode == debug', SKIP]],
+
+  # This test non-deterministically runs out of memory on Windows ia32.
+  'regress/regress-crbug-160010': [SKIP],
+
+  ##############################################################################
+  # Too slow in debug mode with --stress-opt mode.
+  'compiler/regress-stacktrace-methods': [PASS, ['mode == debug', SKIP]],
+  'compiler/regress-funcaller': [PASS, ['mode == debug', SKIP]],
+  'regress/regress-2318': [PASS, ['mode == debug', SKIP]],
+  'regress/regress-create-exception': [PASS, ['mode == debug', SKIP]],
+  'regress/regress-2612': [PASS, ['mode == debug', SKIP]],
+
+  ##############################################################################
+  # Too slow in debug mode for GC stress mode.
+  'regress/regress-crbug-217858': [PASS, ['mode == debug', SKIP]],
+
+  ##############################################################################
+  # These use a built-in that's only present in debug mode. They take
+  # too long to run in debug mode on ARM and MIPS.
+  'fuzz-natives-part*': [PASS, ['mode == release or arch == arm or arch == android_arm or arch == mipsel', SKIP]],
+
+  'big-object-literal': [PASS, ['arch == arm or arch == android_arm', SKIP]],
+
+  # Issue 488: this test sometimes times out.
+  'array-constructor': [PASS, TIMEOUT],
+
+  # Very slow on ARM and MIPS, contains no architecture dependent code.
+  'unicode-case-overoptimization': [PASS, ['arch == arm or arch == android_arm or arch == mipsel', TIMEOUT]],
+
+  ##############################################################################
+  # This test expects to reach a certain recursion depth, which may not work
+  # for debug mode.
+  'json-recursive': [PASS, ['mode == debug', PASS, FAIL]],
+
+  ##############################################################################
+  # Skip long running tests that time out in debug mode.
+  'generated-transition-stub': [PASS, ['mode == debug', SKIP]],
+
+  ##############################################################################
+  # This test sets the umask on a per-process basis and hence cannot be
+  # used in multi-threaded runs.
+  # On android there is no /tmp directory.
+  'd8-os': [PASS, ['isolates or arch == android_arm or arch == android_ia32', SKIP]],
+  'tools/tickprocessor': [PASS, ['arch == android_arm or arch == android_ia32', SKIP]],
+
+  ##############################################################################
+  # Long running test that reproduces memory leak and should be run manually.
+  'regress/regress-2073': [SKIP],
+}],  # ALWAYS
 
 ##############################################################################
-# Fails.
-regress/regress-1119: FAIL
+['arch == arm or arch == android_arm', {
 
-# Issue 1719: Slow to collect arrays over several contexts.
-regress/regress-524: SKIP
-# When that bug is fixed, revert the expectation to:
-# Skip long running test in debug and allow it to timeout in release mode.
-# regress/regress-524: (PASS || TIMEOUT), SKIP if $mode == debug
+  # Slow tests which times out in debug mode.
+  'try': [PASS, ['mode == debug', SKIP]],
+  'debug-scripts-request': [PASS, ['mode == debug', SKIP]],
+  'array-constructor': [PASS, ['mode == debug', SKIP]],
+  'regress/regress-1122': [PASS, ['mode == debug and arch == android_arm', SKIP]],
 
-# This test non-deterministically runs out of memory on Windows ia32.
-regress/regress-crbug-160010: SKIP
+  # Flaky test that can hit compilation-time stack overflow in debug mode.
+  'unicode-test': [PASS, ['mode == debug', PASS, FAIL]],
+
+  # Times out often in release mode on ARM.
+  'compiler/regress-stacktrace-methods': [PASS, PASS, ['mode == release', TIMEOUT]],
+  'array-splice': [PASS, TIMEOUT],
+
+  # Long running test.
+  'string-indexof-2': [PASS, TIMEOUT],
+  'mirror-object': [PASS, TIMEOUT],
+
+  # BUG(3251035): Timeouts in long looping crankshaft optimization
+  # tests. Skipping because having them timeout takes too long on the
+  # buildbot.
+  'compiler/alloc-number': [SKIP],
+  'compiler/array-length': [SKIP],
+  'compiler/assignment-deopt': [SKIP],
+  'compiler/deopt-args': [SKIP],
+  'compiler/inline-compare': [SKIP],
+  'compiler/inline-global-access': [SKIP],
+  'compiler/optimized-function-calls': [SKIP],
+  'compiler/pic': [SKIP],
+  'compiler/property-calls': [SKIP],
+  'compiler/recursive-deopt': [SKIP],
+  'compiler/regress-4': [SKIP],
+  'compiler/regress-funcaller': [SKIP],
+  'compiler/regress-rep-change': [SKIP],
+  'compiler/regress-arguments': [SKIP],
+  'compiler/regress-funarguments': [SKIP],
+  'compiler/regress-3249650': [SKIP],
+  'compiler/simple-deopt': [SKIP],
+  'regress/regress-490': [SKIP],
+  'regress/regress-634': [SKIP],
+  'regress/regress-create-exception': [SKIP],
+  'regress/regress-3218915': [SKIP],
+  'regress/regress-3247124': [SKIP],
+
+  # Requires bigger stack size in the Genesis and if stack size is increased,
+  # the test requires too much time to run.  However, the problem test covers
+  # should be platform-independent.
+  'regress/regress-1132': [SKIP],
+
+  # Stack manipulations in LiveEdit is not implemented for this arch.
+  'debug-liveedit-check-stack': [SKIP],
+  'debug-liveedit-stack-padding': [SKIP],
+  'debug-liveedit-restart-frame': [SKIP],
+  'debug-liveedit-double-call': [SKIP],
+
+  # Currently always deopt on minus zero
+  'math-floor-of-div-minus-zero': [SKIP],
+}],  # 'arch == arm or arch == android_arm'
 
 ##############################################################################
-# Too slow in debug mode with --stress-opt mode.
-compiler/regress-stacktrace-methods: PASS, SKIP if $mode == debug
-compiler/regress-funcaller: PASS, SKIP if $mode == debug
-regress/regress-2318: PASS, SKIP if $mode == debug
-regress/regress-create-exception: PASS, SKIP if $mode == debug
-regress/regress-2612: PASS, SKIP if $mode == debug
+['arch == mipsel', {
 
-##############################################################################
-# Too slow in debug mode for GC stress mode.
-regress/regress-crbug-217858: PASS, SKIP if $mode == debug
+  # Slow tests which times out in debug mode.
+  'try': [PASS, ['mode == debug', SKIP]],
+  'debug-scripts-request': [PASS, ['mode == debug', SKIP]],
+  'array-constructor': [PASS, ['mode == debug', SKIP]],
 
-##############################################################################
-# These use a built-in that's only present in debug mode. They take
-# too long to run in debug mode on ARM and MIPS.
-fuzz-natives-part*: PASS, SKIP if ($mode == release || $arch == arm || $arch == android_arm || $arch == mipsel)
+  # Times out often in release mode on MIPS.
+  'compiler/regress-stacktrace-methods': [PASS, PASS, ['mode == release', TIMEOUT]],
+  'array-splice': [PASS, TIMEOUT],
 
-big-object-literal: PASS, SKIP if ($arch == arm || $arch == android_arm)
+  # Long running test.
+  'mirror-object': [PASS, TIMEOUT],
+  'string-indexof-2': [PASS, TIMEOUT],
 
-# Issue 488: this test sometimes times out.
-array-constructor: PASS || TIMEOUT
+  # BUG(3251035): Timeouts in long looping crankshaft optimization
+  # tests. Skipping because having them timeout takes too long on the
+  # buildbot.
+  'compiler/alloc-number': [SKIP],
+  'compiler/array-length': [SKIP],
+  'compiler/assignment-deopt': [SKIP],
+  'compiler/deopt-args': [SKIP],
+  'compiler/inline-compare': [SKIP],
+  'compiler/inline-global-access': [SKIP],
+  'compiler/optimized-function-calls': [SKIP],
+  'compiler/pic': [SKIP],
+  'compiler/property-calls': [SKIP],
+  'compiler/recursive-deopt': [SKIP],
+  'compiler/regress-4': [SKIP],
+  'compiler/regress-funcaller': [SKIP],
+  'compiler/regress-rep-change': [SKIP],
+  'compiler/regress-arguments': [SKIP],
+  'compiler/regress-funarguments': [SKIP],
+  'compiler/regress-3249650': [SKIP],
+  'compiler/simple-deopt': [SKIP],
+  'regress/regress-490': [SKIP],
+  'regress/regress-634': [SKIP],
+  'regress/regress-create-exception': [SKIP],
+  'regress/regress-3218915': [SKIP],
+  'regress/regress-3247124': [SKIP],
 
-# Very slow on ARM and MIPS, contains no architecture dependent code.
-unicode-case-overoptimization: PASS, TIMEOUT if ($arch == arm || $arch == android_arm || $arch == mipsel)
+  # Requires bigger stack size in the Genesis and if stack size is increased,
+  # the test requires too much time to run.  However, the problem test covers
+  # should be platform-independent.
+  'regress/regress-1132': [SKIP],
 
-##############################################################################
-# This test expects to reach a certain recursion depth, which may not work
-# for debug mode.
-json-recursive: PASS, (PASS || FAIL) if $mode == debug
+  # Stack manipulations in LiveEdit is not implemented for this arch.
+  'debug-liveedit-check-stack': [SKIP],
+  'debug-liveedit-stack-padding': [SKIP],
+  'debug-liveedit-restart-frame': [SKIP],
+  'debug-liveedit-double-call': [SKIP],
 
-##############################################################################
-# Skip long running tests that time out in debug mode.
-generated-transition-stub: PASS, SKIP if $mode == debug
-
-##############################################################################
-# This test sets the umask on a per-process basis and hence cannot be
-# used in multi-threaded runs.
-# On android there is no /tmp directory.
-d8-os: PASS, SKIP if ($isolates || $arch == android_arm || $arch == android_ia32)
-tools/tickprocessor: PASS, SKIP if ($arch == android_arm || $arch == android_ia32)
-
-##############################################################################
-# Long running test that reproduces memory leak and should be run manually.
-regress/regress-2073: SKIP
-
-##############################################################################
-[ $arch == arm || $arch == android_arm ]
-
-# Slow tests which times out in debug mode.
-try: PASS, SKIP if $mode == debug
-debug-scripts-request: PASS, SKIP if $mode == debug
-array-constructor: PASS, SKIP if $mode == debug
-regress/regress-1122: PASS, SKIP if ($mode == debug && $arch == android_arm)
-
-# Flaky test that can hit compilation-time stack overflow in debug mode.
-unicode-test: PASS, (PASS || FAIL) if $mode == debug
-
-# Times out often in release mode on ARM.
-compiler/regress-stacktrace-methods: PASS, PASS || TIMEOUT if $mode == release
-array-splice: PASS || TIMEOUT
-
-# Long running test.
-string-indexof-2: PASS || TIMEOUT
-mirror-object: PASS || TIMEOUT
-
-# BUG(3251035): Timeouts in long looping crankshaft optimization
-# tests. Skipping because having them timeout takes too long on the
-# buildbot.
-compiler/alloc-number: SKIP
-compiler/array-length: SKIP
-compiler/assignment-deopt: SKIP
-compiler/deopt-args: SKIP
-compiler/inline-compare: SKIP
-compiler/inline-global-access: SKIP
-compiler/optimized-function-calls: SKIP
-compiler/pic: SKIP
-compiler/property-calls: SKIP
-compiler/recursive-deopt: SKIP
-compiler/regress-4: SKIP
-compiler/regress-funcaller: SKIP
-compiler/regress-rep-change: SKIP
-compiler/regress-arguments: SKIP
-compiler/regress-funarguments: SKIP
-compiler/regress-3249650: SKIP
-compiler/simple-deopt: SKIP
-regress/regress-490: SKIP
-regress/regress-634: SKIP
-regress/regress-create-exception: SKIP
-regress/regress-3218915: SKIP
-regress/regress-3247124: SKIP
-
-# Requires bigger stack size in the Genesis and if stack size is increased,
-# the test requires too much time to run.  However, the problem test covers
-# should be platform-independent.
-regress/regress-1132: SKIP
-
-# Stack manipulations in LiveEdit is not implemented for this arch.
-debug-liveedit-check-stack: SKIP
-debug-liveedit-stack-padding: SKIP
-debug-liveedit-restart-frame: SKIP
-debug-liveedit-double-call: SKIP
-
-# Currently always deopt on minus zero
-math-floor-of-div-minus-zero: SKIP
-
-##############################################################################
-[ $arch == mipsel ]
-
-# Slow tests which times out in debug mode.
-try: PASS, SKIP if $mode == debug
-debug-scripts-request: PASS, SKIP if $mode == debug
-array-constructor: PASS, SKIP if $mode == debug
-
-# Times out often in release mode on MIPS.
-compiler/regress-stacktrace-methods: PASS, PASS || TIMEOUT if $mode == release
-array-splice: PASS || TIMEOUT
-
-# Long running test.
-mirror-object: PASS || TIMEOUT
-string-indexof-2: PASS || TIMEOUT
-
-# BUG(3251035): Timeouts in long looping crankshaft optimization
-# tests. Skipping because having them timeout takes too long on the
-# buildbot.
-compiler/alloc-number: SKIP
-compiler/array-length: SKIP
-compiler/assignment-deopt: SKIP
-compiler/deopt-args: SKIP
-compiler/inline-compare: SKIP
-compiler/inline-global-access: SKIP
-compiler/optimized-function-calls: SKIP
-compiler/pic: SKIP
-compiler/property-calls: SKIP
-compiler/recursive-deopt: SKIP
-compiler/regress-4: SKIP
-compiler/regress-funcaller: SKIP
-compiler/regress-rep-change: SKIP
-compiler/regress-arguments: SKIP
-compiler/regress-funarguments: SKIP
-compiler/regress-3249650: SKIP
-compiler/simple-deopt: SKIP
-regress/regress-490: SKIP
-regress/regress-634: SKIP
-regress/regress-create-exception: SKIP
-regress/regress-3218915: SKIP
-regress/regress-3247124: SKIP
-
-# Requires bigger stack size in the Genesis and if stack size is increased,
-# the test requires too much time to run.  However, the problem test covers
-# should be platform-independent.
-regress/regress-1132: SKIP
-
-# Stack manipulations in LiveEdit is not implemented for this arch.
-debug-liveedit-check-stack: SKIP
-debug-liveedit-stack-padding: SKIP
-debug-liveedit-restart-frame: SKIP
-debug-liveedit-double-call: SKIP
-
-# Currently always deopt on minus zero
-math-floor-of-div-minus-zero: SKIP
+  # Currently always deopt on minus zero
+  'math-floor-of-div-minus-zero': [SKIP],
+}],  # 'arch == mipsel'
 
 ##############################################################################
 # Native Client uses the ARM simulator so will behave similarly to arm
@@ -210,46 +213,49 @@
 # TODO(bradchen): enable more tests for NaCl V8 when it stops using
 # the ARM simulator.
 ##############################################################################
-[ $arch == nacl_ia32 || $arch == nacl_x64 ]
-# There is no /tmp directory for NaCl runs
-d8-os: SKIP
+['arch == nacl_ia32 or arch == nacl_x64', {
+  # There is no /tmp directory for NaCl runs
+  'd8-os': [SKIP],
 
-# Stack manipulations in LiveEdit is not implemented for this arch.
-debug-liveedit-check-stack: SKIP
-debug-liveedit-stack-padding: SKIP
-debug-liveedit-restart-frame: SKIP
-debug-liveedit-double-call: SKIP
+  # Stack manipulations in LiveEdit is not implemented for this arch.
+  'debug-liveedit-check-stack': [SKIP],
+  'debug-liveedit-stack-padding': [SKIP],
+  'debug-liveedit-restart-frame': [SKIP],
+  'debug-liveedit-double-call': [SKIP],
 
-# This test dumps core for arm.debug, so no reason to expect it to work
-# for NaCl. The other three fuzz-natives tests seem to run fine.
-# As noted above none of them are run in the arm.debug case.
-fuzz-natives-part4: SKIP
+  # This test dumps core for arm.debug, so no reason to expect it to work
+  # for NaCl. The other three fuzz-natives tests seem to run fine.
+  # As noted above none of them are run in the arm.debug case.
+  'fuzz-natives-part4': [SKIP],
 
-# NaCl builds have problems with this test since Pepper_28.
-# V8 Issue 2786
-math-exp-precision: SKIP
+  # NaCl builds have problems with this test since Pepper_28.
+  # V8 Issue 2786
+  'math-exp-precision': [SKIP],
 
-# Requires bigger stack size in the Genesis and if stack size is increased,
-# the test requires too much time to run.  However, the problem test covers
-# should be platform-independent.
-regress/regress-1132: SKIP
+  # Requires bigger stack size in the Genesis and if stack size is increased,
+  # the test requires too much time to run.  However, the problem test covers
+  # should be platform-independent.
+  'regress/regress-1132': [SKIP],
 
-# Poor performance for NaCl V8 causes an assertion failure for this test.
-regress/regress-165637: SKIP
+  # Poor performance for NaCl V8 causes an assertion failure for this test.
+  'regress/regress-165637': [SKIP],
 
-# Skip long running test that times out in debug mode and goes OOM on NaCl.
-regress/regress-crbug-160010: SKIP
+  # Skip long running test that times out in debug mode and goes OOM on NaCl.
+  'regress/regress-crbug-160010': [SKIP],
+}],  # 'arch == nacl_ia32 or arch == nacl_x64'
 
 ##############################################################################
-[ $deopt_fuzzer == True ]
+['deopt_fuzzer == True', {
 
-# Skip tests that are not suitable for deoptimization fuzzing.
-assert-opt-and-deopt: SKIP
-never-optimize: SKIP
-regress/regress-2185-2: SKIP
-harmony/object-observe: SKIP
-readonly: SKIP
-array-feedback: SKIP
+  # Skip tests that are not suitable for deoptimization fuzzing.
+  'assert-opt-and-deopt': [SKIP],
+  'never-optimize': [SKIP],
+  'regress/regress-2185-2': [SKIP],
+  'harmony/object-observe': [SKIP],
+  'readonly': [SKIP],
+  'array-feedback': [SKIP],
 
-# Deopt every n garbage collections collides with the deopt every n times flag.
-regress/regress-2653: SKIP
+  # Deopt every n garbage collections collides with deopt every n times.
+  'regress/regress-2653': [SKIP],
+}],  # 'deopt_fuzzer == True'
+]
diff --git a/test/mjsunit/opt-elements-kind.js b/test/mjsunit/opt-elements-kind.js
index 83ad702..fe6b8b9 100644
--- a/test/mjsunit/opt-elements-kind.js
+++ b/test/mjsunit/opt-elements-kind.js
@@ -40,6 +40,11 @@
 // in this test case.  Depending on whether smi-only arrays are actually
 // enabled, this test takes the appropriate code path to check smi-only arrays.
 
+// Reset the GC stress mode to be off. Needed because AllocationMementos only
+// live for one gc, so a gc that happens in certain fragile areas of the test
+// can break assumptions.
+%SetFlags("--gc-interval=-1")
+
 support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
 
 if (support_smi_only_arrays) {
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index bf1578f..b27e991 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -42,813 +42,816 @@
 # debugging.
 # --------------------------------------------------------------------
 
-prefix mozilla
-def FAIL_OK = FAIL, OKAY
+[
+[ALWAYS, {
+  ##################### NEEDS INVESTIGATION ##############
 
-##################### NEEDS INVESTIGATION ##############
+  # BUG(2893): These tests started to fail after i18n support was turned on.
+  # Need to investigate why.
+  'ecma_3/Number/15.7.4.3-02': [PASS, FAIL],
+  'ecma_3/Date/15.9.5.5-02': [PASS, FAIL],
 
-# BUG(2893): These tests started to fail after i18n support was turned on. Need
-# to investigate why.
-ecma_3/Number/15.7.4.3-02: PASS || FAIL
-ecma_3/Date/15.9.5.5-02: PASS || FAIL
+  ##################### SKIPPED TESTS #####################
 
-##################### SKIPPED TESTS #####################
+  # This test checks that we behave properly in an out-of-memory
+  # situation.  The test fails in V8 with an exception and takes a long
+  # time to do so.
+  'js1_5/Regress/regress-271716-n': [SKIP],
 
-# This test checks that we behave properly in an out-of-memory
-# situation.  The test fails in V8 with an exception and takes a long
-# time to do so.
-js1_5/Regress/regress-271716-n: SKIP
+  # BUG(960): This test has an insane amount of output when it times out,
+  # messing up ability to see other failures on the waterfall.
+  'js1_5/extensions/regress-342960': [SKIP],
 
-# BUG(960): This test has an insane amount of output when it times out,
-# messing up ability to see other failures on the waterfall.
-js1_5/extensions/regress-342960: SKIP
+  # This test uses a unitialized variable. A Bug has been filed:
+  # https://bugzilla.mozilla.org/show_bug.cgi?id=575575
+  'js1_5/Array/regress-465980-02': [SKIP],
 
-# This test uses a unitialized variable. A Bug has been filed:
-# https://bugzilla.mozilla.org/show_bug.cgi?id=575575
-js1_5/Array/regress-465980-02: SKIP
+  # These tests are simply wrong (i.e., they do not test what they intend
+  # to test).
+  # In particular, these two compare numbers to NaN with != in the current
+  # version of the Mozilla tests. This is *fixed* in a later version.
+  # The tests should be re-enabled when switching to a new version.
+  'ecma_3/Date/15.9.3.2-1': [SKIP],
+  'js1_2/function/Number': [SKIP],
 
-# These tests are simply wrong (i.e., they do not test what they intend
-# to test).
-# In particular, these two compare numbers to NaN with != in the current
-# version of the Mozilla tests. This is *fixed* in a later version.
-# The tests should be re-enabled when switching to a new version.
-ecma_3/Date/15.9.3.2-1: SKIP
-js1_2/function/Number: SKIP
+  # TODO(2018): Temporarily allow timeout in debug mode.
+  'js1_5/GC/regress-203278-2': [PASS, ['mode == debug', TIMEOUT, FAIL]],
 
-# TODO(2018): Temporarily allow timeout in debug mode.
-js1_5/GC/regress-203278-2: PASS || (TIMEOUT || FAIL) if $mode == debug
+  ##################### SLOW TESTS #####################
 
-##################### SLOW TESTS #####################
+  # This takes a long time to run (~100 seconds). It should only be run
+  # by the really patient.
+  'js1_5/GC/regress-324278': [SLOW],
 
-# This takes a long time to run (~100 seconds). It should only be run
-# by the really patient.
-js1_5/GC/regress-324278: SLOW
+  # This takes a long time to run because our indexOf operation is
+  # pretty slow - it causes a lot of GCs; see issue
+  # #926379. We could consider marking this SKIP because it takes a
+  # while to run to completion.
+  'js1_5/GC/regress-338653': [SLOW],
 
-# This takes a long time to run because our indexOf operation is
-# pretty slow - it causes a lot of GCs; see issue
-# #926379. We could consider marking this SKIP because it takes a
-# while to run to completion.
-js1_5/GC/regress-338653: SLOW
+  # This test is designed to run until it runs out of memory. This takes
+  # a very long time because it builds strings character by character
+  # and compiles a lot of regular expressions. We could consider marking
+  # this SKIP because it takes a while to run to completion.
+  'js1_5/GC/regress-346794': [SLOW],
 
-# This test is designed to run until it runs out of memory. This takes
-# a very long time because it builds strings character by character
-# and compiles a lot of regular expressions. We could consider marking
-# this SKIP because it takes a while to run to completion.
-js1_5/GC/regress-346794: SLOW
+  # Runs out of memory while trying to build huge string of 'x'
+  # characters. This takes a long time to run (~32 seconds).
+  'js1_5/GC/regress-348532': [SLOW],
 
-# Runs out of memory while trying to build huge string of 'x'
-# characters. This takes a long time to run (~32 seconds).
-js1_5/GC/regress-348532: SLOW
 
+  ##################### FLAKY TESTS #####################
 
-##################### FLAKY TESTS #####################
+  # These tests time out in debug mode but pass in product mode
+  'js1_5/Regress/regress-360969-03': [PASS, ['mode == debug', TIMEOUT]],
+  'js1_5/Regress/regress-360969-04': [PASS, ['mode == debug', TIMEOUT]],
+  'js1_5/Regress/regress-360969-05': [PASS, ['mode == debug', TIMEOUT]],
+  'js1_5/Regress/regress-360969-06': [PASS, ['mode == debug', TIMEOUT]],
+  'js1_5/extensions/regress-365527': [PASS, ['mode == debug', TIMEOUT]],
 
-# These tests time out in debug mode but pass in product mode
-js1_5/Regress/regress-360969-03: PASS || TIMEOUT if $mode == debug
-js1_5/Regress/regress-360969-04: PASS || TIMEOUT if $mode == debug
-js1_5/Regress/regress-360969-05: PASS || TIMEOUT if $mode == debug
-js1_5/Regress/regress-360969-06: PASS || TIMEOUT if $mode == debug
-js1_5/extensions/regress-365527: PASS || TIMEOUT if $mode == debug
+  'js1_5/Regress/regress-280769-3': [PASS, ['mode == debug', FAIL]],
+  'js1_5/Regress/regress-203278-1': [PASS, ['mode == debug', FAIL]],
+  'js1_5/Regress/regress-244470': [PASS, ['mode == debug', FAIL]],
+  'ecma_3/RegExp/regress-209067': [PASS, ['mode == debug', FAIL]],
+  'js1_5/GC/regress-278725': [PASS, ['mode == debug', FAIL]],
+  # http://b/issue?id=1206983
+  'js1_5/Regress/regress-367561-03': [PASS, ['mode == debug', FAIL]],
+  'ecma/Date/15.9.5.10-2': [PASS, FAIL, ['mode == debug', TIMEOUT]],
 
-js1_5/Regress/regress-280769-3: PASS || FAIL if $mode == debug
-js1_5/Regress/regress-203278-1: PASS || FAIL if $mode == debug
-js1_5/Regress/regress-244470: PASS || FAIL if $mode == debug
-ecma_3/RegExp/regress-209067: PASS || FAIL if $mode == debug
-js1_5/GC/regress-278725: PASS || FAIL if $mode == debug
-# http://b/issue?id=1206983
-js1_5/Regress/regress-367561-03: PASS || FAIL if $mode == debug
-ecma/Date/15.9.5.10-2: PASS || (FAIL || TIMEOUT if $mode == debug)
+  # These tests create two Date objects just after each other and
+  # expects them to match.  Sometimes this happens on the border
+  # between one second and the next.
+  'ecma/Date/15.9.2.1': [PASS, FAIL],
+  'ecma/Date/15.9.2.2-1': [PASS, FAIL],
+  'ecma/Date/15.9.2.2-2': [PASS, FAIL],
+  'ecma/Date/15.9.2.2-3': [PASS, FAIL],
+  'ecma/Date/15.9.2.2-4': [PASS, FAIL],
+  'ecma/Date/15.9.2.2-5': [PASS, FAIL],
+  'ecma/Date/15.9.2.2-6': [PASS, FAIL],
 
-# These tests create two Date objects just after each other and
-# expects them to match.  Sometimes this happens on the border
-# between one second and the next.
-ecma/Date/15.9.2.1: PASS || FAIL
-ecma/Date/15.9.2.2-1: PASS || FAIL
-ecma/Date/15.9.2.2-2: PASS || FAIL
-ecma/Date/15.9.2.2-3: PASS || FAIL
-ecma/Date/15.9.2.2-4: PASS || FAIL
-ecma/Date/15.9.2.2-5: PASS || FAIL
-ecma/Date/15.9.2.2-6: PASS || FAIL
+  # 1026139: These date tests fail on arm and mips
+  'ecma/Date/15.9.5.29-1': [PASS, ['arch == arm or arch == mipsel', FAIL]],
+  'ecma/Date/15.9.5.28-1': [PASS, ['arch == arm or arch == mipsel', FAIL]],
 
-# 1026139: These date tests fail on arm and mips
-ecma/Date/15.9.5.29-1: PASS || FAIL if ($arch == arm || $arch == mipsel)
-ecma/Date/15.9.5.28-1: PASS || FAIL if ($arch == arm || $arch == mipsel)
+  # 1050186: Arm/MIPS vm is broken; probably unrelated to dates
+  'ecma/Array/15.4.4.5-3': [PASS, ['arch == arm or arch == mipsel', FAIL]],
+  'ecma/Date/15.9.5.22-2': [PASS, ['arch == arm or arch == mipsel', FAIL]],
 
-# 1050186: Arm/MIPS vm is broken; probably unrelated to dates
-ecma/Array/15.4.4.5-3: PASS || FAIL if ($arch == arm || $arch == mipsel)
-ecma/Date/15.9.5.22-2: PASS || FAIL if ($arch == arm || $arch == mipsel)
+  # Flaky test that fails due to what appears to be a bug in the test.
+  # Occurs depending on current time
+  'ecma/Date/15.9.5.8': [PASS, FAIL],
 
-# Flaky test that fails due to what appears to be a bug in the test.
-# Occurs depending on current time
-ecma/Date/15.9.5.8: PASS || FAIL
+  # Severely brain-damaged test. Access to local variables must not
+  # be more than 2.5 times faster than access to global variables? WTF?
+  'js1_5/Regress/regress-169559': [PASS, FAIL],
 
-# Severely brain-damaged test. Access to local variables must not
-# be more than 2.5 times faster than access to global variables? WTF?
-js1_5/Regress/regress-169559: PASS || FAIL
 
+  # Test that rely on specific timezone (not working in Denmark).
+  'js1_5/Regress/regress-58116': [PASS, FAIL],
 
-# Test that rely on specific timezone (not working in Denmark).
-js1_5/Regress/regress-58116: PASS || FAIL
 
+  # Flaky random() test. Tests the distribution of calls to Math.random().
+  'js1_5/Regress/regress-211590': [PASS, FAIL],
 
-# Flaky random() test. Tests the distribution of calls to Math.random().
-js1_5/Regress/regress-211590: PASS || FAIL
 
+  # Flaky tests; expect BigO-order computations to yield 1, but the code
+  # cannot handle outliers. See bug #925864.
+  'ecma_3/RegExp/regress-311414': [PASS, FAIL],
+  'ecma_3/RegExp/regress-289669': [PASS, FAIL],
+  'js1_5/String/regress-314890': [PASS, FAIL],
+  'js1_5/String/regress-56940-01': [PASS, FAIL],
+  'js1_5/String/regress-56940-02': [PASS, FAIL],
+  'js1_5/String/regress-157334-01': [PASS, FAIL],
+  'js1_5/String/regress-322772': [PASS, FAIL],
+  'js1_5/Array/regress-99120-01': [PASS, FAIL],
+  'js1_5/Array/regress-99120-02': [PASS, FAIL],
+  'js1_5/Regress/regress-347306-01': [PASS, FAIL],
+  'js1_5/Regress/regress-416628': [PASS, FAIL, ['mode == debug', TIMEOUT]],
 
-# Flaky tests; expect BigO-order computations to yield 1, but the code
-# cannot handle outliers. See bug #925864.
-ecma_3/RegExp/regress-311414: PASS || FAIL
-ecma_3/RegExp/regress-289669: PASS || FAIL
-js1_5/String/regress-314890: PASS || FAIL
-js1_5/String/regress-56940-01: PASS || FAIL
-js1_5/String/regress-56940-02: PASS || FAIL
-js1_5/String/regress-157334-01: PASS || FAIL
-js1_5/String/regress-322772: PASS || FAIL
-js1_5/Array/regress-99120-01: PASS || FAIL
-js1_5/Array/regress-99120-02: PASS || FAIL
-js1_5/Regress/regress-347306-01: PASS || FAIL
-js1_5/Regress/regress-416628: PASS || FAIL || TIMEOUT if $mode == debug
 
+  # The following two tests assume that daylight savings time starts first
+  # Sunday in April. This is not true when executing the tests outside
+  # California! In Denmark the adjustment starts one week earlier.
+  # Tests based on shell that use dates in this gap are flaky.
+  'ecma/Date/15.9.5.10-1': [PASS, FAIL],
+  'ecma/Date/15.9.5.12-1': [PASS, FAIL],
+  'ecma/Date/15.9.5.14': [PASS, FAIL],
+  'ecma/Date/15.9.5.34-1': [PASS, FAIL],
 
-# The following two tests assume that daylight savings time starts first Sunday
-# in April. This is not true when executing the tests outside California!
-# In Denmark the adjustment starts one week earlier!.
-# Tests based on shell that use dates in this gap are flaky.
-ecma/Date/15.9.5.10-1: PASS || FAIL
-ecma/Date/15.9.5.12-1: PASS || FAIL
-ecma/Date/15.9.5.14: PASS || FAIL
-ecma/Date/15.9.5.34-1: PASS || FAIL
 
+  # These tests sometimes pass (in particular on Windows). They build up
+  # a lot of stuff on the stack, which normally causes a stack overflow,
+  # but sometimes it makes it through?
+  'js1_5/Regress/regress-98901': [PASS, FAIL],
 
-# These tests sometimes pass (in particular on Windows). They build up
-# a lot of stuff on the stack, which normally causes a stack overflow,
-# but sometimes it makes it through?
-js1_5/Regress/regress-98901: PASS || FAIL
 
+  # Tests that sorting arrays of ints is less than 3 times as fast
+  # as sorting arrays of strings.
+  'js1_5/extensions/regress-371636': [PASS, FAIL, ['mode == debug', TIMEOUT]],
 
-# Tests that sorting arrays of ints is less than 3 times as fast
-# as sorting arrays of strings.
-js1_5/extensions/regress-371636: PASS || FAIL || TIMEOUT if $mode == debug
 
+  # Tests depend on GC timings. Inherently flaky.
+  'js1_5/GC/regress-383269-01': [PASS, FAIL],
+  'js1_5/GC/regress-383269-02': [PASS, FAIL],
+  'js1_5/Regress/regress-404755': [PASS, FAIL],
 
-# Tests depend on GC timings. Inherently flaky.
-js1_5/GC/regress-383269-01: PASS || FAIL
-js1_5/GC/regress-383269-02: PASS || FAIL
-js1_5/Regress/regress-404755: PASS || FAIL
 
+  # Test that depends on timer resolution. Fails every now and then
+  # if we're unlucky enough to get a context switch at a bad time.
+  'js1_5/extensions/regress-363258': [PASS, FAIL],
 
-# Test that depends on timer resolution. Fails every now and then
-# if we're unlucky enough to get a context switch at a bad time.
-js1_5/extensions/regress-363258: PASS || FAIL
 
+  # Test that assumes specific runtime for a regexp, flaky in debug mode.
+  'ecma_3/RegExp/regress-85721': [PASS, ['mode == debug', FAIL]],
 
-# Test that assumes specific runtime for a regexp, flaky in debug mode.
-ecma_3/RegExp/regress-85721: PASS || FAIL if $mode == debug
 
+  # Test that assumes specific execution time, flaky in debug mode.
+  'js1_5/Array/regress-101964': [PASS, ['mode == debug', FAIL]],
 
-# Test that assumes specific execution time, flaky in debug mode.
-js1_5/Array/regress-101964: PASS || FAIL if $mode == debug
 
+  ##################### INCOMPATIBLE TESTS #####################
 
-##################### INCOMPATIBLE TESTS #####################
+  # This section is for tests that fail in both V8 and JSC.  Thus they
+  # have been determined to be incompatible between Mozilla and V8/JSC.
 
-# This section is for tests that fail in both V8 and JSC.  Thus they
-# have been determined to be incompatible between Mozilla and V8/JSC.
+  # toPrecision argument restricted to range 1..21 in JSC/V8 and ECMA-262
+  'js1_5/Regress/regress-452346': [FAIL_OK],
 
-# toPrecision argument restricted to range 1..21 in JSC/V8 and ECMA-262
-js1_5/Regress/regress-452346: FAIL_OK
+  # Fail because it calls builtins as functions and do not expect the
+  # builtin to have undefined as the receiver.
+  'ecma/String/15.5.4.6-2': [FAIL_OK],
 
-# Fail because it calls builtins as functions and do not expect the
-# builtin to have undefined as the receiver.
-ecma/String/15.5.4.6-2: FAIL_OK
+  # Fail because it expects String.prototype.split to distinguish whether
+  # separator was undefined or not passed at all.
+  'ecma/String/15.5.4.8-2': [FAIL_OK],
 
-# Fail because it expects String.prototype.split to distinguish whether
-# separator was undefined or not passed at all.
-ecma/String/15.5.4.8-2: FAIL_OK
+  # Fail because of toLowerCase and toUpperCase conversion.
+  'ecma/String/15.5.4.11-2': [FAIL_OK],
+  'ecma/String/15.5.4.11-5': [FAIL_OK],
+  'ecma/String/15.5.4.12-1': [FAIL_OK],
+  'ecma/String/15.5.4.12-4': [FAIL_OK],
 
-# Fail because of toLowerCase and toUpperCase conversion.
-ecma/String/15.5.4.11-2: FAIL_OK
-ecma/String/15.5.4.11-5: FAIL_OK
-ecma/String/15.5.4.12-1: FAIL_OK
-ecma/String/15.5.4.12-4: FAIL_OK
+  # This test uses an older version of the unicode standard that fails
+  # us because we correctly convert the armenian small ligature ech-yiwn
+  # to the two upper-case characters ECH and YIWN, whereas the older
+  # unicode version converts it to itself.
+  'ecma/String/15.5.4.12-5': [FAIL_OK],
 
-# This test uses an older version of the unicode standard that fails
-# us because we correctly convert the armenian small ligature ech-yiwn
-# to the two upper-case characters ECH and YIWN, whereas the older
-# unicode version converts it to itself.
-ecma/String/15.5.4.12-5: FAIL_OK
+  # Creates a linked list of arrays until we run out of memory or timeout.
+  'js1_5/Regress/regress-312588': [SKIP],
 
-# Creates a linked list of arrays until we run out of memory or timeout.
-js1_5/Regress/regress-312588: SKIP
 
+  # Runs out of memory because it compiles huge functions.
+  'js1_5/Function/regress-338001': [FAIL_OK],
+  'js1_5/Function/regress-338121-01': [FAIL_OK],
+  'js1_5/Function/regress-338121-02': [FAIL_OK],
+  'js1_5/Function/regress-338121-03': [FAIL_OK],
 
-# Runs out of memory because it compiles huge functions.
-js1_5/Function/regress-338001: FAIL_OK
-js1_5/Function/regress-338121-01: FAIL_OK
-js1_5/Function/regress-338121-02: FAIL_OK
-js1_5/Function/regress-338121-03: FAIL_OK
+  # Expectes 'prototype' property of functions to be enumerable.
+  'js1_5/Function/10.1.6-01': [FAIL_OK],
 
-# Expectes 'prototype' property of functions to be enumerable.
-js1_5/Function/10.1.6-01: FAIL_OK
+  #:=== RegExp:===
+  # We don't match the syntax error message of Mozilla for invalid
+  # RegExp flags.
+  'ecma_3/RegExp/15.10.4.1-6': [FAIL_OK],
 
-#:=== RegExp:===
-# We don't match the syntax error message of Mozilla for invalid
-# RegExp flags.
-ecma_3/RegExp/15.10.4.1-6: FAIL_OK
-
-# PCRE doesn't allow subpattern nesting deeper than 200, this tests
-# depth 500.  JSC detects the case, and return null from the match,
-# and passes this test (the test doesn't check for a correct return
-# value).
-ecma_3/RegExp/regress-119909: PASS || FAIL_OK
+  # PCRE doesn't allow subpattern nesting deeper than 200, this tests
+  # depth 500.  JSC detects the case, and return null from the match,
+  # and passes this test (the test doesn't check for a correct return
+  # value).
+  'ecma_3/RegExp/regress-119909': [PASS, FAIL_OK],
 
 
-# Difference in the way capturing subpatterns work.  In JS, when the
-# 'minimum repeat count' is reached, the empty string must not match.
-# In this case, we are similar but not identical to JSC.  Hard to
-# support the JS behavior with PCRE, so maybe emulate JSC?
-ecma_3/RegExp/regress-209919: PASS || FAIL_OK
-js1_5/extensions/regress-459606: PASS || FAIL_OK
+  # Difference in the way capturing subpatterns work.  In JS, when the
+  # 'minimum repeat count' is reached, the empty string must not match.
+  # In this case, we are similar but not identical to JSC.  Hard to
+  # support the JS behavior with PCRE, so maybe emulate JSC?
+  'ecma_3/RegExp/regress-209919': [PASS, FAIL_OK],
+  'js1_5/extensions/regress-459606': [PASS, FAIL_OK],
 
 
-# PCRE's match limit is reached.  SpiderMonkey hangs on the first one,
-# JSC returns true somehow.  Maybe they up the match limit?  There is
-# an open V8 bug 676063 about this.
-ecma_3/RegExp/regress-330684: TIMEOUT
+  # PCRE's match limit is reached.  SpiderMonkey hangs on the first one,
+  # JSC returns true somehow.  Maybe they up the match limit?  There is
+  # an open V8 bug 676063 about this.
+  'ecma_3/RegExp/regress-330684': [TIMEOUT],
 
 
-# This test contains a regexp that runs exponentially long.  Spidermonkey
-# standalone will hang, though apparently inside Firefox it will trigger a
-# long-running-script timeout.  JSCRE passes by hitting the matchLimit and
-# just pretending that an exhaustive search found no match.
-ecma_3/RegExp/regress-307456: PASS || TIMEOUT
+  # This test contains a regexp that runs exponentially long.  Spidermonkey
+  # standalone will hang, though apparently inside Firefox it will trigger a
+  # long-running-script timeout.  JSCRE passes by hitting the matchLimit and
+  # just pretending that an exhaustive search found no match.
+  'ecma_3/RegExp/regress-307456': [PASS, TIMEOUT],
 
 
-# We do not detect overflow in bounds for back references and {}
-# quantifiers.  Might fix by parsing numbers differently?
-js1_5/Regress/regress-230216-2: FAIL_OK
+  # We do not detect overflow in bounds for back references and {}
+  # quantifiers.  Might fix by parsing numbers differently?
+  'js1_5/Regress/regress-230216-2': [FAIL_OK],
 
 
-# Regexp too long for PCRE.
-js1_5/Regress/regress-280769: PASS || FAIL
-js1_5/Regress/regress-280769-1: PASS || FAIL
-js1_5/Regress/regress-280769-2: PASS || FAIL
-js1_5/Regress/regress-280769-4: PASS || FAIL
-js1_5/Regress/regress-280769-5: PASS || FAIL
+  # Regexp too long for PCRE.
+  'js1_5/Regress/regress-280769': [PASS, FAIL],
+  'js1_5/Regress/regress-280769-1': [PASS, FAIL],
+  'js1_5/Regress/regress-280769-2': [PASS, FAIL],
+  'js1_5/Regress/regress-280769-4': [PASS, FAIL],
+  'js1_5/Regress/regress-280769-5': [PASS, FAIL],
 
 
-# We do not support static RegExp.multiline - should we?.
-js1_2/regexp/RegExp_multiline: FAIL_OK
-js1_2/regexp/RegExp_multiline_as_array: FAIL_OK
-js1_2/regexp/beginLine: FAIL_OK
-js1_2/regexp/endLine: FAIL_OK
+  # We do not support static RegExp.multiline - should we?.
+  'js1_2/regexp/RegExp_multiline': [FAIL_OK],
+  'js1_2/regexp/RegExp_multiline_as_array': [FAIL_OK],
+  'js1_2/regexp/beginLine': [FAIL_OK],
+  'js1_2/regexp/endLine': [FAIL_OK],
 
-# We no longer let calls to test and exec with no argument implicitly
-# use the previous input.
-js1_2/regexp/RegExp_input: FAIL_OK
-js1_2/regexp/RegExp_input_as_array: FAIL_OK
+  # We no longer let calls to test and exec with no argument implicitly
+  # use the previous input.
+  'js1_2/regexp/RegExp_input': [FAIL_OK],
+  'js1_2/regexp/RegExp_input_as_array': [FAIL_OK],
 
 
-# To be compatible with safari typeof a regexp yields 'function';
-# in firefox it yields 'object'.
-js1_2/function/regexparg-1: FAIL_OK
+  # To be compatible with safari typeof a regexp yields 'function';
+  # in firefox it yields 'object'.
+  'js1_2/function/regexparg-1': [FAIL_OK],
 
 
-# Date trouble?
-js1_5/Date/regress-301738-02: FAIL_OK
+  # Date trouble?
+  'js1_5/Date/regress-301738-02': [FAIL_OK],
 
 
-# This test fails for all browsers on in the CET timezone.
-ecma/Date/15.9.5.35-1: PASS || FAIL_OK
+  # This test fails for all browsers on in the CET timezone.
+  'ecma/Date/15.9.5.35-1': [PASS, FAIL_OK],
 
 
-# Spidermonkey allows stuff in parenthesis directly after the minutes
-# in a date.  JSC does not, so we don't either.
-js1_5/Date/regress-309925-02: FAIL_OK
+  # Spidermonkey allows stuff in parenthesis directly after the minutes
+  # in a date.  JSC does not, so we don't either.
+  'js1_5/Date/regress-309925-02': [FAIL_OK],
 
 
-# Print string after deleting array element?
-js1_5/Expressions/regress-96526-delelem: FAIL_OK
+  # Print string after deleting array element?
+  'js1_5/Expressions/regress-96526-delelem': [FAIL_OK],
 
 
-# Stack overflows should be InternalError: too much recursion?
-js1_5/Regress/regress-234389: FAIL_OK
+  # Stack overflows should be InternalError: too much recursion?
+  'js1_5/Regress/regress-234389': [FAIL_OK],
 
 
-# This may very well be a bogus test. I'm not sure yet.
-js1_5/Regress/regress-320119: FAIL_OK
+  # This may very well be a bogus test. I'm not sure yet.
+  'js1_5/Regress/regress-320119': [FAIL_OK],
 
 
-# No support for toSource().
-js1_5/Regress/regress-248444: FAIL_OK
-js1_5/Regress/regress-313967-01: FAIL_OK
-js1_5/Regress/regress-313967-02: FAIL_OK
+  # No support for toSource().
+  'js1_5/Regress/regress-248444': [FAIL_OK],
+  'js1_5/Regress/regress-313967-01': [FAIL_OK],
+  'js1_5/Regress/regress-313967-02': [FAIL_OK],
 
-# This fails because we don't have stack space for Function.prototype.apply
-# with very large numbers of arguments.  The test uses 2^24 arguments.
-js1_5/Array/regress-350256-03: FAIL_OK
+  # This fails because we don't have stack space for Function.prototype.apply
+  # with very large numbers of arguments.  The test uses 2^24 arguments.
+  'js1_5/Array/regress-350256-03': [FAIL_OK],
 
 
-# Extra arguments not handled properly in String.prototype.match
-js1_5/Regress/regress-179524: FAIL_OK
+  # Extra arguments not handled properly in String.prototype.match
+  'js1_5/Regress/regress-179524': [FAIL_OK],
 
 
-# Uncategorized failures. Please help categorize (or fix) these failures.
-js1_5/Regress/regress-172699: FAIL_OK
+  # Uncategorized failures. Please help categorize (or fix) these failures.
+  'js1_5/Regress/regress-172699': [FAIL_OK],
 
 
-# Assumes that the prototype of a function is enumerable. Non-ECMA,
-# see section 15.3.3.1, page 86.
-ecma/GlobalObject/15.1.2.2-1: FAIL_OK
-ecma/GlobalObject/15.1.2.3-1: FAIL_OK
-ecma/GlobalObject/15.1.2.4: FAIL_OK
-ecma/GlobalObject/15.1.2.5-1: FAIL_OK
-ecma/GlobalObject/15.1.2.6: FAIL_OK
-ecma/GlobalObject/15.1.2.7: FAIL_OK
+  # Assumes that the prototype of a function is enumerable. Non-ECMA,
+  # see section 15.3.3.1, page 86.
+  'ecma/GlobalObject/15.1.2.2-1': [FAIL_OK],
+  'ecma/GlobalObject/15.1.2.3-1': [FAIL_OK],
+  'ecma/GlobalObject/15.1.2.4': [FAIL_OK],
+  'ecma/GlobalObject/15.1.2.5-1': [FAIL_OK],
+  'ecma/GlobalObject/15.1.2.6': [FAIL_OK],
+  'ecma/GlobalObject/15.1.2.7': [FAIL_OK],
 
 
-# Leading zero no longer signal octal numbers (ECMA-262 Annex E 15.1.2.2).
-ecma/GlobalObject/15.1.2.2-2: FAIL_OK
+  # Leading zero no longer signal octal numbers (ECMA-262 Annex E 15.1.2.2).
+  'ecma/GlobalObject/15.1.2.2-2': [FAIL_OK],
 
 
-# Tests that rely on specific details of function decompilation or
-# print strings for errors. Non-ECMA behavior.
-js1_2/function/tostring-2: FAIL_OK
-js1_2/Objects/toString-001: FAIL_OK
-js1_5/LexicalConventions/regress-469940: FAIL_OK
-js1_5/Exceptions/regress-332472: FAIL_OK
-js1_5/Regress/regress-173067: FAIL_OK
-js1_5/Regress/regress-355556: FAIL_OK
-js1_5/Regress/regress-328664: FAIL_OK
-js1_5/Regress/regress-252892: FAIL_OK
-js1_5/Regress/regress-352208: FAIL_OK
-ecma_3/Array/15.4.5.1-01: FAIL_OK
-ecma_3/Array/regress-387501: FAIL_OK
-ecma_3/LexicalConventions/7.9.1: FAIL_OK
-ecma_3/RegExp/regress-375711: FAIL_OK
-ecma_3/Unicode/regress-352044-01: FAIL_OK
-ecma_3/extensions/regress-274152: FAIL_OK
-js1_5/Regress/regress-372364: FAIL_OK
-js1_5/Regress/regress-420919: FAIL_OK
-js1_5/Regress/regress-422348: FAIL_OK
-js1_5/Regress/regress-410852: FAIL_OK
-ecma_3/RegExp/regress-375715-04: FAIL_OK
-js1_5/decompilation/regress-456964-01: FAIL_OK
-js1_5/decompilation/regress-437288-02: FAIL_OK
-js1_5/decompilation/regress-457824: FAIL_OK
-js1_5/decompilation/regress-460116-01: FAIL_OK
-js1_5/decompilation/regress-460116-02: FAIL_OK
-js1_5/decompilation/regress-460501: FAIL_OK
-js1_5/decompilation/regress-460116-03: FAIL_OK
-js1_5/decompilation/regress-461110: FAIL_OK
+  # Tests that rely on specific details of function decompilation or
+  # print strings for errors. Non-ECMA behavior.
+  'js1_2/function/tostring-2': [FAIL_OK],
+  'js1_2/Objects/toString-001': [FAIL_OK],
+  'js1_5/LexicalConventions/regress-469940': [FAIL_OK],
+  'js1_5/Exceptions/regress-332472': [FAIL_OK],
+  'js1_5/Regress/regress-173067': [FAIL_OK],
+  'js1_5/Regress/regress-355556': [FAIL_OK],
+  'js1_5/Regress/regress-328664': [FAIL_OK],
+  'js1_5/Regress/regress-252892': [FAIL_OK],
+  'js1_5/Regress/regress-352208': [FAIL_OK],
+  'ecma_3/Array/15.4.5.1-01': [FAIL_OK],
+  'ecma_3/Array/regress-387501': [FAIL_OK],
+  'ecma_3/LexicalConventions/7.9.1': [FAIL_OK],
+  'ecma_3/RegExp/regress-375711': [FAIL_OK],
+  'ecma_3/Unicode/regress-352044-01': [FAIL_OK],
+  'ecma_3/extensions/regress-274152': [FAIL_OK],
+  'js1_5/Regress/regress-372364': [FAIL_OK],
+  'js1_5/Regress/regress-420919': [FAIL_OK],
+  'js1_5/Regress/regress-422348': [FAIL_OK],
+  'js1_5/Regress/regress-410852': [FAIL_OK],
+  'ecma_3/RegExp/regress-375715-04': [FAIL_OK],
+  'js1_5/decompilation/regress-456964-01': [FAIL_OK],
+  'js1_5/decompilation/regress-437288-02': [FAIL_OK],
+  'js1_5/decompilation/regress-457824': [FAIL_OK],
+  'js1_5/decompilation/regress-460116-01': [FAIL_OK],
+  'js1_5/decompilation/regress-460116-02': [FAIL_OK],
+  'js1_5/decompilation/regress-460501': [FAIL_OK],
+  'js1_5/decompilation/regress-460116-03': [FAIL_OK],
+  'js1_5/decompilation/regress-461110': [FAIL_OK],
 
 
-# Tests that use uneval.  Non-ECMA.
-js1_5/GC/regress-418128: FAIL_OK
-js1_5/extensions/regress-465276: FAIL_OK
-js1_5/Error/regress-465377: FAIL_OK
+  # Tests that use uneval.  Non-ECMA.
+  'js1_5/GC/regress-418128': [FAIL_OK],
+  'js1_5/extensions/regress-465276': [FAIL_OK],
+  'js1_5/Error/regress-465377': [FAIL_OK],
 
-# Tests that use the watch method.  Non-ECMA.
-js1_5/extensions/regress-435345-01: FAIL_OK
-js1_5/extensions/regress-455413: FAIL_OK
+  # Tests that use the watch method.  Non-ECMA.
+  'js1_5/extensions/regress-435345-01': [FAIL_OK],
+  'js1_5/extensions/regress-455413': [FAIL_OK],
 
 
-# Uses Mozilla-specific QName, XML, XMLList and Iterator.
-js1_5/Regress/regress-407323: FAIL_OK
-js1_5/Regress/regress-407957: FAIL_OK
+  # Uses Mozilla-specific QName, XML, XMLList and Iterator.
+  'js1_5/Regress/regress-407323': [FAIL_OK],
+  'js1_5/Regress/regress-407957': [FAIL_OK],
 
 
-# Relies on JavaScript 1.2 / 1.3 deprecated features.
-js1_2/function/String: FAIL_OK
-js1_2/operator/equality: FAIL_OK
-js1_2/version120/boolean-001: FAIL_OK
-js1_2/String/concat: FAIL_OK
-js1_2/function/Function_object: FAIL_OK
-js1_2/function/tostring-1: FAIL_OK
-js1_2/version120/regress-99663: FAIL_OK
-js1_2/regexp/RegExp_lastIndex: FAIL_OK
-js1_2/regexp/string_split: FAIL_OK
+  # Relies on JavaScript 1.2 / 1.3 deprecated features.
+  'js1_2/function/String': [FAIL_OK],
+  'js1_2/operator/equality': [FAIL_OK],
+  'js1_2/version120/boolean-001': [FAIL_OK],
+  'js1_2/String/concat': [FAIL_OK],
+  'js1_2/function/Function_object': [FAIL_OK],
+  'js1_2/function/tostring-1': [FAIL_OK],
+  'js1_2/version120/regress-99663': [FAIL_OK],
+  'js1_2/regexp/RegExp_lastIndex': [FAIL_OK],
+  'js1_2/regexp/string_split': [FAIL_OK],
 
 
-# RegExps are not callable.
-js1_2/regexp/simple_form: FAIL_OK
-js1_2/regexp/regress-6359: FAIL_OK
-js1_2/regexp/regress-9141: FAIL_OK
-js1_5/Regress/regress-224956: FAIL_OK
-js1_5/Regress/regress-325925: FAIL_OK
-ecma_2/RegExp/regress-001: FAIL_OK
+  # RegExps are not callable.
+  'js1_2/regexp/simple_form': [FAIL_OK],
+  'js1_2/regexp/regress-6359': [FAIL_OK],
+  'js1_2/regexp/regress-9141': [FAIL_OK],
+  'js1_5/Regress/regress-224956': [FAIL_OK],
+  'js1_5/Regress/regress-325925': [FAIL_OK],
+  'ecma_2/RegExp/regress-001': [FAIL_OK],
 
-# We do not check for bad surrogate pairs when quoting strings.
-js1_5/Regress/regress-315974: FAIL_OK
+  # We do not check for bad surrogate pairs when quoting strings.
+  'js1_5/Regress/regress-315974': [FAIL_OK],
 
 
-# Use unsupported "watch".
-js1_5/Regress/regress-213482: FAIL_OK
-js1_5/Regress/regress-240577: FAIL_OK
-js1_5/Regress/regress-355344: FAIL_OK
-js1_5/Object/regress-362872-01: FAIL_OK
-js1_5/Object/regress-362872-02: FAIL_OK
-js1_5/Regress/regress-361467: FAIL_OK
-js1_5/Regress/regress-385393-06: FAIL_OK
-js1_5/Regress/regress-506567: FAIL_OK
+  # Use unsupported "watch".
+  'js1_5/Regress/regress-213482': [FAIL_OK],
+  'js1_5/Regress/regress-240577': [FAIL_OK],
+  'js1_5/Regress/regress-355344': [FAIL_OK],
+  'js1_5/Object/regress-362872-01': [FAIL_OK],
+  'js1_5/Object/regress-362872-02': [FAIL_OK],
+  'js1_5/Regress/regress-361467': [FAIL_OK],
+  'js1_5/Regress/regress-385393-06': [FAIL_OK],
+  'js1_5/Regress/regress-506567': [FAIL_OK],
 
 
-# Use special Mozilla getter/setter syntax
-js1_5/Regress/regress-354924: FAIL_OK
-js1_5/Regress/regress-355341: FAIL_OK
-js1_5/GC/regress-316885-01: FAIL_OK
-js1_5/GetSet/getset-002: FAIL_OK
-js1_5/GetSet/regress-353264: FAIL_OK
-js1_5/Regress/regress-361617: FAIL_OK
-js1_5/Regress/regress-362583: FAIL_OK
-js1_5/extensions/regress-356378: FAIL_OK
-js1_5/extensions/regress-452178: FAIL_OK
+  # Use special Mozilla getter/setter syntax
+  'js1_5/Regress/regress-354924': [FAIL_OK],
+  'js1_5/Regress/regress-355341': [FAIL_OK],
+  'js1_5/GC/regress-316885-01': [FAIL_OK],
+  'js1_5/GetSet/getset-002': [FAIL_OK],
+  'js1_5/GetSet/regress-353264': [FAIL_OK],
+  'js1_5/Regress/regress-361617': [FAIL_OK],
+  'js1_5/Regress/regress-362583': [FAIL_OK],
+  'js1_5/extensions/regress-356378': [FAIL_OK],
+  'js1_5/extensions/regress-452178': [FAIL_OK],
 
 
-# Requires Mozilla-specific strict mode or options() function.
-ecma_3/Object/8.6.1-01: FAIL_OK
-js1_5/Exceptions/regress-315147: FAIL_OK
-js1_5/Regress/regress-106244: FAIL_OK
-js1_5/Regress/regress-317533: FAIL_OK
-js1_5/Regress/regress-323314-1: FAIL_OK
-js1_5/Regress/regress-352197: FAIL_OK
+  # Requires Mozilla-specific strict mode or options() function.
+  'ecma_3/Object/8.6.1-01': [FAIL_OK],
+  'js1_5/Exceptions/regress-315147': [FAIL_OK],
+  'js1_5/Regress/regress-106244': [FAIL_OK],
+  'js1_5/Regress/regress-317533': [FAIL_OK],
+  'js1_5/Regress/regress-323314-1': [FAIL_OK],
+  'js1_5/Regress/regress-352197': [FAIL_OK],
 
 
-# Equivalent to assert(false).
-ecma_2/RegExp/exec-001: FAIL_OK
-ecma_2/String/replace-001: FAIL_OK
+  # Equivalent to assert(false).
+  'ecma_2/RegExp/exec-001': [FAIL_OK],
+  'ecma_2/String/replace-001': [FAIL_OK],
 
 
-# We do not strip unicode format control characters. This is really
-# required for working with non-latin character sets.  We match JSC
-# and IE here.  Firefox matches the spec (section 7.1).
-ecma_3/Unicode/uc-001: FAIL_OK
+  # We do not strip unicode format control characters. This is really
+  # required for working with non-latin character sets.  We match JSC
+  # and IE here.  Firefox matches the spec (section 7.1).
+  'ecma_3/Unicode/uc-001': [FAIL_OK],
 
 
-# A non-breaking space doesn't match \s in a regular expression.  This behaviour
-# matches JSC.  All the VMs have different behaviours in which characters match
-# \s so we do the same as JSC until they change.
-ecma_3/Unicode/uc-002: PASS || FAIL_OK
+  # A non-breaking space doesn't match \s in a regular expression.  This
+  # behaviour matches JSC.  All the VMs have different behaviours in which
+  # characters match \s so we do the same as JSC until they change.
+  'ecma_3/Unicode/uc-002': [PASS, FAIL_OK],
 
 
-# String.prototype.split on empty strings always returns an array
-# with one element (as specified in ECMA-262).
-js1_2/Array/array_split_1: FAIL_OK
+  # String.prototype.split on empty strings always returns an array
+  # with one element (as specified in ECMA-262).
+  'js1_2/Array/array_split_1': [FAIL_OK],
 
 
-# The concat() method is defined in Array.prototype; not Array.
-js1_5/Array/regress-313153: FAIL_OK
+  # The concat() method is defined in Array.prototype; not Array.
+  'js1_5/Array/regress-313153': [FAIL_OK],
 
-# The join() method is defined on Array.prototype; not Array.
-js1_5/Array/regress-474529: FAIL_OK
+  # The join() method is defined on Array.prototype; not Array.
+  'js1_5/Array/regress-474529': [FAIL_OK],
 
-# The lastIndexOf() method is defined on Array.prototype, not Array.
-ecma_3/Array/15.5.4.8-01: FAIL_OK
+  # The lastIndexOf() method is defined on Array.prototype, not Array.
+  'ecma_3/Array/15.5.4.8-01': [FAIL_OK],
 
-# Properties fileName, and lineNumber of Error instances are
-# not supported. Mozilla specific extension.
-js1_5/Exceptions/errstack-001: FAIL_OK
-js1_5/Exceptions/regress-257751: FAIL_OK
-js1_5/Regress/regress-119719: FAIL_OK
-js1_5/Regress/regress-167328: FAIL_OK
-js1_5/Regress/regress-243869: FAIL_OK
+  # Properties fileName, and lineNumber of Error instances are
+  # not supported. Mozilla specific extension.
+  'js1_5/Exceptions/errstack-001': [FAIL_OK],
+  'js1_5/Exceptions/regress-257751': [FAIL_OK],
+  'js1_5/Regress/regress-119719': [FAIL_OK],
+  'js1_5/Regress/regress-167328': [FAIL_OK],
+  'js1_5/Regress/regress-243869': [FAIL_OK],
 
 
-# Unsupported import/export and <xml> literals. Mozilla extensions.
-js1_5/Regress/regress-249211: FAIL_OK
-js1_5/Regress/regress-309242: FAIL_OK
-js1_5/Regress/regress-350692: FAIL_OK
-js1_5/extensions/regress-421621: FAIL_OK
-js1_5/extensions/regress-432075: FAIL_OK
+  # Unsupported import/export and <xml> literals. Mozilla extensions.
+  'js1_5/Regress/regress-249211': [FAIL_OK],
+  'js1_5/Regress/regress-309242': [FAIL_OK],
+  'js1_5/Regress/regress-350692': [FAIL_OK],
+  'js1_5/extensions/regress-421621': [FAIL_OK],
+  'js1_5/extensions/regress-432075': [FAIL_OK],
 
 
-# The length of Error functions is 1 not 3.
-js1_5/Exceptions/regress-123002: FAIL_OK
+  # The length of Error functions is 1 not 3.
+  'js1_5/Exceptions/regress-123002': [FAIL_OK],
 
 
-# Reserved keywords as function names, etc is not supported.
-js1_5/LexicalConventions/regress-343675: FAIL_OK
+  # Reserved keywords as function names, etc is not supported.
+  'js1_5/LexicalConventions/regress-343675': [FAIL_OK],
 
 
-# Tests if future reserved keywords of ECMA-262, edition 3 emit warnings. We
-# implement the edition 5 behaviour and fail on use of edition 5 future reserved
-# keywords as identifiers.
-js1_5/Regress/regress-240317: FAIL_OK
+  # Tests if future reserved keywords of ECMA-262, edition 3 emit warnings. We
+  # implement the edition 5 behaviour and fail on use of edition 5 future
+  # reserved keywords as identifiers.
+  'js1_5/Regress/regress-240317': [FAIL_OK],
 
 
-# Unsupported list comprehensions: [ ... for ... ] and for each.
-js1_5/Regress/regress-352009: FAIL_OK
-js1_5/Regress/regress-349648: FAIL_OK
+  # Unsupported list comprehensions: [ ... for ... ] and for each.
+  'js1_5/Regress/regress-352009': [FAIL_OK],
+  'js1_5/Regress/regress-349648': [FAIL_OK],
 
 
-# Expects top level arguments (passed on command line?) to be
-# the empty string?
-js1_5/Regress/regress-336100: FAIL_OK
+  # Expects top level arguments (passed on command line?) to be
+  # the empty string?
+  'js1_5/Regress/regress-336100': [FAIL_OK],
 
 
-# Regular expression test failures due to PCRE. We match JSC (ie, perl)
-# behavior and not the ECMA spec.
-ecma_3/RegExp/perlstress-001: PASS || FAIL_OK
-ecma_3/RegExp/regress-334158: PASS || FAIL
+  # Regular expression test failures due to PCRE. We match JSC (ie, perl)
+  # behavior and not the ECMA spec.
+  'ecma_3/RegExp/perlstress-001': [PASS, FAIL_OK],
+  'ecma_3/RegExp/regress-334158': [PASS, FAIL],
 
-# This test fails due to http://code.google.com/p/v8/issues/detail?id=187
-# Failure to clear captures when a lookahead is unwound.
-ecma_3/RegExp/15.10.2-1: PASS || FAIL_OK
+  # This test fails due to http://code.google.com/p/v8/issues/detail?id=187
+  # Failure to clear captures when a lookahead is unwound.
+  'ecma_3/RegExp/15.10.2-1': [PASS, FAIL_OK],
 
-# This test requires a failure if we try to compile a function with more
-# than 65536 arguments.  This seems to be a Mozilla restriction.
-js1_5/Regress/regress-290575: PASS || FAIL_OK
+  # This test requires a failure if we try to compile a function with more
+  # than 65536 arguments.  This seems to be a Mozilla restriction.
+  'js1_5/Regress/regress-290575': [PASS, FAIL_OK],
 
 
-# Fails because of the way function declarations are
-# handled in V8/JSC. V8 follows IE behavior and introduce
-# all nested function declarations when entering the
-# surrounding function, whereas Spidermonkey declares
-# them dynamically when the statement is executed.
-ecma_3/Function/scope-001: FAIL_OK
-ecma_3/FunExpr/fe-001: FAIL_OK
-js1_5/Scope/regress-184107: FAIL_OK
+  # Fails because of the way function declarations are
+  # handled in V8/JSC. V8 follows IE behavior and introduce
+  # all nested function declarations when entering the
+  # surrounding function, whereas Spidermonkey declares
+  # them dynamically when the statement is executed.
+  'ecma_3/Function/scope-001': [FAIL_OK],
+  'ecma_3/FunExpr/fe-001': [FAIL_OK],
+  'js1_5/Scope/regress-184107': [FAIL_OK],
 
 
-# Function is deletable in V8 and JSC.
-js1_5/Regress/regress-352604: FAIL_OK
+  # Function is deletable in V8 and JSC.
+  'js1_5/Regress/regress-352604': [FAIL_OK],
 
 
-# Cannot call strings as functions. Expects not to crash.
-js1_5/Regress/regress-417893: FAIL_OK
+  # Cannot call strings as functions. Expects not to crash.
+  'js1_5/Regress/regress-417893': [FAIL_OK],
 
 
-# Unsupported use of "[]" as function parameter. We match JSC.
-js1_5/Regress/regress-416737-01: FAIL_OK
-js1_5/Regress/regress-416737-02: FAIL_OK
+  # Unsupported use of "[]" as function parameter. We match JSC.
+  'js1_5/Regress/regress-416737-01': [FAIL_OK],
+  'js1_5/Regress/regress-416737-02': [FAIL_OK],
 
 
-# Illegal escape-sequences in string literals. Has already been fixed
-# by most engines (i.e. V8, JSC, Opera and FF).
-ecma/Array/15.4.5.1-1: FAIL_OK
-ecma/LexicalConventions/7.7.4: FAIL_OK
-ecma_2/RegExp/hex-001: FAIL_OK
-js1_2/regexp/hexadecimal: FAIL_OK
+  # Illegal escape-sequences in string literals. Has already been fixed
+  # by most engines (i.e. V8, JSC, Opera and FF).
+  'ecma/Array/15.4.5.1-1': [FAIL_OK],
+  'ecma/LexicalConventions/7.7.4': [FAIL_OK],
+  'ecma_2/RegExp/hex-001': [FAIL_OK],
+  'js1_2/regexp/hexadecimal': [FAIL_OK],
 
 
-# The source field of RegExp objects is properly escaped. We match JSC.
-ecma_2/RegExp/constructor-001: FAIL_OK
-ecma_2/RegExp/function-001: FAIL_OK
-ecma_2/RegExp/properties-001: FAIL_OK
+  # The source field of RegExp objects is properly escaped. We match JSC.
+  'ecma_2/RegExp/constructor-001': [FAIL_OK],
+  'ecma_2/RegExp/function-001': [FAIL_OK],
+  'ecma_2/RegExp/properties-001': [FAIL_OK],
 
 
-# Negative hexadecimal literals are parsed as NaN. This test is outdated.
-ecma/TypeConversion/9.3.1-3: FAIL_OK
+  # Negative hexadecimal literals are parsed as NaN. This test is outdated.
+  'ecma/TypeConversion/9.3.1-3': [FAIL_OK],
 
 
-##################### FAILING TESTS #####################
+  ##################### FAILING TESTS #####################
 
-# This section is for tests that fail in V8 and pass in JSC.
-# Tests that fail in both V8 and JSC belong in the FAIL_OK
-# category.
+  # This section is for tests that fail in V8 and pass in JSC.
+  # Tests that fail in both V8 and JSC belong in the FAIL_OK
+  # category.
 
-# This fails because we don't handle Function.prototype.apply with very large
-# numbers of arguments (depending on max stack size).  350256-02 needs more than
-# 4Mbytes of stack space.
-js1_5/Array/regress-350256-02: FAIL
+  # This fails because we don't handle Function.prototype.apply with very large
+  # numbers of arguments (depending on max stack size).  350256-02 needs more
+  # than 4Mbytes of stack space.
+  'js1_5/Array/regress-350256-02': [FAIL],
 
 
-# This test seems designed to fail (it produces a 700Mbyte string).
-# We fail on out of memory.  The important thing is not to crash.
-js1_5/Regress/regress-303213: FAIL || TIMEOUT if $mode == debug
+  # This test seems designed to fail (it produces a 700Mbyte string).
+  # We fail on out of memory.  The important thing is not to crash.
+  'js1_5/Regress/regress-303213': [FAIL, ['mode == debug', TIMEOUT]],
 
-# This test fails since we now throw in String.prototype.match when apply
-# is given null or undefined as this argument (and so does firefox nightly).
-js1_5/Regress/regress-295052: FAIL
+  # This test fails since we now throw in String.prototype.match when apply
+  # is given null or undefined as this argument (and so does firefox nightly).
+  'js1_5/Regress/regress-295052': [FAIL],
 
-# Bug 1202592: New ecma_3/String/15.5.4.11 is failing.
-ecma_3/String/15.5.4.11: FAIL
+  # Bug 1202592: New ecma_3/String/15.5.4.11 is failing.
+  'ecma_3/String/15.5.4.11': [FAIL],
 
-# Bug 1202597: New js1_5/Expressions/regress-394673 is failing.
-# Marked as: Will not fix. V8 throws an acceptable RangeError.
-js1_5/Expressions/regress-394673: FAIL
+  # Bug 1202597: New js1_5/Expressions/regress-394673 is failing.
+  # Marked as: Will not fix. V8 throws an acceptable RangeError.
+  'js1_5/Expressions/regress-394673': [FAIL],
 
 
-# Bug 762: http://code.google.com/p/v8/issues/detail?id=762
-# We do not correctly handle assignments within "with"
-ecma_3/Statements/12.10-01: FAIL
+  # Bug 762: http://code.google.com/p/v8/issues/detail?id=762
+  # We do not correctly handle assignments within "with"
+  'ecma_3/Statements/12.10-01': [FAIL],
 
-# We do not throw an exception when a const is redeclared.
-# (We only fail section 1 of the test.)
-js1_5/Regress/regress-103602: FAIL
+  # We do not throw an exception when a const is redeclared.
+  # (We only fail section 1 of the test.)
+  'js1_5/Regress/regress-103602': [FAIL],
 
-##################### MOZILLA EXTENSION TESTS #####################
+  ##################### MOZILLA EXTENSION TESTS #####################
 
-ecma/extensions/15.1.2.1-1: FAIL_OK
-ecma_3/extensions/regress-385393-03: FAIL_OK
-ecma_3/extensions/7.9.1: FAIL_OK
-js1_5/extensions/catchguard-001: FAIL_OK
-js1_5/extensions/catchguard-002: FAIL_OK
-js1_5/extensions/catchguard-003: FAIL_OK
-js1_5/extensions/getset-001: FAIL_OK
-js1_5/extensions/getset-003: FAIL_OK
-js1_5/extensions/no-such-method: FAIL_OK
-js1_5/extensions/regress-104077: FAIL_OK
-js1_5/extensions/regress-226078: FAIL_OK
-js1_5/extensions/regress-303277: FAIL_OK
-js1_5/extensions/regress-304897: FAIL_OK
-js1_5/extensions/regress-306738: FAIL_OK
-js1_5/extensions/regress-311161: FAIL_OK
-js1_5/extensions/regress-311583: FAIL_OK
-js1_5/extensions/regress-311792-01: FAIL_OK
-js1_5/extensions/regress-312278: FAIL_OK
-js1_5/extensions/regress-313630: FAIL_OK
-js1_5/extensions/regress-313763: FAIL_OK
-js1_5/extensions/regress-313803: FAIL_OK
-js1_5/extensions/regress-314874: FAIL_OK
-js1_5/extensions/regress-322957: FAIL_OK
-js1_5/extensions/regress-328556: FAIL_OK
-js1_5/extensions/regress-333541: FAIL_OK
-js1_5/extensions/regress-335700: FAIL_OK
-js1_5/extensions/regress-336409-1: FAIL_OK
-js1_5/extensions/regress-336409-2: FAIL_OK
-js1_5/extensions/regress-336410-2: FAIL_OK
-js1_5/extensions/regress-341956-01: FAIL_OK
-js1_5/extensions/regress-345967: FAIL_OK
-js1_5/extensions/regress-346494-01: FAIL_OK
-js1_5/extensions/regress-346494: FAIL_OK
-js1_5/extensions/regress-347306-02: FAIL_OK
-js1_5/extensions/regress-348986: FAIL_OK
-js1_5/extensions/regress-349616: FAIL_OK
-js1_5/extensions/regress-350312-02: FAIL_OK
-js1_5/extensions/regress-350312-03: FAIL_OK
-js1_5/extensions/regress-350531: FAIL_OK
-js1_5/extensions/regress-351102-01: FAIL_OK
-js1_5/extensions/regress-351102-02: FAIL_OK
-js1_5/extensions/regress-351102-06: FAIL_OK
-js1_5/extensions/regress-351973: FAIL_OK
-js1_5/extensions/regress-352060: FAIL_OK
-js1_5/extensions/regress-352094: FAIL_OK
-js1_5/extensions/regress-352261: FAIL_OK
-js1_5/extensions/regress-352281: FAIL_OK
-js1_5/extensions/regress-352455: FAIL_OK
-js1_5/extensions/regress-352604: FAIL_OK
-js1_5/extensions/regress-353214: FAIL_OK
-js1_5/extensions/regress-355339: FAIL_OK
-js1_5/extensions/regress-355497: FAIL_OK
-js1_5/extensions/regress-355622: FAIL_OK
-js1_5/extensions/regress-355736: FAIL_OK
-js1_5/extensions/regress-356085: FAIL_OK
-js1_5/extensions/regress-356106: FAIL_OK
-js1_5/extensions/regress-358594-01: FAIL_OK
-js1_5/extensions/regress-358594-02: FAIL_OK
-js1_5/extensions/regress-358594-03: FAIL_OK
-js1_5/extensions/regress-358594-04: FAIL_OK
-js1_5/extensions/regress-358594-05: FAIL_OK
-js1_5/extensions/regress-358594-06: FAIL_OK
-js1_5/extensions/regress-361346: FAIL_OK
-js1_5/extensions/regress-361360: FAIL_OK
-js1_5/extensions/regress-361558: FAIL_OK
-js1_5/extensions/regress-361571: FAIL_OK
-js1_5/extensions/regress-361856: FAIL_OK
-js1_5/extensions/regress-361964: FAIL_OK
-js1_5/extensions/regress-363988: FAIL_OK
-js1_5/extensions/regress-365869: FAIL_OK
-js1_5/extensions/regress-367630: FAIL_OK
-js1_5/extensions/regress-367923: FAIL_OK
-js1_5/extensions/regress-368859: FAIL_OK
-js1_5/extensions/regress-369696-01: FAIL_OK
-js1_5/extensions/regress-369696-02: FAIL_OK
-js1_5/extensions/regress-369696-03: FAIL_OK
-js1_5/extensions/regress-374589: FAIL_OK
-js1_5/extensions/regress-375801: FAIL_OK
-js1_5/extensions/regress-376052: FAIL_OK
-js1_5/extensions/regress-379523: FAIL_OK
-js1_5/extensions/regress-380581: FAIL_OK
-js1_5/extensions/regress-380831: FAIL_OK
-js1_5/extensions/regress-381205: FAIL_OK
-js1_5/extensions/regress-381211: FAIL_OK
-js1_5/extensions/regress-381304: FAIL_OK
-js1_5/extensions/regress-382509: FAIL_OK
-js1_5/extensions/regress-383965: FAIL_OK
-js1_5/extensions/regress-384680: FAIL_OK
-js1_5/extensions/regress-385393-09: FAIL_OK
-js1_5/extensions/regress-407501: FAIL_OK
-js1_5/extensions/regress-418730: FAIL_OK
-js1_5/extensions/regress-420612: FAIL_OK
-js1_5/extensions/regress-420869-01: FAIL_OK
-js1_5/extensions/regress-424257: FAIL_OK
-js1_5/extensions/regress-424683-01: FAIL_OK
-js1_5/extensions/regress-429739: FAIL_OK
-js1_5/extensions/regress-454142: FAIL_OK
-js1_5/extensions/regress-465145: FAIL_OK
-js1_5/extensions/regress-469625: FAIL_OK
-js1_5/extensions/regress-472787: FAIL_OK
-js1_5/extensions/regress-44009: FAIL_OK
-js1_5/extensions/regress-50447-1: FAIL_OK
-js1_5/extensions/regress-50447: FAIL_OK
-js1_5/extensions/regress-90596-001: FAIL_OK
-js1_5/extensions/regress-90596-002: FAIL_OK
-js1_5/extensions/regress-96284-001: FAIL_OK
-js1_5/extensions/regress-96284-002: FAIL_OK
-js1_5/extensions/toLocaleFormat-01: FAIL_OK
-js1_5/extensions/toLocaleFormat-02: FAIL_OK
+  'ecma/extensions/15.1.2.1-1': [FAIL_OK],
+  'ecma_3/extensions/regress-385393-03': [FAIL_OK],
+  'ecma_3/extensions/7.9.1': [FAIL_OK],
+  'js1_5/extensions/catchguard-001': [FAIL_OK],
+  'js1_5/extensions/catchguard-002': [FAIL_OK],
+  'js1_5/extensions/catchguard-003': [FAIL_OK],
+  'js1_5/extensions/getset-001': [FAIL_OK],
+  'js1_5/extensions/getset-003': [FAIL_OK],
+  'js1_5/extensions/no-such-method': [FAIL_OK],
+  'js1_5/extensions/regress-104077': [FAIL_OK],
+  'js1_5/extensions/regress-226078': [FAIL_OK],
+  'js1_5/extensions/regress-303277': [FAIL_OK],
+  'js1_5/extensions/regress-304897': [FAIL_OK],
+  'js1_5/extensions/regress-306738': [FAIL_OK],
+  'js1_5/extensions/regress-311161': [FAIL_OK],
+  'js1_5/extensions/regress-311583': [FAIL_OK],
+  'js1_5/extensions/regress-311792-01': [FAIL_OK],
+  'js1_5/extensions/regress-312278': [FAIL_OK],
+  'js1_5/extensions/regress-313630': [FAIL_OK],
+  'js1_5/extensions/regress-313763': [FAIL_OK],
+  'js1_5/extensions/regress-313803': [FAIL_OK],
+  'js1_5/extensions/regress-314874': [FAIL_OK],
+  'js1_5/extensions/regress-322957': [FAIL_OK],
+  'js1_5/extensions/regress-328556': [FAIL_OK],
+  'js1_5/extensions/regress-333541': [FAIL_OK],
+  'js1_5/extensions/regress-335700': [FAIL_OK],
+  'js1_5/extensions/regress-336409-1': [FAIL_OK],
+  'js1_5/extensions/regress-336409-2': [FAIL_OK],
+  'js1_5/extensions/regress-336410-2': [FAIL_OK],
+  'js1_5/extensions/regress-341956-01': [FAIL_OK],
+  'js1_5/extensions/regress-345967': [FAIL_OK],
+  'js1_5/extensions/regress-346494-01': [FAIL_OK],
+  'js1_5/extensions/regress-346494': [FAIL_OK],
+  'js1_5/extensions/regress-347306-02': [FAIL_OK],
+  'js1_5/extensions/regress-348986': [FAIL_OK],
+  'js1_5/extensions/regress-349616': [FAIL_OK],
+  'js1_5/extensions/regress-350312-02': [FAIL_OK],
+  'js1_5/extensions/regress-350312-03': [FAIL_OK],
+  'js1_5/extensions/regress-350531': [FAIL_OK],
+  'js1_5/extensions/regress-351102-01': [FAIL_OK],
+  'js1_5/extensions/regress-351102-02': [FAIL_OK],
+  'js1_5/extensions/regress-351102-06': [FAIL_OK],
+  'js1_5/extensions/regress-351973': [FAIL_OK],
+  'js1_5/extensions/regress-352060': [FAIL_OK],
+  'js1_5/extensions/regress-352094': [FAIL_OK],
+  'js1_5/extensions/regress-352261': [FAIL_OK],
+  'js1_5/extensions/regress-352281': [FAIL_OK],
+  'js1_5/extensions/regress-352455': [FAIL_OK],
+  'js1_5/extensions/regress-352604': [FAIL_OK],
+  'js1_5/extensions/regress-353214': [FAIL_OK],
+  'js1_5/extensions/regress-355339': [FAIL_OK],
+  'js1_5/extensions/regress-355497': [FAIL_OK],
+  'js1_5/extensions/regress-355622': [FAIL_OK],
+  'js1_5/extensions/regress-355736': [FAIL_OK],
+  'js1_5/extensions/regress-356085': [FAIL_OK],
+  'js1_5/extensions/regress-356106': [FAIL_OK],
+  'js1_5/extensions/regress-358594-01': [FAIL_OK],
+  'js1_5/extensions/regress-358594-02': [FAIL_OK],
+  'js1_5/extensions/regress-358594-03': [FAIL_OK],
+  'js1_5/extensions/regress-358594-04': [FAIL_OK],
+  'js1_5/extensions/regress-358594-05': [FAIL_OK],
+  'js1_5/extensions/regress-358594-06': [FAIL_OK],
+  'js1_5/extensions/regress-361346': [FAIL_OK],
+  'js1_5/extensions/regress-361360': [FAIL_OK],
+  'js1_5/extensions/regress-361558': [FAIL_OK],
+  'js1_5/extensions/regress-361571': [FAIL_OK],
+  'js1_5/extensions/regress-361856': [FAIL_OK],
+  'js1_5/extensions/regress-361964': [FAIL_OK],
+  'js1_5/extensions/regress-363988': [FAIL_OK],
+  'js1_5/extensions/regress-365869': [FAIL_OK],
+  'js1_5/extensions/regress-367630': [FAIL_OK],
+  'js1_5/extensions/regress-367923': [FAIL_OK],
+  'js1_5/extensions/regress-368859': [FAIL_OK],
+  'js1_5/extensions/regress-369696-01': [FAIL_OK],
+  'js1_5/extensions/regress-369696-02': [FAIL_OK],
+  'js1_5/extensions/regress-369696-03': [FAIL_OK],
+  'js1_5/extensions/regress-374589': [FAIL_OK],
+  'js1_5/extensions/regress-375801': [FAIL_OK],
+  'js1_5/extensions/regress-376052': [FAIL_OK],
+  'js1_5/extensions/regress-379523': [FAIL_OK],
+  'js1_5/extensions/regress-380581': [FAIL_OK],
+  'js1_5/extensions/regress-380831': [FAIL_OK],
+  'js1_5/extensions/regress-381205': [FAIL_OK],
+  'js1_5/extensions/regress-381211': [FAIL_OK],
+  'js1_5/extensions/regress-381304': [FAIL_OK],
+  'js1_5/extensions/regress-382509': [FAIL_OK],
+  'js1_5/extensions/regress-383965': [FAIL_OK],
+  'js1_5/extensions/regress-384680': [FAIL_OK],
+  'js1_5/extensions/regress-385393-09': [FAIL_OK],
+  'js1_5/extensions/regress-407501': [FAIL_OK],
+  'js1_5/extensions/regress-418730': [FAIL_OK],
+  'js1_5/extensions/regress-420612': [FAIL_OK],
+  'js1_5/extensions/regress-420869-01': [FAIL_OK],
+  'js1_5/extensions/regress-424257': [FAIL_OK],
+  'js1_5/extensions/regress-424683-01': [FAIL_OK],
+  'js1_5/extensions/regress-429739': [FAIL_OK],
+  'js1_5/extensions/regress-454142': [FAIL_OK],
+  'js1_5/extensions/regress-465145': [FAIL_OK],
+  'js1_5/extensions/regress-469625': [FAIL_OK],
+  'js1_5/extensions/regress-472787': [FAIL_OK],
+  'js1_5/extensions/regress-44009': [FAIL_OK],
+  'js1_5/extensions/regress-50447-1': [FAIL_OK],
+  'js1_5/extensions/regress-50447': [FAIL_OK],
+  'js1_5/extensions/regress-90596-001': [FAIL_OK],
+  'js1_5/extensions/regress-90596-002': [FAIL_OK],
+  'js1_5/extensions/regress-96284-001': [FAIL_OK],
+  'js1_5/extensions/regress-96284-002': [FAIL_OK],
+  'js1_5/extensions/toLocaleFormat-01': [FAIL_OK],
+  'js1_5/extensions/toLocaleFormat-02': [FAIL_OK],
 
-js1_5/extensions/regress-330569: TIMEOUT
-js1_5/extensions/regress-351448: TIMEOUT
-# In the 64-bit version, this test takes longer to run out of memory
-# than it does in the 32-bit version when attempting to generate a huge
-# error message in debug mode.
-js1_5/extensions/regress-336410-1: FAIL_OK || TIMEOUT if ($mode == debug && $arch == x64)
+  'js1_5/extensions/regress-330569': [TIMEOUT],
+  'js1_5/extensions/regress-351448': [TIMEOUT],
+  # In the 64-bit version, this test takes longer to run out of memory
+  # than it does in the 32-bit version when attempting to generate a huge
+  # error message in debug mode.
+  'js1_5/extensions/regress-336410-1': [FAIL_OK, ['mode == debug and arch == x64', TIMEOUT]],
 
-##################### DECOMPILATION TESTS #####################
+  ##################### DECOMPILATION TESTS #####################
 
-# We don't really about the outcome of running the
-# decompilation tests as long as they don't crash or
-# timeout.
+  # We don't really about the outcome of running the
+  # decompilation tests as long as they don't crash or
+  # timeout.
 
-js1_5/decompilation/regress-344120: PASS || FAIL
-js1_5/decompilation/regress-346892: PASS || FAIL
-js1_5/decompilation/regress-346902: PASS || FAIL
-js1_5/decompilation/regress-346904: PASS || FAIL
-js1_5/decompilation/regress-346915: PASS || FAIL
-js1_5/decompilation/regress-349484: PASS || FAIL
-js1_5/decompilation/regress-349489: PASS || FAIL
-js1_5/decompilation/regress-349491: PASS || FAIL
-js1_5/decompilation/regress-349596: PASS || FAIL
-js1_5/decompilation/regress-349650: PASS || FAIL
-js1_5/decompilation/regress-349663: PASS || FAIL
-js1_5/decompilation/regress-350242: PASS || FAIL
-js1_5/decompilation/regress-350263: PASS || FAIL
-js1_5/decompilation/regress-350271: PASS || FAIL
-js1_5/decompilation/regress-350666: PASS || FAIL
-js1_5/decompilation/regress-350670: PASS || FAIL
-js1_5/decompilation/regress-351104: PASS || FAIL
-js1_5/decompilation/regress-351219: PASS || FAIL
-js1_5/decompilation/regress-351336: PASS || FAIL
-js1_5/decompilation/regress-351597: PASS || FAIL
-js1_5/decompilation/regress-351625: PASS || FAIL
-js1_5/decompilation/regress-351626: PASS || FAIL
-js1_5/decompilation/regress-351693: PASS || FAIL
-js1_5/decompilation/regress-351705: PASS || FAIL
-js1_5/decompilation/regress-351793: PASS || FAIL
-js1_5/decompilation/regress-352013: PASS || FAIL
-js1_5/decompilation/regress-352022: PASS || FAIL
-js1_5/decompilation/regress-352073: PASS || FAIL
-js1_5/decompilation/regress-352202: PASS || FAIL
-js1_5/decompilation/regress-352312: PASS || FAIL
-js1_5/decompilation/regress-352360: PASS || FAIL
-js1_5/decompilation/regress-352375: PASS || FAIL
-js1_5/decompilation/regress-352453: PASS || FAIL
-js1_5/decompilation/regress-352649: PASS || FAIL
-js1_5/decompilation/regress-352873-01: PASS || FAIL
-js1_5/decompilation/regress-352873-02: PASS || FAIL
-js1_5/decompilation/regress-353000: PASS || FAIL
-js1_5/decompilation/regress-353120: PASS || FAIL
-js1_5/decompilation/regress-353146: PASS || FAIL
-js1_5/decompilation/regress-354878: PASS || FAIL
-js1_5/decompilation/regress-354910: PASS || FAIL
-js1_5/decompilation/regress-355992: PASS || FAIL
-js1_5/decompilation/regress-356083: PASS || FAIL
-js1_5/decompilation/regress-356248: PASS || FAIL
-js1_5/decompilation/regress-371692: PASS || FAIL
-js1_5/decompilation/regress-373678: PASS || FAIL
-js1_5/decompilation/regress-375639: PASS || FAIL
-js1_5/decompilation/regress-375882: PASS || FAIL
-js1_5/decompilation/regress-376564: PASS || FAIL
-js1_5/decompilation/regress-383721: PASS || FAIL
-js1_5/decompilation/regress-406555: PASS || FAIL
-js1_5/decompilation/regress-460870: PASS || FAIL
+  'js1_5/decompilation/regress-344120': [PASS, FAIL],
+  'js1_5/decompilation/regress-346892': [PASS, FAIL],
+  'js1_5/decompilation/regress-346902': [PASS, FAIL],
+  'js1_5/decompilation/regress-346904': [PASS, FAIL],
+  'js1_5/decompilation/regress-346915': [PASS, FAIL],
+  'js1_5/decompilation/regress-349484': [PASS, FAIL],
+  'js1_5/decompilation/regress-349489': [PASS, FAIL],
+  'js1_5/decompilation/regress-349491': [PASS, FAIL],
+  'js1_5/decompilation/regress-349596': [PASS, FAIL],
+  'js1_5/decompilation/regress-349650': [PASS, FAIL],
+  'js1_5/decompilation/regress-349663': [PASS, FAIL],
+  'js1_5/decompilation/regress-350242': [PASS, FAIL],
+  'js1_5/decompilation/regress-350263': [PASS, FAIL],
+  'js1_5/decompilation/regress-350271': [PASS, FAIL],
+  'js1_5/decompilation/regress-350666': [PASS, FAIL],
+  'js1_5/decompilation/regress-350670': [PASS, FAIL],
+  'js1_5/decompilation/regress-351104': [PASS, FAIL],
+  'js1_5/decompilation/regress-351219': [PASS, FAIL],
+  'js1_5/decompilation/regress-351336': [PASS, FAIL],
+  'js1_5/decompilation/regress-351597': [PASS, FAIL],
+  'js1_5/decompilation/regress-351625': [PASS, FAIL],
+  'js1_5/decompilation/regress-351626': [PASS, FAIL],
+  'js1_5/decompilation/regress-351693': [PASS, FAIL],
+  'js1_5/decompilation/regress-351705': [PASS, FAIL],
+  'js1_5/decompilation/regress-351793': [PASS, FAIL],
+  'js1_5/decompilation/regress-352013': [PASS, FAIL],
+  'js1_5/decompilation/regress-352022': [PASS, FAIL],
+  'js1_5/decompilation/regress-352073': [PASS, FAIL],
+  'js1_5/decompilation/regress-352202': [PASS, FAIL],
+  'js1_5/decompilation/regress-352312': [PASS, FAIL],
+  'js1_5/decompilation/regress-352360': [PASS, FAIL],
+  'js1_5/decompilation/regress-352375': [PASS, FAIL],
+  'js1_5/decompilation/regress-352453': [PASS, FAIL],
+  'js1_5/decompilation/regress-352649': [PASS, FAIL],
+  'js1_5/decompilation/regress-352873-01': [PASS, FAIL],
+  'js1_5/decompilation/regress-352873-02': [PASS, FAIL],
+  'js1_5/decompilation/regress-353000': [PASS, FAIL],
+  'js1_5/decompilation/regress-353120': [PASS, FAIL],
+  'js1_5/decompilation/regress-353146': [PASS, FAIL],
+  'js1_5/decompilation/regress-354878': [PASS, FAIL],
+  'js1_5/decompilation/regress-354910': [PASS, FAIL],
+  'js1_5/decompilation/regress-355992': [PASS, FAIL],
+  'js1_5/decompilation/regress-356083': [PASS, FAIL],
+  'js1_5/decompilation/regress-356248': [PASS, FAIL],
+  'js1_5/decompilation/regress-371692': [PASS, FAIL],
+  'js1_5/decompilation/regress-373678': [PASS, FAIL],
+  'js1_5/decompilation/regress-375639': [PASS, FAIL],
+  'js1_5/decompilation/regress-375882': [PASS, FAIL],
+  'js1_5/decompilation/regress-376564': [PASS, FAIL],
+  'js1_5/decompilation/regress-383721': [PASS, FAIL],
+  'js1_5/decompilation/regress-406555': [PASS, FAIL],
+  'js1_5/decompilation/regress-460870': [PASS, FAIL],
+}],  # ALWAYS
 
 
-[ $arch == arm ]
+['arch == arm', {
 
-# BUG(3251229): Times out when running new crankshaft test script.
-ecma_3/RegExp/regress-311414: SKIP
-ecma/Date/15.9.5.8: SKIP
-ecma/Date/15.9.5.10-2: SKIP
-ecma/Date/15.9.5.11-2: SKIP
-ecma/Date/15.9.5.12-2: SKIP
-js1_5/Array/regress-99120-02: SKIP
-js1_5/extensions/regress-371636: SKIP
-js1_5/Regress/regress-203278-1: SKIP
-js1_5/Regress/regress-404755:  SKIP
-js1_5/Regress/regress-451322: SKIP
+  # BUG(3251229): Times out when running new crankshaft test script.
+  'ecma_3/RegExp/regress-311414': [SKIP],
+  'ecma/Date/15.9.5.8': [SKIP],
+  'ecma/Date/15.9.5.10-2': [SKIP],
+  'ecma/Date/15.9.5.11-2': [SKIP],
+  'ecma/Date/15.9.5.12-2': [SKIP],
+  'js1_5/Array/regress-99120-02': [SKIP],
+  'js1_5/extensions/regress-371636': [SKIP],
+  'js1_5/Regress/regress-203278-1': [SKIP],
+  'js1_5/Regress/regress-404755': [SKIP],
+  'js1_5/Regress/regress-451322': [SKIP],
 
 
-# BUG(1040): Allow this test to timeout.
-js1_5/GC/regress-203278-2: PASS || TIMEOUT
+  # BUG(1040): Allow this test to timeout.
+  'js1_5/GC/regress-203278-2': [PASS, TIMEOUT],
+}],  # 'arch == arm'
 
 
-[ $arch == mipsel ]
+['arch == mipsel', {
 
-# BUG(3251229): Times out when running new crankshaft test script.
-ecma_3/RegExp/regress-311414: SKIP
-ecma/Date/15.9.5.8: SKIP
-ecma/Date/15.9.5.10-2: SKIP
-ecma/Date/15.9.5.11-2: SKIP
-ecma/Date/15.9.5.12-2: SKIP
-js1_5/Array/regress-99120-02: SKIP
-js1_5/extensions/regress-371636: SKIP
-js1_5/Regress/regress-203278-1: SKIP
-js1_5/Regress/regress-404755:  SKIP
-js1_5/Regress/regress-451322: SKIP
+  # BUG(3251229): Times out when running new crankshaft test script.
+  'ecma_3/RegExp/regress-311414': [SKIP],
+  'ecma/Date/15.9.5.8': [SKIP],
+  'ecma/Date/15.9.5.10-2': [SKIP],
+  'ecma/Date/15.9.5.11-2': [SKIP],
+  'ecma/Date/15.9.5.12-2': [SKIP],
+  'js1_5/Array/regress-99120-02': [SKIP],
+  'js1_5/extensions/regress-371636': [SKIP],
+  'js1_5/Regress/regress-203278-1': [SKIP],
+  'js1_5/Regress/regress-404755': [SKIP],
+  'js1_5/Regress/regress-451322': [SKIP],
 
 
-# BUG(1040): Allow this test to timeout.
-js1_5/GC/regress-203278-2: PASS || TIMEOUT
+  # BUG(1040): Allow this test to timeout.
+  'js1_5/GC/regress-203278-2': [PASS, TIMEOUT],
+}],  # 'arch == mipsel'
+]
diff --git a/test/preparser/preparser.status b/test/preparser/preparser.status
index 40c5caf..e66251b 100644
--- a/test/preparser/preparser.status
+++ b/test/preparser/preparser.status
@@ -25,14 +25,17 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-prefix preparser
+[
+[ALWAYS, {
+  # We don't parse RegExps at scanning time, so we can't fail on octal
+  # escapes (we need to parse to distinguish octal escapes from valid
+  # back-references).
+  'strict-octal-regexp': [FAIL],
+}],  # ALWAYS
 
-# We don't parse RegExps at scanning time, so we can't fail on octal
-# escapes (we need to parse to distinguish octal escapes from valid
-# back-references).
-strict-octal-regexp: FAIL
-
-[ $arch == android_arm || $arch == android_ia32 ]
-# Remove this once the issue above is fixed. Android test runner does not
-# handle "FAIL" test expectation correctly.
-strict-octal-regexp: SKIP
+['arch == android_arm or arch == android_ia32', {
+  # Remove this once the issue above is fixed. Android test runner does not
+  # handle "FAIL" test expectation correctly.
+  'strict-octal-regexp': [SKIP],
+}],  # 'arch == android_arm or arch == android_ia32'
+]
diff --git a/test/test262/test262.status b/test/test262/test262.status
index 2f4b77f..e546266 100644
--- a/test/test262/test262.status
+++ b/test/test262/test262.status
@@ -25,95 +25,97 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-prefix test262
-def FAIL_OK = FAIL, OKAY
+[
+[ALWAYS, {
+  ############################### BUGS ###################################
 
-############################### BUGS ###################################
+  # Sequencing of getter side effects on receiver and argument properties
+  # is wrong. The receiver callback should be called before any arguments
+  # are evaluated.
+  # V8 Bug: http://code.google.com/p/v8/issues/detail?id=691
+  '11.2.3-3_3': [FAIL],
 
-# Sequencing of getter side effects on receiver and argument properties
-# is wrong. The receiver callback should be called before any arguments
-# are evaluated.
-# V8 Bug: http://code.google.com/p/v8/issues/detail?id=691
-11.2.3-3_3: FAIL
+  '15.5.4.9_CE': [['no_i18n', SKIP]],
 
-15.5.4.9_CE: SKIP if $no_i18n
+  ######################## NEEDS INVESTIGATION ###########################
 
-######################## NEEDS INVESTIGATION ###########################
+  # These test failures are specific to the intl402 suite and need investigation
+  # to be either marked as bugs with issues filed for them or as deliberate
+  # incompatibilities if the test cases turn out to be broken or ambiguous.
+  '6.2.3': [FAIL],
+  '9.2.1_2': [FAIL],
+  '9.2.5_11_g_ii_2': [FAIL],
+  '9.2.6_2': [FAIL],
+  '10.1.1_a': [FAIL],
+  '10.1.1_19_c': [PASS, FAIL],
+  '10.1.2.1_4': [FAIL],
+  '10.2.3_b': [PASS, FAIL],
+  '10.3_a': [FAIL],
+  '11.1.1_17': [PASS, FAIL],
+  '11.1.1_19': [PASS, FAIL],
+  '11.1.1_20_c': [FAIL],
+  '11.1.1_a': [FAIL],
+  '11.1.2.1_4': [FAIL],
+  '11.3.2_FN_2': [PASS, FAIL],
+  '11.3.2_TRF': [PASS, FAIL],
+  '11.3.2_TRP': [FAIL],
+  '11.3_a': [FAIL],
+  '12.1.1_a': [FAIL],
+  '12.1.2.1_4': [FAIL],
+  '12.3.2_FDT_7_a_iv': [FAIL],
+  '12.3.3': [FAIL],
+  '12.3_a': [FAIL],
+  '15.5.4.9_3': [PASS, FAIL],
 
-# These test failures are specific to the intl402 suite and need investigation
-# to be either marked as bugs with issues filed for them or as deliberate
-# incompatibilities if the test cases turn out to be broken or ambiguous.
-6.2.3: FAIL
-9.2.1_2: FAIL
-9.2.5_11_g_ii_2: FAIL
-9.2.6_2: FAIL
-10.1.1_a: FAIL
-10.1.1_19_c: PASS || FAIL
-10.1.2.1_4: FAIL
-10.2.3_b: PASS || FAIL
-10.3_a: FAIL
-11.1.1_17: PASS || FAIL
-11.1.1_19: PASS || FAIL
-11.1.1_20_c: FAIL
-11.1.1_a: FAIL
-11.1.2.1_4: FAIL
-11.3.2_FN_2: PASS || FAIL
-11.3.2_TRF: PASS || FAIL
-11.3.2_TRP: FAIL
-11.3_a: FAIL
-12.1.1_a: FAIL
-12.1.2.1_4: FAIL
-12.3.2_FDT_7_a_iv: FAIL
-12.3.3: FAIL
-12.3_a: FAIL
-15.5.4.9_3: PASS || FAIL
+  ##################### DELIBERATE INCOMPATIBILITIES #####################
 
-##################### DELIBERATE INCOMPATIBILITIES #####################
+  # This tests precision of Math functions.  The implementation for those
+  # trigonometric functions are platform/compiler dependent.  Furthermore, the
+  # expectation values by far deviates from the actual result given by an
+  # arbitrary-precision calculator, making those tests partly bogus.
+  'S15.8.2.8_A6': [PASS, FAIL_OK],  # Math.exp (less precise with --fast-math)
+  'S15.8.2.16_A7': [PASS, FAIL_OK],  # Math.sin
+  'S15.8.2.18_A7': [PASS, FAIL_OK],  # Math.tan
 
-# This tests precision of Math functions.  The implementation for those
-# trigonometric functions are platform/compiler dependent.  Furthermore, the
-# expectation values by far deviates from the actual result given by an
-# arbitrary-precision calculator, making those tests partly bogus.
-S15.8.2.8_A6: PASS || FAIL_OK   # Math.exp (less precise with --fast-math)
-S15.8.2.16_A7: PASS || FAIL_OK  # Math.sin
-S15.8.2.18_A7: PASS || FAIL_OK  # Math.tan
+  # Linux for ia32 (and therefore simulators) default to extended 80 bit
+  # floating point formats, so these tests checking 64-bit FP precision fail.
+  # The other platforms/arch's pass these tests.
+  # We follow the other major JS engines by keeping this default.
+  'S8.5_A2.1': [PASS, FAIL_OK],
+  'S8.5_A2.2': [PASS, FAIL_OK],
 
-# Linux for ia32 (and therefore simulators) default to extended 80 bit floating
-# point formats, so these tests checking 64-bit FP precision fail. The other
-# platforms/arch's pass these tests.
-# We follow the other major JS engines by keeping this default.
-S8.5_A2.1: PASS || FAIL_OK
-S8.5_A2.2: PASS || FAIL_OK
+  ############################ INVALID TESTS #############################
 
-############################ INVALID TESTS #############################
+  # The reference value calculated by Test262 is incorrect if you run these
+  # tests in PST/PDT between first Sunday in March and first Sunday in April.
+  # The DST switch was moved in 2007 whereas Test262 bases the reference value
+  # on 2000. Test262 Bug: https://bugs.ecmascript.org/show_bug.cgi?id=293
+  'S15.9.3.1_A5_T1': [PASS, FAIL_OK],
+  'S15.9.3.1_A5_T2': [PASS, FAIL_OK],
+  'S15.9.3.1_A5_T3': [PASS, FAIL_OK],
+  'S15.9.3.1_A5_T4': [PASS, FAIL_OK],
+  'S15.9.3.1_A5_T5': [PASS, FAIL_OK],
+  'S15.9.3.1_A5_T6': [PASS, FAIL_OK],
 
-# The reference value calculated by Test262 is incorrect if you run these tests
-# in PST/PDT between first Sunday in March and first Sunday in April. The DST
-# switch was moved in 2007 whereas Test262 bases the reference value on 2000.
-# Test262 Bug: https://bugs.ecmascript.org/show_bug.cgi?id=293
-S15.9.3.1_A5_T1: PASS || FAIL_OK
-S15.9.3.1_A5_T2: PASS || FAIL_OK
-S15.9.3.1_A5_T3: PASS || FAIL_OK
-S15.9.3.1_A5_T4: PASS || FAIL_OK
-S15.9.3.1_A5_T5: PASS || FAIL_OK
-S15.9.3.1_A5_T6: PASS || FAIL_OK
+  ############################ SKIPPED TESTS #############################
 
-############################ SKIPPED TESTS #############################
+  # These tests take a looong time to run in debug mode.
+  'S15.1.3.1_A2.5_T1': [PASS, ['mode == debug', SKIP]],
+  'S15.1.3.2_A2.5_T1': [PASS, ['mode == debug', SKIP]],
+}],  # ALWAYS
 
-# These tests take a looong time to run in debug mode.
-S15.1.3.1_A2.5_T1: PASS, SKIP if $mode == debug
-S15.1.3.2_A2.5_T1: PASS, SKIP if $mode == debug
+['arch == arm or arch == mipsel', {
 
-[ $arch == arm || $arch == mipsel ]
+  # TODO(mstarzinger): Causes stack overflow on simulators due to eager
+  # compilation of parenthesized function literals. Needs investigation.
+  'S13.2.1_A1_T1': [SKIP],
 
-# TODO(mstarzinger): Causes stack overflow on simulators due to eager
-# compilation of parenthesized function literals. Needs investigation.
-S13.2.1_A1_T1: SKIP
-
-# BUG(3251225): Tests that timeout with --nocrankshaft.
-S15.1.3.1_A2.4_T1: SKIP
-S15.1.3.1_A2.5_T1: SKIP
-S15.1.3.2_A2.4_T1: SKIP
-S15.1.3.2_A2.5_T1: SKIP
-S15.1.3.3_A2.3_T1: SKIP
-S15.1.3.4_A2.3_T1: SKIP
+  # BUG(3251225): Tests that timeout with --nocrankshaft.
+  'S15.1.3.1_A2.4_T1': [SKIP],
+  'S15.1.3.1_A2.5_T1': [SKIP],
+  'S15.1.3.2_A2.4_T1': [SKIP],
+  'S15.1.3.2_A2.5_T1': [SKIP],
+  'S15.1.3.3_A2.3_T1': [SKIP],
+  'S15.1.3.4_A2.3_T1': [SKIP],
+}],  # 'arch == arm or arch == mipsel'
+]
diff --git a/test/webkit/webkit.status b/test/webkit/webkit.status
index 4aaf8a9..eba1be3 100644
--- a/test/webkit/webkit.status
+++ b/test/webkit/webkit.status
@@ -25,11 +25,12 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-# Too slow in debug mode.
-dfg-int-overflow-in-loop: PASS, SKIP if $mode == debug
-dfg-double-vote-fuzz: PASS, SKIP if $mode == debug
-reentrant-caching: PASS, SKIP if $mode == debug
-sort-large-array: PASS, SKIP if $mode == debug
-
-##############################################################################
-[ $deopt_fuzzer == True ]
+[
+['mode == debug', {
+  # Too slow in debug mode.
+  'dfg-int-overflow-in-loop': [SKIP],
+  'dfg-double-vote-fuzz': [SKIP],
+  'reentrant-caching': [SKIP],
+  'sort-large-array': [SKIP],
+}],  # 'mode == debug'
+]
diff --git a/tools/android-sync.sh b/tools/android-sync.sh
index 183b111..f172754 100755
--- a/tools/android-sync.sh
+++ b/tools/android-sync.sh
@@ -101,6 +101,7 @@
 sync_file tools/tickprocessor.js
 echo ""
 sync_dir tools/profviz
+sync_dir test/intl
 sync_dir test/message
 sync_dir test/mjsunit
 sync_dir test/preparser
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index f5d82df..1850c0e 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -432,7 +432,6 @@
         '../../src/platform/elapsed-timer.h',
         '../../src/platform/time.cc',
         '../../src/platform/time.h',
-        '../../src/platform-posix.h',
         '../../src/platform.h',
         '../../src/platform/condition-variable.cc',
         '../../src/platform/condition-variable.h',
@@ -806,6 +805,9 @@
           ]},
         ],
         ['OS=="win"', {
+          'defines': [
+            '_CRT_RAND_S'  # for rand_s()
+          ],
           'variables': {
             'gyp_generators': '<!(echo $GYP_GENERATORS)',
           },
diff --git a/tools/merge-to-branch.sh b/tools/merge-to-branch.sh
index e0011ed..260dc8a 100755
--- a/tools/merge-to-branch.sh
+++ b/tools/merge-to-branch.sh
@@ -229,7 +229,8 @@
   git checkout $BRANCHNAME \
     || die "cannot ensure that the current branch is $BRANCHNAME"
   wait_for_lgtm
-  git cl dcommit || die "failed to commit to $MERGE_TO_BRANCH"
+  PRESUBMIT_TREE_CHECK="skip" git cl dcommit \
+    || die "failed to commit to $MERGE_TO_BRANCH"
 fi
 
 let CURRENT_STEP+=1
diff --git a/tools/push-to-trunk.sh b/tools/push-to-trunk.sh
index 8512d12..c91cd19 100755
--- a/tools/push-to-trunk.sh
+++ b/tools/push-to-trunk.sh
@@ -211,7 +211,8 @@
     };
     print $0;
   }' > "$CHANGELOG_ENTRY_FILE"
-  git cl dcommit || die "'git cl dcommit' failed, please try again."
+  PRESUBMIT_TREE_CHECK="skip" git cl dcommit \
+    || die "'git cl dcommit' failed, please try again."
 fi
 
 let CURRENT_STEP+=1
diff --git a/tools/testrunner/local/old_statusfile.py b/tools/testrunner/local/old_statusfile.py
deleted file mode 100644
index d634e3e..0000000
--- a/tools/testrunner/local/old_statusfile.py
+++ /dev/null
@@ -1,462 +0,0 @@
-# Copyright 2012 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-import cStringIO
-import re
-
-# These outcomes can occur in a TestCase's outcomes list:
-SKIP = 'SKIP'
-FAIL = 'FAIL'
-PASS = 'PASS'
-OKAY = 'OKAY'
-TIMEOUT = 'TIMEOUT'
-CRASH = 'CRASH'
-SLOW = 'SLOW'
-FLAKY = 'FLAKY'
-# These are just for the status files and are mapped below in DEFS:
-FAIL_OK = 'FAIL_OK'
-PASS_OR_FAIL = 'PASS_OR_FAIL'
-
-KEYWORDS = {SKIP: SKIP,
-            FAIL: FAIL,
-            PASS: PASS,
-            OKAY: OKAY,
-            TIMEOUT: TIMEOUT,
-            CRASH: CRASH,
-            SLOW: SLOW,
-            FLAKY: FLAKY,
-            FAIL_OK: FAIL_OK,
-            PASS_OR_FAIL: PASS_OR_FAIL}
-
-class Expression(object):
-  pass
-
-
-class Constant(Expression):
-
-  def __init__(self, value):
-    self.value = value
-
-  def Evaluate(self, env, defs):
-    return self.value
-
-
-class Variable(Expression):
-
-  def __init__(self, name):
-    self.name = name
-
-  def GetOutcomes(self, env, defs):
-    if self.name in env: return set([env[self.name]])
-    else: return set([])
-
-  def Evaluate(self, env, defs):
-    return env[self.name]
-
-  def __str__(self):
-    return self.name
-
-  def string(self, logical):
-    return self.__str__()
-
-
-class Outcome(Expression):
-
-  def __init__(self, name):
-    self.name = name
-
-  def GetOutcomes(self, env, defs):
-    if self.name in defs:
-      return defs[self.name].GetOutcomes(env, defs)
-    else:
-      return set([self.name])
-
-  def __str__(self):
-    if self.name in KEYWORDS:
-      return "%s" % KEYWORDS[self.name]
-    return "'%s'" % self.name
-
-  def string(self, logical):
-    if logical:
-      return "%s" % self.name
-    return self.__str__()
-
-
-class Operation(Expression):
-
-  def __init__(self, left, op, right):
-    self.left = left
-    self.op = op
-    self.right = right
-
-  def Evaluate(self, env, defs):
-    if self.op == '||' or self.op == ',':
-      return self.left.Evaluate(env, defs) or self.right.Evaluate(env, defs)
-    elif self.op == 'if':
-      return False
-    elif self.op == '==':
-      return not self.left.GetOutcomes(env, defs).isdisjoint(self.right.GetOutcomes(env, defs))
-    elif self.op == '!=':
-      return self.left.GetOutcomes(env, defs).isdisjoint(self.right.GetOutcomes(env, defs))
-    else:
-      assert self.op == '&&'
-      return self.left.Evaluate(env, defs) and self.right.Evaluate(env, defs)
-
-  def GetOutcomes(self, env, defs):
-    if self.op == '||' or self.op == ',':
-      return self.left.GetOutcomes(env, defs) | self.right.GetOutcomes(env, defs)
-    elif self.op == 'if':
-      if self.right.Evaluate(env, defs): return self.left.GetOutcomes(env, defs)
-      else: return set([])
-    else:
-      assert self.op == '&&'
-      return self.left.GetOutcomes(env, defs) & self.right.GetOutcomes(env, defs)
-
-  def __str__(self):
-    return self.string(False)
-
-  def string(self, logical=False):
-    if self.op == 'if':
-      return "['%s', %s]" % (self.right.string(True), self.left.string(logical))
-    elif self.op == "||" or self.op == ",":
-      if logical:
-        return "%s or %s" % (self.left.string(True), self.right.string(True))
-      else:
-        return "%s, %s" % (self.left, self.right)
-    elif self.op == "&&":
-      return "%s and %s" % (self.left.string(True), self.right.string(True))
-    return "%s %s %s" % (self.left.string(logical), self.op,
-                         self.right.string(logical))
-
-
-def IsAlpha(string):
-  for char in string:
-    if not (char.isalpha() or char.isdigit() or char == '_'):
-      return False
-  return True
-
-
-class Tokenizer(object):
-  """A simple string tokenizer that chops expressions into variables,
-  parens and operators"""
-
-  def __init__(self, expr):
-    self.index = 0
-    self.expr = expr
-    self.length = len(expr)
-    self.tokens = None
-
-  def Current(self, length=1):
-    if not self.HasMore(length): return ""
-    return self.expr[self.index:self.index + length]
-
-  def HasMore(self, length=1):
-    return self.index < self.length + (length - 1)
-
-  def Advance(self, count=1):
-    self.index = self.index + count
-
-  def AddToken(self, token):
-    self.tokens.append(token)
-
-  def SkipSpaces(self):
-    while self.HasMore() and self.Current().isspace():
-      self.Advance()
-
-  def Tokenize(self):
-    self.tokens = [ ]
-    while self.HasMore():
-      self.SkipSpaces()
-      if not self.HasMore():
-        return None
-      if self.Current() == '(':
-        self.AddToken('(')
-        self.Advance()
-      elif self.Current() == ')':
-        self.AddToken(')')
-        self.Advance()
-      elif self.Current() == '$':
-        self.AddToken('$')
-        self.Advance()
-      elif self.Current() == ',':
-        self.AddToken(',')
-        self.Advance()
-      elif IsAlpha(self.Current()):
-        buf = ""
-        while self.HasMore() and IsAlpha(self.Current()):
-          buf += self.Current()
-          self.Advance()
-        self.AddToken(buf)
-      elif self.Current(2) == '&&':
-        self.AddToken('&&')
-        self.Advance(2)
-      elif self.Current(2) == '||':
-        self.AddToken('||')
-        self.Advance(2)
-      elif self.Current(2) == '==':
-        self.AddToken('==')
-        self.Advance(2)
-      elif self.Current(2) == '!=':
-        self.AddToken('!=')
-        self.Advance(2)
-      else:
-        return None
-    return self.tokens
-
-
-class Scanner(object):
-  """A simple scanner that can serve out tokens from a given list"""
-
-  def __init__(self, tokens):
-    self.tokens = tokens
-    self.length = len(tokens)
-    self.index = 0
-
-  def HasMore(self):
-    return self.index < self.length
-
-  def Current(self):
-    return self.tokens[self.index]
-
-  def Advance(self):
-    self.index = self.index + 1
-
-
-def ParseAtomicExpression(scan):
-  if scan.Current() == "true":
-    scan.Advance()
-    return Constant(True)
-  elif scan.Current() == "false":
-    scan.Advance()
-    return Constant(False)
-  elif IsAlpha(scan.Current()):
-    name = scan.Current()
-    scan.Advance()
-    return Outcome(name)
-  elif scan.Current() == '$':
-    scan.Advance()
-    if not IsAlpha(scan.Current()):
-      return None
-    name = scan.Current()
-    scan.Advance()
-    return Variable(name.lower())
-  elif scan.Current() == '(':
-    scan.Advance()
-    result = ParseLogicalExpression(scan)
-    if (not result) or (scan.Current() != ')'):
-      return None
-    scan.Advance()
-    return result
-  else:
-    return None
-
-
-BINARIES = ['==', '!=']
-def ParseOperatorExpression(scan):
-  left = ParseAtomicExpression(scan)
-  if not left: return None
-  while scan.HasMore() and (scan.Current() in BINARIES):
-    op = scan.Current()
-    scan.Advance()
-    right = ParseOperatorExpression(scan)
-    if not right:
-      return None
-    left = Operation(left, op, right)
-  return left
-
-
-def ParseConditionalExpression(scan):
-  left = ParseOperatorExpression(scan)
-  if not left: return None
-  while scan.HasMore() and (scan.Current() == 'if'):
-    scan.Advance()
-    right = ParseOperatorExpression(scan)
-    if not right:
-      return None
-    left = Operation(left, 'if', right)
-  return left
-
-
-LOGICALS = ["&&", "||", ","]
-def ParseLogicalExpression(scan):
-  left = ParseConditionalExpression(scan)
-  if not left: return None
-  while scan.HasMore() and (scan.Current() in LOGICALS):
-    op = scan.Current()
-    scan.Advance()
-    right = ParseConditionalExpression(scan)
-    if not right:
-      return None
-    left = Operation(left, op, right)
-  return left
-
-
-def ParseCondition(expr):
-  """Parses a logical expression into an Expression object"""
-  tokens = Tokenizer(expr).Tokenize()
-  if not tokens:
-    print "Malformed expression: '%s'" % expr
-    return None
-  scan = Scanner(tokens)
-  ast = ParseLogicalExpression(scan)
-  if not ast:
-    print "Malformed expression: '%s'" % expr
-    return None
-  if scan.HasMore():
-    print "Malformed expression: '%s'" % expr
-    return None
-  return ast
-
-
-class Section(object):
-  """A section of the configuration file.  Sections are enabled or
-  disabled prior to running the tests, based on their conditions"""
-
-  def __init__(self, condition):
-    self.condition = condition
-    self.rules = [ ]
-
-  def AddRule(self, rule):
-    self.rules.append(rule)
-
-
-class Rule(object):
-  """A single rule that specifies the expected outcome for a single
-  test."""
-
-  def __init__(self, raw_path, path, value):
-    self.raw_path = raw_path
-    self.path = path
-    self.value = value
-
-  def GetOutcomes(self, env, defs):
-    return self.value.GetOutcomes(env, defs)
-
-  def Contains(self, path):
-    if len(self.path) > len(path):
-      return False
-    for i in xrange(len(self.path)):
-      if not self.path[i].match(path[i]):
-        return False
-    return True
-
-
-HEADER_PATTERN = re.compile(r'\[([^]]+)\]')
-RULE_PATTERN = re.compile(r'\s*([^: ]*)\s*:(.*)')
-DEF_PATTERN = re.compile(r'^def\s*(\w+)\s*=(.*)$')
-PREFIX_PATTERN = re.compile(r'^\s*prefix\s+([\w\_\.\-\/]+)$')
-
-
-class ConvertNotation(object):
-  def __init__(self, path):
-    self.path = path
-    self.indent = ""
-    self.comment = []
-    self.init = False
-    self.section = False
-    self.out = cStringIO.StringIO()
-
-  def OpenGlobal(self):
-    if self.init: return
-    self.WriteComment()
-    print >> self.out, "["
-    self.init = True
-
-  def CloseGlobal(self):
-    if not self.init: self.OpenGlobal()
-    print >> self.out, "]"
-    self.init = False
-
-  def OpenSection(self, condition="ALWAYS"):
-    if self.section: return
-    self.OpenGlobal()
-    if type(condition) != str:
-      condition = "'%s'" % condition.string(True)
-    print >> self.out, "%s[%s, {" % (self.indent, condition)
-    self.indent += " " * 2
-    self.section = condition
-
-  def CloseSection(self):
-    if not self.section: return
-    self.indent = self.indent[:-2]
-    print >> self.out, "%s}],  # %s" % (self.indent, self.section)
-    self.section = False
-
-  def WriteComment(self):
-    if not self.comment: return
-    for c in self.comment:
-      if len(c.strip()) == 0:
-        print >> self.out, ""
-      else:
-        print >> self.out, "%s%s" % (self.indent, c),
-    self.comment = []
-
-  def GetOutput(self):
-    with open(self.path) as f:
-      for line in f:
-        if line[0] == '#':
-          self.comment += [line]
-          continue
-        if len(line.strip()) == 0:
-          self.comment += [line]
-          continue
-        header_match = HEADER_PATTERN.match(line)
-        if header_match:
-          condition = ParseCondition(header_match.group(1).strip())
-          self.CloseSection()
-          self.WriteComment()
-          self.OpenSection(condition)
-          continue
-        rule_match = RULE_PATTERN.match(line)
-        if rule_match:
-          self.OpenSection()
-          self.WriteComment()
-          path = rule_match.group(1).strip()
-          value_str = rule_match.group(2).strip()
-          comment = ""
-          if '#' in value_str:
-            pos = value_str.find('#')
-            comment = "  %s" % value_str[pos:].strip()
-            value_str = value_str[:pos].strip()
-          value = ParseCondition(value_str)
-          print >> self.out, ("%s'%s': [%s],%s" %
-                              (self.indent, path, value, comment))
-          continue
-        def_match = DEF_PATTERN.match(line)
-        if def_match:
-          # Custom definitions are deprecated.
-          continue
-        prefix_match = PREFIX_PATTERN.match(line)
-        if prefix_match:
-          continue
-        print "Malformed line: '%s'." % line
-    self.CloseSection()
-    self.CloseGlobal()
-    result = self.out.getvalue()
-    self.out.close()
-    return result
diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py
index dcb7fd5..7e01d3b 100644
--- a/tools/testrunner/local/statusfile.py
+++ b/tools/testrunner/local/statusfile.py
@@ -26,14 +26,6 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
-# These imports are required for the on-demand conversion from
-# old to new status file format.
-from os.path import exists
-from os.path import getmtime
-
-from . import old_statusfile
-
-
 # These outcomes can occur in a TestCase's outcomes list:
 SKIP = "SKIP"
 FAIL = "FAIL"
@@ -116,18 +108,6 @@
 
 
 def ReadStatusFile(path, variables):
-  # As long as the old-format .status files are authoritative, just
-  # create the converted version on demand and cache it to speed up
-  # subsequent runs.
-  if path.endswith(".status"):
-    newpath = path + "2"
-    if not exists(newpath) or getmtime(newpath) < getmtime(path):
-      print "Converting status file."
-      converted = old_statusfile.ConvertNotation(path).GetOutput()
-      with open(newpath, 'w') as f:
-        f.write(converted)
-    path = newpath
-
   with open(path) as f:
     global KEYWORDS
     contents = eval(f.read(), KEYWORDS)