Version 2.3.9

Fix compilation for ARMv4 on OpenBSD/FreeBSD.

Removed specialized handling of GCC 4.4 (issue 830).

Fixed DST cache to take into account the suspension of DST in Egypt during the 2010 Ramadan (issue http://crbug.com/51855).

Performance improvements on all platforms.


git-svn-id: http://v8.googlecode.com/svn/trunk@5295 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 136c82e..6df6411 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -1820,6 +1820,7 @@
   ASSERT(CpuFeatures::IsEnabled(VFP3));
   ASSERT(offset % 4 == 0);
   ASSERT((offset / 4) < 256);
+  ASSERT(offset >= 0);
   emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
        0xB*B8 | ((offset / 4) & 255));
 }
@@ -1836,6 +1837,7 @@
   ASSERT(CpuFeatures::IsEnabled(VFP3));
   ASSERT(offset % 4 == 0);
   ASSERT((offset / 4) < 256);
+  ASSERT(offset >= 0);
   emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
        0xA*B8 | ((offset / 4) & 255));
 }
@@ -1852,11 +1854,29 @@
   ASSERT(CpuFeatures::IsEnabled(VFP3));
   ASSERT(offset % 4 == 0);
   ASSERT((offset / 4) < 256);
+  ASSERT(offset >= 0);
   emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 |
        0xB*B8 | ((offset / 4) & 255));
 }
 
 
+void Assembler::vstr(const SwVfpRegister src,
+                     const Register base,
+                     int offset,
+                     const Condition cond) {
+  // MEM(Rbase + offset) = SSrc.
+  // Instruction details available in ARM DDI 0406A, A8-786.
+  // cond(31-28) | 1101(27-24)| 1000(23-20) | Rbase(19-16) |
+  // Vdst(15-12) | 1010(11-8) | (offset/4)
+  ASSERT(CpuFeatures::IsEnabled(VFP3));
+  ASSERT(offset % 4 == 0);
+  ASSERT((offset / 4) < 256);
+  ASSERT(offset >= 0);
+  emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 |
+       0xA*B8 | ((offset / 4) & 255));
+}
+
+
 static void DoubleAsTwoUInt32(double d, uint32_t* lo, uint32_t* hi) {
   uint64_t i;
   memcpy(&i, &d, 8);
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 218eb97..cc6ec05 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -966,6 +966,11 @@
             int offset,  // Offset must be a multiple of 4.
             const Condition cond = al);
 
+  void vstr(const SwVfpRegister src,
+            const Register base,
+            int offset,  // Offset must be a multiple of 4.
+            const Condition cond = al);
+
   void vmov(const DwVfpRegister dst,
             double imm,
             const Condition cond = al);
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index df17b6f..15f34b5 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -3445,12 +3445,18 @@
   frame_->EmitPush(Operand(Smi::FromInt(node->literal_index())));
   frame_->EmitPush(Operand(node->constant_elements()));
   int length = node->values()->length();
-  if (node->depth() > 1) {
+  if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
+    frame_->CallStub(&stub, 3);
+    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2);
+  } else if (node->depth() > 1) {
     frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
-  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
   } else {
-    FastCloneShallowArrayStub stub(length);
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
     frame_->CallStub(&stub, 3);
   }
   frame_->EmitPush(r0);  // save the result
@@ -5402,7 +5408,7 @@
   __ tst(tmp2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
   deferred->Branch(nz);
 
-  // Check the object's elements are in fast case.
+  // Check the object's elements are in fast case and writable.
   __ ldr(tmp1, FieldMemOperand(object, JSObject::kElementsOffset));
   __ ldr(tmp2, FieldMemOperand(tmp1, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
@@ -6694,15 +6700,9 @@
       __ cmp(scratch1, scratch2);
       deferred->Branch(ne);
 
-      // Get the elements array from the receiver and check that it
-      // is not a dictionary.
+      // Get the elements array from the receiver.
       __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset));
-      if (FLAG_debug_code) {
-        __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset));
-        __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
-        __ cmp(scratch2, ip);
-        __ Assert(eq, "JSObject with fast elements map has slow elements");
-      }
+      __ AssertFastElements(scratch1);
 
       // Check that key is within bounds. Use unsigned comparison to handle
       // negative keys.
@@ -7112,6 +7112,26 @@
   __ cmp(r3, ip);
   __ b(eq, &slow_case);
 
+  if (FLAG_debug_code) {
+    const char* message;
+    Heap::RootListIndex expected_map_index;
+    if (mode_ == CLONE_ELEMENTS) {
+      message = "Expected (writable) fixed array";
+      expected_map_index = Heap::kFixedArrayMapRootIndex;
+    } else {
+      ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS);
+      message = "Expected copy-on-write fixed array";
+      expected_map_index = Heap::kFixedCOWArrayMapRootIndex;
+    }
+    __ push(r3);
+    __ ldr(r3, FieldMemOperand(r3, JSArray::kElementsOffset));
+    __ ldr(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
+    __ LoadRoot(ip, expected_map_index);
+    __ cmp(r3, ip);
+    __ Assert(eq, message);
+    __ pop(r3);
+  }
+
   // Allocate both the JS array and the elements array in one big
   // allocation. This avoids multiple limit checks.
   __ AllocateInNewSpace(size,
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 029d599..8a632a9 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -278,7 +278,7 @@
 
   // Constants related to patching of inlined load/store.
   static int GetInlinedKeyedLoadInstructionsAfterPatch() {
-    return FLAG_debug_code ? 27 : 13;
+    return FLAG_debug_code ? 32 : 13;
   }
   static const int kInlinedKeyedStoreInstructionsAfterPatch = 5;
   static int GetInlinedNamedStoreInstructionsAfterPatch() {
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index b58a4a5..f3adab2 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1223,12 +1223,18 @@
   __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
   __ mov(r1, Operand(expr->constant_elements()));
   __ Push(r3, r2, r1);
-  if (expr->depth() > 1) {
+  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
+    __ CallStub(&stub);
+    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1, r1, r2);
+  } else if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
-  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
   } else {
-    FastCloneShallowArrayStub stub(length);
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
     __ CallStub(&stub);
   }
 
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 1fd7098..abc0922 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -414,17 +414,17 @@
 // Falls through for regular JS object.
 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
                                            Register receiver,
-                                           Register scratch1,
-                                           Register scratch2,
+                                           Register map,
+                                           Register scratch,
                                            int interceptor_bit,
                                            Label* slow) {
   // Check that the object isn't a smi.
   __ BranchOnSmi(receiver, slow);
   // Get the map of the receiver.
-  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
   // Check bit field.
-  __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
-  __ tst(scratch2,
+  __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
+  __ tst(scratch,
          Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)));
   __ b(nz, slow);
   // Check that the object is some kind of JS object EXCEPT JS Value type.
@@ -432,13 +432,14 @@
   // we enter the runtime system to make sure that indexing into string
   // objects work as intended.
   ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
-  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
-  __ cmp(scratch1, Operand(JS_OBJECT_TYPE));
+  __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  __ cmp(scratch, Operand(JS_OBJECT_TYPE));
   __ b(lt, slow);
 }
 
 
 // Loads an indexed element from a fast case array.
+// If not_fast_array is NULL, doesn't perform the elements map check.
 static void GenerateFastArrayLoad(MacroAssembler* masm,
                                   Register receiver,
                                   Register key,
@@ -471,11 +472,15 @@
   // scratch2 - used to hold the loaded value.
 
   __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
-  __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
-  __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
-  __ cmp(scratch1, ip);
-  __ b(ne, not_fast_array);
+  if (not_fast_array != NULL) {
+    // Check that the object is in fast mode and writable.
+    __ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
+    __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
+    __ cmp(scratch1, ip);
+    __ b(ne, not_fast_array);
+  } else {
+    __ AssertFastElements(elements);
+  }
   // Check that the key (index) is within bounds.
   __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
   __ cmp(key, Operand(scratch1));
@@ -1120,16 +1125,23 @@
   GenerateKeyedLoadReceiverCheck(
       masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow);
 
+  // Check the "has fast elements" bit in the receiver's map which is
+  // now in r2.
+  __ ldrb(r3, FieldMemOperand(r2, Map::kBitField2Offset));
+  __ tst(r3, Operand(1 << Map::kHasFastElements));
+  __ b(eq, &check_pixel_array);
+
   GenerateFastArrayLoad(
-      masm, receiver, key, r4, r3, r2, r0, &check_pixel_array, &slow);
+      masm, receiver, key, r4, r3, r2, r0, NULL, &slow);
   __ IncrementCounter(&Counters::keyed_load_generic_smi, 1, r2, r3);
   __ Ret();
 
   // Check whether the elements is a pixel array.
   // r0: key
-  // r3: elements map
-  // r4: elements
+  // r1: receiver
   __ bind(&check_pixel_array);
+  __ ldr(r4, FieldMemOperand(r1, JSObject::kElementsOffset));
+  __ ldr(r3, FieldMemOperand(r4, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kPixelArrayMapRootIndex);
   __ cmp(r3, ip);
   __ b(ne, &check_number_dictionary);
@@ -1690,7 +1702,7 @@
 
   // Object case: Check key against length in the elements array.
   __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
+  // Check that the object is in fast mode and writable.
   __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
   __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
   __ cmp(r4, ip);
@@ -1748,8 +1760,8 @@
   __ b(&fast);
 
   // Array case: Get the length and the elements array from the JS
-  // array. Check that the array is in fast mode; if it is the
-  // length is always a smi.
+  // array. Check that the array is in fast mode (and writable); if it
+  // is the length is always a smi.
   __ bind(&array);
   __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
   __ ldr(r4, FieldMemOperand(elements, HeapObject::kMapOffset));
@@ -1779,19 +1791,22 @@
 }
 
 
-// Convert int passed in register ival to IEE 754 single precision
-// floating point value and store it into register fval.
+// Convert and store int passed in register ival to IEEE 754 single precision
+// floating point value at memory location (dst + 4 * wordoffset)
 // If VFP3 is available use it for conversion.
-static void ConvertIntToFloat(MacroAssembler* masm,
-                              Register ival,
-                              Register fval,
-                              Register scratch1,
-                              Register scratch2) {
+static void StoreIntAsFloat(MacroAssembler* masm,
+                            Register dst,
+                            Register wordoffset,
+                            Register ival,
+                            Register fval,
+                            Register scratch1,
+                            Register scratch2) {
   if (CpuFeatures::IsSupported(VFP3)) {
     CpuFeatures::Scope scope(VFP3);
     __ vmov(s0, ival);
+    __ add(scratch1, dst, Operand(wordoffset, LSL, 2));
     __ vcvt_f32_s32(s0, s0);
-    __ vmov(fval, s0);
+    __ vstr(s0, scratch1, 0);
   } else {
     Label not_special, done;
     // Move sign bit from source to destination.  This works because the sign
@@ -1841,6 +1856,7 @@
            Operand(ival, LSR, kBitsPerInt - kBinary32MantissaBits));
 
     __ bind(&done);
+    __ str(fval, MemOperand(dst, wordoffset, LSL, 2));
   }
 }
 
@@ -1935,9 +1951,8 @@
       __ str(r5, MemOperand(r3, r4, LSL, 2));
       break;
     case kExternalFloatArray:
-      // Need to perform int-to-float conversion.
-      ConvertIntToFloat(masm, r5, r6, r7, r9);
-      __ str(r6, MemOperand(r3, r4, LSL, 2));
+      // Perform int-to-float conversion and store to memory.
+      StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
       break;
     default:
       UNREACHABLE();
@@ -1971,9 +1986,9 @@
       // include -kHeapObjectTag into it.
       __ sub(r5, r0, Operand(kHeapObjectTag));
       __ vldr(d0, r5, HeapNumber::kValueOffset);
+      __ add(r5, r3, Operand(r4, LSL, 2));
       __ vcvt_f32_f64(s0, d0);
-      __ vmov(r5, s0);
-      __ str(r5, MemOperand(r3, r4, LSL, 2));
+      __ vstr(s0, r5, 0);
     } else {
       // Need to perform float-to-int conversion.
       // Test for NaN or infinity (both give zero).
@@ -2217,6 +2232,8 @@
   __ b(ne, &miss);
 
   // Check that elements are FixedArray.
+  // We rely on StoreIC_ArrayLength below to deal with all types of
+  // fast elements (including COW).
   __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset));
   __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE);
   __ b(ne, &miss);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 38c7c28..2058ee2 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1567,6 +1567,25 @@
 }
 
 
+void MacroAssembler::AssertFastElements(Register elements) {
+  if (FLAG_debug_code) {
+    ASSERT(!elements.is(ip));
+    Label ok;
+    push(elements);
+    ldr(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
+    LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
+    cmp(elements, ip);
+    b(eq, &ok);
+    LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
+    cmp(elements, ip);
+    b(eq, &ok);
+    Abort("JSObject with fast elements map has slow elements");
+    bind(&ok);
+    pop(elements);
+  }
+}
+
+
 void MacroAssembler::Check(Condition cc, const char* msg) {
   Label L;
   b(cc, &L);
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 836ed74..7843f00 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -597,6 +597,7 @@
   // Use --debug_code to enable.
   void Assert(Condition cc, const char* msg);
   void AssertRegisterIsRoot(Register reg, Heap::RootListIndex index);
+  void AssertFastElements(Register elements);
 
   // Like Assert(), but always enabled.
   void Check(Condition cc, const char* msg);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index fa90ca7..2a7c22d 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -1297,11 +1297,6 @@
   // Check that the maps haven't changed.
   CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss);
 
-  if (object->IsGlobalObject()) {
-    __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
-    __ str(r3, MemOperand(sp, argc * kPointerSize));
-  }
-
   __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
                                argc + 1,
                                1);
@@ -1349,11 +1344,6 @@
   // Check that the maps haven't changed.
   CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss);
 
-  if (object->IsGlobalObject()) {
-    __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
-    __ str(r3, MemOperand(sp, argc * kPointerSize));
-  }
-
   __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
                                argc + 1,
                                1);
diff --git a/src/builtins.cc b/src/builtins.cc
index 3a0393e..eedee9f 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -269,6 +269,7 @@
                          int src_index,
                          int len) {
   ASSERT(dst != src);  // Use MoveElements instead.
+  ASSERT(dst->map() != Heap::fixed_cow_array_map());
   ASSERT(len > 0);
   CopyWords(dst->data_start() + dst_index,
             src->data_start() + src_index,
@@ -286,6 +287,7 @@
                          FixedArray* src,
                          int src_index,
                          int len) {
+  ASSERT(dst->map() != Heap::fixed_cow_array_map());
   memmove(dst->data_start() + dst_index,
           src->data_start() + src_index,
           len * kPointerSize);
@@ -297,11 +299,13 @@
 
 
 static void FillWithHoles(FixedArray* dst, int from, int to) {
+  ASSERT(dst->map() != Heap::fixed_cow_array_map());
   MemsetPointer(dst->data_start() + from, Heap::the_hole_value(), to - from);
 }
 
 
 static FixedArray* LeftTrimFixedArray(FixedArray* elms, int to_trim) {
+  ASSERT(elms->map() != Heap::fixed_cow_array_map());
   // For now this trick is only applied to fixed arrays in new space.
   // In large object space the object's start must coincide with chunk
   // and thus the trick is just not applicable.
@@ -348,33 +352,24 @@
 }
 
 
-static bool IsJSArrayWithFastElements(Object* receiver,
-                                      FixedArray** elements) {
-  if (!receiver->IsJSArray()) {
-    return false;
-  }
-
+static inline Object* EnsureJSArrayWithWritableFastElements(Object* receiver) {
+  if (!receiver->IsJSArray()) return NULL;
   JSArray* array = JSArray::cast(receiver);
-
   HeapObject* elms = HeapObject::cast(array->elements());
-  if (elms->map() != Heap::fixed_array_map()) {
-    return false;
+  if (elms->map() == Heap::fixed_array_map()) return elms;
+  if (elms->map() == Heap::fixed_cow_array_map()) {
+    return array->EnsureWritableFastElements();
   }
-
-  *elements = FixedArray::cast(elms);
-  return true;
+  return NULL;
 }
 
 
-static bool IsFastElementMovingAllowed(Object* receiver,
-                                       FixedArray** elements) {
-  if (!IsJSArrayWithFastElements(receiver, elements)) return false;
-
+static inline bool IsJSArrayFastElementMovingAllowed(JSArray* receiver) {
   Context* global_context = Top::context()->global_context();
   JSObject* array_proto =
       JSObject::cast(global_context->array_function()->prototype());
-  if (JSArray::cast(receiver)->GetPrototype() != array_proto) return false;
-  return ArrayPrototypeHasNoElements(global_context, array_proto);
+  return receiver->GetPrototype() == array_proto &&
+         ArrayPrototypeHasNoElements(global_context, array_proto);
 }
 
 
@@ -405,10 +400,10 @@
 
 BUILTIN(ArrayPush) {
   Object* receiver = *args.receiver();
-  FixedArray* elms = NULL;
-  if (!IsJSArrayWithFastElements(receiver, &elms)) {
-    return CallJsBuiltin("ArrayPush", args);
-  }
+  Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
+  if (elms_obj == NULL) return CallJsBuiltin("ArrayPush", args);
+  if (elms_obj->IsFailure()) return elms_obj;
+  FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
 
   int len = Smi::cast(array->length())->value();
@@ -454,10 +449,10 @@
 
 BUILTIN(ArrayPop) {
   Object* receiver = *args.receiver();
-  FixedArray* elms = NULL;
-  if (!IsJSArrayWithFastElements(receiver, &elms)) {
-    return CallJsBuiltin("ArrayPop", args);
-  }
+  Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
+  if (elms_obj == NULL) return CallJsBuiltin("ArrayPop", args);
+  if (elms_obj->IsFailure()) return elms_obj;
+  FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
 
   int len = Smi::cast(array->length())->value();
@@ -483,10 +478,13 @@
 
 BUILTIN(ArrayShift) {
   Object* receiver = *args.receiver();
-  FixedArray* elms = NULL;
-  if (!IsFastElementMovingAllowed(receiver, &elms)) {
+  Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
+  if (elms_obj->IsFailure()) return elms_obj;
+  if (elms_obj == NULL ||
+      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
     return CallJsBuiltin("ArrayShift", args);
   }
+  FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
   ASSERT(array->HasFastElements());
 
@@ -519,10 +517,13 @@
 
 BUILTIN(ArrayUnshift) {
   Object* receiver = *args.receiver();
-  FixedArray* elms = NULL;
-  if (!IsFastElementMovingAllowed(receiver, &elms)) {
+  Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
+  if (elms_obj->IsFailure()) return elms_obj;
+  if (elms_obj == NULL ||
+      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
     return CallJsBuiltin("ArrayUnshift", args);
   }
+  FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
   ASSERT(array->HasFastElements());
 
@@ -568,10 +569,13 @@
 
 BUILTIN(ArraySlice) {
   Object* receiver = *args.receiver();
-  FixedArray* elms = NULL;
-  if (!IsFastElementMovingAllowed(receiver, &elms)) {
+  Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
+  if (elms_obj->IsFailure()) return elms_obj;
+  if (elms_obj == NULL ||
+      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
     return CallJsBuiltin("ArraySlice", args);
   }
+  FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
   ASSERT(array->HasFastElements());
 
@@ -637,10 +641,13 @@
 
 BUILTIN(ArraySplice) {
   Object* receiver = *args.receiver();
-  FixedArray* elms = NULL;
-  if (!IsFastElementMovingAllowed(receiver, &elms)) {
+  Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
+  if (elms_obj->IsFailure()) return elms_obj;
+  if (elms_obj == NULL ||
+      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
     return CallJsBuiltin("ArraySplice", args);
   }
+  FixedArray* elms = FixedArray::cast(elms_obj);
   JSArray* array = JSArray::cast(receiver);
   ASSERT(array->HasFastElements());
 
diff --git a/src/codegen.h b/src/codegen.h
index 3b31c04..353e186 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -181,6 +181,7 @@
   CodeGenerator* previous_;
 };
 
+
 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
 
 // State of used registers in a virtual frame.
@@ -395,20 +396,33 @@
 
 class FastCloneShallowArrayStub : public CodeStub {
  public:
-  static const int kMaximumLength = 8;
+  // Maximum length of copied elements array.
+  static const int kMaximumClonedLength = 8;
 
-  explicit FastCloneShallowArrayStub(int length) : length_(length) {
-    ASSERT(length >= 0 && length <= kMaximumLength);
+  enum Mode {
+    CLONE_ELEMENTS,
+    COPY_ON_WRITE_ELEMENTS
+  };
+
+  FastCloneShallowArrayStub(Mode mode, int length)
+      : mode_(mode),
+        length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
+    ASSERT(length_ >= 0);
+    ASSERT(length_ <= kMaximumClonedLength);
   }
 
   void Generate(MacroAssembler* masm);
 
  private:
+  Mode mode_;
   int length_;
 
   const char* GetName() { return "FastCloneShallowArrayStub"; }
   Major MajorKey() { return FastCloneShallowArray; }
-  int MinorKey() { return length_; }
+  int MinorKey() {
+    ASSERT(mode_ == 0 || mode_ == 1);
+    return (length_ << 1) | mode_;
+  }
 };
 
 
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index 14252a5..7402e68 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -79,10 +79,9 @@
   // young generation.
   void Age();
 
-  bool HasFunction(SharedFunctionInfo* function_info);
-
   // GC support.
   void Iterate(ObjectVisitor* v);
+  void IterateFunctions(ObjectVisitor* v);
 
   // Clear this sub-cache evicting all its content.
   void Clear();
@@ -206,27 +205,6 @@
 }
 
 
-bool CompilationSubCache::HasFunction(SharedFunctionInfo* function_info) {
-  if (function_info->script()->IsUndefined() ||
-      Script::cast(function_info->script())->source()->IsUndefined()) {
-    return false;
-  }
-
-  String* source =
-      String::cast(Script::cast(function_info->script())->source());
-  // Check all generations.
-  for (int generation = 0; generation < generations(); generation++) {
-    if (tables_[generation]->IsUndefined()) continue;
-
-    CompilationCacheTable* table =
-        CompilationCacheTable::cast(tables_[generation]);
-    Object* object = table->Lookup(source);
-    if (object->IsSharedFunctionInfo()) return true;
-  }
-  return false;
-}
-
-
 void CompilationSubCache::Age() {
   // Age the generations implicitly killing off the oldest.
   for (int i = generations_ - 1; i > 0; i--) {
@@ -238,6 +216,16 @@
 }
 
 
+void CompilationSubCache::IterateFunctions(ObjectVisitor* v) {
+  Object* undefined = Heap::raw_unchecked_undefined_value();
+  for (int i = 0; i < generations_; i++) {
+    if (tables_[i] != undefined) {
+      reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v);
+    }
+  }
+}
+
+
 void CompilationSubCache::Iterate(ObjectVisitor* v) {
   v->VisitPointers(&tables_[0], &tables_[generations_]);
 }
@@ -528,12 +516,6 @@
   }
 }
 
-
-bool CompilationCache::HasFunction(SharedFunctionInfo* function_info) {
-  return script.HasFunction(function_info);
-}
-
-
 void CompilationCache::Iterate(ObjectVisitor* v) {
   for (int i = 0; i < kSubCacheCount; i++) {
     subcaches[i]->Iterate(v);
@@ -541,6 +523,13 @@
 }
 
 
+void CompilationCache::IterateFunctions(ObjectVisitor* v) {
+  for (int i = 0; i < kSubCacheCount; i++) {
+    subcaches[i]->IterateFunctions(v);
+  }
+}
+
+
 void CompilationCache::MarkCompactPrologue() {
   for (int i = 0; i < kSubCacheCount; i++) {
     subcaches[i]->Age();
diff --git a/src/compilation-cache.h b/src/compilation-cache.h
index 583f04c..22ecff8 100644
--- a/src/compilation-cache.h
+++ b/src/compilation-cache.h
@@ -79,11 +79,9 @@
   // Clear the cache - also used to initialize the cache at startup.
   static void Clear();
 
-
-  static bool HasFunction(SharedFunctionInfo* function_info);
-
   // GC support.
   static void Iterate(ObjectVisitor* v);
+  static void IterateFunctions(ObjectVisitor* v);
 
   // Notify the cache that a mark-sweep garbage collection is about to
   // take place. This is used to retire entries from the cache to
diff --git a/src/compiler.cc b/src/compiler.cc
index 9f0162e..ff3cb7a 100755
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -454,6 +454,7 @@
 
   // Check the function has compiled code.
   ASSERT(shared->is_compiled());
+  shared->set_code_age(0);
   return true;
 }
 
diff --git a/src/contexts.h b/src/contexts.h
index d1c98bd..181efc9 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -243,7 +243,8 @@
 
   GlobalObject* global() {
     Object* result = get(GLOBAL_INDEX);
-    ASSERT(IsBootstrappingOrGlobalObject(result));
+    ASSERT(Heap::gc_state() != Heap::NOT_IN_GC ||
+           IsBootstrappingOrGlobalObject(result));
     return reinterpret_cast<GlobalObject*>(result);
   }
   void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); }
diff --git a/src/date.js b/src/date.js
index 9c42a04..b101ea6 100644
--- a/src/date.js
+++ b/src/date.js
@@ -137,12 +137,18 @@
   // Time interval where the cached offset is valid.
   start: 0, end: -1,
   // Size of next interval expansion.
-  increment: 0
+  increment: 0,
+  initial_increment: 19 * msPerDay
 };
 
 
 // NOTE: The implementation relies on the fact that no time zones have
-// more than one daylight savings offset change per month.
+// more than one daylight savings offset change per 19 days.
+//
+// In Egypt in 2010 they decided to suspend DST during Ramadan. This
+// led to a short interval where DST is in effect from September 10 to
+// September 30.
+//
 // If this function is called with NaN it returns NaN.
 function DaylightSavingsOffset(t) {
   // Load the cache object from the builtins object.
@@ -171,7 +177,7 @@
         // the offset in the cache, we grow the cached time interval
         // and return the offset.
         cache.end = new_end;
-        cache.increment = msPerMonth;
+        cache.increment = cache.initial_increment;
         return end_offset;
       } else {
         var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
@@ -182,7 +188,7 @@
           // the interval to reflect this and reset the increment.
           cache.start = t;
           cache.end = new_end;
-          cache.increment = msPerMonth;
+          cache.increment = cache.initial_increment;
         } else {
           // The interval contains a DST offset change and the given time is
           // before it. Adjust the increment to avoid a linear search for
@@ -207,7 +213,7 @@
   var offset = %DateDaylightSavingsOffset(EquivalentTime(t));
   cache.offset = offset;
   cache.start = cache.end = t;
-  cache.increment = msPerMonth;
+  cache.increment = cache.initial_increment;
   return offset;
 }
 
diff --git a/src/debug.cc b/src/debug.cc
index c13c8c9..1234196 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -461,6 +461,8 @@
       KeyedStoreIC::ClearInlinedVersion(pc());
     } else if (code->is_load_stub()) {
       LoadIC::ClearInlinedVersion(pc());
+    } else if (code->is_store_stub()) {
+      StoreIC::ClearInlinedVersion(pc());
     }
   }
 }
@@ -549,6 +551,7 @@
   thread_local_.after_break_target_ = 0;
   thread_local_.debugger_entry_ = NULL;
   thread_local_.pending_interrupts_ = 0;
+  thread_local_.restarter_frame_function_pointer_ = NULL;
 }
 
 
diff --git a/src/frames.cc b/src/frames.cc
index bdd5100..9f815c3 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -372,8 +372,8 @@
 }
 
 
-Code* EntryFrame::code() const {
-  return Heap::js_entry_code();
+Code* EntryFrame::unchecked_code() const {
+  return Heap::raw_unchecked_js_entry_code();
 }
 
 
@@ -395,8 +395,8 @@
 }
 
 
-Code* EntryConstructFrame::code() const {
-  return Heap::js_construct_entry_code();
+Code* EntryConstructFrame::unchecked_code() const {
+  return Heap::raw_unchecked_js_construct_entry_code();
 }
 
 
@@ -406,8 +406,8 @@
 }
 
 
-Code* ExitFrame::code() const {
-  return Code::cast(code_slot());
+Code* ExitFrame::unchecked_code() const {
+  return reinterpret_cast<Code*>(code_slot());
 }
 
 
@@ -493,22 +493,22 @@
 }
 
 
-Code* JavaScriptFrame::code() const {
+Code* JavaScriptFrame::unchecked_code() const {
   JSFunction* function = JSFunction::cast(this->function());
-  return function->shared()->code();
+  return function->unchecked_code();
 }
 
 
-Code* ArgumentsAdaptorFrame::code() const {
+Code* ArgumentsAdaptorFrame::unchecked_code() const {
   return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline);
 }
 
 
-Code* InternalFrame::code() const {
+Code* InternalFrame::unchecked_code() const {
   const int offset = InternalFrameConstants::kCodeOffset;
   Object* code = Memory::Object_at(fp() + offset);
   ASSERT(code != NULL);
-  return Code::cast(code);
+  return reinterpret_cast<Code*>(code);
 }
 
 
diff --git a/src/frames.h b/src/frames.h
index 102244c..cb791d2 100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -112,7 +112,13 @@
 
   // Opaque data type for identifying stack frames. Used extensively
   // by the debugger.
-  enum Id { NO_ID = 0 };
+  // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
+  // has correct value range (see Issue 830 for more details).
+  enum Id {
+    ID_MIN_VALUE = kMinInt,
+    ID_MAX_VALUE = kMaxInt,
+    NO_ID = 0
+  };
 
   // Copy constructor; it breaks the connection to host iterator.
   StackFrame(const StackFrame& original) {
@@ -152,7 +158,13 @@
   virtual Type type() const = 0;
 
   // Get the code associated with this frame.
-  virtual Code* code() const = 0;
+  // This method could be called during marking phase of GC.
+  virtual Code* unchecked_code() const = 0;
+
+  // Get the code associated with this frame.
+  inline Code* code() const {
+    return Code::cast(unchecked_code());
+  }
 
   // Garbage collection support.
   static void CookFramesForThread(ThreadLocalTop* thread);
@@ -218,7 +230,7 @@
  public:
   virtual Type type() const { return ENTRY; }
 
-  virtual Code* code() const;
+  virtual Code* unchecked_code() const;
 
   // Garbage collection support.
   virtual void Iterate(ObjectVisitor* v) const;
@@ -249,7 +261,7 @@
  public:
   virtual Type type() const { return ENTRY_CONSTRUCT; }
 
-  virtual Code* code() const;
+  virtual Code* unchecked_code() const;
 
   static EntryConstructFrame* cast(StackFrame* frame) {
     ASSERT(frame->is_entry_construct());
@@ -271,7 +283,7 @@
   enum Mode { MODE_NORMAL, MODE_DEBUG };
   virtual Type type() const { return EXIT; }
 
-  virtual Code* code() const;
+  virtual Code* unchecked_code() const;
 
   Object*& code_slot() const;
 
@@ -397,7 +409,7 @@
                      int index) const;
 
   // Determine the code for the frame.
-  virtual Code* code() const;
+  virtual Code* unchecked_code() const;
 
   static JavaScriptFrame* cast(StackFrame* frame) {
     ASSERT(frame->is_java_script());
@@ -433,7 +445,7 @@
   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
 
   // Determine the code for the frame.
-  virtual Code* code() const;
+  virtual Code* unchecked_code() const;
 
   static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
     ASSERT(frame->is_arguments_adaptor());
@@ -463,7 +475,7 @@
   virtual void Iterate(ObjectVisitor* v) const;
 
   // Determine the code for the frame.
-  virtual Code* code() const;
+  virtual Code* unchecked_code() const;
 
   static InternalFrame* cast(StackFrame* frame) {
     ASSERT(frame->is_internal());
diff --git a/src/handles.cc b/src/handles.cc
index 7b76e92..0146401 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -773,6 +773,7 @@
                  ClearExceptionFlag flag) {
   if (function->shared()->is_compiled()) {
     function->set_code(function->shared()->code());
+    function->shared()->set_code_age(0);
     return true;
   } else {
     CompilationInfo info(function, 0, receiver);
@@ -788,6 +789,7 @@
                        ClearExceptionFlag flag) {
   if (function->shared()->is_compiled()) {
     function->set_code(function->shared()->code());
+    function->shared()->set_code_age(0);
     return true;
   } else {
     CompilationInfo info(function, 1, receiver);
diff --git a/src/heap.cc b/src/heap.cc
index 1d696c7..5f46fa7 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -637,12 +637,6 @@
   int start_new_space_size = Heap::new_space()->Size();
 
   if (collector == MARK_COMPACTOR) {
-    if (FLAG_flush_code) {
-      // Flush all potentially unused code.
-      GCTracer::Scope gc_scope(tracer, GCTracer::Scope::MC_FLUSH_CODE);
-      FlushCode();
-    }
-
     // Perform mark-sweep with optional compaction.
     MarkCompact(tracer);
 
@@ -1100,6 +1094,10 @@
                     &ObjectEvacuationStrategy<POINTER_OBJECT>::
                         VisitSpecialized<SharedFunctionInfo::kSize>);
 
+    table_.Register(kVisitJSFunction,
+                    &ObjectEvacuationStrategy<POINTER_OBJECT>::
+                    VisitSpecialized<JSFunction::kSize>);
+
     table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>,
                                    kVisitDataObject,
                                    kVisitDataObjectGeneric>();
@@ -1457,6 +1455,11 @@
   oddball_map()->set_prototype(null_value());
   oddball_map()->set_constructor(null_value());
 
+  obj = AllocateMap(FIXED_ARRAY_TYPE, FixedArray::kHeaderSize);
+  if (obj->IsFailure()) return false;
+  set_fixed_cow_array_map(Map::cast(obj));
+  ASSERT(fixed_array_map() != fixed_cow_array_map());
+
   obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
   if (obj->IsFailure()) return false;
   set_heap_number_map(Map::cast(obj));
@@ -2354,109 +2357,6 @@
 }
 
 
-// The StackVisitor is used to traverse all the archived threads to see if
-// there are activations on any of the stacks corresponding to the code.
-class FlushingStackVisitor : public ThreadVisitor {
- public:
-  explicit FlushingStackVisitor(Code* code) : found_(false), code_(code) {}
-
-  void VisitThread(ThreadLocalTop* top) {
-    // If we already found the code in a previous traversed thread we return.
-    if (found_) return;
-
-    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
-      if (code_->contains(it.frame()->pc())) {
-        found_ = true;
-        return;
-      }
-    }
-  }
-  bool FoundCode() {return found_;}
-
- private:
-  bool found_;
-  Code* code_;
-};
-
-
-static bool CodeIsActive(Code* code) {
-  // Make sure we are not referencing the code from the stack.
-  for (StackFrameIterator it; !it.done(); it.Advance()) {
-    if (code->contains(it.frame()->pc())) return true;
-  }
-  // Iterate the archived stacks in all threads to check if
-  // the code is referenced.
-  FlushingStackVisitor threadvisitor(code);
-  ThreadManager::IterateArchivedThreads(&threadvisitor);
-  if (threadvisitor.FoundCode()) return true;
-  return false;
-}
-
-
-static void FlushCodeForFunction(JSFunction* function) {
-  SharedFunctionInfo* shared_info = function->shared();
-
-  // Special handling if the function and shared info objects
-  // have different code objects.
-  if (function->code() != shared_info->code()) {
-    // If the shared function has been flushed but the function has not,
-    // we flush the function if possible.
-    if (!shared_info->is_compiled() && function->is_compiled() &&
-        !CodeIsActive(function->code())) {
-      function->set_code(shared_info->code());
-    }
-    return;
-  }
-
-  // The function must be compiled and have the source code available,
-  // to be able to recompile it in case we need the function again.
-  if (!(shared_info->is_compiled() && shared_info->HasSourceCode())) return;
-
-  // We never flush code for Api functions.
-  if (shared_info->IsApiFunction()) return;
-
-  // Only flush code for functions.
-  if (!shared_info->code()->kind() == Code::FUNCTION) return;
-
-  // Function must be lazy compilable.
-  if (!shared_info->allows_lazy_compilation()) return;
-
-  // If this is a full script wrapped in a function we do no flush the code.
-  if (shared_info->is_toplevel()) return;
-
-  // If this function is in the compilation cache we do not flush the code.
-  if (CompilationCache::HasFunction(shared_info)) return;
-
-  // Check stack and archived threads for the code.
-  if (CodeIsActive(shared_info->code())) return;
-
-  // Compute the lazy compilable version of the code.
-  Code* code = Builtins::builtin(Builtins::LazyCompile);
-  shared_info->set_code(code);
-  function->set_code(code);
-}
-
-
-void Heap::FlushCode() {
-#ifdef ENABLE_DEBUGGER_SUPPORT
-  // Do not flush code if the debugger is loaded or there are breakpoints.
-  if (Debug::IsLoaded() || Debug::has_break_points()) return;
-#endif
-  HeapObjectIterator it(old_pointer_space());
-  for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
-    if (obj->IsJSFunction()) {
-      JSFunction* function = JSFunction::cast(obj);
-
-      // The function must have a valid context and not be a builtin.
-      if (function->unchecked_context()->IsContext() &&
-          !function->IsBuiltin()) {
-        FlushCodeForFunction(function);
-      }
-    }
-  }
-}
-
-
 Object* Heap::CreateCode(const CodeDesc& desc,
                          Code::Flags flags,
                          Handle<Object> self_reference) {
@@ -2910,7 +2810,9 @@
   FixedArray* properties = FixedArray::cast(source->properties());
   // Update elements if necessary.
   if (elements->length() > 0) {
-    Object* elem = CopyFixedArray(elements);
+    Object* elem =
+        (elements->map() == fixed_cow_array_map()) ?
+        elements : CopyFixedArray(elements);
     if (elem->IsFailure()) return elem;
     JSObject::cast(clone)->set_elements(FixedArray::cast(elem));
   }
@@ -4057,8 +3959,8 @@
 
 
 void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
-  *stats->start_marker = 0xDECADE00;
-  *stats->end_marker = 0xDECADE01;
+  *stats->start_marker = HeapStats::kStartMarker;
+  *stats->end_marker = HeapStats::kEndMarker;
   *stats->new_space_size = new_space_.Size();
   *stats->new_space_capacity = new_space_.Capacity();
   *stats->old_pointer_space_size = old_pointer_space_->Size();
@@ -4815,7 +4717,6 @@
     PrintF("sweep=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP]));
     PrintF("sweepns=%d ", static_cast<int>(scopes_[Scope::MC_SWEEP_NEWSPACE]));
     PrintF("compact=%d ", static_cast<int>(scopes_[Scope::MC_COMPACT]));
-    PrintF("flushcode=%d ", static_cast<int>(scopes_[Scope::MC_FLUSH_CODE]));
 
     PrintF("total_size_before=%d ", start_size_);
     PrintF("total_size_after=%d ", Heap::SizeOfObjects());
diff --git a/src/heap.h b/src/heap.h
index 93b90b1..45fee17 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -55,6 +55,7 @@
   V(Map, heap_number_map, HeapNumberMap)                                       \
   V(Map, global_context_map, GlobalContextMap)                                 \
   V(Map, fixed_array_map, FixedArrayMap)                                       \
+  V(Map, fixed_cow_array_map, FixedCOWArrayMap)                                \
   V(Object, no_interceptor_result_sentinel, NoInterceptorResultSentinel)       \
   V(Map, meta_map, MetaMap)                                                    \
   V(Object, termination_exception, TerminationException)                       \
@@ -1257,10 +1258,6 @@
   // Flush the number to string cache.
   static void FlushNumberStringCache();
 
-  // Flush code from functions we do not expect to use again. The code will
-  // be replaced with a lazy compilable version.
-  static void FlushCode();
-
   static void UpdateSurvivalRateTrend(int start_new_space_size);
 
   enum SurvivalRateTrend { INCREASING, STABLE, DECREASING, FLUCTUATING };
@@ -1322,6 +1319,9 @@
 
 class HeapStats {
  public:
+  static const int kStartMarker = 0xDECADE00;
+  static const int kEndMarker = 0xDECADE01;
+
   int* start_marker;                    //  0
   int* new_space_size;                  //  1
   int* new_space_capacity;              //  2
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index cc89cc7..02a03fc 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -5712,12 +5712,18 @@
   frame_->Push(node->constant_elements());
   int length = node->values()->length();
   Result clone;
-  if (node->depth() > 1) {
+  if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
+    clone = frame_->CallStub(&stub, 3);
+    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+  } else if (node->depth() > 1) {
     clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
-  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
   } else {
-    FastCloneShallowArrayStub stub(length);
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
     clone = frame_->CallStub(&stub, 3);
   }
   frame_->Push(&clone);
@@ -5727,12 +5733,9 @@
   for (int i = 0; i < length; i++) {
     Expression* value = node->values()->at(i);
 
-    // If value is a literal the property value is already set in the
-    // boilerplate object.
-    if (value->AsLiteral() != NULL) continue;
-    // If value is a materialized literal the property value is already set
-    // in the boilerplate object if it is simple.
-    if (CompileTimeValue::IsCompileTimeValue(value)) continue;
+    if (!CompileTimeValue::ArrayLiteralElementNeedsInitialization(value)) {
+      continue;
+    }
 
     // The property must be set by generated code.
     Load(value);
@@ -7601,7 +7604,7 @@
             KeyedLoadIC::kSlowCaseBitFieldMask);
   deferred->Branch(not_zero);
 
-  // Check the object's elements are in fast case.
+  // Check the object's elements are in fast case and writable.
   __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
   __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
          Immediate(Factory::fixed_array_map()));
@@ -9496,15 +9499,10 @@
       if (FLAG_debug_code) __ AbortIfNotSmi(key.reg());
     }
 
-    // Get the elements array from the receiver and check that it
-    // is not a dictionary.
+    // Get the elements array from the receiver.
     __ mov(elements.reg(),
            FieldOperand(receiver.reg(), JSObject::kElementsOffset));
-    if (FLAG_debug_code) {
-      __ cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset),
-             Immediate(Factory::fixed_array_map()));
-      __ Assert(equal, "JSObject with fast elements map has slow elements");
-    }
+    __ AssertFastElements(elements.reg());
 
     // Check that the key is within bounds.
     __ cmp(key.reg(),
@@ -9901,6 +9899,24 @@
   __ cmp(ecx, Factory::undefined_value());
   __ j(equal, &slow_case);
 
+  if (FLAG_debug_code) {
+    const char* message;
+    Handle<Map> expected_map;
+    if (mode_ == CLONE_ELEMENTS) {
+      message = "Expected (writable) fixed array";
+      expected_map = Factory::fixed_array_map();
+    } else {
+      ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS);
+      message = "Expected copy-on-write fixed array";
+      expected_map = Factory::fixed_cow_array_map();
+    }
+    __ push(ecx);
+    __ mov(ecx, FieldOperand(ecx, JSArray::kElementsOffset));
+    __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), expected_map);
+    __ Assert(equal, message);
+    __ pop(ecx);
+  }
+
   // Allocate both the JS array and the elements array in one big
   // allocation. This avoids multiple limit checks.
   __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index cb36904..68a0a96 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1326,12 +1326,18 @@
   __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
   __ push(Immediate(Smi::FromInt(expr->literal_index())));
   __ push(Immediate(expr->constant_elements()));
-  if (expr->depth() > 1) {
+  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
+    __ CallStub(&stub);
+    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+  } else if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
-  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
   } else {
-    FastCloneShallowArrayStub stub(length);
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
     __ CallStub(&stub);
   }
 
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 2cd41a1..283ae4d 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -452,6 +452,7 @@
 
 
 // Loads an indexed element from a fast case array.
+// If not_fast_array is NULL, doesn't perform the elements map check.
 static void GenerateFastArrayLoad(MacroAssembler* masm,
                                   Register receiver,
                                   Register key,
@@ -468,8 +469,12 @@
   //            we fall through.
 
   __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
-  __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true);
+  if (not_fast_array != NULL) {
+    // Check that the object is in fast mode and writable.
+    __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true);
+  } else {
+    __ AssertFastElements(scratch);
+  }
   // Check that the key (index) is within bounds.
   __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
   __ j(above_equal, out_of_range);
@@ -558,12 +563,18 @@
   GenerateKeyedLoadReceiverCheck(
       masm, edx, ecx, Map::kHasIndexedInterceptor, &slow);
 
+  // Check the "has fast elements" bit in the receiver's map which is
+  // now in ecx.
+  __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
+            1 << Map::kHasFastElements);
+  __ j(zero, &check_pixel_array, not_taken);
+
   GenerateFastArrayLoad(masm,
                         edx,
                         eax,
                         ecx,
                         eax,
-                        &check_pixel_array,
+                        NULL,
                         &slow);
   __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
   __ ret(0);
@@ -572,7 +583,7 @@
   // Check whether the elements is a pixel array.
   // edx: receiver
   // eax: key
-  // ecx: elements
+  __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
   __ mov(ebx, eax);
   __ SmiUntag(ebx);
   __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true);
@@ -967,7 +978,7 @@
   // edx: JSObject
   // ecx: key (a smi)
   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
+  // Check that the object is in fast mode and writable.
   __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true);
   __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
   __ j(below, &fast, taken);
@@ -1023,8 +1034,8 @@
   __ jmp(&fast);
 
   // Array case: Get the length and the elements array from the JS
-  // array. Check that the array is in fast mode; if it is the
-  // length is always a smi.
+  // array. Check that the array is in fast mode (and writable); if it
+  // is the length is always a smi.
   __ bind(&array);
   // eax: value
   // edx: receiver, a JSArray
@@ -1872,6 +1883,8 @@
   __ j(not_equal, &miss, not_taken);
 
   // Check that elements are FixedArray.
+  // We rely on StoreIC_ArrayLength below to deal with all types of
+  // fast elements (including COW).
   __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
   __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
   __ j(not_equal, &miss, not_taken);
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 2453846..658caf1 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -1464,6 +1464,21 @@
 }
 
 
+void MacroAssembler::AssertFastElements(Register elements) {
+  if (FLAG_debug_code) {
+    Label ok;
+    cmp(FieldOperand(elements, HeapObject::kMapOffset),
+        Immediate(Factory::fixed_array_map()));
+    j(equal, &ok);
+    cmp(FieldOperand(elements, HeapObject::kMapOffset),
+        Immediate(Factory::fixed_cow_array_map()));
+    j(equal, &ok);
+    Abort("JSObject with fast elements map has slow elements");
+    bind(&ok);
+  }
+}
+
+
 void MacroAssembler::Check(Condition cc, const char* msg) {
   Label L;
   j(cc, &L, taken);
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 0b16f0d..c23f687 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -508,6 +508,8 @@
   // Use --debug_code to enable.
   void Assert(Condition cc, const char* msg);
 
+  void AssertFastElements(Register elements);
+
   // Like Assert(), but always enabled.
   void Check(Condition cc, const char* msg);
 
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index b2c9dab..c6c65f0 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -1366,16 +1366,18 @@
     __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
     __ ret((argc + 1) * kPointerSize);
   } else {
+    Label call_builtin;
+
     // Get the elements array of the object.
     __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
 
-    // Check that the elements are in fast mode (not dictionary).
+    // Check that the elements are in fast mode and writable.
     __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
            Immediate(Factory::fixed_array_map()));
-    __ j(not_equal, &miss);
+    __ j(not_equal, &call_builtin);
 
     if (argc == 1) {  // Otherwise fall through to call builtin.
-      Label call_builtin, exit, with_write_barrier, attempt_to_grow_elements;
+      Label exit, with_write_barrier, attempt_to_grow_elements;
 
       // Get the array's length into eax and calculate new length.
       __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
@@ -1456,10 +1458,9 @@
 
       // Elements are in new space, so write barrier is not required.
       __ ret((argc + 1) * kPointerSize);
-
-      __ bind(&call_builtin);
     }
 
+    __ bind(&call_builtin);
     __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
                                  argc + 1,
                                  1);
@@ -1511,10 +1512,10 @@
   // Get the elements array of the object.
   __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
 
-  // Check that the elements are in fast mode (not dictionary).
+  // Check that the elements are in fast mode and writable.
   __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
          Immediate(Factory::fixed_array_map()));
-  __ j(not_equal, &miss);
+  __ j(not_equal, &call_builtin);
 
   // Get the array's length into ecx and calculate new length.
   __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset));
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index c9afc62..5dfde94 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -478,11 +478,9 @@
 
   OffsetsVector registers(required_registers);
 
-  IrregexpResult res = IrregexpExecOnce(jsregexp,
-                                        subject,
-                                        previous_index,
-                                        Vector<int>(registers.vector(),
-                                                    registers.length()));
+  IrregexpResult res = RegExpImpl::IrregexpExecOnce(
+      jsregexp, subject, previous_index, Vector<int>(registers.vector(),
+                                                     registers.length()));
   if (res == RE_SUCCESS) {
     int capture_register_count =
         (IrregexpNumberOfCaptures(FixedArray::cast(jsregexp->data())) + 1) * 2;
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 1a020e5..c5eabeb 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -27,6 +27,7 @@
 
 #include "v8.h"
 
+#include "compilation-cache.h"
 #include "execution.h"
 #include "heap-profiler.h"
 #include "global-handles.h"
@@ -252,6 +253,15 @@
     table_.GetVisitor(map)(map, obj);
   }
 
+  static void EnableCodeFlushing(bool enabled) {
+    if (enabled) {
+      table_.Register(kVisitJSFunction, &VisitJSFunction);
+    } else {
+      table_.Register(kVisitJSFunction,
+                      &JSObjectVisitor::VisitSpecialized<JSFunction::kSize>);
+    }
+  }
+
   static void Initialize() {
     table_.Register(kVisitShortcutCandidate,
                     &FixedBodyVisitor<StaticMarkingVisitor,
@@ -289,6 +299,8 @@
 
     table_.Register(kVisitCode, &VisitCode);
 
+    table_.Register(kVisitJSFunction, &VisitJSFunction);
+
     table_.Register(kVisitPropertyCell,
                     &FixedBodyVisitor<StaticMarkingVisitor,
                                       JSGlobalPropertyCell::BodyDescriptor,
@@ -405,6 +417,134 @@
     reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>();
   }
 
+  // Code flushing support.
+
+  // How many collections newly compiled code object will survive before being
+  // flushed.
+  static const int kCodeAgeThreshold = 5;
+
+  inline static bool HasSourceCode(SharedFunctionInfo* info) {
+    Object* undefined = Heap::raw_unchecked_undefined_value();
+    return (info->script() != undefined) &&
+        (reinterpret_cast<Script*>(info->script())->source() != undefined);
+  }
+
+
+  inline static bool IsCompiled(JSFunction* function) {
+    return
+        function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile);
+  }
+
+
+  inline static bool IsCompiled(SharedFunctionInfo* function) {
+    return
+        function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile);
+  }
+
+
+  static void FlushCodeForFunction(JSFunction* function) {
+    SharedFunctionInfo* shared_info = function->unchecked_shared();
+
+    if (shared_info->IsMarked()) return;
+
+    // Special handling if the function and shared info objects
+    // have different code objects.
+    if (function->unchecked_code() != shared_info->unchecked_code()) {
+      // If the shared function has been flushed but the function has not,
+      // we flush the function if possible.
+      if (!IsCompiled(shared_info) &&
+          IsCompiled(function) &&
+          !function->unchecked_code()->IsMarked()) {
+        function->set_code(shared_info->unchecked_code());
+      }
+      return;
+    }
+
+    // Code is either on stack or in compilation cache.
+    if (shared_info->unchecked_code()->IsMarked()) {
+      shared_info->set_code_age(0);
+      return;
+    }
+
+    // The function must be compiled and have the source code available,
+    // to be able to recompile it in case we need the function again.
+    if (!(shared_info->is_compiled() && HasSourceCode(shared_info))) return;
+
+    // We never flush code for Api functions.
+    Object* function_data = shared_info->function_data();
+    if (function_data->IsHeapObject() &&
+        (SafeMap(function_data)->instance_type() ==
+         FUNCTION_TEMPLATE_INFO_TYPE)) {
+      return;
+    }
+
+    // Only flush code for functions.
+    if (shared_info->code()->kind() != Code::FUNCTION) return;
+
+    // Function must be lazy compilable.
+    if (!shared_info->allows_lazy_compilation()) return;
+
+    // If this is a full script wrapped in a function we do no flush the code.
+    if (shared_info->is_toplevel()) return;
+
+    // Age this shared function info.
+    if (shared_info->code_age() < kCodeAgeThreshold) {
+      shared_info->set_code_age(shared_info->code_age() + 1);
+      return;
+    }
+
+    // Compute the lazy compilable version of the code.
+    Code* code = Builtins::builtin(Builtins::LazyCompile);
+    shared_info->set_code(code);
+    function->set_code(code);
+  }
+
+
+  static inline Map* SafeMap(Object* obj) {
+    MapWord map_word = HeapObject::cast(obj)->map_word();
+    map_word.ClearMark();
+    map_word.ClearOverflow();
+    return map_word.ToMap();
+  }
+
+
+  static inline bool IsJSBuiltinsObject(Object* obj) {
+    return obj->IsHeapObject() &&
+        (SafeMap(obj)->instance_type() == JS_BUILTINS_OBJECT_TYPE);
+  }
+
+
+  static inline bool IsValidNotBuiltinContext(Object* ctx) {
+    if (!ctx->IsHeapObject()) return false;
+
+    Map* map = SafeMap(ctx);
+    if (!(map == Heap::raw_unchecked_context_map() ||
+          map == Heap::raw_unchecked_catch_context_map() ||
+          map == Heap::raw_unchecked_global_context_map())) {
+      return false;
+    }
+
+    Context* context = reinterpret_cast<Context*>(ctx);
+
+    if (IsJSBuiltinsObject(context->global())) {
+      return false;
+    }
+
+    return true;
+  }
+
+
+  static void VisitJSFunction(Map* map, HeapObject* object) {
+    JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
+
+    // The function must have a valid context and not be a builtin.
+    if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
+      FlushCodeForFunction(jsfunction);
+    }
+
+    JSObjectVisitor::VisitSpecialized<JSFunction::kSize>(map, object);
+  }
+
   typedef void (*Callback)(Map* map, HeapObject* object);
 
   static VisitorDispatchTable<Callback> table_;
@@ -435,6 +575,62 @@
 };
 
 
+class CodeMarkingVisitor : public ThreadVisitor {
+ public:
+  void VisitThread(ThreadLocalTop* top) {
+    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
+      MarkCompactCollector::MarkObject(it.frame()->unchecked_code());
+    }
+  }
+};
+
+
+class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
+ public:
+  void VisitPointers(Object** start, Object** end) {
+    for (Object** p = start; p < end; p++) VisitPointer(p);
+  }
+
+  void VisitPointer(Object** slot) {
+    Object* obj = *slot;
+    if (obj->IsHeapObject()) {
+      MarkCompactCollector::MarkObject(HeapObject::cast(obj));
+    }
+  }
+};
+
+
+void MarkCompactCollector::PrepareForCodeFlushing() {
+  if (!FLAG_flush_code) {
+    StaticMarkingVisitor::EnableCodeFlushing(false);
+    return;
+  }
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+  if (Debug::IsLoaded() || Debug::has_break_points()) {
+    StaticMarkingVisitor::EnableCodeFlushing(false);
+    return;
+  }
+#endif
+  StaticMarkingVisitor::EnableCodeFlushing(true);
+
+  // Make sure we are not referencing the code from the stack.
+  for (StackFrameIterator it; !it.done(); it.Advance()) {
+    MarkCompactCollector::MarkObject(it.frame()->unchecked_code());
+  }
+
+  // Iterate the archived stacks in all threads to check if
+  // the code is referenced.
+  CodeMarkingVisitor code_marking_visitor;
+  ThreadManager::IterateArchivedThreads(&code_marking_visitor);
+
+  SharedFunctionInfoMarkingVisitor visitor;
+  CompilationCache::IterateFunctions(&visitor);
+
+  MarkCompactCollector::ProcessMarkingStack();
+}
+
+
 // Visitor class for marking heap roots.
 class RootMarkingVisitor : public ObjectVisitor {
  public:
@@ -793,6 +989,8 @@
 
   ASSERT(!marking_stack.overflowed());
 
+  PrepareForCodeFlushing();
+
   RootMarkingVisitor root_visitor;
   MarkRoots(&root_visitor);
 
diff --git a/src/mark-compact.h b/src/mark-compact.h
index ad63586..a5fd8d3 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -175,6 +175,10 @@
   friend class RootMarkingVisitor;
   friend class MarkingVisitor;
   friend class StaticMarkingVisitor;
+  friend class CodeMarkingVisitor;
+  friend class SharedFunctionInfoMarkingVisitor;
+
+  static void PrepareForCodeFlushing();
 
   // Marking operations for objects reachable from roots.
   static void MarkLiveObjects();
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index d340e4b..0a97128 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -540,7 +540,8 @@
               map()->NextFreePropertyIndex()));
   }
   ASSERT(map()->has_fast_elements() ==
-         (elements()->map() == Heap::fixed_array_map()));
+         (elements()->map() == Heap::fixed_array_map() ||
+          elements()->map() == Heap::fixed_cow_array_map()));
   ASSERT(map()->has_fast_elements() == HasFastElements());
 }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 5e8022e..c70ab02 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1167,7 +1167,8 @@
 
 void JSObject::set_elements(HeapObject* value, WriteBarrierMode mode) {
   ASSERT(map()->has_fast_elements() ==
-         (value->map() == Heap::fixed_array_map()));
+         (value->map() == Heap::fixed_array_map() ||
+          value->map() == Heap::fixed_cow_array_map()));
   // In the assert below Dictionary is covered under FixedArray.
   ASSERT(value->IsFixedArray() || value->IsPixelArray() ||
          value->IsExternalArray());
@@ -1397,6 +1398,7 @@
 
 
 void FixedArray::set(int index, Smi* value) {
+  ASSERT(map() != Heap::fixed_cow_array_map());
   ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
@@ -1404,6 +1406,7 @@
 
 
 void FixedArray::set(int index, Object* value) {
+  ASSERT(map() != Heap::fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
@@ -1420,6 +1423,7 @@
 void FixedArray::set(int index,
                      Object* value,
                      WriteBarrierMode mode) {
+  ASSERT(map() != Heap::fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
   int offset = kHeaderSize + index * kPointerSize;
   WRITE_FIELD(this, offset, value);
@@ -1428,6 +1432,7 @@
 
 
 void FixedArray::fast_set(FixedArray* array, int index, Object* value) {
+  ASSERT(array->map() != Heap::raw_unchecked_fixed_cow_array_map());
   ASSERT(index >= 0 && index < array->length());
   ASSERT(!Heap::InNewSpace(value));
   WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
@@ -1435,6 +1440,7 @@
 
 
 void FixedArray::set_undefined(int index) {
+  ASSERT(map() != Heap::fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
   ASSERT(!Heap::InNewSpace(Heap::undefined_value()));
   WRITE_FIELD(this, kHeaderSize + index * kPointerSize,
@@ -1443,6 +1449,7 @@
 
 
 void FixedArray::set_null(int index) {
+  ASSERT(map() != Heap::fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
   ASSERT(!Heap::InNewSpace(Heap::null_value()));
   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
@@ -1450,12 +1457,27 @@
 
 
 void FixedArray::set_the_hole(int index) {
+  ASSERT(map() != Heap::fixed_cow_array_map());
   ASSERT(index >= 0 && index < this->length());
   ASSERT(!Heap::InNewSpace(Heap::the_hole_value()));
   WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::the_hole_value());
 }
 
 
+void FixedArray::set_unchecked(int index, Smi* value) {
+  ASSERT(reinterpret_cast<Object*>(value)->IsSmi());
+  int offset = kHeaderSize + index * kPointerSize;
+  WRITE_FIELD(this, offset, value);
+}
+
+
+void FixedArray::set_null_unchecked(int index) {
+  ASSERT(index >= 0 && index < this->length());
+  ASSERT(!Heap::InNewSpace(Heap::null_value()));
+  WRITE_FIELD(this, kHeaderSize + index * kPointerSize, Heap::null_value());
+}
+
+
 Object** FixedArray::data_start() {
   return HeapObject::RawField(this, kHeaderSize);
 }
@@ -2398,6 +2420,7 @@
   if (obj->IsFailure()) return obj;
   Map* new_map = Map::cast(obj);
   new_map->set_has_fast_elements(true);
+  Counters::map_slow_to_fast_elements.Increment();
   return new_map;
 }
 
@@ -2408,6 +2431,7 @@
   if (obj->IsFailure()) return obj;
   Map* new_map = Map::cast(obj);
   new_map->set_has_fast_elements(false);
+  Counters::map_fast_to_slow_elements.Increment();
   return new_map;
 }
 
@@ -2539,6 +2563,7 @@
                allows_lazy_compilation,
                kAllowLazyCompilation)
 
+
 #if V8_HOST_ARCH_32_BIT
 SMI_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
 SMI_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
@@ -2638,6 +2663,11 @@
 }
 
 
+Code* SharedFunctionInfo::unchecked_code() {
+  return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
+}
+
+
 void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
   WRITE_FIELD(this, kCodeOffset, value);
   CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, mode);
@@ -2684,6 +2714,17 @@
 }
 
 
+int SharedFunctionInfo::code_age() {
+  return (compiler_hints() >> kCodeAgeShift) & kCodeAgeMask;
+}
+
+
+void SharedFunctionInfo::set_code_age(int code_age) {
+  set_compiler_hints(compiler_hints() |
+                     ((code_age & kCodeAgeMask) << kCodeAgeShift));
+}
+
+
 bool JSFunction::IsBuiltin() {
   return context()->global()->IsJSBuiltinsObject();
 }
@@ -2694,6 +2735,11 @@
 }
 
 
+Code* JSFunction::unchecked_code() {
+  return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
+}
+
+
 void JSFunction::set_code(Code* value) {
   // Skip the write barrier because code is never in new space.
   ASSERT(!Heap::InNewSpace(value));
@@ -2711,6 +2757,12 @@
 }
 
 
+SharedFunctionInfo* JSFunction::unchecked_shared() {
+  return reinterpret_cast<SharedFunctionInfo*>(
+      READ_FIELD(this, kSharedFunctionInfoOffset));
+}
+
+
 void JSFunction::set_context(Object* value) {
   ASSERT(value == Heap::undefined_value() || value->IsContext());
   WRITE_FIELD(this, kContextOffset, value);
@@ -2928,18 +2980,18 @@
 
 
 JSObject::ElementsKind JSObject::GetElementsKind() {
+  if (map()->has_fast_elements()) {
+    ASSERT(elements()->map() == Heap::fixed_array_map() ||
+           elements()->map() == Heap::fixed_cow_array_map());
+    return FAST_ELEMENTS;
+  }
   HeapObject* array = elements();
   if (array->IsFixedArray()) {
-    // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a FixedArray.
-    if (array->map() == Heap::fixed_array_map()) {
-      ASSERT(map()->has_fast_elements());
-      return FAST_ELEMENTS;
-    }
+    // FAST_ELEMENTS or DICTIONARY_ELEMENTS are both stored in a
+    // FixedArray, but FAST_ELEMENTS is already handled above.
     ASSERT(array->IsDictionary());
-    ASSERT(!map()->has_fast_elements());
     return DICTIONARY_ELEMENTS;
   }
-  ASSERT(!map()->has_fast_elements());
   if (array->IsExternalArray()) {
     switch (array->map()->instance_type()) {
       case EXTERNAL_BYTE_ARRAY_TYPE:
@@ -3042,6 +3094,19 @@
 }
 
 
+Object* JSObject::EnsureWritableFastElements() {
+  ASSERT(HasFastElements());
+  FixedArray* elems = FixedArray::cast(elements());
+  if (elems->map() != Heap::fixed_cow_array_map()) return elems;
+  Object* writable_elems = Heap::CopyFixedArray(elems);
+  if (writable_elems->IsFailure()) return writable_elems;
+  FixedArray::cast(writable_elems)->set_map(Heap::fixed_array_map());
+  set_elements(FixedArray::cast(writable_elems));
+  Counters::cow_arrays_converted.Increment();
+  return writable_elems;
+}
+
+
 StringDictionary* JSObject::property_dictionary() {
   ASSERT(!HasFastProperties());
   return StringDictionary::cast(properties());
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index 293c9bf..c35e02c 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -101,7 +101,6 @@
     case JS_VALUE_TYPE:
     case JS_ARRAY_TYPE:
     case JS_REGEXP_TYPE:
-    case JS_FUNCTION_TYPE:
     case JS_GLOBAL_PROXY_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
     case JS_BUILTINS_OBJECT_TYPE:
@@ -109,6 +108,9 @@
                                  kVisitJSObjectGeneric,
                                  instance_size);
 
+    case JS_FUNCTION_TYPE:
+      return kVisitJSFunction;
+
     case HEAP_NUMBER_TYPE:
     case PIXEL_ARRAY_TYPE:
     case EXTERNAL_BYTE_ARRAY_TYPE:
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index 6280bac..335a4be 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -100,6 +100,7 @@
     kVisitMap,
     kVisitPropertyCell,
     kVisitSharedFunctionInfo,
+    kVisitJSFunction,
 
     kVisitorIdCount,
     kMinObjectSizeInWords = 2
@@ -204,6 +205,7 @@
 
   template<int object_size>
   static inline ReturnType VisitSpecialized(Map* map, HeapObject* object) {
+    ASSERT(BodyDescriptor::SizeOf(map, object) == object_size);
     IteratePointers(object, BodyDescriptor::kStartOffset, object_size);
     return static_cast<ReturnType>(object_size);
   }
@@ -268,6 +270,10 @@
 
     table_.Register(kVisitSeqTwoByteString, &VisitSeqTwoByteString);
 
+    table_.Register(kVisitJSFunction,
+                    &JSObjectVisitor::
+                        template VisitSpecialized<JSFunction::kSize>);
+
     table_.RegisterSpecializations<DataObjectVisitor,
                                    kVisitDataObject,
                                    kVisitDataObjectGeneric>();
@@ -275,8 +281,8 @@
                                    kVisitJSObject,
                                    kVisitJSObjectGeneric>();
     table_.RegisterSpecializations<StructVisitor,
-        kVisitStruct,
-        kVisitStructGeneric>();
+                                   kVisitStruct,
+                                   kVisitStructGeneric>();
   }
 
   static inline int IterateBody(Map* map, HeapObject* obj) {
diff --git a/src/objects.cc b/src/objects.cc
index 5687a3a..8359aa3 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2338,6 +2338,8 @@
   ASSERT(!HasPixelElements() && !HasExternalArrayElements());
   switch (GetElementsKind()) {
     case FAST_ELEMENTS: {
+      Object* obj = EnsureWritableFastElements();
+      if (obj->IsFailure()) return obj;
       uint32_t length = IsJSArray() ?
       static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
       static_cast<uint32_t>(FixedArray::cast(elements())->length());
@@ -2418,6 +2420,8 @@
 
   switch (GetElementsKind()) {
     case FAST_ELEMENTS: {
+      Object* obj = EnsureWritableFastElements();
+      if (obj->IsFailure()) return obj;
       uint32_t length = IsJSArray() ?
       static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
       static_cast<uint32_t>(FixedArray::cast(elements())->length());
@@ -5009,8 +5013,8 @@
       ASSERT(target->IsHeapObject());
       if (!target->IsMarked()) {
         ASSERT(target->IsMap());
-        contents->set(i + 1, NullDescriptorDetails);
-        contents->set_null(i);
+        contents->set_unchecked(i + 1, NullDescriptorDetails);
+        contents->set_null_unchecked(i);
         ASSERT(target->prototype() == this ||
                target->prototype() == real_prototype);
         // Getter prototype() is read-only, set_prototype() has side effects.
@@ -5095,7 +5099,7 @@
 
 bool SharedFunctionInfo::HasSourceCode() {
   return !script()->IsUndefined() &&
-         !Script::cast(script())->source()->IsUndefined();
+         !reinterpret_cast<Script*>(script())->source()->IsUndefined();
 }
 
 
@@ -5591,6 +5595,8 @@
         int old_capacity = FixedArray::cast(elements())->length();
         if (value <= old_capacity) {
           if (IsJSArray()) {
+            Object* obj = EnsureWritableFastElements();
+            if (obj->IsFailure()) return obj;
             int old_length = FastD2I(JSArray::cast(this)->length()->Number());
             // NOTE: We may be able to optimize this by removing the
             // last part of the elements backing storage array and
@@ -6051,7 +6057,9 @@
 Object* JSObject::SetFastElement(uint32_t index, Object* value) {
   ASSERT(HasFastElements());
 
-  FixedArray* elms = FixedArray::cast(elements());
+  Object* elms_obj = EnsureWritableFastElements();
+  if (elms_obj->IsFailure()) return elms_obj;
+  FixedArray* elms = FixedArray::cast(elms_obj);
   uint32_t elms_length = static_cast<uint32_t>(elms->length());
 
   if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
@@ -6095,6 +6103,7 @@
   return SetElement(index, value);
 }
 
+
 Object* JSObject::SetElement(uint32_t index, Object* value) {
   // Check access rights if needed.
   if (IsAccessCheckNeeded() &&
@@ -7573,6 +7582,9 @@
 
     set_map(new_map);
     set_elements(fast_elements);
+  } else {
+    Object* obj = EnsureWritableFastElements();
+    if (obj->IsFailure()) return obj;
   }
   ASSERT(HasFastElements());
 
diff --git a/src/objects.h b/src/objects.h
index d2f6d35..65e0f36 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -230,19 +230,21 @@
   V(CONS_SYMBOL_TYPE)                                                          \
   V(CONS_ASCII_SYMBOL_TYPE)                                                    \
   V(EXTERNAL_SYMBOL_TYPE)                                                      \
+  V(EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE)                                      \
   V(EXTERNAL_ASCII_SYMBOL_TYPE)                                                \
   V(STRING_TYPE)                                                               \
   V(ASCII_STRING_TYPE)                                                         \
   V(CONS_STRING_TYPE)                                                          \
   V(CONS_ASCII_STRING_TYPE)                                                    \
   V(EXTERNAL_STRING_TYPE)                                                      \
+  V(EXTERNAL_STRING_WITH_ASCII_DATA_TYPE)                                      \
   V(EXTERNAL_ASCII_STRING_TYPE)                                                \
   V(PRIVATE_EXTERNAL_ASCII_STRING_TYPE)                                        \
                                                                                \
   V(MAP_TYPE)                                                                  \
   V(CODE_TYPE)                                                                 \
-  V(JS_GLOBAL_PROPERTY_CELL_TYPE)                                              \
   V(ODDBALL_TYPE)                                                              \
+  V(JS_GLOBAL_PROPERTY_CELL_TYPE)                                              \
                                                                                \
   V(HEAP_NUMBER_TYPE)                                                          \
   V(PROXY_TYPE)                                                                \
@@ -260,11 +262,9 @@
   V(EXTERNAL_FLOAT_ARRAY_TYPE)                                                 \
   V(FILLER_TYPE)                                                               \
                                                                                \
-  V(FIXED_ARRAY_TYPE)                                                          \
   V(ACCESSOR_INFO_TYPE)                                                        \
   V(ACCESS_CHECK_INFO_TYPE)                                                    \
   V(INTERCEPTOR_INFO_TYPE)                                                     \
-  V(SHARED_FUNCTION_INFO_TYPE)                                                 \
   V(CALL_HANDLER_INFO_TYPE)                                                    \
   V(FUNCTION_TEMPLATE_INFO_TYPE)                                               \
   V(OBJECT_TEMPLATE_INFO_TYPE)                                                 \
@@ -273,6 +273,9 @@
   V(SCRIPT_TYPE)                                                               \
   V(CODE_CACHE_TYPE)                                                           \
                                                                                \
+  V(FIXED_ARRAY_TYPE)                                                          \
+  V(SHARED_FUNCTION_INFO_TYPE)                                                 \
+                                                                               \
   V(JS_VALUE_TYPE)                                                             \
   V(JS_OBJECT_TYPE)                                                            \
   V(JS_CONTEXT_EXTENSION_OBJECT_TYPE)                                          \
@@ -1211,7 +1214,9 @@
  public:
   enum DeleteMode { NORMAL_DELETION, FORCE_DELETION };
   enum ElementsKind {
+    // The only "fast" kind.
     FAST_ELEMENTS,
+    // All the kinds below are "slow".
     DICTIONARY_ELEMENTS,
     PIXEL_ELEMENTS,
     EXTERNAL_BYTE_ELEMENTS,
@@ -1232,8 +1237,21 @@
   inline StringDictionary* property_dictionary();  // Gets slow properties.
 
   // [elements]: The elements (properties with names that are integers).
-  // elements is a FixedArray in the fast case, a Dictionary in the slow
-  // case, and a PixelArray or ExternalArray in special cases.
+  //
+  // Elements can be in two general modes: fast and slow. Each mode
+  // corrensponds to a set of object representations of elements that
+  // have something in common.
+  //
+  // In the fast mode elements is a FixedArray and so each element can
+  // be quickly accessed. This fact is used in the generated code. The
+  // elements array can have one of the two maps in this mode:
+  // fixed_array_map or fixed_cow_array_map (for copy-on-write
+  // arrays). In the latter case the elements array may be shared by a
+  // few objects and so before writing to any element the array must
+  // be copied. Use EnsureWritableFastElements in this case.
+  //
+  // In the slow mode elements is either a NumberDictionary or a
+  // PixelArray or an ExternalArray.
   DECL_ACCESSORS(elements, HeapObject)
   inline void initialize_elements();
   inline Object* ResetElements();
@@ -1251,6 +1269,8 @@
   inline bool HasExternalFloatElements();
   inline bool AllowsSetElementsLength();
   inline NumberDictionary* element_dictionary();  // Gets slow elements.
+  // Requires: this->HasFastElements().
+  inline Object* EnsureWritableFastElements();
 
   // Collects elements starting at index 0.
   // Undefined values are placed after non-undefined values.
@@ -1703,6 +1723,10 @@
   inline void set_null(int index);
   inline void set_the_hole(int index);
 
+  // Setters with less debug checks for the GC to use.
+  inline void set_unchecked(int index, Smi* value);
+  inline void set_null_unchecked(int index);
+
   // Gives access to raw memory which stores the array's data.
   inline Object** data_start();
 
@@ -2762,7 +2786,12 @@
  public:
   // Opaque data type for encapsulating code flags like kind, inline
   // cache state, and arguments count.
-  enum Flags { };
+  // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
+  // enumeration type has correct value range (see Issue 830 for more details).
+  enum Flags {
+    FLAGS_MIN_VALUE = kMinInt,
+    FLAGS_MAX_VALUE = kMaxInt
+  };
 
   enum Kind {
     FUNCTION,
@@ -3061,7 +3090,8 @@
   inline bool is_extensible();
 
   // Tells whether the instance has fast elements.
-  void set_has_fast_elements(bool value) {
+  // Equivalent to instance->GetElementsKind() == FAST_ELEMENTS.
+  inline void set_has_fast_elements(bool value) {
     if (value) {
       set_bit_field2(bit_field2() | (1 << kHasFastElements));
     } else {
@@ -3069,7 +3099,7 @@
     }
   }
 
-  bool has_fast_elements() {
+  inline bool has_fast_elements() {
     return ((1 << kHasFastElements) & bit_field2()) != 0;
   }
 
@@ -3344,6 +3374,8 @@
   // [construct stub]: Code stub for constructing instances of this function.
   DECL_ACCESSORS(construct_stub, Code)
 
+  inline Code* unchecked_code();
+
   // Returns if this function has been compiled to native code yet.
   inline bool is_compiled();
 
@@ -3451,6 +3483,15 @@
   inline bool allows_lazy_compilation();
   inline void set_allows_lazy_compilation(bool flag);
 
+  // Indicates how many full GCs this function has survived with assigned
+  // code object. Used to determine when it is relatively safe to flush
+  // this code object and replace it with lazy compilation stub.
+  // Age is reset when GC notices that the code object is referenced
+  // from the stack or compilation cache.
+  inline int code_age();
+  inline void set_code_age(int age);
+
+
   // Check whether a inlined constructor can be generated with the given
   // prototype.
   bool CanGenerateInlineConstructor(Object* prototype);
@@ -3581,6 +3622,8 @@
   static const int kHasOnlySimpleThisPropertyAssignments = 0;
   static const int kTryFullCodegen = 1;
   static const int kAllowLazyCompilation = 2;
+  static const int kCodeAgeShift = 3;
+  static const int kCodeAgeMask = 7;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
 };
@@ -3596,6 +3639,8 @@
   // can be shared by instances.
   DECL_ACCESSORS(shared, SharedFunctionInfo)
 
+  inline SharedFunctionInfo* unchecked_shared();
+
   // [context]: The context for this function.
   inline Context* context();
   inline Object* unchecked_context();
@@ -3608,6 +3653,8 @@
   inline Code* code();
   inline void set_code(Code* value);
 
+  inline Code* unchecked_code();
+
   // Tells whether this function is builtin.
   inline bool IsBuiltin();
 
diff --git a/src/parser.cc b/src/parser.cc
index 1df7c21..0fef2e2 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -3461,6 +3461,12 @@
     }
   }
 
+  // Simple and shallow arrays can be lazily copied, we transform the
+  // elements array to a copy-on-write array.
+  if (is_simple && depth == 1 && values.length() > 0) {
+    literals->set_map(Heap::fixed_cow_array_map());
+  }
+
   return NEW(ArrayLiteral(literals, values.elements(),
                           literal_index, is_simple, depth));
 }
@@ -3477,6 +3483,19 @@
   return lit != NULL && lit->is_simple();
 }
 
+
+bool CompileTimeValue::ArrayLiteralElementNeedsInitialization(
+    Expression* value) {
+  // If value is a literal the property value is already set in the
+  // boilerplate object.
+  if (value->AsLiteral() != NULL) return false;
+  // If value is a materialized literal the property value is already set
+  // in the boilerplate object if it is simple.
+  if (CompileTimeValue::IsCompileTimeValue(value)) return false;
+  return true;
+}
+
+
 Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
   ASSERT(IsCompileTimeValue(expression));
   Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
diff --git a/src/parser.h b/src/parser.h
index 89966a6..f918a3a 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -175,6 +175,8 @@
 
   static bool IsCompileTimeValue(Expression* expression);
 
+  static bool ArrayLiteralElementNeedsInitialization(Expression* value);
+
   // Get the value as a compile time value.
   static Handle<FixedArray> GetValue(Expression* expression);
 
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 9b8b206..ae44944 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -198,9 +198,10 @@
 
 
 void OS::DebugBreak() {
-#if (defined(__arm__) || defined(__thumb__)) && \
-    defined(CAN_USE_ARMV5_INSTRUCTIONS)
+#if (defined(__arm__) || defined(__thumb__))
+# if defined(CAN_USE_ARMV5_INSTRUCTIONS)
   asm("bkpt 0");
+# endif
 #else
   asm("int $3");
 #endif
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index 58ff154..05ed9ee 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -196,9 +196,10 @@
 
 
 void OS::DebugBreak() {
-#if (defined(__arm__) || defined(__thumb__)) && \
-    defined(CAN_USE_ARMV5_INSTRUCTIONS)
+#if (defined(__arm__) || defined(__thumb__))
+# if defined(CAN_USE_ARMV5_INSTRUCTIONS)
   asm("bkpt 0");
+# endif
 #else
   asm("int $3");
 #endif
diff --git a/src/platform.h b/src/platform.h
index 7539fd2..e0dd66e 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -363,7 +363,13 @@
 class Thread: public ThreadHandle {
  public:
   // Opaque data type for thread-local storage keys.
-  enum LocalStorageKey {};
+  // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
+  // to ensure that enumeration type has correct value range (see Issue 830 for
+  // more details).
+  enum LocalStorageKey {
+    LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
+    LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
+  };
 
   // Create new thread.
   Thread();
diff --git a/src/runtime.cc b/src/runtime.cc
index fc6ca76..2eddaab 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -160,13 +160,22 @@
   switch (copy->GetElementsKind()) {
     case JSObject::FAST_ELEMENTS: {
       FixedArray* elements = FixedArray::cast(copy->elements());
-      for (int i = 0; i < elements->length(); i++) {
-        Object* value = elements->get(i);
-        if (value->IsJSObject()) {
-          JSObject* js_object = JSObject::cast(value);
-          result = DeepCopyBoilerplate(js_object);
-          if (result->IsFailure()) return result;
-          elements->set(i, result);
+      if (elements->map() == Heap::fixed_cow_array_map()) {
+        Counters::cow_arrays_created_runtime.Increment();
+#ifdef DEBUG
+        for (int i = 0; i < elements->length(); i++) {
+          ASSERT(!elements->get(i)->IsJSObject());
+        }
+#endif
+      } else {
+        for (int i = 0; i < elements->length(); i++) {
+          Object* value = elements->get(i);
+          if (value->IsJSObject()) {
+            JSObject* js_object = JSObject::cast(value);
+            result = DeepCopyBoilerplate(js_object);
+            if (result->IsFailure()) return result;
+            elements->set(i, result);
+          }
         }
       }
       break;
@@ -343,18 +352,29 @@
       JSFunction::GlobalContextFromLiterals(*literals)->array_function());
   Handle<Object> object = Factory::NewJSObject(constructor);
 
-  Handle<Object> copied_elements = Factory::CopyFixedArray(elements);
+  const bool is_cow = (elements->map() == Heap::fixed_cow_array_map());
+  Handle<FixedArray> copied_elements =
+      is_cow ? elements : Factory::CopyFixedArray(elements);
 
   Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
-  for (int i = 0; i < content->length(); i++) {
-    if (content->get(i)->IsFixedArray()) {
-      // The value contains the constant_properties of a
-      // simple object literal.
-      Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
-      Handle<Object> result =
-        CreateLiteralBoilerplate(literals, fa);
-      if (result.is_null()) return result;
-      content->set(i, *result);
+  if (is_cow) {
+#ifdef DEBUG
+    // Copy-on-write arrays must be shallow (and simple).
+    for (int i = 0; i < content->length(); i++) {
+      ASSERT(!content->get(i)->IsFixedArray());
+    }
+#endif
+  } else {
+    for (int i = 0; i < content->length(); i++) {
+      if (content->get(i)->IsFixedArray()) {
+        // The value contains the constant_properties of a
+        // simple object literal.
+        Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
+        Handle<Object> result =
+            CreateLiteralBoilerplate(literals, fa);
+        if (result.is_null()) return result;
+        content->set(i, *result);
+      }
     }
   }
 
@@ -483,6 +503,10 @@
     // Update the functions literal and return the boilerplate.
     literals->set(literals_index, *boilerplate);
   }
+  if (JSObject::cast(*boilerplate)->elements()->map() ==
+      Heap::fixed_cow_array_map()) {
+    Counters::cow_arrays_created_runtime.Increment();
+  }
   return Heap::CopyJSObject(JSObject::cast(*boilerplate));
 }
 
@@ -6699,9 +6723,13 @@
   int year, month, day;
   DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
 
-  res_array->SetElement(0, Smi::FromInt(year));
-  res_array->SetElement(1, Smi::FromInt(month));
-  res_array->SetElement(2, Smi::FromInt(day));
+  RUNTIME_ASSERT(res_array->elements()->map() == Heap::fixed_array_map());
+  FixedArray* elms = FixedArray::cast(res_array->elements());
+  RUNTIME_ASSERT(elms->length() == 3);
+
+  elms->set(0, Smi::FromInt(year));
+  elms->set(1, Smi::FromInt(month));
+  elms->set(2, Smi::FromInt(day));
 
   return Heap::undefined_value();
 }
@@ -8057,7 +8085,8 @@
   CONVERT_CHECKED(JSArray, to, args[1]);
   HeapObject* new_elements = from->elements();
   Object* new_map;
-  if (new_elements->map() == Heap::fixed_array_map()) {
+  if (new_elements->map() == Heap::fixed_array_map() ||
+      new_elements->map() == Heap::fixed_cow_array_map()) {
     new_map = to->map()->GetFastElementsMap();
   } else {
     new_map = to->map()->GetSlowElementsMap();
diff --git a/src/serialize.h b/src/serialize.h
index d1b668d..80be50d 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -536,7 +536,8 @@
     // would cause dupes.
     ASSERT(!o->IsScript());
     return o->IsString() || o->IsSharedFunctionInfo() ||
-           o->IsHeapNumber() || o->IsCode();
+           o->IsHeapNumber() || o->IsCode() ||
+           o->map() == Heap::fixed_cow_array_map();
   }
 
  private:
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 663201b..19d54f8 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -210,7 +210,6 @@
   static Object* ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind);
 #endif
 
-
   // Update cache for entry hash(name, map).
   static Code* Set(String* name, Map* map, Code* code);
 
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 64ea9fc..2f2edfe 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -120,6 +120,8 @@
      V8.GCCompactorCausedByWeakHandles)                               \
   SC(gc_last_resort_from_js, V8.GCLastResortFromJS)                   \
   SC(gc_last_resort_from_handles, V8.GCLastResortFromHandles)         \
+  SC(map_slow_to_fast_elements, V8.MapSlowToFastElements)             \
+  SC(map_fast_to_slow_elements, V8.MapFastToSlowElements)             \
   /* How is the generic keyed-load stub used? */                      \
   SC(keyed_load_generic_smi, V8.KeyedLoadGenericSmi)                  \
   SC(keyed_load_generic_symbol, V8.KeyedLoadGenericSymbol)            \
@@ -155,6 +157,9 @@
   SC(named_store_global_inline_miss, V8.NamedStoreGlobalInlineMiss)   \
   SC(store_normal_miss, V8.StoreNormalMiss)                           \
   SC(store_normal_hit, V8.StoreNormalHit)                             \
+  SC(cow_arrays_created_stub, V8.COWArraysCreatedStub)                \
+  SC(cow_arrays_created_runtime, V8.COWArraysCreatedRuntime)          \
+  SC(cow_arrays_converted, V8.COWArraysConverted)                     \
   SC(call_miss, V8.CallMiss)                                          \
   SC(keyed_call_miss, V8.KeyedCallMiss)                               \
   SC(load_miss, V8.LoadMiss)                                          \
diff --git a/src/version.cc b/src/version.cc
index 61c0a0e..c448a0f 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     3
-#define BUILD_NUMBER      8
+#define BUILD_NUMBER      9
 #define PATCH_LEVEL       0
 #define CANDIDATE_VERSION false
 
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index e545ffa..1885182 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -4989,12 +4989,18 @@
   frame_->Push(node->constant_elements());
   int length = node->values()->length();
   Result clone;
-  if (node->depth() > 1) {
+  if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
+    clone = frame_->CallStub(&stub, 3);
+    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+  } else if (node->depth() > 1) {
     clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
-  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
   } else {
-    FastCloneShallowArrayStub stub(length);
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
     clone = frame_->CallStub(&stub, 3);
   }
   frame_->Push(&clone);
@@ -5004,12 +5010,9 @@
   for (int i = 0; i < length; i++) {
     Expression* value = node->values()->at(i);
 
-    // If value is a literal the property value is already set in the
-    // boilerplate object.
-    if (value->AsLiteral() != NULL) continue;
-    // If value is a materialized literal the property value is already set
-    // in the boilerplate object if it is simple.
-    if (CompileTimeValue::IsCompileTimeValue(value)) continue;
+    if (!CompileTimeValue::ArrayLiteralElementNeedsInitialization(value)) {
+      continue;
+    }
 
     // The property must be set by generated code.
     Load(value);
@@ -6875,7 +6878,7 @@
            Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
   deferred->Branch(not_zero);
 
-  // Check the object's elements are in fast case.
+  // Check the object's elements are in fast case and writable.
   __ movq(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
   __ CompareRoot(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
                  Heap::kFixedArrayMapRootIndex);
@@ -8419,15 +8422,10 @@
     // Check that the key is a non-negative smi.
     __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label());
 
-    // Get the elements array from the receiver and check that it
-    // is not a dictionary.
+    // Get the elements array from the receiver.
     __ movq(elements.reg(),
             FieldOperand(receiver.reg(), JSObject::kElementsOffset));
-    if (FLAG_debug_code) {
-      __ Cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset),
-             Factory::fixed_array_map());
-      __ Assert(equal, "JSObject with fast elements map has slow elements");
-    }
+    __ AssertFastElements(elements.reg());
 
     // Check that key is within bounds.
     __ SmiCompare(key.reg(),
@@ -8841,6 +8839,25 @@
   __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
   __ j(equal, &slow_case);
 
+  if (FLAG_debug_code) {
+    const char* message;
+    Heap::RootListIndex expected_map_index;
+    if (mode_ == CLONE_ELEMENTS) {
+      message = "Expected (writable) fixed array";
+      expected_map_index = Heap::kFixedArrayMapRootIndex;
+    } else {
+      ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS);
+      message = "Expected copy-on-write fixed array";
+      expected_map_index = Heap::kFixedCOWArrayMapRootIndex;
+    }
+    __ push(rcx);
+    __ movq(rcx, FieldOperand(rcx, JSArray::kElementsOffset));
+    __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
+                   expected_map_index);
+    __ Assert(equal, message);
+    __ pop(rcx);
+  }
+
   // Allocate both the JS array and the elements array in one big
   // allocation. This avoids multiple limit checks.
   __ AllocateInNewSpace(size, rax, rbx, rdx, &slow_case, TAG_OBJECT);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 725cbb0..a5ccaf5 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1330,12 +1330,18 @@
   __ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
   __ Push(Smi::FromInt(expr->literal_index()));
   __ Push(expr->constant_elements());
-  if (expr->depth() > 1) {
+  if (expr->constant_elements()->map() == Heap::fixed_cow_array_map()) {
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
+    __ CallStub(&stub);
+    __ IncrementCounter(&Counters::cow_arrays_created_stub, 1);
+  } else if (expr->depth() > 1) {
     __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
-  } else if (length > FastCloneShallowArrayStub::kMaximumLength) {
+  } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
     __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
   } else {
-    FastCloneShallowArrayStub stub(length);
+    FastCloneShallowArrayStub stub(
+        FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
     __ CallStub(&stub);
   }
 
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index a8971f5..114ae84 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -487,6 +487,7 @@
 
 
 // Loads an indexed element from a fast case array.
+// If not_fast_array is NULL, doesn't perform the elements map check.
 static void GenerateFastArrayLoad(MacroAssembler* masm,
                                   Register receiver,
                                   Register key,
@@ -515,10 +516,14 @@
   //   scratch - used to hold elements of the receiver and the loaded value.
 
   __ movq(elements, FieldOperand(receiver, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
-  __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
-                 Heap::kFixedArrayMapRootIndex);
-  __ j(not_equal, not_fast_array);
+  if (not_fast_array != NULL) {
+    // Check that the object is in fast mode and writable.
+    __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
+                   Heap::kFixedArrayMapRootIndex);
+    __ j(not_equal, not_fast_array);
+  } else {
+    __ AssertFastElements(elements);
+  }
   // Check that the key (index) is within bounds.
   __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
   // Unsigned comparison rejects negative indices.
@@ -611,13 +616,19 @@
   GenerateKeyedLoadReceiverCheck(
       masm, rdx, rcx, Map::kHasIndexedInterceptor, &slow);
 
+  // Check the "has fast elements" bit in the receiver's map which is
+  // now in rcx.
+  __ testb(FieldOperand(rcx, Map::kBitField2Offset),
+           Immediate(1 << Map::kHasFastElements));
+  __ j(zero, &check_pixel_array);
+
   GenerateFastArrayLoad(masm,
                         rdx,
                         rax,
                         rcx,
                         rbx,
                         rax,
-                        &check_pixel_array,
+                        NULL,
                         &slow);
   __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
   __ ret(0);
@@ -626,7 +637,7 @@
   // Check whether the elements object is a pixel array.
   // rdx: receiver
   // rax: key
-  // rcx: elements array
+  __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
   __ SmiToInteger32(rbx, rax);  // Used on both directions of next branch.
   __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
                  Heap::kPixelArrayMapRootIndex);
@@ -1012,7 +1023,7 @@
   // rdx: JSObject
   // rcx: index
   __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
-  // Check that the object is in fast mode (not dictionary).
+  // Check that the object is in fast mode and writable.
   __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
                  Heap::kFixedArrayMapRootIndex);
   __ j(not_equal, &check_pixel_array);
@@ -1075,8 +1086,8 @@
   __ jmp(&fast);
 
   // Array case: Get the length and the elements array from the JS
-  // array. Check that the array is in fast mode; if it is the
-  // length is always a smi.
+  // array. Check that the array is in fast mode (and writable); if it
+  // is the length is always a smi.
   __ bind(&array);
   // rax: value
   // rdx: receiver (a JSArray)
@@ -1862,6 +1873,8 @@
   __ j(not_equal, &miss);
 
   // Check that elements are FixedArray.
+  // We rely on StoreIC_ArrayLength below to deal with all types of
+  // fast elements (including COW).
   __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
   __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
   __ j(not_equal, &miss);
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index c1954a8..2f4b5f6 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -262,6 +262,21 @@
 }
 
 
+void MacroAssembler::AssertFastElements(Register elements) {
+  if (FLAG_debug_code) {
+    Label ok;
+    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
+                Heap::kFixedArrayMapRootIndex);
+    j(equal, &ok);
+    CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
+                Heap::kFixedCOWArrayMapRootIndex);
+    j(equal, &ok);
+    Abort("JSObject with fast elements map has slow elements");
+    bind(&ok);
+  }
+}
+
+
 void MacroAssembler::Check(Condition cc, const char* msg) {
   Label L;
   j(cc, &L);
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 7083224..aedc3b9 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -832,6 +832,8 @@
   // Use --debug_code to enable.
   void Assert(Condition cc, const char* msg);
 
+  void AssertFastElements(Register elements);
+
   // Like Assert(), but always enabled.
   void Check(Condition cc, const char* msg);
 
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 7aaeab7..e0644cd 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -1084,16 +1084,18 @@
     __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset));
     __ ret((argc + 1) * kPointerSize);
   } else {
+    Label call_builtin;
+
     // Get the elements array of the object.
     __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
 
-    // Check that the elements are in fast mode (not dictionary).
+    // Check that the elements are in fast mode and writable.
     __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
            Factory::fixed_array_map());
-    __ j(not_equal, &miss);
+    __ j(not_equal, &call_builtin);
 
     if (argc == 1) {  // Otherwise fall through to call builtin.
-      Label call_builtin, exit, with_write_barrier, attempt_to_grow_elements;
+      Label exit, with_write_barrier, attempt_to_grow_elements;
 
       // Get the array's length into rax and calculate new length.
       __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
@@ -1164,7 +1166,7 @@
       // Push the argument...
       __ movq(Operand(rdx, 0), rcx);
       // ... and fill the rest with holes.
-      __ Move(kScratchRegister, Factory::the_hole_value());
+      __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
       for (int i = 1; i < kAllocationDelta; i++) {
         __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
       }
@@ -1175,15 +1177,16 @@
       // Increment element's and array's sizes.
       __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset),
                         Smi::FromInt(kAllocationDelta));
+
       // Make new length a smi before returning it.
       __ Integer32ToSmi(rax, rax);
       __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
+
       // Elements are in new space, so write barrier is not required.
       __ ret((argc + 1) * kPointerSize);
-
-      __ bind(&call_builtin);
     }
 
+    __ bind(&call_builtin);
     __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush),
                                  argc + 1,
                                  1);
@@ -1204,11 +1207,11 @@
                                               String* name,
                                               CheckType check) {
   // ----------- S t a t e -------------
-  //  -- ecx                 : name
-  //  -- esp[0]              : return address
-  //  -- esp[(argc - n) * 4] : arg[n] (zero-based)
+  //  -- rcx                 : name
+  //  -- rsp[0]              : return address
+  //  -- rsp[(argc - n) * 8] : arg[n] (zero-based)
   //  -- ...
-  //  -- esp[(argc + 1) * 4] : receiver
+  //  -- rsp[(argc + 1) * 8] : receiver
   // -----------------------------------
   ASSERT(check == RECEIVER_MAP_CHECK);
 
@@ -1235,9 +1238,10 @@
   // Get the elements array of the object.
   __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
 
-  // Check that the elements are in fast mode (not dictionary).
-  __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), Factory::fixed_array_map());
-  __ j(not_equal, &miss);
+  // Check that the elements are in fast mode and writable.
+  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
+                 Heap::kFixedArrayMapRootIndex);
+  __ j(not_equal, &call_builtin);
 
   // Get the array's length into rcx and calculate new length.
   __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
@@ -1245,7 +1249,7 @@
   __ j(negative, &return_undefined);
 
   // Get the last element.
-  __ Move(r9, Factory::the_hole_value());
+  __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
   __ movq(rax, FieldOperand(rbx,
                             rcx, times_pointer_size,
                             FixedArray::kHeaderSize));
@@ -1265,14 +1269,14 @@
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&return_undefined);
-
-  __ Move(rax, Factory::undefined_value());
+  __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
   __ ret((argc + 1) * kPointerSize);
 
   __ bind(&call_builtin);
   __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop),
                                argc + 1,
                                1);
+
   __ bind(&miss);
   Object* obj = GenerateMissBranch();
   if (obj->IsFailure()) return obj;