Version 3.19.4

Fixed edge case in stack trace formatting. (Chromium issue 237617)

Fixed embedded new-space pointer in LCmpObjectEqAndBranch. (Chromium 	issue 240032)

Made Object.freeze fast (issue 1858, Chromium issue 115960)

Fixed bogus deopt in BuildEmitDeepCopy for holey arrays. (Chromium issue 242924)

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@14804 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 7099ca8..b2ded30 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -645,11 +645,8 @@
 }
 
 
-void V8::DisposeGlobal(i::Isolate* isolate, i::Object** obj) {
-  ASSERT(isolate == i::Isolate::Current());
-  LOG_API(isolate, "DisposeGlobal");
-  if (!isolate->IsInitialized()) return;
-  isolate->global_handles()->Destroy(obj);
+void V8::DisposeGlobal(i::Object** obj) {
+  i::GlobalHandles::Destroy(obj);
 }
 
 // --- H a n d l e s ---
@@ -985,7 +982,7 @@
 
 template<typename Callback>
 static Local<FunctionTemplate> FunctionTemplateNew(
-    Callback callback_in,
+    Callback callback,
     v8::Handle<Value> data,
     v8::Handle<Signature> signature,
     int length) {
@@ -1001,10 +998,8 @@
   int next_serial_number = isolate->next_serial_number();
   isolate->set_next_serial_number(next_serial_number + 1);
   obj->set_serial_number(i::Smi::FromInt(next_serial_number));
-  if (callback_in != 0) {
+  if (callback != 0) {
     if (data.IsEmpty()) data = v8::Undefined();
-    InvocationCallback callback =
-        i::CallbackTable::Register(isolate, callback_in);
     Utils::ToLocal(obj)->SetCallHandler(callback, data);
   }
   obj->set_length(length);
@@ -1228,7 +1223,7 @@
 
 template<typename Callback>
 static void FunctionTemplateSetCallHandler(FunctionTemplate* function_template,
-                                           Callback callback,
+                                           Callback callback_in,
                                            v8::Handle<Value> data) {
   i::Isolate* isolate = Utils::OpenHandle(function_template)->GetIsolate();
   if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetCallHandler()")) return;
@@ -1238,6 +1233,8 @@
       isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
   i::Handle<i::CallHandlerInfo> obj =
       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
+  InvocationCallback callback =
+      i::CallbackTable::Register(isolate, callback_in);
   SET_FIELD_WRAPPED(obj, set_callback, callback);
   if (data.IsEmpty()) data = v8::Undefined();
   obj->set_data(*Utils::OpenHandle(*data));
@@ -6019,6 +6016,32 @@
 }
 
 
+bool v8::ArrayBuffer::IsExternal() const {
+  return Utils::OpenHandle(this)->is_external();
+}
+
+v8::ArrayBufferContents::~ArrayBufferContents() {
+  free(data_);
+  data_ = NULL;
+  byte_length_ = 0;
+}
+
+
+void v8::ArrayBuffer::Externalize(ArrayBufferContents* contents) {
+  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
+  ApiCheck(!obj->is_external(),
+            "v8::ArrayBuffer::Externalize",
+            "ArrayBuffer already externalized");
+  obj->set_is_external(true);
+  size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
+  ApiCheck(contents->data_ == NULL,
+           "v8::ArrayBuffer::Externalize",
+           "Externalizing into non-empty ArrayBufferContents");
+  contents->data_ = obj->backing_store();
+  contents->byte_length_ = byte_length;
+}
+
+
 size_t v8::ArrayBuffer::ByteLength() const {
   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
   if (IsDeadCheck(isolate, "v8::ArrayBuffer::ByteLength()")) return 0;
@@ -6027,14 +6050,6 @@
 }
 
 
-void* v8::ArrayBuffer::Data() const {
-  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
-  if (IsDeadCheck(isolate, "v8::ArrayBuffer::Data()")) return 0;
-  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
-  return obj->backing_store();
-}
-
-
 Local<ArrayBuffer> v8::ArrayBuffer::New(size_t byte_length) {
   i::Isolate* isolate = i::Isolate::Current();
   EnsureInitializedForIsolate(isolate, "v8::ArrayBuffer::New(size_t)");
@@ -6054,7 +6069,7 @@
   ENTER_V8(isolate);
   i::Handle<i::JSArrayBuffer> obj =
       isolate->factory()->NewJSArrayBuffer();
-  i::Runtime::SetupArrayBuffer(isolate, obj, data, byte_length);
+  i::Runtime::SetupArrayBuffer(isolate, obj, true, data, byte_length);
   return Utils::ToLocal(obj);
 }
 
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index c667c90..201ecb2 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -127,8 +127,8 @@
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(CompareNilIC_Miss);
-  descriptor->miss_handler_ =
-      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
 }
 
 
@@ -218,7 +218,7 @@
     for (int i = 0; i < param_count; ++i) {
       __ push(descriptor->register_params_[i]);
     }
-    ExternalReference miss = descriptor->miss_handler_;
+    ExternalReference miss = descriptor->miss_handler();
     __ CallExternalReference(miss, descriptor->register_param_count_);
   }
 
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 7bf253a..5b2980a 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -504,50 +504,6 @@
 }
 
 
-void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
-                                         String::Encoding encoding,
-                                         Register string,
-                                         Register index,
-                                         Register value) {
-  if (FLAG_debug_code) {
-    __ SmiTst(index);
-    __ Check(eq, "Non-smi index");
-    __ SmiTst(value);
-    __ Check(eq, "Non-smi value");
-
-    __ ldr(ip, FieldMemOperand(string, String::kLengthOffset));
-    __ cmp(index, ip);
-    __ Check(lt, "Index is too large");
-
-    __ cmp(index, Operand(Smi::FromInt(0)));
-    __ Check(ge, "Index is negative");
-
-    __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
-    __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
-
-    __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ cmp(ip, Operand(encoding == String::ONE_BYTE_ENCODING
-                           ? one_byte_seq_type : two_byte_seq_type));
-    __ Check(eq, "Unexpected string type");
-  }
-
-  __ add(ip,
-         string,
-         Operand(SeqString::kHeaderSize - kHeapObjectTag));
-  __ SmiUntag(value, value);
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  if (encoding == String::ONE_BYTE_ENCODING) {
-    // Smis are tagged by left shift by 1, thus LSR by 1 to smi-untag inline.
-    __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
-  } else {
-    // No need to untag a smi for two-byte addressing.
-    __ strh(value, MemOperand(ip, index));  // LSL(1 - kSmiTagSize).
-  }
-}
-
-
 static MemOperand ExpConstant(int index, Register base) {
   return MemOperand(base, index * kDoubleSize);
 }
diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h
index 75899a9..c020ab6 100644
--- a/src/arm/codegen-arm.h
+++ b/src/arm/codegen-arm.h
@@ -51,7 +51,7 @@
   static bool MakeCode(CompilationInfo* info);
 
   // Printing of AST, etc. as requested by flags.
-  static void MakeCodePrologue(CompilationInfo* info);
+  static void MakeCodePrologue(CompilationInfo* info, const char* kind);
 
   // Allocate and install the code.
   static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 33a499c..967a4d4 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -3425,19 +3425,56 @@
 }
 
 
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+                                                  Register index,
+                                                  Register value,
+                                                  uint32_t encoding_mask) {
+  __ SmiTst(index);
+  __ Check(eq, "Non-smi index");
+  __ SmiTst(value);
+  __ Check(eq, "Non-smi value");
+
+  __ ldr(ip, FieldMemOperand(string, String::kLengthOffset));
+  __ cmp(index, ip);
+  __ Check(lt, "Index is too large");
+
+  __ cmp(index, Operand(Smi::FromInt(0)));
+  __ Check(ge, "Index is negative");
+
+  __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
+
+  __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
+  __ cmp(ip, Operand(encoding_mask));
+  __ Check(eq, "Unexpected string type");
+}
+
+
 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = r0;
+  Register index = r1;
+  Register value = r2;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(r2);
-  __ pop(r1);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, r0, r1, r2);
-  context()->Plug(r0);
+  if (FLAG_debug_code) {
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
+  __ SmiUntag(value, value);
+  __ add(ip,
+         string,
+         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
+  __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
+  context()->Plug(string);
 }
 
 
@@ -3445,15 +3482,28 @@
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = r0;
+  Register index = r1;
+  Register value = r2;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(r2);
-  __ pop(r1);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, r0, r1, r2);
-  context()->Plug(r0);
+  if (FLAG_debug_code) {
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
+  __ SmiUntag(value, value);
+  __ add(ip,
+         string,
+         Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+  __ strh(value, MemOperand(ip, index));
+  context()->Plug(string);
 }
 
 
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index e1bb69e..6cfcd31 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -369,8 +369,7 @@
 
 void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
-  stream->Add(".");
-  stream->Add(*String::cast(*name())->ToCString());
+  hydrogen()->access().PrintTo(stream);
   stream->Add(" <- ");
   value()->PrintTo(stream);
 }
@@ -1887,12 +1886,33 @@
 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   Representation from = instr->from();
   Representation to = instr->to();
+  if (from.IsSmi()) {
+    if (to.IsTagged()) {
+      LOperand* value = UseRegister(instr->value());
+      // For now, always deopt on hole.
+      if (instr->value()->IsLoadKeyed() &&
+          HLoadKeyed::cast(instr->value())->UsesMustHandleHole()) {
+        return AssignEnvironment(
+            DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
+      }
+      return DefineSameAsFirst(new(zone()) LDummyUse(value));
+    }
+    from = Representation::Tagged();
+  }
   if (from.IsTagged()) {
     if (to.IsDouble()) {
       info()->MarkAsDeferredCalling();
       LOperand* value = UseRegister(instr->value());
       LNumberUntagD* res = new(zone()) LNumberUntagD(value);
       return AssignEnvironment(DefineAsRegister(res));
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      if (val->type().IsSmi()) {
+        return DefineSameAsFirst(new(zone()) LDummyUse(value));
+      }
+      return AssignEnvironment(
+          DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = NULL;
@@ -1900,6 +1920,13 @@
       if (instr->value()->type().IsSmi()) {
         value = UseRegisterAtStart(instr->value());
         res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
+        if (instr->value()->IsLoadKeyed()) {
+          HLoadKeyed* load_keyed = HLoadKeyed::cast(instr->value());
+          if (load_keyed->UsesMustHandleHole() &&
+              load_keyed->hole_mode() == NEVER_RETURN_HOLE) {
+            res = AssignEnvironment(res);
+          }
+        }
       } else {
         value = UseRegister(instr->value());
         LOperand* temp1 = TempRegister();
@@ -1927,6 +1954,10 @@
       LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
       Define(result, result_temp);
       return AssignPointerMap(result);
+    } else if (to.IsSmi()) {
+      LOperand* value = UseRegister(instr->value());
+      return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToSmi(value,
+          TempRegister(), TempRegister())));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
@@ -1949,6 +1980,15 @@
         LNumberTagI* result = new(zone()) LNumberTagI(value);
         return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
       }
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      LInstruction* result =
+          DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
+      if (val->HasRange() && val->range()->IsInSmiRange()) {
+        return result;
+      }
+      return AssignEnvironment(result);
     } else {
       ASSERT(to.IsDouble());
       if (instr->value()->CheckFlag(HInstruction::kUint32)) {
@@ -1992,12 +2032,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoCheckSmiOrInt32(HCheckSmiOrInt32* instr) {
-  LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new(zone()) LCheckSmi(value));
-}
-
-
 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   return AssignEnvironment(new(zone()) LCheckFunction(value));
@@ -2042,7 +2076,7 @@
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     return DefineAsRegister(new(zone()) LConstantD);
-  } else if (r.IsTagged()) {
+  } else if (r.IsSmiOrTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
@@ -2154,7 +2188,7 @@
 
 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
+         instr->key()->representation().IsSmi());
   ElementsKind elements_kind = instr->elements_kind();
   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   LLoadKeyed* result = NULL;
@@ -2164,7 +2198,7 @@
     if (instr->representation().IsDouble()) {
       obj = UseTempRegister(instr->elements());
     } else {
-      ASSERT(instr->representation().IsTagged());
+      ASSERT(instr->representation().IsSmiOrTagged());
       obj = UseRegisterAtStart(instr->elements());
     }
     result = new(zone()) LLoadKeyed(obj, key);
@@ -2214,7 +2248,7 @@
       val = UseTempRegister(instr->value());
       key = UseRegisterOrConstantAtStart(instr->key());
     } else {
-      ASSERT(instr->value()->representation().IsTagged());
+      ASSERT(instr->value()->representation().IsSmiOrTagged());
       object = UseTempRegister(instr->elements());
       val = needs_write_barrier ? UseTempRegister(instr->value())
           : UseRegisterAtStart(instr->value());
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 9bcd44a..0d01bfd 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -76,6 +76,7 @@
   V(CheckMaps)                                  \
   V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
+  V(CheckSmiAndReturn)                          \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
   V(ClampTToUint8)                              \
@@ -95,6 +96,7 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(DoubleToSmi)                                \
   V(DummyUse)                                   \
   V(ElementsKind)                               \
   V(FixedArrayBaseLength)                       \
@@ -111,6 +113,7 @@
   V(InstanceSize)                               \
   V(InstructionGap)                             \
   V(Integer32ToDouble)                          \
+  V(Integer32ToSmi)                             \
   V(Uint32ToDouble)                             \
   V(InvokeFunction)                             \
   V(IsConstructCallAndBranch)                   \
@@ -1954,6 +1957,19 @@
 };
 
 
+class LInteger32ToSmi: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LInteger32ToSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(Change)
+};
+
+
 class LUint32ToDouble: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LUint32ToDouble(LOperand* value) {
@@ -2007,6 +2023,25 @@
 };
 
 
+class LDoubleToSmi: public LTemplateInstruction<1, 1, 2> {
+ public:
+  LDoubleToSmi(LOperand* value, LOperand* temp, LOperand* temp2) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+    temps_[1] = temp2;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
+
+  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
+};
+
+
 // Sometimes truncating conversion from a tagged value to an int32.
 class LDoubleToI: public LTemplateInstruction<1, 1, 2> {
  public:
@@ -2087,6 +2122,7 @@
   LOperand* value() { return inputs_[0]; }
   bool needs_check() const { return needs_check_; }
 
+  DECLARE_HYDROGEN_ACCESSOR(Change);
   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
 
  private:
@@ -2364,6 +2400,18 @@
 };
 
 
+class LCheckSmiAndReturn: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCheckSmiAndReturn(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmiAndReturn, "check-smi-and-return")
+};
+
+
 class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckNonSmi(LOperand* value) {
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 09a0e9c..b175c58 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -518,7 +518,7 @@
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
   return constant->handle();
 }
 
@@ -528,6 +528,11 @@
 }
 
 
+bool LCodeGen::IsSmi(LConstantOperand* op) const {
+  return chunk_->LookupLiteralRepresentation(op).IsSmi();
+}
+
+
 int LCodeGen::ToInteger32(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
   return constant->Integer32Value();
@@ -2003,11 +2008,34 @@
 
 
 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
-  SeqStringSetCharGenerator::Generate(masm(),
-                                      instr->encoding(),
-                                      ToRegister(instr->string()),
-                                      ToRegister(instr->index()),
-                                      ToRegister(instr->value()));
+  Register string = ToRegister(instr->string());
+  Register index = ToRegister(instr->index());
+  Register value = ToRegister(instr->value());
+  String::Encoding encoding = instr->encoding();
+
+  if (FLAG_debug_code) {
+    __ ldr(ip, FieldMemOperand(string, HeapObject::kMapOffset));
+    __ ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
+
+    __ and_(ip, ip, Operand(kStringRepresentationMask | kStringEncodingMask));
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    __ cmp(ip, Operand(encoding == String::ONE_BYTE_ENCODING
+                           ? one_byte_seq_type : two_byte_seq_type));
+    __ Check(eq, "Unexpected string type");
+  }
+
+  __ add(ip,
+         string,
+         Operand(SeqString::kHeaderSize - kHeapObjectTag));
+  if (encoding == String::ONE_BYTE_ENCODING) {
+    __ strb(value, MemOperand(ip, index));
+  } else {
+    // MemOperand with ip as the base register is not allowed for strh, so
+    // we do the address calculation explicitly.
+    __ add(ip, ip, Operand(index, LSL, 1));
+    __ strh(value, MemOperand(ip));
+  }
 }
 
 
@@ -2207,7 +2235,7 @@
   int false_block = chunk_->LookupDestination(instr->false_block_id());
 
   Representation r = instr->hydrogen()->value()->representation();
-  if (r.IsInteger32()) {
+  if (r.IsInteger32() || r.IsSmi()) {
     Register reg = ToRegister(instr->value());
     __ cmp(reg, Operand::Zero());
     EmitBranch(true_block, false_block, ne);
@@ -3123,8 +3151,7 @@
     bool last = (i == map_count - 1);
     Handle<Map> map = instr->hydrogen()->types()->at(i);
     Label check_passed;
-    __ CompareMap(
-        object_map, map, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS);
+    __ CompareMap(object_map, map, &check_passed);
     if (last && !need_generic) {
       DeoptimizeIf(ne, instr->environment());
       __ bind(&check_passed);
@@ -3249,7 +3276,7 @@
     key = ToRegister(instr->key());
   }
   int element_size_shift = ElementsKindToShiftSize(elements_kind);
-  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int additional_offset = instr->additional_index() << element_size_shift;
 
@@ -3321,7 +3348,7 @@
   Register scratch = scratch0();
 
   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
-  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int constant_key = 0;
   if (key_is_constant) {
@@ -3366,7 +3393,7 @@
     // representation for the key to be an integer, the input gets replaced
     // during bound check elimination with the index argument to the bounds
     // check, which can be tagged, so that case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ add(scratch, elements, Operand::PointerOffsetFromSmiKey(key));
     } else {
       __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
@@ -4210,13 +4237,7 @@
 
   Handle<Map> transition = instr->transition();
 
-  if (FLAG_track_fields && representation.IsSmi()) {
-    Register value = ToRegister(instr->value());
-    __ SmiTag(value, value, SetCC);
-    if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
-      DeoptimizeIf(vs, instr->environment());
-    }
-  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
+  if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
     Register value = ToRegister(instr->value());
     if (!instr->hydrogen()->value()->type().IsHeapObject()) {
       __ SmiTst(value);
@@ -4308,7 +4329,7 @@
   if (instr->index()->IsConstantOperand()) {
     int constant_index =
         ToInteger32(LConstantOperand::cast(instr->index()));
-    if (instr->hydrogen()->length()->representation().IsTagged()) {
+    if (instr->hydrogen()->length()->representation().IsSmi()) {
       __ mov(ip, Operand(Smi::FromInt(constant_index)));
     } else {
       __ mov(ip, Operand(constant_index));
@@ -4336,7 +4357,7 @@
     key = ToRegister(instr->key());
   }
   int element_size_shift = ElementsKindToShiftSize(elements_kind);
-  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   int additional_offset = instr->additional_index() << element_size_shift;
 
@@ -4409,7 +4430,7 @@
     key = ToRegister(instr->key());
   }
   int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS);
-  int shift_size = (instr->hydrogen()->key()->representation().IsTagged())
+  int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
       ? (element_size_shift - kSmiTagSize) : element_size_shift;
   Operand operand = key_is_constant
       ? Operand((constant_key << element_size_shift) +
@@ -4455,7 +4476,7 @@
     // representation for the key to be an integer, the input gets replaced
     // during bound check elimination with the index argument to the bounds
     // check, which can be tagged, so that case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ add(scratch, elements, Operand::PointerOffsetFromSmiKey(key));
     } else {
       __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
@@ -4702,6 +4723,19 @@
 }
 
 
+void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister());
+  LOperand* output = instr->result();
+  ASSERT(output->IsRegister());
+  __ SmiTag(ToRegister(output), ToRegister(input), SetCC);
+  if (!instr->hydrogen()->value()->HasRange() ||
+      !instr->hydrogen()->value()->range()->IsInSmiRange()) {
+    DeoptimizeIf(vs, instr->environment());
+  }
+}
+
+
 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
   LOperand* input = instr->value();
   LOperand* output = instr->result();
@@ -4905,6 +4939,21 @@
     // If the input is a HeapObject, SmiUntag will set the carry flag.
     __ SmiUntag(result, input, SetCC);
     DeoptimizeIf(cs, instr->environment());
+  } else if (instr->hydrogen()->value()->IsLoadKeyed()) {
+    HLoadKeyed* load = HLoadKeyed::cast(instr->hydrogen()->value());
+    if (load->UsesMustHandleHole()) {
+      __ SmiUntag(result, input, SetCC);
+      if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+        Label done;
+        __ b(cc, &done);
+        __ mov(result, Operand(Smi::FromInt(0)));
+        __ bind(&done);
+      } else {
+        DeoptimizeIf(cs, instr->environment());
+      }
+    } else {
+      __ SmiUntag(result, input);
+    }
   } else {
     __ SmiUntag(result, input);
   }
@@ -5124,7 +5173,33 @@
   DwVfpRegister double_input = ToDoubleRegister(instr->value());
   DwVfpRegister double_scratch = double_scratch0();
 
-  Label done;
+  if (instr->truncating()) {
+    Register scratch3 = ToRegister(instr->temp2());
+    __ ECMAToInt32(result_reg, double_input,
+                   scratch1, scratch2, scratch3, double_scratch);
+  } else {
+    __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
+    // Deoptimize if the input wasn't a int32 (inside a double).
+    DeoptimizeIf(ne, instr->environment());
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      Label done;
+      __ cmp(result_reg, Operand::Zero());
+      __ b(ne, &done);
+      __ vmov(scratch1, double_input.high());
+      __ tst(scratch1, Operand(HeapNumber::kSignMask));
+      DeoptimizeIf(ne, instr->environment());
+      __ bind(&done);
+    }
+  }
+}
+
+
+void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
+  Register result_reg = ToRegister(instr->result());
+  Register scratch1 = scratch0();
+  Register scratch2 = ToRegister(instr->temp());
+  DwVfpRegister double_input = ToDoubleRegister(instr->value());
+  DwVfpRegister double_scratch = double_scratch0();
 
   if (instr->truncating()) {
     Register scratch3 = ToRegister(instr->temp2());
@@ -5134,8 +5209,25 @@
     __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
     // Deoptimize if the input wasn't a int32 (inside a double).
     DeoptimizeIf(ne, instr->environment());
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      Label done;
+      __ cmp(result_reg, Operand::Zero());
+      __ b(ne, &done);
+      __ vmov(scratch1, double_input.high());
+      __ tst(scratch1, Operand(HeapNumber::kSignMask));
+      DeoptimizeIf(ne, instr->environment());
+      __ bind(&done);
+    }
   }
-    __ bind(&done);
+  __ SmiTag(result_reg, SetCC);
+  DeoptimizeIf(vs, instr->environment());
+}
+
+
+void LCodeGen::DoCheckSmiAndReturn(LCheckSmiAndReturn* instr) {
+  LOperand* input = instr->value();
+  __ SmiTst(ToRegister(input));
+  DeoptimizeIf(ne, instr->environment());
 }
 
 
@@ -5216,10 +5308,9 @@
 
 void LCodeGen::DoCheckMapCommon(Register map_reg,
                                 Handle<Map> map,
-                                CompareMapMode mode,
                                 LEnvironment* env) {
   Label success;
-  __ CompareMap(map_reg, map, &success, mode);
+  __ CompareMap(map_reg, map, &success);
   DeoptimizeIf(ne, env);
   __ bind(&success);
 }
@@ -5236,11 +5327,11 @@
   __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
-    __ CompareMap(map_reg, map, &success, REQUIRE_EXACT_MAP);
+    __ CompareMap(map_reg, map, &success);
     __ b(eq, &success);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(map_reg, map, REQUIRE_EXACT_MAP, instr->environment());
+  DoCheckMapCommon(map_reg, map, instr->environment());
   __ bind(&success);
 }
 
@@ -5314,10 +5405,7 @@
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(prototype_reg, prototypes->at(i));
       __ ldr(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
-      DoCheckMapCommon(map_reg,
-                       maps->at(i),
-                       ALLOW_ELEMENT_TRANSITION_MAPS,
-                       instr->environment());
+      DoCheckMapCommon(map_reg, maps->at(i), instr->environment());
     }
   }
 }
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 1a34169..8b5b94f 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -126,6 +126,7 @@
   MemOperand ToHighMemOperand(LOperand* op) const;
 
   bool IsInteger32(LConstantOperand* op) const;
+  bool IsSmi(LConstantOperand* op) const;
   Handle<Object> ToHandle(LConstantOperand* op) const;
 
   // Try to generate code for the entire chunk, but it may fail if the
@@ -160,8 +161,7 @@
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
 
-  void DoCheckMapCommon(Register map_reg, Handle<Map> map,
-                        CompareMapMode mode, LEnvironment* env);
+  void DoCheckMapCommon(Register map_reg, Handle<Map> map, LEnvironment* env);
 
   // Parallel move support.
   void DoParallelMove(LParallelMove* move);
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index a3b21a2..9d87c60 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -2105,32 +2105,16 @@
 void MacroAssembler::CompareMap(Register obj,
                                 Register scratch,
                                 Handle<Map> map,
-                                Label* early_success,
-                                CompareMapMode mode) {
+                                Label* early_success) {
   ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
-  CompareMap(scratch, map, early_success, mode);
+  CompareMap(scratch, map, early_success);
 }
 
 
 void MacroAssembler::CompareMap(Register obj_map,
                                 Handle<Map> map,
-                                Label* early_success,
-                                CompareMapMode mode) {
+                                Label* early_success) {
   cmp(obj_map, Operand(map));
-  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
-    ElementsKind kind = map->elements_kind();
-    if (IsFastElementsKind(kind)) {
-      bool packed = IsFastPackedElementsKind(kind);
-      Map* current_map = *map;
-      while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
-        kind = GetNextMoreGeneralFastElementsKind(kind, packed);
-        current_map = current_map->LookupElementsTransitionMap(kind);
-        if (!current_map) break;
-        b(eq, early_success);
-        cmp(obj_map, Operand(Handle<Map>(current_map)));
-      }
-    }
-  }
 }
 
 
@@ -2138,14 +2122,13 @@
                               Register scratch,
                               Handle<Map> map,
                               Label* fail,
-                              SmiCheckType smi_check_type,
-                              CompareMapMode mode) {
+                              SmiCheckType smi_check_type) {
   if (smi_check_type == DO_SMI_CHECK) {
     JumpIfSmi(obj, fail);
   }
 
   Label success;
-  CompareMap(obj, scratch, map, &success, mode);
+  CompareMap(obj, scratch, map, &success);
   b(ne, fail);
   bind(&success);
 }
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 50f53b3..25e4a04 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -884,15 +884,13 @@
   void CompareMap(Register obj,
                   Register scratch,
                   Handle<Map> map,
-                  Label* early_success,
-                  CompareMapMode mode = REQUIRE_EXACT_MAP);
+                  Label* early_success);
 
   // As above, but the map of the object is already loaded into the register
   // which is preserved by the code generated.
   void CompareMap(Register obj_map,
                   Handle<Map> map,
-                  Label* early_success,
-                  CompareMapMode mode = REQUIRE_EXACT_MAP);
+                  Label* early_success);
 
   // Check if the map of an object is equal to a specified map and branch to
   // label if not. Skip the smi check if not required (object is known to be a
@@ -902,8 +900,7 @@
                 Register scratch,
                 Handle<Map> map,
                 Label* fail,
-                SmiCheckType smi_check_type,
-                CompareMapMode mode = REQUIRE_EXACT_MAP);
+                SmiCheckType smi_check_type);
 
 
   void CheckMap(Register obj,
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index b0de014..1ede12c 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -462,7 +462,7 @@
 
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
-              DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+              DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -581,6 +581,8 @@
   index -= object->map()->inobject_properties();
 
   // TODO(verwaest): Share this code as a code stub.
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index < 0) {
     // Set the property straight into the object.
     int offset = object->map()->instance_size() + (index * kPointerSize);
@@ -606,7 +608,9 @@
                           name_reg,
                           scratch1,
                           kLRHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   } else {
     // Write to the properties array.
@@ -636,7 +640,9 @@
                           name_reg,
                           receiver_reg,
                           kLRHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   }
 
@@ -665,7 +671,7 @@
 
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
-              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+              DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -723,6 +729,8 @@
   }
 
   // TODO(verwaest): Share this code as a code stub.
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index < 0) {
     // Set the property straight into the object.
     int offset = object->map()->instance_size() + (index * kPointerSize);
@@ -740,7 +748,9 @@
                           name_reg,
                           scratch1,
                           kLRHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   } else {
     // Write to the properties array.
@@ -762,7 +772,9 @@
                           name_reg,
                           receiver_reg,
                           kLRHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   }
 
@@ -1247,8 +1259,7 @@
       if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) {
         Handle<Map> current_map(current->map());
         // CheckMap implicitly loads the map of |reg| into |map_reg|.
-        __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK,
-                    ALLOW_ELEMENT_TRANSITION_MAPS);
+        __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK);
       } else {
         __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
       }
@@ -1285,7 +1296,7 @@
   if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) {
     // Check the holder map.
     __ CheckMap(reg, scratch1, Handle<Map>(holder->map()), miss,
-                DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+                DONT_DO_SMI_CHECK);
   }
 
   // Perform security check for access to the global object.
@@ -2797,7 +2808,7 @@
 
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
-              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+              DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 7c9e436..d7b74f8 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1320,10 +1320,12 @@
   if (FLAG_harmony_array_buffer) {
     // -- A r r a y B u f f e r
     Handle<JSFunction> array_buffer_fun =
-        InstallFunction(global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
-                        JSArrayBuffer::kSize,
-                        isolate()->initial_object_prototype(),
-                        Builtins::kIllegal, true, true);
+        InstallFunction(
+            global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE,
+            JSArrayBuffer::kSize +
+              v8::ArrayBuffer::kInternalFieldCount * kPointerSize,
+            isolate()->initial_object_prototype(),
+            Builtins::kIllegal, true, true);
     native_context()->set_array_buffer_fun(*array_buffer_fun);
   }
 
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 6e837dd..451b20b 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -148,7 +148,7 @@
                                                  HParameter::REGISTER_PARAMETER,
                                                  Representation::Integer32());
     stack_parameter_count->set_type(HType::Smi());
-    // it's essential to bind this value to the environment in case of deopt
+    // It's essential to bind this value to the environment in case of deopt.
     AddInstruction(stack_parameter_count);
     start_environment->Bind(param_count, stack_parameter_count);
     arguments_length_ = stack_parameter_count;
@@ -169,7 +169,7 @@
   HValue* return_value = BuildCodeStub();
 
   // We might have extra expressions to pop from the stack in addition to the
-  // arguments above
+  // arguments above.
   HInstruction* stack_pop_count = stack_parameter_count;
   if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) {
     if (!stack_parameter_count->IsConstant() &&
@@ -204,10 +204,10 @@
 
  protected:
   virtual HValue* BuildCodeStub() {
-    if (casted_stub()->IsMiss()) {
-      return BuildCodeInitializedStub();
-    } else {
+    if (casted_stub()->IsUninitialized()) {
       return BuildCodeUninitializedStub();
+    } else {
+      return BuildCodeInitializedStub();
     }
   }
 
@@ -276,16 +276,17 @@
   if (descriptor->register_param_count_ < 0) {
     stub->InitializeInterfaceDescriptor(isolate, descriptor);
   }
-  // The miss case without stack parameters can use a light-weight stub to enter
+
+  // If we are uninitialized we can use a light-weight stub to enter
   // the runtime that is significantly faster than using the standard
   // stub-failure deopt mechanism.
-  if (stub->IsMiss() && descriptor->stack_parameter_count_ == NULL) {
+  if (stub->IsUninitialized() && descriptor->has_miss_handler()) {
+    ASSERT(descriptor->stack_parameter_count_ == NULL);
     return stub->GenerateLightweightMissCode(isolate);
-  } else {
-    CodeStubGraphBuilder<Stub> builder(stub);
-    LChunk* chunk = OptimizeGraph(builder.CreateGraph());
-    return chunk->Codegen();
   }
+  CodeStubGraphBuilder<Stub> builder(stub);
+  LChunk* chunk = OptimizeGraph(builder.CreateGraph());
+  return chunk->Codegen();
 }
 
 
@@ -358,7 +359,6 @@
 template <>
 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() {
   Zone* zone = this->zone();
-  Factory* factory = isolate()->factory();
   HValue* undefined = graph()->GetConstantUndefined();
 
   HInstruction* boilerplate =
@@ -383,24 +383,17 @@
   HValue* size_in_bytes =
       AddInstruction(new(zone) HConstant(size, Representation::Integer32()));
   HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
-  if (FLAG_pretenure_literals) {
+  if (isolate()->heap()->ShouldGloballyPretenure()) {
     flags = static_cast<HAllocate::Flags>(
        flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
   }
-  HInstruction* object =
-      AddInstruction(new(zone) HAllocate(context(),
-                                         size_in_bytes,
-                                         HType::JSObject(),
-                                         flags));
+
+  HInstruction* object = AddInstruction(new(zone)
+      HAllocate(context(), size_in_bytes, HType::JSObject(), flags));
 
   for (int i = 0; i < size; i += kPointerSize) {
-    HInstruction* value =
-        AddInstruction(new(zone) HLoadNamedField(
-            boilerplate, true, Representation::Tagged(), i));
-    AddInstruction(new(zone) HStoreNamedField(object,
-                                              factory->empty_string(),
-                                              value, true,
-                                              Representation::Tagged(), i));
+    HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
+    AddStore(object, access, AddLoad(boilerplate, access));
   }
 
   checker.ElseDeopt();
@@ -418,7 +411,7 @@
   HInstruction* load = BuildUncheckedMonomorphicElementAccess(
       GetParameter(0), GetParameter(1), NULL, NULL,
       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
-      false, NEVER_RETURN_HOLE, STANDARD_STORE, Representation::Tagged());
+      false, NEVER_RETURN_HOLE, STANDARD_STORE, Representation::Smi());
   return load;
 }
 
@@ -430,11 +423,11 @@
 
 template<>
 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() {
-  Representation representation = casted_stub()->representation();
-  HInstruction* load = AddInstruction(DoBuildLoadNamedField(
-      GetParameter(0), casted_stub()->is_inobject(),
-      representation, casted_stub()->offset()));
-  return load;
+  HObjectAccess access = casted_stub()->is_inobject() ?
+      HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
+      HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
+  return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
+      casted_stub()->representation()));
 }
 
 
@@ -445,11 +438,11 @@
 
 template<>
 HValue* CodeStubGraphBuilder<KeyedLoadFieldStub>::BuildCodeStub() {
-  Representation representation = casted_stub()->representation();
-  HInstruction* load = AddInstruction(DoBuildLoadNamedField(
-      GetParameter(0), casted_stub()->is_inobject(),
-      representation, casted_stub()->offset()));
-  return load;
+  HObjectAccess access = casted_stub()->is_inobject() ?
+      HObjectAccess::ForJSObjectOffset(casted_stub()->offset()) :
+      HObjectAccess::ForBackingStoreOffset(casted_stub()->offset());
+  return AddInstruction(BuildLoadNamedField(GetParameter(0), access,
+      casted_stub()->representation()));
 }
 
 
@@ -464,7 +457,7 @@
       GetParameter(0), GetParameter(1), GetParameter(2), NULL,
       casted_stub()->is_js_array(), casted_stub()->elements_kind(),
       true, NEVER_RETURN_HOLE, casted_stub()->store_mode(),
-      Representation::Tagged());
+      Representation::Smi());
 
   return GetParameter(2);
 }
@@ -487,8 +480,8 @@
   AddInstruction(new(zone) HTrapAllocationMemento(js_array));
 
   HInstruction* array_length =
-      AddInstruction(HLoadNamedField::NewArrayLength(
-            zone, js_array, js_array, HType::Smi()));
+      AddLoad(js_array, HObjectAccess::ForArrayLength());
+  array_length->set_type(HType::Smi());
 
   ElementsKind to_kind = casted_stub()->to_kind();
   BuildNewSpaceArrayCheck(array_length, to_kind);
@@ -514,20 +507,12 @@
                     casted_stub()->from_kind(), new_elements,
                     to_kind, array_length, elements_length);
 
-  Factory* factory = isolate()->factory();
-
-  AddInstruction(new(zone) HStoreNamedField(js_array,
-                                            factory->elements_field_string(),
-                                            new_elements, true,
-                                            Representation::Tagged(),
-                                            JSArray::kElementsOffset));
+  AddStore(js_array, HObjectAccess::ForElementsPointer(), new_elements);
 
   if_builder.End();
 
-  AddInstruction(new(zone) HStoreNamedField(js_array, factory->length_string(),
-                                            map, true,
-                                            Representation::Tagged(),
-                                            JSArray::kMapOffset));
+  AddStore(js_array, HObjectAccess::ForMap(), map);
+
   return js_array;
 }
 
@@ -588,11 +573,9 @@
       new(zone()) HConstant(initial_capacity, Representation::Tagged());
   AddInstruction(initial_capacity_node);
 
-  // Since we're forcing Integer32 representation for this HBoundsCheck,
-  // there's no need to Smi-check the index.
   HBoundsCheck* checked_arg = AddBoundsCheck(argument, max_alloc_length,
                                              ALLOW_SMI_KEY,
-                                             Representation::Tagged());
+                                             Representation::Smi());
   IfBuilder if_builder(this);
   if_builder.IfCompare(checked_arg, constant_zero, Token::EQ);
   if_builder.Then();
@@ -676,7 +659,7 @@
 
 
 template <>
-HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeUninitializedStub() {
+HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeInitializedStub() {
   CompareNilICStub* stub = casted_stub();
   HIfContinuation continuation;
   Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map());
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 312febc..30478da 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -45,7 +45,8 @@
       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
       register_params_(NULL),
       deoptimization_handler_(NULL),
-      miss_handler_(IC_Utility(IC::kUnreachable), Isolate::Current()) { }
+      miss_handler_(IC_Utility(IC::kUnreachable), Isolate::Current()),
+      has_miss_handler_(false) { }
 
 
 bool CodeStub::FindCodeInCache(Code** code_out, Isolate* isolate) {
diff --git a/src/code-stubs.h b/src/code-stubs.h
index aa6a410..f66db94 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -277,7 +277,6 @@
   StubFunctionMode function_mode_;
   Register* register_params_;
   Address deoptimization_handler_;
-  ExternalReference miss_handler_;
 
   int environment_length() const {
     if (stack_parameter_count_ != NULL) {
@@ -287,6 +286,24 @@
   }
 
   bool initialized() const { return register_param_count_ >= 0; }
+
+  void SetMissHandler(ExternalReference handler) {
+    miss_handler_ = handler;
+    has_miss_handler_ = true;
+  }
+
+  ExternalReference miss_handler() {
+    ASSERT(has_miss_handler_);
+    return miss_handler_;
+  }
+
+  bool has_miss_handler() {
+    return has_miss_handler_;
+  }
+
+ private:
+  ExternalReference miss_handler_;
+  bool has_miss_handler_;
 };
 
 // A helper to make up for the fact that type Register is not fully
@@ -300,12 +317,12 @@
 class HydrogenCodeStub : public CodeStub {
  public:
   enum InitializationState {
-    CODE_STUB_IS_NOT_MISS,
-    CODE_STUB_IS_MISS
+    UNINITIALIZED,
+    INITIALIZED
   };
 
-  explicit HydrogenCodeStub(InitializationState state) {
-    is_miss_ = (state == CODE_STUB_IS_MISS);
+  explicit HydrogenCodeStub(InitializationState state = INITIALIZED) {
+    is_uninitialized_ = (state == UNINITIALIZED);
   }
 
   virtual Code::Kind GetCodeKind() const { return Code::STUB; }
@@ -314,7 +331,7 @@
     return isolate->code_stub_interface_descriptor(MajorKey());
   }
 
-  bool IsMiss() { return is_miss_; }
+  bool IsUninitialized() { return is_uninitialized_; }
 
   template<class SubClass>
   static Handle<Code> GetUninitialized(Isolate* isolate) {
@@ -339,11 +356,11 @@
 
   void GenerateLightweightMiss(MacroAssembler* masm);
   virtual int MinorKey() {
-    return IsMissBits::encode(is_miss_) |
+    return IsMissBits::encode(is_uninitialized_) |
         MinorKeyBits::encode(NotMissMinorKey());
   }
 
-  bool is_miss_;
+  bool is_uninitialized_;
 };
 
 
@@ -516,8 +533,7 @@
   FastCloneShallowArrayStub(Mode mode,
                             AllocationSiteMode allocation_site_mode,
                             int length)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS),
-        mode_(mode),
+      : mode_(mode),
         allocation_site_mode_(allocation_site_mode),
         length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
     ASSERT_GE(length_, 0);
@@ -577,8 +593,7 @@
   static const int kMaximumClonedProperties = 6;
 
   explicit FastCloneShallowObjectStub(int length)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS),
-        length_(length) {
+      : length_(length) {
     ASSERT_GE(length_, 0);
     ASSERT_LE(length_, kMaximumClonedProperties);
   }
@@ -763,7 +778,7 @@
   virtual InlineCacheState GetICState() { return MONOMORPHIC; }
 
  protected:
-  HICStub() : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) { }
+  HICStub() { }
   class KindBits: public BitField<Code::Kind, 0, 4> {};
   virtual Code::Kind kind() const = 0;
 };
@@ -1076,14 +1091,15 @@
   // boolean flags we need to store. :-P
   STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
 
-  CompareNilICStub(EqualityKind kind, NilValue nil, Types types)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS), types_(types) {
+  CompareNilICStub(EqualityKind kind, NilValue nil, Types types = Types())
+      : types_(types) {
     equality_kind_ = kind;
     nil_value_ = nil;
   }
 
-  explicit CompareNilICStub(Code::ExtraICState ic_state)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
+  CompareNilICStub(Code::ExtraICState ic_state,
+                   InitializationState init_state = INITIALIZED)
+      : HydrogenCodeStub(init_state) {
     equality_kind_ = EqualityKindField::decode(ic_state);
     nil_value_ = NilValueField::decode(ic_state);
     types_ = Types(ExtractTypesFromExtraICState(ic_state));
@@ -1092,7 +1108,7 @@
   static Handle<Code> GetUninitialized(Isolate* isolate,
                                        EqualityKind kind,
                                        NilValue nil) {
-    return CompareNilICStub(kind, nil, CODE_STUB_IS_MISS).GetCode(isolate);
+    return CompareNilICStub(kind, nil, UNINITIALIZED).GetCode(isolate);
   }
 
   virtual void InitializeInterfaceDescriptor(
@@ -1100,8 +1116,7 @@
       CodeStubInterfaceDescriptor* descriptor);
 
   static void InitializeForIsolate(Isolate* isolate) {
-    CompareNilICStub compare_stub(kStrictEquality, kNullValue,
-                                  CODE_STUB_IS_MISS);
+    CompareNilICStub compare_stub(kStrictEquality, kNullValue, UNINITIALIZED);
     compare_stub.InitializeInterfaceDescriptor(
         isolate,
         isolate->code_stub_interface_descriptor(CodeStub::CompareNilIC));
@@ -1148,18 +1163,11 @@
 
   CompareNilICStub(EqualityKind kind, NilValue nil,
                    InitializationState init_state)
-      : HydrogenCodeStub(init_state), types_(0) {
+      : HydrogenCodeStub(init_state) {
     equality_kind_ = kind;
     nil_value_ = nil;
   }
 
-  CompareNilICStub(Code::ExtraICState ic_state, InitializationState init_state)
-      : HydrogenCodeStub(init_state) {
-    equality_kind_ = EqualityKindField::decode(ic_state);
-    nil_value_ = NilValueField::decode(ic_state);
-    types_ = Types(ExtractTypesFromExtraICState(ic_state));
-  }
-
   class EqualityKindField : public BitField<EqualityKind, NUMBER_OF_TYPES, 1> {
   };
   class NilValueField : public BitField<NilValue, NUMBER_OF_TYPES+1, 1> {};
@@ -1567,8 +1575,7 @@
 
 class KeyedLoadFastElementStub : public HydrogenCodeStub {
  public:
-  KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
+  KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
     bit_field_ = ElementsKindBits::encode(elements_kind) |
         IsJSArrayBits::encode(is_js_array);
   }
@@ -1603,8 +1610,7 @@
  public:
   KeyedStoreFastElementStub(bool is_js_array,
                             ElementsKind elements_kind,
-                            KeyedAccessStoreMode mode)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
+                            KeyedAccessStoreMode mode) {
     bit_field_ = ElementsKindBits::encode(elements_kind) |
         IsJSArrayBits::encode(is_js_array) |
         StoreModeBits::encode(mode);
@@ -1644,8 +1650,7 @@
 class TransitionElementsKindStub : public HydrogenCodeStub {
  public:
   TransitionElementsKindStub(ElementsKind from_kind,
-                             ElementsKind to_kind)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
+                             ElementsKind to_kind) {
     bit_field_ = FromKindBits::encode(from_kind) |
         ToKindBits::encode(to_kind);
   }
@@ -1678,8 +1683,7 @@
 
 class ArrayConstructorStubBase : public HydrogenCodeStub {
  public:
-  ArrayConstructorStubBase(ElementsKind kind, AllocationSiteMode mode)
-      : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
+  ArrayConstructorStubBase(ElementsKind kind, AllocationSiteMode mode) {
     bit_field_ = ElementsKindBits::encode(kind) |
         AllocationSiteModeBits::encode(mode == TRACK_ALLOCATION_SITE);
   }
diff --git a/src/codegen.cc b/src/codegen.cc
index ff4003c..af2f1f6 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -58,13 +58,12 @@
 #undef __
 
 
-void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
-#ifdef DEBUG
+void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) {
   bool print_source = false;
   bool print_ast = false;
   const char* ftype;
 
-  if (Isolate::Current()->bootstrapper()->IsActive()) {
+  if (info->isolate()->bootstrapper()->IsActive()) {
     print_source = FLAG_print_builtin_source;
     print_ast = FLAG_print_builtin_ast;
     ftype = "builtin";
@@ -75,17 +74,18 @@
   }
 
   if (FLAG_trace_codegen || print_source || print_ast) {
-    PrintF("*** Generate code for %s function: ", ftype);
+    PrintF("[generating %s code for %s function: ", kind, ftype);
     if (info->IsStub()) {
       const char* name =
           CodeStub::MajorName(info->code_stub()->MajorKey(), true);
       PrintF("%s", name == NULL ? "<unknown>" : name);
     } else {
-      info->function()->name()->ShortPrint();
+      PrintF("%s", *info->function()->debug_name()->ToCString());
     }
-    PrintF(" ***\n");
+    PrintF("]\n");
   }
 
+#ifdef DEBUG
   if (!info->IsStub() && print_source) {
     PrintF("--- Source from AST ---\n%s\n",
            PrettyPrinter().PrintProgram(info->function()));
diff --git a/src/codegen.h b/src/codegen.h
index 09907c4..53ff2e1 100644
--- a/src/codegen.h
+++ b/src/codegen.h
@@ -113,18 +113,6 @@
 };
 
 
-class SeqStringSetCharGenerator : public AllStatic {
- public:
-  static void Generate(MacroAssembler* masm,
-                       String::Encoding encoding,
-                       Register string,
-                       Register index,
-                       Register value);
- private:
-  DISALLOW_COPY_AND_ASSIGN(SeqStringSetCharGenerator);
-};
-
-
 } }  // namespace v8::internal
 
 #endif  // V8_CODEGEN_H_
diff --git a/src/d8.cc b/src/d8.cc
index b95432e..3a4ba3b 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -1048,6 +1048,16 @@
   return chars;
 }
 
+static void ReadBufferWeakCallback(v8::Isolate* isolate,
+                                   Persistent<Value>* object,
+                                   uint8_t* data) {
+  size_t byte_length = ArrayBuffer::Cast(**object)->ByteLength();
+  isolate->AdjustAmountOfExternalAllocatedMemory(
+      -static_cast<intptr_t>(byte_length));
+
+  delete[] data;
+  object->Dispose(isolate);
+}
 
 Handle<Value> Shell::ReadBuffer(const Arguments& args) {
   ASSERT(sizeof(char) == sizeof(uint8_t));  // NOLINT
@@ -1057,14 +1067,19 @@
     return Throw("Error loading file");
   }
 
+  Isolate* isolate = args.GetIsolate();
   uint8_t* data = reinterpret_cast<uint8_t*>(
       ReadChars(args.GetIsolate(), *filename, &length));
   if (data == NULL) {
     return Throw("Error reading file");
   }
-  Handle<v8::ArrayBuffer> buffer = ArrayBuffer::New(length);
-  memcpy(buffer->Data(), data, length);
-  delete[] data;
+  Handle<v8::ArrayBuffer> buffer = ArrayBuffer::New(data, length);
+  v8::Persistent<v8::Value> weak_handle =
+      v8::Persistent<v8::Value>::New(isolate, buffer);
+  weak_handle.MakeWeak(isolate, data, ReadBufferWeakCallback);
+  weak_handle.MarkIndependent();
+  isolate->AdjustAmountOfExternalAllocatedMemory(length);
+
   return buffer;
 }
 
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 58f29b4..8fe6778 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -192,7 +192,7 @@
 DEFINE_bool(clever_optimizations,
             true,
             "Optimize object size, Array shift, DOM strings and string +")
-DEFINE_bool(pretenure_literals, true, "allocate literals in old space")
+DEFINE_bool(pretenuring, true, "allocate objects in old space")
 DEFINE_bool(track_fields, true, "track fields with only smi values")
 DEFINE_bool(track_double_fields, true, "track fields with double values")
 DEFINE_bool(track_heap_object_fields, true, "track fields with heap values")
@@ -258,7 +258,7 @@
             "eliminate unreachable code (hidden behind soft deopts)")
 DEFINE_bool(track_allocation_sites, true,
             "Use allocation site info to reduce transitions")
-DEFINE_bool(optimize_constructed_arrays, false,
+DEFINE_bool(optimize_constructed_arrays, true,
             "Use allocation site info on constructed arrays")
 DEFINE_bool(trace_osr, false, "trace on-stack replacement")
 DEFINE_int(stress_runs, 0, "number of stress runs")
@@ -377,6 +377,8 @@
             "print a stack trace if an assertion failure occurs")
 
 // codegen-ia32.cc / codegen-arm.cc
+DEFINE_bool(trace_codegen, false,
+            "print name of functions for which code is generated")
 DEFINE_bool(trace, false, "trace function calls")
 DEFINE_bool(mask_constants_with_cookie,
             true,
@@ -636,8 +638,6 @@
             "enable asserts that are slow to execute")
 
 // codegen-ia32.cc / codegen-arm.cc
-DEFINE_bool(trace_codegen, false,
-            "print name of functions for which code is generated")
 DEFINE_bool(print_source, false, "pretty print source code")
 DEFINE_bool(print_builtin_source, false,
             "pretty print source code for builtins")
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index dc646b1..ad2a994 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -304,10 +304,7 @@
     int len = String::cast(script->source())->length();
     isolate->counters()->total_full_codegen_source_size()->Increment(len);
   }
-  if (FLAG_trace_codegen) {
-    PrintF("Full Compiler - ");
-  }
-  CodeGenerator::MakeCodePrologue(info);
+  CodeGenerator::MakeCodePrologue(info, "full");
   const int kInitialBufferSize = 4 * KB;
   MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
 #ifdef ENABLE_GDB_JIT_INTERFACE
diff --git a/src/full-codegen.h b/src/full-codegen.h
index 32242b2..68263a5 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -491,6 +491,11 @@
   INLINE_RUNTIME_FUNCTION_LIST(EMIT_INLINE_RUNTIME_CALL)
 #undef EMIT_INLINE_RUNTIME_CALL
 
+  void EmitSeqStringSetCharCheck(Register string,
+                                 Register index,
+                                 Register value,
+                                 uint32_t encoding_mask);
+
   // Platform-specific code for resuming generators.
   void EmitGeneratorResume(Expression *generator,
                            Expression *value,
diff --git a/src/global-handles.cc b/src/global-handles.cc
index 29432bb..bfd8357 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -105,7 +105,7 @@
     *first_free = this;
   }
 
-  void Acquire(Object* object, GlobalHandles* global_handles) {
+  void Acquire(Object* object) {
     ASSERT(state() == FREE);
     object_ = object;
     class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
@@ -114,10 +114,10 @@
     set_state(NORMAL);
     parameter_or_next_free_.parameter = NULL;
     near_death_callback_ = NULL;
-    IncreaseBlockUses(global_handles);
+    IncreaseBlockUses();
   }
 
-  void Release(GlobalHandles* global_handles) {
+  void Release() {
     ASSERT(state() != FREE);
     set_state(FREE);
 #ifdef ENABLE_EXTRA_CHECKS
@@ -128,9 +128,7 @@
     set_partially_dependent(false);
     near_death_callback_ = NULL;
 #endif
-    parameter_or_next_free_.next_free = global_handles->first_free_;
-    global_handles->first_free_ = this;
-    DecreaseBlockUses(global_handles);
+    DecreaseBlockUses();
   }
 
   // Object slot accessors.
@@ -256,11 +254,10 @@
     set_parameter(NULL);
   }
 
-  bool PostGarbageCollectionProcessing(Isolate* isolate,
-                                       GlobalHandles* global_handles) {
+  bool PostGarbageCollectionProcessing(Isolate* isolate) {
     if (state() != Node::PENDING) return false;
     if (near_death_callback_ == NULL) {
-      Release(global_handles);
+      Release();
       return false;
     }
     void* par = parameter();
@@ -299,8 +296,8 @@
 
  private:
   inline NodeBlock* FindBlock();
-  inline void IncreaseBlockUses(GlobalHandles* global_handles);
-  inline void DecreaseBlockUses(GlobalHandles* global_handles);
+  inline void IncreaseBlockUses();
+  inline void DecreaseBlockUses();
 
   // Storage for object pointer.
   // Placed first to avoid offset computation.
@@ -343,8 +340,12 @@
  public:
   static const int kSize = 256;
 
-  explicit NodeBlock(NodeBlock* next)
-      : next_(next), used_nodes_(0), next_used_(NULL), prev_used_(NULL) {}
+  explicit NodeBlock(GlobalHandles* global_handles, NodeBlock* next)
+      : next_(next),
+        used_nodes_(0),
+        next_used_(NULL),
+        prev_used_(NULL),
+        global_handles_(global_handles) {}
 
   void PutNodesOnFreeList(Node** first_free) {
     for (int i = kSize - 1; i >= 0; --i) {
@@ -357,11 +358,11 @@
     return &nodes_[index];
   }
 
-  void IncreaseUses(GlobalHandles* global_handles) {
+  void IncreaseUses() {
     ASSERT(used_nodes_ < kSize);
     if (used_nodes_++ == 0) {
-      NodeBlock* old_first = global_handles->first_used_block_;
-      global_handles->first_used_block_ = this;
+      NodeBlock* old_first = global_handles_->first_used_block_;
+      global_handles_->first_used_block_ = this;
       next_used_ = old_first;
       prev_used_ = NULL;
       if (old_first == NULL) return;
@@ -369,17 +370,19 @@
     }
   }
 
-  void DecreaseUses(GlobalHandles* global_handles) {
+  void DecreaseUses() {
     ASSERT(used_nodes_ > 0);
     if (--used_nodes_ == 0) {
       if (next_used_ != NULL) next_used_->prev_used_ = prev_used_;
       if (prev_used_ != NULL) prev_used_->next_used_ = next_used_;
-      if (this == global_handles->first_used_block_) {
-        global_handles->first_used_block_ = next_used_;
+      if (this == global_handles_->first_used_block_) {
+        global_handles_->first_used_block_ = next_used_;
       }
     }
   }
 
+  GlobalHandles* global_handles() { return global_handles_; }
+
   // Next block in the list of all blocks.
   NodeBlock* next() const { return next_; }
 
@@ -393,6 +396,7 @@
   int used_nodes_;
   NodeBlock* next_used_;
   NodeBlock* prev_used_;
+  GlobalHandles* global_handles_;
 };
 
 
@@ -405,13 +409,23 @@
 }
 
 
-void GlobalHandles::Node::IncreaseBlockUses(GlobalHandles* global_handles) {
-  FindBlock()->IncreaseUses(global_handles);
+void GlobalHandles::Node::IncreaseBlockUses() {
+  NodeBlock* node_block = FindBlock();
+  node_block->IncreaseUses();
+  GlobalHandles* global_handles = node_block->global_handles();
+  global_handles->isolate()->counters()->global_handles()->Increment();
+  global_handles->number_of_global_handles_++;
 }
 
 
-void GlobalHandles::Node::DecreaseBlockUses(GlobalHandles* global_handles) {
-  FindBlock()->DecreaseUses(global_handles);
+void GlobalHandles::Node::DecreaseBlockUses() {
+  NodeBlock* node_block = FindBlock();
+  GlobalHandles* global_handles = node_block->global_handles();
+  parameter_or_next_free_.next_free = global_handles->first_free_;
+  global_handles->first_free_ = this;
+  node_block->DecreaseUses();
+  global_handles->isolate()->counters()->global_handles()->Decrement();
+  global_handles->number_of_global_handles_--;
 }
 
 
@@ -465,17 +479,15 @@
 
 
 Handle<Object> GlobalHandles::Create(Object* value) {
-  isolate_->counters()->global_handles()->Increment();
-  number_of_global_handles_++;
   if (first_free_ == NULL) {
-    first_block_ = new NodeBlock(first_block_);
+    first_block_ = new NodeBlock(this, first_block_);
     first_block_->PutNodesOnFreeList(&first_free_);
   }
   ASSERT(first_free_ != NULL);
   // Take the first node in the free list.
   Node* result = first_free_;
   first_free_ = result->next_free();
-  result->Acquire(value, this);
+  result->Acquire(value);
   if (isolate_->heap()->InNewSpace(value) &&
       !result->is_in_new_space_list()) {
     new_space_nodes_.Add(result);
@@ -486,10 +498,7 @@
 
 
 void GlobalHandles::Destroy(Object** location) {
-  isolate_->counters()->global_handles()->Decrement();
-  number_of_global_handles_--;
-  if (location == NULL) return;
-  Node::FromLocation(location)->Release(this);
+  if (location != NULL) Node::FromLocation(location)->Release();
 }
 
 
@@ -653,7 +662,7 @@
         continue;
       }
       node->clear_partially_dependent();
-      if (node->PostGarbageCollectionProcessing(isolate_, this)) {
+      if (node->PostGarbageCollectionProcessing(isolate_)) {
         if (initial_post_gc_processing_count != post_gc_processing_count_) {
           // Weak callback triggered another GC and another round of
           // PostGarbageCollection processing.  The current node might
@@ -669,7 +678,7 @@
   } else {
     for (NodeIterator it(this); !it.done(); it.Advance()) {
       it.node()->clear_partially_dependent();
-      if (it.node()->PostGarbageCollectionProcessing(isolate_, this)) {
+      if (it.node()->PostGarbageCollectionProcessing(isolate_)) {
         if (initial_post_gc_processing_count != post_gc_processing_count_) {
           // See the comment above.
           return next_gc_likely_to_collect_more;
diff --git a/src/global-handles.h b/src/global-handles.h
index f502dfa..3cca384 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -128,7 +128,7 @@
   Handle<Object> Create(Object* value);
 
   // Destroy a global handle.
-  void Destroy(Object** location);
+  static void Destroy(Object** location);
 
   typedef WeakReferenceCallbacks<v8::Value, void>::Revivable RevivableCallback;
 
diff --git a/src/heap.cc b/src/heap.cc
index 98844f0..587e2f1 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -118,8 +118,7 @@
       disallow_allocation_failure_(false),
 #endif  // DEBUG
       new_space_high_promotion_mode_active_(false),
-      old_gen_promotion_limit_(kMinimumPromotionLimit),
-      old_gen_allocation_limit_(kMinimumAllocationLimit),
+      old_generation_allocation_limit_(kMinimumOldGenerationAllocationLimit),
       size_of_old_gen_at_last_old_space_gc_(0),
       external_allocation_limit_(0),
       amount_of_external_allocated_memory_(0),
@@ -282,7 +281,7 @@
   }
 
   // Is enough data promoted to justify a global GC?
-  if (OldGenerationPromotionLimitReached()) {
+  if (OldGenerationAllocationLimitReached()) {
     isolate_->counters()->gc_compactor_caused_by_promoted_data()->Increment();
     *reason = "promotion limit reached";
     return MARK_COMPACTOR;
@@ -916,10 +915,8 @@
 
     size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSizeOfObjects();
 
-    old_gen_promotion_limit_ =
-        OldGenPromotionLimit(size_of_old_gen_at_last_old_space_gc_);
-    old_gen_allocation_limit_ =
-        OldGenAllocationLimit(size_of_old_gen_at_last_old_space_gc_);
+    old_generation_allocation_limit_ =
+        OldGenerationAllocationLimit(size_of_old_gen_at_last_old_space_gc_);
 
     old_gen_exhausted_ = false;
   } else {
@@ -938,7 +935,7 @@
     // maximum capacity indicates that most objects will be promoted.
     // To decrease scavenger pauses and final mark-sweep pauses, we
     // have to limit maximal capacity of the young generation.
-    new_space_high_promotion_mode_active_ = true;
+    SetNewSpaceHighPromotionModeActive(true);
     if (FLAG_trace_gc) {
       PrintPID("Limited new space size due to high promotion rate: %d MB\n",
                new_space_.InitialCapacity() / MB);
@@ -947,7 +944,7 @@
     // heuristic indicator of whether to pretenure or not, we trigger
     // deoptimization here to take advantage of pre-tenuring as soon as
     // possible.
-    if (FLAG_pretenure_literals) {
+    if (FLAG_pretenuring) {
       isolate_->stack_guard()->FullDeopt();
     }
   } else if (new_space_high_promotion_mode_active_ &&
@@ -956,14 +953,14 @@
     // Decreasing low survival rates might indicate that the above high
     // promotion mode is over and we should allow the young generation
     // to grow again.
-    new_space_high_promotion_mode_active_ = false;
+    SetNewSpaceHighPromotionModeActive(false);
     if (FLAG_trace_gc) {
       PrintPID("Unlimited new space size due to low promotion rate: %d MB\n",
                new_space_.MaximumCapacity() / MB);
     }
     // Trigger deoptimization here to turn off pre-tenuring as soon as
     // possible.
-    if (FLAG_pretenure_literals) {
+    if (FLAG_pretenuring) {
       isolate_->stack_guard()->FullDeopt();
     }
   }
@@ -2964,6 +2961,17 @@
   }
   set_observation_state(JSObject::cast(obj));
 
+  { MaybeObject* maybe_obj = AllocateSymbol();
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_frozen_symbol(Symbol::cast(obj));
+
+  { MaybeObject* maybe_obj = SeededNumberDictionary::Allocate(this, 0, TENURED);
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  SeededNumberDictionary::cast(obj)->set_requires_slow_elements();
+  set_empty_slow_element_dictionary(SeededNumberDictionary::cast(obj));
+
   // Handling of script id generation is in FACTORY->NewScript.
   set_last_script_id(undefined_value());
 
@@ -5959,10 +5967,8 @@
   USE(title);
   PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n",
          title, gc_count_);
-  PrintF("old_gen_promotion_limit_ %" V8_PTR_PREFIX "d\n",
-         old_gen_promotion_limit_);
-  PrintF("old_gen_allocation_limit_ %" V8_PTR_PREFIX "d\n",
-         old_gen_allocation_limit_);
+  PrintF("old_generation_allocation_limit_ %" V8_PTR_PREFIX "d\n",
+         old_generation_allocation_limit_);
 
   PrintF("\n");
   PrintF("Number of handles : %d\n", HandleScope::NumberOfHandles(isolate_));
diff --git a/src/heap.h b/src/heap.h
index b24b0b3..a694257 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -181,7 +181,10 @@
   V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset)                 \
   V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset)                 \
   V(JSObject, observation_state, ObservationState)                             \
-  V(Map, external_map, ExternalMap)
+  V(Map, external_map, ExternalMap)                                            \
+  V(Symbol, frozen_symbol, FrozenSymbol)                                       \
+  V(SeededNumberDictionary, empty_slow_element_dictionary,                     \
+      EmptySlowElementDictionary)
 
 #define ROOT_LIST(V)                                  \
   STRONG_ROOT_LIST(V)                                 \
@@ -1546,7 +1549,12 @@
   // Predicate that governs global pre-tenuring decisions based on observed
   // promotion rates of previous collections.
   inline bool ShouldGloballyPretenure() {
-    return new_space_high_promotion_mode_active_;
+    return FLAG_pretenuring && new_space_high_promotion_mode_active_;
+  }
+
+  // This is only needed for testing high promotion mode.
+  void SetNewSpaceHighPromotionModeActive(bool mode) {
+    new_space_high_promotion_mode_active_ = mode;
   }
 
   inline PretenureFlag GetPretenureMode() {
@@ -1561,44 +1569,23 @@
     return PromotedSpaceSizeOfObjects() + PromotedExternalMemorySize();
   }
 
-  // True if we have reached the allocation limit in the old generation that
-  // should force the next GC (caused normally) to be a full one.
-  inline bool OldGenerationPromotionLimitReached() {
-    return PromotedTotalSize() > old_gen_promotion_limit_;
-  }
-
   inline intptr_t OldGenerationSpaceAvailable() {
-    return old_gen_allocation_limit_ - PromotedTotalSize();
+    return old_generation_allocation_limit_ - PromotedTotalSize();
   }
 
   inline intptr_t OldGenerationCapacityAvailable() {
     return max_old_generation_size_ - PromotedTotalSize();
   }
 
-  static const intptr_t kMinimumPromotionLimit = 5 * Page::kPageSize;
-  static const intptr_t kMinimumAllocationLimit =
+  static const intptr_t kMinimumOldGenerationAllocationLimit =
       8 * (Page::kPageSize > MB ? Page::kPageSize : MB);
 
-  intptr_t OldGenPromotionLimit(intptr_t old_gen_size) {
+  intptr_t OldGenerationAllocationLimit(intptr_t old_gen_size) {
     const int divisor = FLAG_stress_compaction ? 10 :
         new_space_high_promotion_mode_active_ ? 1 : 3;
     intptr_t limit =
-        Max(old_gen_size + old_gen_size / divisor, kMinimumPromotionLimit);
-    limit += new_space_.Capacity();
-    // TODO(hpayer): Can be removed when when pretenuring is supported for all
-    // allocation sites.
-    if (IsHighSurvivalRate() && IsStableOrIncreasingSurvivalTrend()) {
-      limit *= 2;
-    }
-    intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2;
-    return Min(limit, halfway_to_the_max);
-  }
-
-  intptr_t OldGenAllocationLimit(intptr_t old_gen_size) {
-    const int divisor = FLAG_stress_compaction ? 8 :
-        new_space_high_promotion_mode_active_ ? 1 : 2;
-    intptr_t limit =
-        Max(old_gen_size + old_gen_size / divisor, kMinimumAllocationLimit);
+        Max(old_gen_size + old_gen_size / divisor,
+            kMinimumOldGenerationAllocationLimit);
     limit += new_space_.Capacity();
     // TODO(hpayer): Can be removed when when pretenuring is supported for all
     // allocation sites.
@@ -1679,22 +1666,14 @@
 
     if (FLAG_stress_compaction && (gc_count_ & 1) != 0) return true;
 
-    intptr_t total_promoted = PromotedTotalSize();
-
-    intptr_t adjusted_promotion_limit =
-        old_gen_promotion_limit_ - new_space_.Capacity();
-
-    if (total_promoted >= adjusted_promotion_limit) return true;
-
     intptr_t adjusted_allocation_limit =
-        old_gen_allocation_limit_ - new_space_.Capacity() / 5;
+        old_generation_allocation_limit_ - new_space_.Capacity();
 
-    if (PromotedSpaceSizeOfObjects() >= adjusted_allocation_limit) return true;
+    if (PromotedTotalSize() >= adjusted_allocation_limit) return true;
 
     return false;
   }
 
-
   void UpdateNewSpaceReferencesInExternalStringTable(
       ExternalStringTableUpdaterCallback updater_func);
 
@@ -2019,13 +1998,9 @@
 
   // Limit that triggers a global GC on the next (normally caused) GC.  This
   // is checked when we have already decided to do a GC to help determine
-  // which collector to invoke.
-  intptr_t old_gen_promotion_limit_;
-
-  // Limit that triggers a global GC as soon as is reasonable.  This is
-  // checked before expanding a paged space in the old generation and on
-  // every allocation in large object space.
-  intptr_t old_gen_allocation_limit_;
+  // which collector to invoke, before expanding a paged space in the old
+  // generation and on every allocation in large object space.
+  intptr_t old_generation_allocation_limit_;
 
   // Used to adjust the limits that control the timing of the next GC.
   intptr_t size_of_old_gen_at_last_old_space_gc_;
@@ -2043,7 +2018,7 @@
 
   // Indicates that an allocation has failed in the old generation since the
   // last GC.
-  int old_gen_exhausted_;
+  bool old_gen_exhausted_;
 
   Object* native_contexts_list_;
 
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index b747387..e949587 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -108,10 +108,12 @@
   int tagged_count = use_count[Representation::kTagged];
   int double_count = use_count[Representation::kDouble];
   int int32_count = use_count[Representation::kInteger32];
+  int smi_count = use_count[Representation::kSmi];
 
   if (tagged_count > 0) return Representation::Tagged();
   if (double_count > 0) return Representation::Double();
   if (int32_count > 0) return Representation::Integer32();
+  if (smi_count > 0) return Representation::Smi();
 
   return Representation::None();
 }
@@ -1143,16 +1145,15 @@
   HValue* actual_length = length()->ActualValue();
   HValue* actual_index = index()->ActualValue();
   if (key_mode_ == DONT_ALLOW_SMI_KEY ||
-      !actual_length->representation().IsTagged()) {
+      !actual_length->representation().IsSmiOrTagged()) {
     r = Representation::Integer32();
-  } else if (actual_index->representation().IsTagged() ||
-      (actual_index->IsConstant() &&
-       HConstant::cast(actual_index)->HasSmiValue())) {
-    // If the index is tagged, or a constant that holds a Smi, allow the length
-    // to be tagged, since it is usually already tagged from loading it out of
-    // the length field of a JSArray. This allows for direct comparison without
-    // untagging.
-    r = Representation::Tagged();
+  } else if (actual_index->representation().IsSmiOrTagged() ||
+             (actual_index->IsConstant() &&
+              HConstant::cast(actual_index)->HasSmiValue())) {
+    // If the index is smi, or a constant that holds a Smi, allow the length to
+    // be smi, since it is usually already smi from loading it out of the length
+    // field of a JSArray. This allows for direct comparison without untagging.
+    r = Representation::Smi();
   } else {
     r = Representation::Integer32();
   }
@@ -1687,7 +1688,7 @@
 Range* HChange::InferRange(Zone* zone) {
   Range* input_range = value()->range();
   if (from().IsInteger32() &&
-      to().IsTagged() &&
+      to().IsSmiOrTagged() &&
       !value()->CheckFlag(HInstruction::kUint32) &&
       input_range != NULL && input_range->IsInSmiRange()) {
     set_type(HType::Smi());
@@ -1910,8 +1911,9 @@
     value->PrintNameTo(stream);
     stream->Add(" ");
   }
-  stream->Add(" uses:%d_%di_%dd_%dt",
+  stream->Add(" uses:%d_%ds_%di_%dd_%dt",
               UseCount(),
+              smi_non_phi_uses() + smi_indirect_uses(),
               int32_non_phi_uses() + int32_indirect_uses(),
               double_non_phi_uses() + double_indirect_uses(),
               tagged_non_phi_uses() + tagged_indirect_uses());
@@ -1990,8 +1992,9 @@
 
 void HPhi::AddNonPhiUsesFrom(HPhi* other) {
   if (FLAG_trace_representation) {
-    PrintF("adding to #%d Phi uses of #%d Phi: i%d d%d t%d\n",
+    PrintF("adding to #%d Phi uses of #%d Phi: s%d i%d d%d t%d\n",
            id(), other->id(),
+           other->non_phi_uses_[Representation::kSmi],
            other->non_phi_uses_[Representation::kInteger32],
            other->non_phi_uses_[Representation::kDouble],
            other->non_phi_uses_[Representation::kTagged]);
@@ -2016,8 +2019,9 @@
     ZoneList<HValue*>* from_values = &from->values_;
     for (int i = 0; i < from_values->length(); ++i) {
       if (from->HasAssignedIndexAt(i)) {
-        AddAssignedValue(from->GetAssignedIndexAt(i),
-                         from_values->at(i));
+        int index = from->GetAssignedIndexAt(i);
+        if (HasValueForIndex(index)) continue;
+        AddAssignedValue(index, from_values->at(i));
       } else {
         if (pop_count_ > 0) {
           pop_count_--;
@@ -2038,13 +2042,13 @@
   if (values_.length() > 0) {
     if (pop_count_ > 0) stream->Add(" /");
     for (int i = values_.length() - 1; i >= 0; --i) {
-      if (i > 0) stream->Add(",");
       if (HasAssignedIndexAt(i)) {
         stream->Add(" var[%d] = ", GetAssignedIndexAt(i));
       } else {
         stream->Add(" push ");
       }
       values_[i]->PrintNameTo(stream);
+      if (i > 0) stream->Add(",");
     }
   }
 }
@@ -2482,7 +2486,7 @@
 
 void HLoadNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintNameTo(stream);
-  stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
+  access_.PrintTo(stream);
   if (HasTypeCheck()) {
     stream->Add(" ");
     typecheck()->PrintNameTo(stream);
@@ -2804,11 +2808,9 @@
 
 void HStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintNameTo(stream);
-  stream->Add(".");
-  stream->Add(*String::cast(*name())->ToCString());
+  access_.PrintTo(stream);
   stream->Add(" = ");
   value()->PrintNameTo(stream);
-  stream->Add(" @%d%s", offset(), is_in_object() ? "[in-object]" : "");
   if (NeedsWriteBarrier()) {
     stream->Add(" (write-barrier)");
   }
@@ -2946,15 +2948,6 @@
 }
 
 
-void HCheckSmiOrInt32::InferRepresentation(HInferRepresentation* h_infer) {
-  ASSERT(CheckFlag(kFlexibleRepresentation));
-  ASSERT(UseCount() == 1);
-  HUseIterator use = uses();
-  Representation r = use.value()->RequiredInputRepresentation(use.index());
-  UpdateRepresentation(r, h_infer, "checksmiorint32");
-}
-
-
 HType HPhi::CalculateInferredType() {
   HType result = HType::Uninitialized();
   for (int i = 0; i < OperandCount(); ++i) {
@@ -3557,6 +3550,7 @@
 Representation HPhi::RepresentationFromInputs() {
   bool double_occurred = false;
   bool int32_occurred = false;
+  bool smi_occurred = false;
   for (int i = 0; i < OperandCount(); ++i) {
     HValue* value = OperandAt(i);
     if (value->IsUnknownOSRValue()) {
@@ -3566,11 +3560,13 @@
         if (hint.IsTagged()) return hint;
         if (hint.IsDouble()) double_occurred = true;
         if (hint.IsInteger32()) int32_occurred = true;
+        if (hint.IsSmi()) smi_occurred = true;
       }
       continue;
     }
     if (value->representation().IsDouble()) double_occurred = true;
     if (value->representation().IsInteger32()) int32_occurred = true;
+    if (value->representation().IsSmi()) smi_occurred = true;
     if (value->representation().IsTagged()) {
       if (value->IsConstant()) {
         HConstant* constant = HConstant::cast(value);
@@ -3590,8 +3586,8 @@
   }
 
   if (double_occurred) return Representation::Double();
-
   if (int32_occurred) return Representation::Integer32();
+  if (smi_occurred) return Representation::Smi();
 
   return Representation::None();
 }
@@ -3668,4 +3664,141 @@
 
 #endif
 
+
+HObjectAccess HObjectAccess::ForFixedArrayHeader(int offset) {
+  ASSERT(offset >= 0);
+  ASSERT(offset < FixedArray::kHeaderSize);
+  if (offset == FixedArray::kLengthOffset) return ForFixedArrayLength();
+  return HObjectAccess(kInobject, offset);
+}
+
+
+HObjectAccess HObjectAccess::ForJSObjectOffset(int offset) {
+  ASSERT(offset >= 0);
+  Portion portion = kInobject;
+
+  if (offset == JSObject::kElementsOffset) {
+    portion = kElementsPointer;
+  } else if (offset == JSObject::kMapOffset) {
+    portion = kMaps;
+  }
+  return HObjectAccess(portion, offset, Handle<String>::null());
+}
+
+
+HObjectAccess HObjectAccess::ForJSArrayOffset(int offset) {
+  ASSERT(offset >= 0);
+  Portion portion = kInobject;
+
+  if (offset == JSObject::kElementsOffset) {
+    portion = kElementsPointer;
+  } else if (offset == JSArray::kLengthOffset) {
+    portion = kArrayLengths;
+  } else if (offset == JSObject::kMapOffset) {
+    portion = kMaps;
+  }
+  return HObjectAccess(portion, offset, Handle<String>::null());
+}
+
+
+HObjectAccess HObjectAccess::ForBackingStoreOffset(int offset) {
+  ASSERT(offset >= 0);
+  return HObjectAccess(kBackingStore, offset, Handle<String>::null());
+}
+
+
+HObjectAccess HObjectAccess::ForField(Handle<Map> map,
+    LookupResult *lookup, Handle<String> name) {
+  ASSERT(lookup->IsField() || lookup->IsTransitionToField(*map));
+  int index;
+  if (lookup->IsField()) {
+    index = lookup->GetLocalFieldIndexFromMap(*map);
+  } else {
+    Map* transition = lookup->GetTransitionMapFromMap(*map);
+    int descriptor = transition->LastAdded();
+    index = transition->instance_descriptors()->GetFieldIndex(descriptor) -
+        map->inobject_properties();
+  }
+  if (index < 0) {
+    // Negative property indices are in-object properties, indexed
+    // from the end of the fixed part of the object.
+    int offset = (index * kPointerSize) + map->instance_size();
+    return HObjectAccess(kInobject, offset);
+  } else {
+    // Non-negative property indices are in the properties array.
+    int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
+    return HObjectAccess(kBackingStore, offset, name);
+  }
+}
+
+
+void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) {
+  // set the appropriate GVN flags for a given load or store instruction
+  if (is_store) {
+    // track dominating allocations in order to eliminate write barriers
+    instr->SetGVNFlag(kDependsOnNewSpacePromotion);
+    instr->SetFlag(HValue::kTrackSideEffectDominators);
+    instr->SetFlag(HValue::kDeoptimizeOnUndefined);
+  } else {
+    // try to GVN loads, but don't hoist above map changes
+    instr->SetFlag(HValue::kUseGVN);
+    instr->SetGVNFlag(kDependsOnMaps);
+  }
+
+  switch (portion()) {
+    case kArrayLengths:
+      instr->SetGVNFlag(is_store
+          ? kChangesArrayLengths : kDependsOnArrayLengths);
+      break;
+    case kInobject:
+      instr->SetGVNFlag(is_store
+          ? kChangesInobjectFields : kDependsOnInobjectFields);
+      break;
+    case kDouble:
+      instr->SetGVNFlag(is_store
+          ? kChangesDoubleFields : kDependsOnDoubleFields);
+      break;
+    case kBackingStore:
+      instr->SetGVNFlag(is_store
+          ? kChangesBackingStoreFields : kDependsOnBackingStoreFields);
+      break;
+    case kElementsPointer:
+      instr->SetGVNFlag(is_store
+          ? kChangesElementsPointer : kDependsOnElementsPointer);
+      break;
+    case kMaps:
+      instr->SetGVNFlag(is_store
+          ? kChangesMaps : kDependsOnMaps);
+      break;
+  }
+}
+
+
+void HObjectAccess::PrintTo(StringStream* stream) {
+  stream->Add(".");
+
+  switch (portion()) {
+    case kArrayLengths:
+      stream->Add("%length");
+      break;
+    case kElementsPointer:
+      stream->Add("%elements");
+      break;
+    case kMaps:
+      stream->Add("%map");
+      break;
+    case kDouble:  // fall through
+    case kInobject:
+      if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
+      stream->Add("[in-object]");
+      break;
+    case kBackingStore:
+      if (!name_.is_null()) stream->Add(*String::cast(*name_)->ToCString());
+      stream->Add("[backing-store]");
+      break;
+  }
+
+  stream->Add("@%d", offset());
+}
+
 } }  // namespace v8::internal
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index c6a5111..43a5ad8 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -93,7 +93,6 @@
   V(CheckNonSmi)                               \
   V(CheckPrototypeMaps)                        \
   V(CheckSmi)                                  \
-  V(CheckSmiOrInt32)                           \
   V(ClampToUint8)                              \
   V(ClassOfTestAndBranch)                      \
   V(CompareIDAndBranch)                        \
@@ -1721,7 +1720,7 @@
     SetFlag(kUseGVN);
     if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
     if (is_truncating) SetFlag(kTruncatingToInt32);
-    if (value->type().IsSmi()) {
+    if (value->representation().IsSmi() || value->type().IsSmi()) {
       set_type(HType::Smi());
     } else {
       set_type(HType::TaggedNumber());
@@ -1858,6 +1857,12 @@
     // use lists are correctly updated.
     SetOperandAt(values_.length() - 1, value);
   }
+  bool HasValueForIndex(int index) {
+    for (int i = 0; i < assigned_indexes_.length(); ++i) {
+      if (assigned_indexes_[i] == index) return true;
+    }
+    return false;
+  }
   BailoutId ast_id_;
   int pop_count_;
   ZoneList<HValue*> values_;
@@ -2416,7 +2421,7 @@
  public:
   explicit HFixedArrayBaseLength(HValue* value) : HUnaryOperation(value) {
     set_type(HType::Smi());
-    set_representation(Representation::Tagged());
+    set_representation(Representation::Smi());
     SetFlag(kUseGVN);
     SetGVNFlag(kDependsOnArrayLengths);
   }
@@ -2946,38 +2951,6 @@
 };
 
 
-class HCheckSmiOrInt32: public HUnaryOperation {
- public:
-  explicit HCheckSmiOrInt32(HValue* value) : HUnaryOperation(value) {
-    SetFlag(kFlexibleRepresentation);
-    SetFlag(kUseGVN);
-  }
-
-  virtual int RedefinedOperandIndex() { return 0; }
-  virtual Representation RequiredInputRepresentation(int index) {
-    return representation();
-  }
-  virtual void InferRepresentation(HInferRepresentation* h_infer);
-
-  virtual Representation observed_input_representation(int index) {
-    return Representation::Integer32();
-  }
-
-  virtual HValue* Canonicalize() {
-    if (representation().IsTagged() && !value()->type().IsSmi()) {
-      return this;
-    } else {
-      return value();
-    }
-  }
-
-  DECLARE_CONCRETE_INSTRUCTION(CheckSmiOrInt32)
-
- protected:
-  virtual bool DataEquals(HValue* other) { return true; }
-};
-
-
 class HPhi: public HValue {
  public:
   HPhi(int merged_index, Zone* zone)
@@ -3027,6 +3000,9 @@
   int tagged_non_phi_uses() const {
     return non_phi_uses_[Representation::kTagged];
   }
+  int smi_non_phi_uses() const {
+    return non_phi_uses_[Representation::kSmi];
+  }
   int int32_non_phi_uses() const {
     return non_phi_uses_[Representation::kInteger32];
   }
@@ -3036,6 +3012,9 @@
   int tagged_indirect_uses() const {
     return indirect_uses_[Representation::kTagged];
   }
+  int smi_indirect_uses() const {
+    return indirect_uses_[Representation::kSmi];
+  }
   int int32_indirect_uses() const {
     return indirect_uses_[Representation::kInteger32];
   }
@@ -3572,8 +3551,7 @@
 class HBoundsCheck: public HTemplateInstruction<2> {
  public:
   // Normally HBoundsCheck should be created using the
-  // HGraphBuilder::AddBoundsCheck() helper, which also guards the index with
-  // a HCheckSmiOrInt32 check.
+  // HGraphBuilder::AddBoundsCheck() helper.
   // However when building stubs, where we know that the arguments are Int32,
   // it makes sense to invoke this constructor directly.
   HBoundsCheck(HValue* index,
@@ -5195,21 +5173,121 @@
 };
 
 
+// Represents an access to a portion of an object, such as the map pointer,
+// array elements pointer, etc, but not accesses to array elements themselves.
+class HObjectAccess {
+ public:
+  inline bool IsInobject() const {
+    return portion() != kBackingStore;
+  }
+
+  inline int offset() const {
+    return OffsetField::decode(value_);
+  }
+
+  inline Handle<String> name() const {
+    return name_;
+  }
+
+  static HObjectAccess ForHeapNumberValue() {
+    return HObjectAccess(kDouble, HeapNumber::kValueOffset);
+  }
+
+  static HObjectAccess ForElementsPointer() {
+    return HObjectAccess(kElementsPointer, JSObject::kElementsOffset);
+  }
+
+  static HObjectAccess ForArrayLength() {
+    return HObjectAccess(kArrayLengths, JSArray::kLengthOffset);
+  }
+
+  static HObjectAccess ForFixedArrayLength() {
+    return HObjectAccess(kArrayLengths, FixedArray::kLengthOffset);
+  }
+
+  static HObjectAccess ForPropertiesPointer() {
+    return HObjectAccess(kInobject, JSObject::kPropertiesOffset);
+  }
+
+  static HObjectAccess ForMap() {
+    return HObjectAccess(kMaps, JSObject::kMapOffset);
+  }
+
+  static HObjectAccess ForAllocationSitePayload() {
+    return HObjectAccess(kInobject, AllocationSiteInfo::kPayloadOffset);
+  }
+
+  // Create an access to an offset in a fixed array header.
+  static HObjectAccess ForFixedArrayHeader(int offset);
+
+  // Create an access to an in-object property in a JSObject.
+  static HObjectAccess ForJSObjectOffset(int offset);
+
+  // Create an access to an in-object property in a JSArray.
+  static HObjectAccess ForJSArrayOffset(int offset);
+
+  // Create an access to the backing store of an object.
+  static HObjectAccess ForBackingStoreOffset(int offset);
+
+  // Create an access to a resolved field (in-object or backing store).
+  static HObjectAccess ForField(Handle<Map> map,
+      LookupResult *lookup, Handle<String> name = Handle<String>::null());
+
+  void PrintTo(StringStream* stream);
+
+ protected:
+  void SetGVNFlags(HValue *instr, bool is_store);
+
+ private:
+  // internal use only; different parts of an object or array
+  enum Portion {
+    kMaps,             // map of an object
+    kArrayLengths,     // the length of an array
+    kElementsPointer,  // elements pointer
+    kBackingStore,     // some field in the backing store
+    kDouble,           // some double field
+    kInobject          // some other in-object field
+  };
+
+  HObjectAccess(Portion portion, int offset,
+      Handle<String> name = Handle<String>::null())
+    : value_(PortionField::encode(portion) | OffsetField::encode(offset)),
+      name_(name) {
+    ASSERT(this->offset() == offset);    // offset should decode correctly
+    ASSERT(this->portion() == portion);  // portion should decode correctly
+  }
+
+  class PortionField : public BitField<Portion, 0, 3> {};
+  class OffsetField : public BitField<int, 3, 29> {};
+
+  uint32_t value_;  // encodes both portion and offset
+  Handle<String> name_;
+
+  friend class HLoadNamedField;
+  friend class HStoreNamedField;
+
+  inline Portion portion() const {
+    return PortionField::decode(value_);
+  }
+};
+
+
 class HLoadNamedField: public HTemplateInstruction<2> {
  public:
-  HLoadNamedField(HValue* object, bool is_in_object,
-                  Representation field_representation,
-                  int offset, HValue* typecheck = NULL)
-      : is_in_object_(is_in_object),
-        field_representation_(field_representation),
-        offset_(offset) {
+  HLoadNamedField(HValue* object,
+                  HObjectAccess access,
+                  HValue* typecheck = NULL,
+                  Representation field_representation
+                      = Representation::Tagged())
+      : access_(access),
+        field_representation_(field_representation) {
     ASSERT(object != NULL);
     SetOperandAt(0, object);
     SetOperandAt(1, typecheck != NULL ? typecheck : object);
 
     if (FLAG_track_fields && field_representation.IsSmi()) {
       set_type(HType::Smi());
-      set_representation(Representation::Tagged());
+      set_representation(field_representation);
     } else if (FLAG_track_double_fields && field_representation.IsDouble()) {
       set_representation(field_representation);
     } else if (FLAG_track_heap_object_fields &&
@@ -5219,31 +5297,7 @@
     } else {
       set_representation(Representation::Tagged());
     }
-    SetFlag(kUseGVN);
-    if (FLAG_track_double_fields && representation().IsDouble()) {
-      ASSERT(is_in_object);
-      ASSERT(offset == HeapNumber::kValueOffset);
-      SetGVNFlag(kDependsOnDoubleFields);
-    } else if (is_in_object) {
-      SetGVNFlag(kDependsOnInobjectFields);
-      SetGVNFlag(kDependsOnMaps);
-    } else {
-      SetGVNFlag(kDependsOnBackingStoreFields);
-      SetGVNFlag(kDependsOnMaps);
-    }
-  }
-
-  static HLoadNamedField* NewArrayLength(Zone* zone, HValue* object,
-                                         HValue* typecheck,
-                                         HType type = HType::Tagged()) {
-    Representation representation =
-        type.IsSmi() ? Representation::Smi() : Representation::Tagged();
-    HLoadNamedField* result = new(zone) HLoadNamedField(
-        object, true, representation, JSArray::kLengthOffset, typecheck);
-    result->set_type(type);
-    result->SetGVNFlag(kDependsOnArrayLengths);
-    result->ClearGVNFlag(kDependsOnInobjectFields);
-    return result;
+    access.SetGVNFlags(this, false);
   }
 
   HValue* object() { return OperandAt(0); }
@@ -5253,9 +5307,10 @@
   }
 
   bool HasTypeCheck() const { return OperandAt(0) != OperandAt(1); }
-  bool is_in_object() const { return is_in_object_; }
+  HObjectAccess access() const { return access_; }
+  bool is_in_object() const { return access_.IsInobject(); }
   Representation field_representation() const { return representation_; }
-  int offset() const { return offset_; }
+  int offset() const { return access_.offset(); }
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::Tagged();
@@ -5267,15 +5322,14 @@
  protected:
   virtual bool DataEquals(HValue* other) {
     HLoadNamedField* b = HLoadNamedField::cast(other);
-    return is_in_object_ == b->is_in_object_ && offset_ == b->offset_;
+    return is_in_object() == b->is_in_object() && offset() == b->offset();
   }
 
  private:
   virtual bool IsDeletable() const { return true; }
 
-  bool is_in_object_;
+  HObjectAccess access_;
   Representation field_representation_;
-  int offset_;
 };
 
 
@@ -5377,7 +5431,7 @@
 
   static Representation KeyedAccessIndexRequirement(Representation r) {
     return r.IsInteger32() ? Representation::Integer32()
-                           : Representation::Tagged();
+                           : Representation::Smi();
   }
 };
 
@@ -5411,11 +5465,13 @@
              IsFastDoubleElementsKind(elements_kind));
 
       if (IsFastSmiOrObjectElementsKind(elements_kind)) {
-        if (elements_kind == FAST_SMI_ELEMENTS) {
+        if (IsFastSmiElementsKind(elements_kind)) {
           set_type(HType::Smi());
+          set_representation(Representation::Smi());
+        } else {
+          set_representation(Representation::Tagged());
         }
 
-        set_representation(Representation::Tagged());
         SetGVNFlag(kDependsOnArrayElements);
       } else {
         set_representation(Representation::Double());
@@ -5570,30 +5626,17 @@
 class HStoreNamedField: public HTemplateInstruction<2> {
  public:
   HStoreNamedField(HValue* obj,
-                   Handle<Name> name,
+                   HObjectAccess access,
                    HValue* val,
-                   bool in_object,
-                   Representation field_representation,
-                   int offset)
-      : name_(name),
-        is_in_object_(in_object),
+                   Representation field_representation
+                       = Representation::Tagged())
+      : access_(access),
         field_representation_(field_representation),
-        offset_(offset),
         transition_unique_id_(),
         new_space_dominator_(NULL) {
     SetOperandAt(0, obj);
     SetOperandAt(1, val);
-    SetFlag(kTrackSideEffectDominators);
-    if (FLAG_track_double_fields && field_representation.IsDouble()) {
-      SetGVNFlag(kChangesDoubleFields);
-    } else if (is_in_object_) {
-      SetGVNFlag(kChangesInobjectFields);
-      SetGVNFlag(kDependsOnNewSpacePromotion);
-    } else {
-      SetGVNFlag(kChangesBackingStoreFields);
-      SetGVNFlag(kDependsOnNewSpacePromotion);
-    }
-    SetFlag(kDeoptimizeOnUndefined);
+    access.SetGVNFlags(this, true);
   }
 
   DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
@@ -5604,7 +5647,7 @@
       return field_representation_;
     } else if (FLAG_track_fields &&
                index == 1 && field_representation_.IsSmi()) {
-      return Representation::Integer32();
+      return field_representation_;
     }
     return Representation::Tagged();
   }
@@ -5617,9 +5660,10 @@
   HValue* object() { return OperandAt(0); }
   HValue* value() { return OperandAt(1); }
 
-  Handle<Name> name() const { return name_; }
-  bool is_in_object() const { return is_in_object_; }
-  int offset() const { return offset_; }
+  HObjectAccess access() const { return access_; }
+  Handle<String> name() const { return access_.name(); }
+  bool is_in_object() const { return access_.IsInobject(); }
+  int offset() const { return access_.offset(); }
   Handle<Map> transition() const { return transition_; }
   UniqueValueId transition_unique_id() const { return transition_unique_id_; }
   void set_transition(Handle<Map> map) { transition_ = map; }
@@ -5648,10 +5692,8 @@
   }
 
  private:
-  Handle<Name> name_;
-  bool is_in_object_;
+  HObjectAccess access_;
   Representation field_representation_;
-  int offset_;
   Handle<Map> transition_;
   UniqueValueId transition_unique_id_;
   HValue* new_space_dominator_;
@@ -5715,6 +5757,9 @@
     } else if (IsFastDoubleElementsKind(elements_kind)) {
       SetGVNFlag(kChangesDoubleArrayElements);
       SetFlag(kDeoptimizeOnUndefined);
+    } else if (IsFastSmiElementsKind(elements_kind)) {
+      SetGVNFlag(kChangesArrayElements);
+      SetFlag(kDeoptimizeOnUndefined);
     } else {
       SetGVNFlag(kChangesArrayElements);
     }
@@ -5743,6 +5788,10 @@
       return Representation::Double();
     }
 
+    if (IsFastSmiElementsKind(elements_kind())) {
+      return Representation::Smi();
+    }
+
     return is_external() ? Representation::Integer32()
                          : Representation::Tagged();
   }
@@ -6266,6 +6315,7 @@
     SetOperandAt(0, string);
     SetOperandAt(1, index);
     SetOperandAt(2, value);
+    set_representation(Representation::Tagged());
   }
 
   String::Encoding encoding() { return encoding_; }
@@ -6274,7 +6324,8 @@
   HValue* value() { return OperandAt(2); }
 
   virtual Representation RequiredInputRepresentation(int index) {
-    return Representation::Tagged();
+    return (index == 0) ? Representation::Tagged()
+                        : Representation::Integer32();
   }
 
   DECLARE_CONCRETE_INSTRUCTION(SeqStringSetChar)
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 097216e..54ae31f 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -157,7 +157,7 @@
   HSimulate* instr =
       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
   // Order of pushed values: newest (top of stack) first. This allows
-  // HSimulate::MergeInto() to easily append additional pushed values
+  // HSimulate::MergeWith() to easily append additional pushed values
   // that are older (from further down the stack).
   for (int i = 0; i < push_count; ++i) {
     instr->AddPushedValue(environment->ExpressionStackAt(i));
@@ -1003,14 +1003,6 @@
                                             HValue* length,
                                             BoundsCheckKeyMode key_mode,
                                             Representation r) {
-  if (!index->type().IsSmi()) {
-    index = new(graph()->zone()) HCheckSmiOrInt32(index);
-    AddInstruction(HCheckSmiOrInt32::cast(index));
-  }
-  if (!length->type().IsSmi()) {
-    length = new(graph()->zone()) HCheckSmiOrInt32(length);
-    AddInstruction(HCheckSmiOrInt32::cast(length));
-  }
   HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(
       index, length, key_mode, r);
   AddInstruction(result);
@@ -1195,16 +1187,10 @@
     new_length->AssumeRepresentation(Representation::Integer32());
     new_length->ClearFlag(HValue::kCanOverflow);
 
-    Factory* factory = isolate()->factory();
     Representation representation = IsFastElementsKind(kind)
         ? Representation::Smi() : Representation::Tagged();
-    HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
-        object,
-        factory->length_field_string(),
-        new_length, true,
-        representation,
-        JSArray::kLengthOffset));
-    length_store->SetGVNFlag(kChangesArrayLengths);
+    AddStore(object, HObjectAccess::ForArrayLength(), new_length,
+        representation);
   }
 
   length_checker.Else();
@@ -1286,8 +1272,9 @@
   }
   HInstruction* length = NULL;
   if (is_js_array) {
-    length = AddInstruction(
-        HLoadNamedField::NewArrayLength(zone, object, mapcheck, HType::Smi()));
+    length = AddLoad(object, HObjectAccess::ForArrayLength(), mapcheck,
+        Representation::Smi());
+    length->set_type(HType::Smi());
   } else {
     length = AddInstruction(new(zone) HFixedArrayBaseLength(elements));
   }
@@ -1338,11 +1325,7 @@
 
     elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
                                          length, key, is_js_array);
-    if (!key->type().IsSmi()) {
-      checked_key = AddInstruction(new(zone) HCheckSmiOrInt32(key));
-    } else {
-      checked_key = key;
-    }
+    checked_key = key;
   } else {
     checked_key = AddBoundsCheck(
         key, length, ALLOW_SMI_KEY, checked_index_representation);
@@ -1391,7 +1374,7 @@
   total_size->ClearFlag(HValue::kCanOverflow);
 
   HAllocate::Flags flags = HAllocate::DefaultFlags(kind);
-  if (FLAG_pretenure_literals) {
+  if (isolate()->heap()->ShouldGloballyPretenure()) {
     // TODO(hpayer): When pretenuring can be internalized, flags can become
     // private to HAllocate.
     if (IsFastDoubleElementsKind(kind)) {
@@ -1413,21 +1396,16 @@
 void HGraphBuilder::BuildInitializeElements(HValue* elements,
                                             ElementsKind kind,
                                             HValue* capacity) {
-  Zone* zone = this->zone();
   Factory* factory = isolate()->factory();
   Handle<Map> map = IsFastDoubleElementsKind(kind)
       ? factory->fixed_double_array_map()
       : factory->fixed_array_map();
-  BuildStoreMap(elements, map);
 
-  Handle<String> fixed_array_length_field_name = factory->length_field_string();
+  AddStoreMapConstant(elements, map);
   Representation representation = IsFastElementsKind(kind)
       ? Representation::Smi() : Representation::Tagged();
-  HInstruction* store_length =
-      new(zone) HStoreNamedField(elements, fixed_array_length_field_name,
-                                 capacity, true, representation,
-                                 FixedArray::kLengthOffset);
-  AddInstruction(store_length);
+  AddStore(elements, HObjectAccess::ForFixedArrayLength(), capacity,
+      representation);
 }
 
 
@@ -1446,7 +1424,7 @@
     HValue* allocation_site_payload,
     HValue* length_field) {
 
-  BuildStoreMap(array, array_map);
+  AddStore(array, HObjectAccess::ForMap(), array_map);
 
   HConstant* empty_fixed_array =
       new(zone()) HConstant(
@@ -1454,21 +1432,9 @@
           Representation::Tagged());
   AddInstruction(empty_fixed_array);
 
-  AddInstruction(new(zone()) HStoreNamedField(array,
-      isolate()->factory()->properties_field_symbol(),
-      empty_fixed_array,
-      true,
-      Representation::Tagged(),
-      JSArray::kPropertiesOffset));
-
-  HInstruction* length_store = AddInstruction(
-      new(zone()) HStoreNamedField(array,
-                                   isolate()->factory()->length_field_string(),
-                                   length_field,
-                                   true,
-                                   Representation::Tagged(),
-                                   JSArray::kLengthOffset));
-  length_store->SetGVNFlag(kChangesArrayLengths);
+  HObjectAccess access = HObjectAccess::ForPropertiesPointer();
+  AddStore(array, access, empty_fixed_array);
+  AddStore(array, HObjectAccess::ForArrayLength(), length_field);
 
   if (mode == TRACK_ALLOCATION_SITE) {
     BuildCreateAllocationSiteInfo(array,
@@ -1482,58 +1448,17 @@
   }
 
   HInnerAllocatedObject* elements = new(zone()) HInnerAllocatedObject(
-      array,
-      elements_location);
+      array, elements_location);
   AddInstruction(elements);
 
-  HInstruction* elements_store = AddInstruction(
-      new(zone()) HStoreNamedField(
-          array,
-          isolate()->factory()->elements_field_string(),
-          elements,
-          true,
-          Representation::Tagged(),
-          JSArray::kElementsOffset));
-  elements_store->SetGVNFlag(kChangesElementsPointer);
-
+  AddStore(array, HObjectAccess::ForElementsPointer(), elements);
   return elements;
 }
 
 
-HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
-                                           HValue* map) {
-  Zone* zone = this->zone();
-  Factory* factory = isolate()->factory();
-  Handle<String> map_field_name = factory->map_field_string();
-  HInstruction* store_map =
-      new(zone) HStoreNamedField(object, map_field_name, map,
-                                 true, Representation::Tagged(),
-                                 JSObject::kMapOffset);
-  store_map->ClearGVNFlag(kChangesInobjectFields);
-  store_map->SetGVNFlag(kChangesMaps);
-  AddInstruction(store_map);
-  return store_map;
-}
-
-
-HInstruction* HGraphBuilder::BuildStoreMap(HValue* object,
-                                           Handle<Map> map) {
-  Zone* zone = this->zone();
-  HValue* map_constant =
-      AddInstruction(new(zone) HConstant(map, Representation::Tagged()));
-  return BuildStoreMap(object, map_constant);
-}
-
-
 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
-    HValue* typecheck) {
-  HLoadNamedField* instr = new(zone()) HLoadNamedField(object, true,
-      Representation::Tagged(), JSObject::kElementsOffset, typecheck);
-  AddInstruction(instr);
-  instr->SetGVNFlag(kDependsOnElementsPointer);
-  instr->ClearGVNFlag(kDependsOnMaps);
-  instr->ClearGVNFlag(kDependsOnInobjectFields);
-  return instr;
+                                                HValue* typecheck) {
+  return AddLoad(object, HObjectAccess::ForElementsPointer(), typecheck);
 }
 
 
@@ -1586,7 +1511,6 @@
                                                  ElementsKind kind,
                                                  HValue* length,
                                                  HValue* new_capacity) {
-  Zone* zone = this->zone();
   HValue* context = environment()->LookupContext();
 
   BuildNewSpaceArrayCheck(new_capacity, kind);
@@ -1598,13 +1522,7 @@
                     new_elements, kind,
                     length, new_capacity);
 
-  Factory* factory = isolate()->factory();
-  HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
-      object,
-      factory->elements_field_string(),
-      new_elements, true, Representation::Tagged(),
-      JSArray::kElementsOffset));
-  elements_store->SetGVNFlag(kChangesElementsPointer);
+  AddStore(object, HObjectAccess::ForElementsPointer(), new_elements);
 
   return new_elements;
 }
@@ -1709,7 +1627,6 @@
                                               ElementsKind kind,
                                               int length) {
   Zone* zone = this->zone();
-  Factory* factory = isolate()->factory();
 
   NoObservableSideEffectsScope no_effects(this);
 
@@ -1739,16 +1656,8 @@
   // Copy the JS array part.
   for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
     if ((i != JSArray::kElementsOffset) || (length == 0)) {
-      HInstruction* value = AddInstruction(new(zone) HLoadNamedField(
-          boilerplate, true, Representation::Tagged(), i));
-      if (i != JSArray::kMapOffset) {
-        AddInstruction(new(zone) HStoreNamedField(object,
-                                                  factory->empty_string(),
-                                                  value, true,
-                                                  Representation::Tagged(), i));
-      } else {
-        BuildStoreMap(object, value);
-      }
+      HObjectAccess access = HObjectAccess::ForJSArrayOffset(i);
+      AddStore(object, access, AddLoad(boilerplate, access));
     }
   }
 
@@ -1763,21 +1672,12 @@
     HValue* boilerplate_elements = AddLoadElements(boilerplate);
     HValue* object_elements =
         AddInstruction(new(zone) HInnerAllocatedObject(object, elems_offset));
-    AddInstruction(new(zone) HStoreNamedField(object,
-                                              factory->elements_field_string(),
-                                              object_elements, true,
-                                              Representation::Tagged(),
-                                              JSObject::kElementsOffset));
+    AddStore(object, HObjectAccess::ForElementsPointer(), object_elements);
 
     // Copy the elements array header.
     for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
-      HInstruction* value =
-          AddInstruction(new(zone) HLoadNamedField(
-              boilerplate_elements, true, Representation::Tagged(), i));
-      AddInstruction(new(zone) HStoreNamedField(object_elements,
-                                                factory->empty_string(),
-                                                value, true,
-                                                Representation::Tagged(), i));
+      HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
+      AddStore(object_elements, access, AddLoad(boilerplate_elements, access));
     }
 
     // Copy the elements array contents.
@@ -1857,34 +1757,30 @@
         HInnerAllocatedObject(previous_object, previous_object_size);
   AddInstruction(alloc_site);
   Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map());
-  BuildStoreMap(alloc_site, alloc_site_map);
-  AddInstruction(new(zone()) HStoreNamedField(alloc_site,
-      isolate()->factory()->payload_string(),
-      payload,
-      true,
-      Representation::Tagged(),
-      AllocationSiteInfo::kPayloadOffset));
+  AddStoreMapConstant(alloc_site, alloc_site_map);
+  HObjectAccess access = HObjectAccess::ForAllocationSitePayload();
+  AddStore(alloc_site, access, payload);
   return alloc_site;
 }
 
 
 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* context) {
+  // Get the global context, then the native context
   HInstruction* global_object = AddInstruction(new(zone())
-                                               HGlobalObject(context));
-  HInstruction* native_context = AddInstruction(new(zone())
-      HLoadNamedField(global_object, true, Representation::Tagged(),
-                      GlobalObject::kNativeContextOffset));
-  return native_context;
+      HGlobalObject(context));
+  HObjectAccess access = HObjectAccess::ForJSObjectOffset(
+      GlobalObject::kNativeContextOffset);
+  return AddLoad(global_object, access);
 }
 
 
 HInstruction* HGraphBuilder::BuildGetArrayFunction(HValue* context) {
   HInstruction* native_context = BuildGetNativeContext(context);
-  int offset = Context::kHeaderSize +
-      kPointerSize * Context::ARRAY_FUNCTION_INDEX;
-  HInstruction* array_function = AddInstruction(new(zone())
-      HLoadNamedField(native_context, true, Representation::Tagged(), offset));
-  return array_function;
+  HInstruction* index = AddInstruction(new(zone())
+      HConstant(Context::ARRAY_FUNCTION_INDEX, Representation::Integer32()));
+
+  return AddInstruction(new (zone())
+      HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS));
 }
 
 
@@ -1905,13 +1801,18 @@
 
 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode(HValue* context) {
   HInstruction* native_context = builder()->BuildGetNativeContext(context);
-  int offset = Context::kHeaderSize +
-      kPointerSize * Context::JS_ARRAY_MAPS_INDEX;
-  HInstruction* map_array = AddInstruction(new(zone())
-      HLoadNamedField(native_context, true, Representation::Tagged(), offset));
-  offset = kind_ * kPointerSize + FixedArrayBase::kHeaderSize;
-  return AddInstruction(new(zone()) HLoadNamedField(
-      map_array, true, Representation::Tagged(), offset));
+
+  HInstruction* index = builder()->AddInstruction(new(zone())
+      HConstant(Context::JS_ARRAY_MAPS_INDEX, Representation::Integer32()));
+
+  HInstruction* map_array = builder()->AddInstruction(new(zone())
+      HLoadKeyed(native_context, index, NULL, FAST_ELEMENTS));
+
+  HInstruction* kind_index = builder()->AddInstruction(new(zone())
+      HConstant(kind_, Representation::Integer32()));
+
+  return builder()->AddInstruction(new(zone())
+      HLoadKeyed(map_array, kind_index, NULL, FAST_ELEMENTS));
 }
 
 
@@ -2020,6 +1921,39 @@
 }
 
 
+HStoreNamedField* HGraphBuilder::AddStore(HValue *object,
+                                          HObjectAccess access,
+                                          HValue *val,
+                                          Representation representation) {
+  HStoreNamedField *instr = new(zone())
+      HStoreNamedField(object, access, val, representation);
+  AddInstruction(instr);
+  return instr;
+}
+
+
+HLoadNamedField* HGraphBuilder::AddLoad(HValue *object,
+                                        HObjectAccess access,
+                                        HValue *typecheck,
+                                        Representation representation) {
+  HLoadNamedField *instr =
+      new(zone()) HLoadNamedField(object, access, typecheck, representation);
+  AddInstruction(instr);
+  return instr;
+}
+
+
+HStoreNamedField* HGraphBuilder::AddStoreMapConstant(HValue *object,
+                                                     Handle<Map> map) {
+  HValue* constant =
+      AddInstruction(new(zone()) HConstant(map, Representation::Tagged()));
+  HStoreNamedField *instr =
+      new(zone()) HStoreNamedField(object, HObjectAccess::ForMap(), constant);
+  AddInstruction(instr);
+  return instr;
+}
+
+
 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
                                                TypeFeedbackOracle* oracle)
     : HGraphBuilder(info),
@@ -4399,7 +4333,9 @@
         Representation from = change->value()->representation();
         ASSERT(from.Equals(change->from()));
         if (from.IsInteger32()) {
-          ASSERT(change->to().IsTagged() || change->to().IsDouble());
+          ASSERT(change->to().IsTagged() ||
+                 change->to().IsDouble() ||
+                 change->to().IsSmi());
           ASSERT(visited.IsEmpty());
           PropagateMinusZeroChecks(change->value(), &visited);
           visited.Clear();
@@ -6388,7 +6324,7 @@
     Code* unoptimized_code, FunctionLiteral* expr) {
   int start_position = expr->start_position();
   RelocIterator it(unoptimized_code);
-  for (;!it.done(); it.next()) {
+  for (; !it.done(); it.next()) {
     RelocInfo* rinfo = it.rinfo();
     if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue;
     Object* obj = rinfo->target_object();
@@ -6690,6 +6626,12 @@
                           int* max_properties,
                           int* data_size,
                           int* pointer_size) {
+  if (boilerplate->map()->is_deprecated()) {
+    Handle<Object> result =
+        JSObject::TryMigrateInstance(boilerplate);
+    if (result->IsSmi()) return false;
+  }
+
   ASSERT(max_depth >= 0 && *max_properties >= 0);
   if (max_depth == 0) return false;
 
@@ -7064,20 +7006,6 @@
 }
 
 
-static int ComputeLoadStoreFieldIndex(Handle<Map> type,
-                                      LookupResult* lookup) {
-  ASSERT(lookup->IsField() || lookup->IsTransitionToField(*type));
-  if (lookup->IsField()) {
-    return lookup->GetLocalFieldIndexFromMap(*type);
-  } else {
-    Map* transition = lookup->GetTransitionMapFromMap(*type);
-    int descriptor = transition->LastAdded();
-    int index = transition->instance_descriptors()->GetFieldIndex(descriptor);
-    return index - type->inobject_properties();
-  }
-}
-
-
 static Representation ComputeLoadStoreRepresentation(Handle<Map> type,
                                                      LookupResult* lookup) {
   if (lookup->IsField()) {
@@ -7142,43 +7070,37 @@
         zone()));
   }
 
-  int index = ComputeLoadStoreFieldIndex(map, lookup);
-  bool is_in_object = index < 0;
+  HObjectAccess field_access = HObjectAccess::ForField(map, lookup, name);
   Representation representation = ComputeLoadStoreRepresentation(map, lookup);
-  int offset = index * kPointerSize;
-  if (index < 0) {
-    // Negative property indices are in-object properties, indexed
-    // from the end of the fixed part of the object.
-    offset += map->instance_size();
-  } else {
-    offset += FixedArray::kHeaderSize;
-  }
   bool transition_to_field = lookup->IsTransitionToField(*map);
+
+  HStoreNamedField *instr;
   if (FLAG_track_double_fields && representation.IsDouble()) {
     if (transition_to_field) {
+      // The store requires a mutable HeapNumber to be allocated.
       NoObservableSideEffectsScope no_side_effects(this);
       HInstruction* heap_number_size = AddInstruction(new(zone()) HConstant(
           HeapNumber::kSize, Representation::Integer32()));
       HInstruction* double_box = AddInstruction(new(zone()) HAllocate(
           environment()->LookupContext(), heap_number_size,
           HType::HeapNumber(), HAllocate::CAN_ALLOCATE_IN_NEW_SPACE));
-      BuildStoreMap(double_box, isolate()->factory()->heap_number_map());
-      AddInstruction(new(zone()) HStoreNamedField(
-          double_box, name, value, true,
-          Representation::Double(), HeapNumber::kValueOffset));
-      value = double_box;
-      representation = Representation::Tagged();
+      AddStoreMapConstant(double_box, isolate()->factory()->heap_number_map());
+      AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
+          value, Representation::Double());
+      instr = new(zone()) HStoreNamedField(object, field_access, double_box);
     } else {
-      HInstruction* double_box = AddInstruction(new(zone()) HLoadNamedField(
-          object, is_in_object, Representation::Tagged(), offset));
+      // Already holds a HeapNumber; load the box and write its value field.
+      HInstruction* double_box = AddLoad(object, field_access);
       double_box->set_type(HType::HeapNumber());
-      return new(zone()) HStoreNamedField(
-          double_box, name, value, true,
-          Representation::Double(), HeapNumber::kValueOffset);
+      instr = new(zone()) HStoreNamedField(double_box,
+          HObjectAccess::ForHeapNumberValue(), value, Representation::Double());
     }
+  } else {
+    // This is a non-double store.
+    instr = new(zone()) HStoreNamedField(
+        object, field_access, value, representation);
   }
-  HStoreNamedField* instr = new(zone()) HStoreNamedField(
-      object, name, value, is_in_object, representation, offset);
+
   if (transition_to_field) {
     Handle<Map> transition(lookup->GetTransitionMapFromMap(*map));
     instr->set_transition(transition);
@@ -7248,9 +7170,10 @@
   BuildCheckNonSmi(object);
 
   HInstruction* typecheck =
-    AddInstruction(HCheckMaps::New(object, types, zone()));
-  HInstruction* instr =
-    HLoadNamedField::NewArrayLength(zone(), object, typecheck);
+      AddInstruction(HCheckMaps::New(object, types, zone()));
+  HInstruction* instr = new(zone())
+      HLoadNamedField(object, HObjectAccess::ForArrayLength(), typecheck);
+
   instr->set_position(expr->position());
   ast_context()->ReturnInstruction(instr, expr->id());
   return true;
@@ -7270,53 +7193,42 @@
   // Use monomorphic load if property lookup results in the same field index
   // for all maps. Requires special map check on the set of all handled maps.
   HInstruction* instr = NULL;
-  if (types->length() > 0 && types->length() <= kMaxLoadPolymorphism) {
-    LookupResult lookup(isolate());
-    int previous_field_offset = 0;
-    bool previous_field_is_in_object = false;
-    Representation representation = Representation::None();
-    int count;
-    for (count = 0; count < types->length(); ++count) {
-      Handle<Map> map = types->at(count);
-      if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
+  LookupResult lookup(isolate());
+  int count;
+  Representation representation = Representation::None();
+  HObjectAccess access = HObjectAccess::ForMap();  // initial value unused.
+  for (count = 0;
+       count < types->length() && count < kMaxLoadPolymorphism;
+       ++count) {
+    Handle<Map> map = types->at(count);
+    if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
 
-      int index = ComputeLoadStoreFieldIndex(map, &lookup);
-      Representation new_representation =
-          ComputeLoadStoreRepresentation(map, &lookup);
-      bool is_in_object = index < 0;
-      int offset = index * kPointerSize;
+    HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
+    Representation new_representation =
+        ComputeLoadStoreRepresentation(map, &lookup);
 
-      if (index < 0) {
-        // Negative property indices are in-object properties, indexed
-        // from the end of the fixed part of the object.
-        offset += map->instance_size();
-      } else {
-        offset += FixedArray::kHeaderSize;
-      }
-
-      if (count == 0) {
-        previous_field_offset = offset;
-        previous_field_is_in_object = is_in_object;
-        representation = new_representation;
-      } else if (offset != previous_field_offset ||
-                 is_in_object != previous_field_is_in_object ||
-                 (FLAG_track_fields &&
-                  !representation.IsCompatibleForLoad(new_representation))) {
-        break;
-      }
-
-      representation = representation.generalize(new_representation);
-    }
-
-    if (count == types->length()) {
-      AddInstruction(HCheckMaps::New(object, types, zone()));
-      instr = DoBuildLoadNamedField(
-          object, previous_field_is_in_object,
-          representation, previous_field_offset);
+    if (count == 0) {
+      // First time through the loop; set access and representation.
+      access = new_access;
+      representation = new_representation;
+    } else if (!representation.IsCompatibleForLoad(new_representation)) {
+      // Representations did not match.
+      break;
+    } else if (access.offset() != new_access.offset()) {
+      // Offsets did not match.
+      break;
+    } else if (access.IsInobject() != new_access.IsInobject()) {
+      // In-objectness did not match.
+      break;
     }
   }
 
-  if (instr == NULL) {
+  if (count == types->length()) {
+    // Everything matched; can use monomorphic load.
+    AddInstruction(HCheckMaps::New(object, types, zone()));
+    instr = BuildLoadNamedField(object, access, representation);
+  } else {
+    // Something did not match; must use a polymorphic load.
     HValue* context = environment()->LookupContext();
     instr = new(zone()) HLoadNamedFieldPolymorphic(
         context, object, types, name, zone());
@@ -7873,40 +7785,22 @@
 }
 
 
-HLoadNamedField* HOptimizedGraphBuilder::BuildLoadNamedField(
+HLoadNamedField* HGraphBuilder::BuildLoadNamedField(
     HValue* object,
-    Handle<Map> map,
-    LookupResult* lookup) {
-  int index = lookup->GetLocalFieldIndexFromMap(*map);
-  // Negative property indices are in-object properties, indexed from the end of
-  // the fixed part of the object. Non-negative property indices are in the
-  // properties array.
-  int inobject = index < 0;
-  Representation representation = lookup->representation();
-  int offset = inobject
-      ? index * kPointerSize + map->instance_size()
-      : index * kPointerSize + FixedArray::kHeaderSize;
-  return DoBuildLoadNamedField(object, inobject, representation, offset);
-}
-
-
-HLoadNamedField* HGraphBuilder::DoBuildLoadNamedField(
-    HValue* object,
-    bool inobject,
-    Representation representation,
-    int offset) {
+    HObjectAccess access,
+    Representation representation) {
   bool load_double = false;
   if (representation.IsDouble()) {
     representation = Representation::Tagged();
     load_double = FLAG_track_double_fields;
   }
   HLoadNamedField* field =
-      new(zone()) HLoadNamedField(object, inobject, representation, offset);
+      new(zone()) HLoadNamedField(object, access, NULL, representation);
   if (load_double) {
     AddInstruction(field);
     field->set_type(HType::HeapNumber());
-    return new(zone()) HLoadNamedField(
-        field, true, Representation::Double(), HeapNumber::kValueOffset);
+    return new(zone()) HLoadNamedField(field,
+        HObjectAccess::ForHeapNumberValue(), NULL, Representation::Double());
   }
   return field;
 }
@@ -7947,7 +7841,8 @@
   if (name->Equals(isolate()->heap()->length_string())) {
     if (map->instance_type() == JS_ARRAY_TYPE) {
       AddCheckMapsWithTransitions(object, map);
-      return HLoadNamedField::NewArrayLength(zone(), object, object);
+      return new(zone()) HLoadNamedField(object,
+          HObjectAccess::ForArrayLength());
     }
   }
 
@@ -7955,7 +7850,9 @@
   map->LookupDescriptor(NULL, *name, &lookup);
   if (lookup.IsField()) {
     AddCheckMap(object, map);
-    return BuildLoadNamedField(object, map, &lookup);
+    return BuildLoadNamedField(object,
+        HObjectAccess::ForField(map, &lookup, name),
+        ComputeLoadStoreRepresentation(map, &lookup));
   }
 
   // Handle a load of a constant known function.
@@ -7974,9 +7871,11 @@
     AddCheckMap(object, map);
     AddInstruction(
         new(zone()) HCheckPrototypeMaps(prototype, holder, zone()));
-    HValue* holder_value = AddInstruction(
-            new(zone()) HConstant(holder, Representation::Tagged()));
-    return BuildLoadNamedField(holder_value, holder_map, &lookup);
+    HValue* holder_value = AddInstruction(new(zone())
+        HConstant(holder, Representation::Tagged()));
+    return BuildLoadNamedField(holder_value,
+        HObjectAccess::ForField(holder_map, &lookup, name),
+        ComputeLoadStoreRepresentation(map, &lookup));
   }
 
   // Handle a load of a constant function somewhere in the prototype chain.
@@ -8252,10 +8151,10 @@
         current_block()->Finish(typecheck);
 
         set_current_block(if_jsarray);
-        HInstruction* length;
-        length = AddInstruction(
-            HLoadNamedField::NewArrayLength(zone(), object, typecheck,
-                                            HType::Smi()));
+        HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(),
+            typecheck, Representation::Smi());
+        length->set_type(HType::Smi());
+
         checked_key = AddBoundsCheck(key, length, ALLOW_SMI_KEY);
         access = AddInstruction(BuildFastElementAccess(
             elements, checked_key, val, elements_kind_branch,
@@ -10867,8 +10766,7 @@
 
   HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE;
   // TODO(hpayer): add support for old data space
-  if (FLAG_pretenure_literals &&
-      isolate()->heap()->ShouldGloballyPretenure() &&
+  if (isolate()->heap()->ShouldGloballyPretenure() &&
       data_size == 0) {
     flags = static_cast<HAllocate::Flags>(
         flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
@@ -10896,7 +10794,6 @@
     int* offset,
     AllocationSiteMode mode) {
   Zone* zone = this->zone();
-  Factory* factory = isolate()->factory();
 
   HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant(
       original_boilerplate_object, Representation::Tagged()));
@@ -10947,6 +10844,12 @@
     Handle<Object> value =
         Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
         isolate());
+
+    // The access for the store depends on the type of the boilerplate.
+    HObjectAccess access = boilerplate_object->IsJSArray() ?
+        HObjectAccess::ForJSArrayOffset(property_offset) :
+        HObjectAccess::ForJSObjectOffset(property_offset);
+
     if (value->IsJSObject()) {
       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
       Handle<JSObject> original_value_object = Handle<JSObject>::cast(
@@ -10954,39 +10857,39 @@
               isolate()));
       HInstruction* value_instruction =
           AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
-      AddInstruction(new(zone) HStoreNamedField(
-          object_properties, name, value_instruction, true,
-          Representation::Tagged(), property_offset));
+
+      AddStore(object_properties, access, value_instruction);
+
       BuildEmitDeepCopy(value_object, original_value_object, target,
-                        offset, DONT_TRACK_ALLOCATION_SITE);
+          offset, DONT_TRACK_ALLOCATION_SITE);
     } else {
       Representation representation = details.representation();
       HInstruction* value_instruction = AddInstruction(new(zone) HConstant(
           value, Representation::Tagged()));
+
       if (representation.IsDouble()) {
+        // Allocate a HeapNumber box and store the value into it.
         HInstruction* double_box =
             AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
-        BuildStoreMap(double_box, factory->heap_number_map());
-        AddInstruction(new(zone) HStoreNamedField(
-            double_box, name, value_instruction, true,
-            Representation::Double(), HeapNumber::kValueOffset));
+        AddStoreMapConstant(double_box,
+            isolate()->factory()->heap_number_map());
+        AddStore(double_box, HObjectAccess::ForHeapNumberValue(),
+            value_instruction, Representation::Double());
         value_instruction = double_box;
         *offset += HeapNumber::kSize;
       }
-      AddInstruction(new(zone) HStoreNamedField(
-          object_properties, name, value_instruction, true,
-          Representation::Tagged(), property_offset));
+
+      AddStore(object_properties, access, value_instruction);
     }
   }
 
   int inobject_properties = boilerplate_object->map()->inobject_properties();
-  HInstruction* value_instruction = AddInstruction(new(zone) HConstant(
-      factory->one_pointer_filler_map(), Representation::Tagged()));
+  HInstruction* value_instruction = AddInstruction(new(zone)
+      HConstant(isolate()->factory()->one_pointer_filler_map(),
+          Representation::Tagged()));
   for (int i = copied_fields; i < inobject_properties; i++) {
-    AddInstruction(new(zone) HStoreNamedField(
-        object_properties, factory->unknown_field_string(), value_instruction,
-        true, Representation::Tagged(),
-        boilerplate_object->GetInObjectPropertyOffset(i)));
+    HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
+    AddStore(object_properties, access, value_instruction);
   }
 
   // Build Allocation Site Info if desired
@@ -11012,9 +10915,11 @@
             AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
         HInstruction* value_instruction =
             AddInstruction(new(zone) HLoadKeyed(
-                boilerplate_elements, key_constant, NULL, kind));
-        AddInstruction(new(zone) HStoreKeyed(
+                boilerplate_elements, key_constant, NULL, kind,
+                ALLOW_RETURN_HOLE));
+        HInstruction* store = AddInstruction(new(zone) HStoreKeyed(
                 object_elements, key_constant, value_instruction, kind));
+        store->ClearFlag(HValue::kDeoptimizeOnUndefined);
       }
     } else if (elements->IsFixedArray()) {
       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
@@ -11037,7 +10942,8 @@
         } else {
           HInstruction* value_instruction =
               AddInstruction(new(zone) HLoadKeyed(
-                  boilerplate_elements, key_constant, NULL, kind));
+                  boilerplate_elements, key_constant, NULL, kind,
+                  ALLOW_RETURN_HOLE));
           AddInstruction(new(zone) HStoreKeyed(
               object_elements, key_constant, value_instruction, kind));
         }
@@ -11057,13 +10963,12 @@
     int elements_size) {
   ASSERT(boilerplate_object->properties()->length() == 0);
   Zone* zone = this->zone();
-  Factory* factory = isolate()->factory();
   HValue* result = NULL;
 
   HValue* object_header =
       AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
   Handle<Map> boilerplate_object_map(boilerplate_object->map());
-  BuildStoreMap(object_header, boilerplate_object_map);
+  AddStoreMapConstant(object_header, boilerplate_object_map);
 
   HInstruction* elements;
   if (elements_size == 0) {
@@ -11076,23 +10981,15 @@
         target, elements_offset));
     result = elements;
   }
-  HInstruction* elements_store = AddInstruction(new(zone) HStoreNamedField(
-      object_header,
-      factory->elements_field_string(),
-      elements,
-      true, Representation::Tagged(), JSObject::kElementsOffset));
-  elements_store->SetGVNFlag(kChangesElementsPointer);
+  AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
 
   Handle<Object> properties_field =
       Handle<Object>(boilerplate_object->properties(), isolate());
   ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
   HInstruction* properties = AddInstruction(new(zone) HConstant(
       properties_field, Representation::None()));
-  AddInstruction(new(zone) HStoreNamedField(object_header,
-                                            factory->empty_string(),
-                                            properties, true,
-                                            Representation::Tagged(),
-                                            JSObject::kPropertiesOffset));
+  HObjectAccess access = HObjectAccess::ForPropertiesPointer();
+  AddStore(object_header, access, properties);
 
   if (boilerplate_object->IsJSArray()) {
     Handle<JSArray> boilerplate_array =
@@ -11101,16 +10998,13 @@
         Handle<Object>(boilerplate_array->length(), isolate());
     HInstruction* length = AddInstruction(new(zone) HConstant(
         length_field, Representation::None()));
+
     ASSERT(boilerplate_array->length()->IsSmi());
     Representation representation =
         IsFastElementsKind(boilerplate_array->GetElementsKind())
         ? Representation::Smi() : Representation::Tagged();
-    HInstruction* length_store = AddInstruction(new(zone) HStoreNamedField(
-        object_header,
-        factory->length_field_string(),
-        length,
-        true, representation, JSArray::kLengthOffset));
-    length_store->SetGVNFlag(kChangesArrayLengths);
+    AddStore(object_header, HObjectAccess::ForArrayLength(),
+        length, representation);
   }
 
   return result;
@@ -11459,9 +11353,6 @@
   HValue* value = Pop();
   HValue* index = Pop();
   HValue* string = Pop();
-  HValue* context = environment()->LookupContext();
-  HInstruction* char_code = BuildStringCharCodeAt(context, string, index);
-  AddInstruction(char_code);
   HSeqStringSetChar* result = new(zone()) HSeqStringSetChar(
       String::TWO_BYTE_ENCODING, string, index, value);
   return ast_context()->ReturnInstruction(result, call->id());
@@ -11497,13 +11388,8 @@
 
   // Create in-object property store to kValueOffset.
   set_current_block(if_js_value);
-  Handle<String> name = isolate()->factory()->undefined_string();
-  AddInstruction(new(zone()) HStoreNamedField(object,
-                                              name,
-                                              value,
-                                              true,  // in-object store.
-                                              Representation::Tagged(),
-                                              JSValue::kValueOffset));
+  AddStore(object,
+      HObjectAccess::ForJSObjectOffset(JSValue::kValueOffset), value);
   if_js_value->Goto(join);
   join->SetJoinId(call->id());
   set_current_block(join);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index b053fc7..631ce9a 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -992,11 +992,6 @@
   HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
 
   // Building common constructs
-  HLoadNamedField* DoBuildLoadNamedField(HValue* object,
-                                         bool inobject,
-                                         Representation representation,
-                                         int offset);
-
   HInstruction* BuildExternalArrayElementAccess(
       HValue* external_elements,
       HValue* checked_key,
@@ -1039,8 +1034,24 @@
       KeyedAccessStoreMode store_mode,
       Representation checked_index_representation = Representation::None());
 
-  HInstruction* BuildStoreMap(HValue* object, HValue* map);
-  HInstruction* BuildStoreMap(HValue* object, Handle<Map> map);
+  HLoadNamedField* AddLoad(
+      HValue *object,
+      HObjectAccess access,
+      HValue *typecheck = NULL,
+      Representation representation = Representation::Tagged());
+
+  HLoadNamedField* BuildLoadNamedField(
+      HValue* object,
+      HObjectAccess access,
+      Representation representation);
+
+  HStoreNamedField* AddStore(
+      HValue *object,
+      HObjectAccess access,
+      HValue *val,
+      Representation representation = Representation::Tagged());
+
+  HStoreNamedField* AddStoreMapConstant(HValue *object, Handle<Map>);
 
   HLoadNamedField* AddLoadElements(HValue *object, HValue *typecheck = NULL);
 
@@ -1692,9 +1703,6 @@
                                    bool is_store,
                                    bool* has_side_effects);
 
-  HLoadNamedField* BuildLoadNamedField(HValue* object,
-                                       Handle<Map> map,
-                                       LookupResult* result);
   HInstruction* BuildLoadNamedGeneric(HValue* object,
                                       Handle<String> name,
                                       Property* expr);
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 2b45d76..4420102 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -486,6 +486,10 @@
 
     // Invoke the code.
     if (is_construct) {
+      // No type feedback cell is available
+      Handle<Object> undefined_sentinel(
+          masm->isolate()->heap()->undefined_value(), masm->isolate());
+      __ mov(ebx, Immediate(undefined_sentinel));
       CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
       __ CallStub(&stub);
     } else {
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 507aeb6..598bf17 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -176,8 +176,8 @@
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(CompareNilIC_Miss);
-  descriptor->miss_handler_ =
-      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
 }
 
 
@@ -200,7 +200,7 @@
     for (int i = 0; i < param_count; ++i) {
       __ push(descriptor->register_params_[i]);
     }
-    ExternalReference miss = descriptor->miss_handler_;
+    ExternalReference miss = descriptor->miss_handler();
     __ CallExternalReference(miss, descriptor->register_param_count_);
   }
 
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 7663c6a..d562238 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -1057,50 +1057,6 @@
 }
 
 
-void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
-                                         String::Encoding encoding,
-                                         Register string,
-                                         Register index,
-                                         Register value) {
-  if (FLAG_debug_code) {
-    __ test(index, Immediate(kSmiTagMask));
-    __ Check(zero, "Non-smi index");
-    __ test(value, Immediate(kSmiTagMask));
-    __ Check(zero, "Non-smi value");
-
-    __ cmp(index, FieldOperand(string, String::kLengthOffset));
-    __ Check(less, "Index is too large");
-
-    __ cmp(index, Immediate(Smi::FromInt(0)));
-    __ Check(greater_equal, "Index is negative");
-
-    __ push(value);
-    __ mov(value, FieldOperand(string, HeapObject::kMapOffset));
-    __ movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
-
-    __ and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ cmp(value, Immediate(encoding == String::ONE_BYTE_ENCODING
-                                ? one_byte_seq_type : two_byte_seq_type));
-    __ Check(equal, "Unexpected string type");
-    __ pop(value);
-  }
-
-  __ SmiUntag(value);
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  if (encoding == String::ONE_BYTE_ENCODING) {
-    __ SmiUntag(index);
-    __ mov_b(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
-             value);
-  } else {
-    // No need to untag a smi for two-byte addressing.
-    __ mov_w(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
-             value);
-  }
-}
-
-
 static Operand ExpConstant(int index) {
   return Operand::StaticVariable(ExternalReference::math_exp_constants(index));
 }
diff --git a/src/ia32/codegen-ia32.h b/src/ia32/codegen-ia32.h
index 5137274..6db381e 100644
--- a/src/ia32/codegen-ia32.h
+++ b/src/ia32/codegen-ia32.h
@@ -43,7 +43,7 @@
 class CodeGenerator {
  public:
   // Printing of AST, etc. as requested by flags.
-  static void MakeCodePrologue(CompilationInfo* info);
+  static void MakeCodePrologue(CompilationInfo* info, const char* kind);
 
   // Allocate and install the code.
   static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 1bc72ec..bf5e02b 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -3373,19 +3373,57 @@
 }
 
 
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+                                                  Register index,
+                                                  Register value,
+                                                  uint32_t encoding_mask) {
+  __ test(index, Immediate(kSmiTagMask));
+  __ Check(zero, "Non-smi index");
+  __ test(value, Immediate(kSmiTagMask));
+  __ Check(zero, "Non-smi value");
+
+  __ cmp(index, FieldOperand(string, String::kLengthOffset));
+  __ Check(less, "Index is too large");
+
+  __ cmp(index, Immediate(Smi::FromInt(0)));
+  __ Check(greater_equal, "Index is negative");
+
+  __ push(value);
+  __ mov(value, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
+
+  __ and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
+  __ cmp(value, Immediate(encoding_mask));
+  __ Check(equal, "Unexpected string type");
+  __ pop(value);
+}
+
+
 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = eax;
+  Register index = ebx;
+  Register value = ecx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(ecx);
-  __ pop(ebx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, eax, ebx, ecx);
-  context()->Plug(eax);
+
+  if (FLAG_debug_code) {
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
+  __ SmiUntag(value);
+  __ SmiUntag(index);
+  __ mov_b(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
+           value);
+  context()->Plug(string);
 }
 
 
@@ -3393,15 +3431,26 @@
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = eax;
+  Register index = ebx;
+  Register value = ecx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(ecx);
-  __ pop(ebx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, eax, ebx, ecx);
-  context()->Plug(eax);
+  if (FLAG_debug_code) {
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
+  __ SmiUntag(value);
+  // No need to untag a smi for two-byte addressing.
+  __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
+           value);
+  context()->Plug(string);
 }
 
 
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index b6244af..3e23763 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -590,7 +590,7 @@
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
   return constant->handle();
 }
 
@@ -607,6 +607,11 @@
 }
 
 
+bool LCodeGen::IsSmi(LConstantOperand* op) const {
+  return chunk_->LookupLiteralRepresentation(op).IsSmi();
+}
+
+
 Operand LCodeGen::ToOperand(LOperand* op) const {
   if (op->IsRegister()) return Operand(ToRegister(op));
   if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op));
@@ -1896,11 +1901,32 @@
 
 
 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
-  SeqStringSetCharGenerator::Generate(masm(),
-                                      instr->encoding(),
-                                      ToRegister(instr->string()),
-                                      ToRegister(instr->index()),
-                                      ToRegister(instr->value()));
+  Register string = ToRegister(instr->string());
+  Register index = ToRegister(instr->index());
+  Register value = ToRegister(instr->value());
+  String::Encoding encoding = instr->encoding();
+
+  if (FLAG_debug_code) {
+    __ push(value);
+    __ mov(value, FieldOperand(string, HeapObject::kMapOffset));
+    __ movzx_b(value, FieldOperand(value, Map::kInstanceTypeOffset));
+
+    __ and_(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    __ cmp(value, Immediate(encoding == String::ONE_BYTE_ENCODING
+                                ? one_byte_seq_type : two_byte_seq_type));
+    __ Check(equal, "Unexpected string type");
+    __ pop(value);
+  }
+
+  if (encoding == String::ONE_BYTE_ENCODING) {
+    __ mov_b(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
+             value);
+  } else {
+    __ mov_w(FieldOperand(string, index, times_2, SeqString::kHeaderSize),
+             value);
+  }
 }
 
 
@@ -2101,7 +2127,7 @@
   CpuFeatureScope scope(masm(), SSE2);
 
   Representation r = instr->hydrogen()->value()->representation();
-  if (r.IsInteger32()) {
+  if (r.IsInteger32() || r.IsSmi()) {
     Register reg = ToRegister(instr->value());
     __ test(reg, Operand(reg));
     EmitBranch(true_block, false_block, not_zero);
@@ -2299,10 +2325,11 @@
   int true_block = chunk_->LookupDestination(instr->true_block_id());
 
   if (instr->right()->IsConstantOperand()) {
-    __ cmp(left, ToHandle(LConstantOperand::cast(instr->right())));
+    Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
+    __ CmpObject(left, right);
   } else {
     Operand right = ToOperand(instr->right());
-    __ cmp(left, Operand(right));
+    __ cmp(left, right);
   }
   EmitBranch(true_block, false_block, equal);
 }
@@ -3064,7 +3091,7 @@
     bool last = (i == map_count - 1);
     Handle<Map> map = instr->hydrogen()->types()->at(i);
     Label check_passed;
-    __ CompareMap(object, map, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS);
+    __ CompareMap(object, map, &check_passed);
     if (last && !need_generic) {
       DeoptimizeIf(not_equal, instr->environment());
       __ bind(&check_passed);
@@ -3337,7 +3364,7 @@
                        + offset);
   } else {
     // Take the tag bit into account while computing the shift size.
-    if (key_representation.IsTagged() && (shift_size >= 1)) {
+    if (key_representation.IsSmi() && (shift_size >= 1)) {
       shift_size -= kSmiTagSize;
     }
     ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
@@ -4220,15 +4247,9 @@
   if (FLAG_track_fields && representation.IsSmi()) {
     if (instr->value()->IsConstantOperand()) {
       LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
-      if (!IsInteger32(operand_value)) {
+      if (!IsSmi(operand_value)) {
         DeoptimizeIf(no_condition, instr->environment());
       }
-    } else {
-      Register value = ToRegister(instr->value());
-      __ SmiTag(value);
-      if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
-        DeoptimizeIf(overflow, instr->environment());
-      }
     }
   } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
     if (instr->value()->IsConstantOperand()) {
@@ -4293,12 +4314,7 @@
 
   if (instr->value()->IsConstantOperand()) {
     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
-    if (IsInteger32(operand_value)) {
-      // In lithium register preparation, we made sure that the constant integer
-      // operand fits into smi range.
-      Smi* smi_value = Smi::FromInt(ToInteger32(operand_value));
-      __ mov(FieldOperand(write_register, offset), Immediate(smi_value));
-    } else if (operand_value->IsRegister()) {
+    if (operand_value->IsRegister()) {
       __ mov(FieldOperand(write_register, offset), ToRegister(operand_value));
     } else {
       Handle<Object> handle_value = ToHandle(operand_value);
@@ -4343,7 +4359,7 @@
   if (instr->index()->IsConstantOperand()) {
     int constant_index =
         ToInteger32(LConstantOperand::cast(instr->index()));
-    if (instr->hydrogen()->length()->representation().IsTagged()) {
+    if (instr->hydrogen()->length()->representation().IsSmi()) {
       __ cmp(ToOperand(instr->length()),
              Immediate(Smi::FromInt(constant_index)));
     } else {
@@ -4769,6 +4785,16 @@
 }
 
 
+void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
+  Register input = ToRegister(instr->value());
+  __ SmiTag(input);
+  if (!instr->hydrogen()->value()->HasRange() ||
+      !instr->hydrogen()->value()->range()->IsInSmiRange()) {
+    DeoptimizeIf(overflow, instr->environment());
+  }
+}
+
+
 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
   CpuFeatureScope scope(masm(), SSE2);
   LOperand* input = instr->value();
@@ -5026,14 +5052,30 @@
 
 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
   LOperand* input = instr->value();
+  Register result = ToRegister(input);
   ASSERT(input->IsRegister() && input->Equals(instr->result()));
   if (instr->needs_check()) {
-    __ test(ToRegister(input), Immediate(kSmiTagMask));
+    __ test(result, Immediate(kSmiTagMask));
     DeoptimizeIf(not_zero, instr->environment());
+  } else if (instr->hydrogen()->value()->IsLoadKeyed()) {
+    HLoadKeyed* load = HLoadKeyed::cast(instr->hydrogen()->value());
+    if (load->UsesMustHandleHole()) {
+      __ test(result, Immediate(kSmiTagMask));
+      if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+        Label done;
+        __ j(equal, &done);
+        __ xor_(result, result);
+        __ bind(&done);
+      } else {
+        DeoptimizeIf(not_zero, instr->environment());
+      }
+    } else {
+      __ AssertSmi(result);
+    }
   } else {
-    __ AssertSmi(ToRegister(input));
+    __ AssertSmi(result);
   }
-  __ SmiUntag(ToRegister(input));
+  __ SmiUntag(result);
 }
 
 
@@ -5621,6 +5663,48 @@
 }
 
 
+void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
+  LOperand* input = instr->value();
+  ASSERT(input->IsDoubleRegister());
+  LOperand* result = instr->result();
+  ASSERT(result->IsRegister());
+  CpuFeatureScope scope(masm(), SSE2);
+
+  XMMRegister input_reg = ToDoubleRegister(input);
+  Register result_reg = ToRegister(result);
+
+  Label done;
+  __ cvttsd2si(result_reg, Operand(input_reg));
+  __ cvtsi2sd(xmm0, Operand(result_reg));
+  __ ucomisd(xmm0, input_reg);
+  DeoptimizeIf(not_equal, instr->environment());
+  DeoptimizeIf(parity_even, instr->environment());  // NaN.
+
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    // The integer converted back is equal to the original. We
+    // only have to test if we got -0 as an input.
+    __ test(result_reg, Operand(result_reg));
+    __ j(not_zero, &done, Label::kNear);
+    __ movmskpd(result_reg, input_reg);
+    // Bit 0 contains the sign of the double in input_reg.
+    // If input was positive, we are ok and return 0, otherwise
+    // deoptimize.
+    __ and_(result_reg, 1);
+    DeoptimizeIf(not_zero, instr->environment());
+    __ bind(&done);
+  }
+  __ SmiTag(result_reg);
+  DeoptimizeIf(overflow, instr->environment());
+}
+
+
+void LCodeGen::DoCheckSmiAndReturn(LCheckSmiAndReturn* instr) {
+  LOperand* input = instr->value();
+  __ test(ToOperand(input), Immediate(kSmiTagMask));
+  DeoptimizeIf(not_zero, instr->environment());
+}
+
+
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   LOperand* input = instr->value();
   __ test(ToOperand(input), Immediate(kSmiTagMask));
@@ -5697,10 +5781,9 @@
 
 void LCodeGen::DoCheckMapCommon(Register reg,
                                 Handle<Map> map,
-                                CompareMapMode mode,
                                 LInstruction* instr) {
   Label success;
-  __ CompareMap(reg, map, &success, mode);
+  __ CompareMap(reg, map, &success);
   DeoptimizeIf(not_equal, instr->environment());
   __ bind(&success);
 }
@@ -5715,11 +5798,11 @@
   SmallMapList* map_set = instr->hydrogen()->map_set();
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
-    __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP);
+    __ CompareMap(reg, map, &success);
     __ j(equal, &success);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr);
+  DoCheckMapCommon(reg, map, instr);
   __ bind(&success);
 }
 
@@ -5911,7 +5994,7 @@
   } else {
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(reg, prototypes->at(i));
-      DoCheckMapCommon(reg, maps->at(i), ALLOW_ELEMENT_TRANSITION_MAPS, instr);
+      DoCheckMapCommon(reg, maps->at(i), instr);
     }
   }
 }
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index 9f8d4fd..59d6b45 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -111,6 +111,7 @@
   bool IsX87TopOfStack(LOperand* op) const;
 
   bool IsInteger32(LConstantOperand* op) const;
+  bool IsSmi(LConstantOperand* op) const;
   Immediate ToInteger32Immediate(LOperand* op) const {
     return Immediate(ToInteger32(LConstantOperand::cast(op)));
   }
@@ -160,8 +161,7 @@
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
 
-  void DoCheckMapCommon(Register reg, Handle<Map> map,
-                        CompareMapMode mode, LInstruction* instr);
+  void DoCheckMapCommon(Register reg, Handle<Map> map, LInstruction* instr);
 
   // Parallel move support.
   void DoParallelMove(LParallelMove* move);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index dec5697..e5b1474 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -416,8 +416,7 @@
 
 void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
-  stream->Add(".");
-  stream->Add(*String::cast(*name())->ToCString());
+  hydrogen()->access().PrintTo(stream);
   stream->Add(" <- ");
   value()->PrintTo(stream);
 }
@@ -1845,7 +1844,6 @@
   LOperand* string = UseRegister(instr->string());
   LOperand* index = UseRegister(instr->index());
   ASSERT(ecx.is_byte_register());
-  // TODO(titzer): the machine code for this instruction overwrites ecx! fix!
   LOperand* value = UseFixed(instr->value(), ecx);
   LSeqStringSetChar* result =
       new(zone()) LSeqStringSetChar(instr->encoding(), string, index, value);
@@ -1908,6 +1906,20 @@
 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   Representation from = instr->from();
   Representation to = instr->to();
+  if (from.IsSmi()) {
+    if (to.IsTagged()) {
+      LOperand* value = UseRegister(instr->value());
+      // For now, always deopt on hole.
+      if (instr->value()->IsLoadKeyed() &&
+          HLoadKeyed::cast(instr->value())->UsesMustHandleHole()) {
+        return AssignEnvironment(
+            DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
+      } else {
+        return DefineSameAsFirst(new(zone()) LDummyUse(value));
+      }
+    }
+    from = Representation::Tagged();
+  }
   // Only mark conversions that might need to allocate as calling rather than
   // all changes. This makes simple, non-allocating conversion not have to force
   // building a stack frame.
@@ -1925,11 +1937,28 @@
       } else {
         return AssignEnvironment(DefineX87TOS(res));
       }
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      if (val->type().IsSmi()) {
+        return DefineSameAsFirst(new(zone()) LDummyUse(value));
+      }
+      return AssignEnvironment(
+          DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
     } else {
       ASSERT(to.IsInteger32());
       if (instr->value()->type().IsSmi()) {
         LOperand* value = UseRegister(instr->value());
-        return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
+        LInstruction* result =
+            DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
+        if (instr->value()->IsLoadKeyed()) {
+          HLoadKeyed* load_keyed = HLoadKeyed::cast(instr->value());
+          if (load_keyed->UsesMustHandleHole() &&
+              load_keyed->hole_mode() == NEVER_RETURN_HOLE) {
+            return AssignEnvironment(result);
+          }
+        }
+        return result;
       } else {
         bool truncating = instr->CanTruncateToInt32();
         if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
@@ -1961,6 +1990,10 @@
       LUnallocated* result_temp = TempRegister();
       LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
       return AssignPointerMap(Define(result, result_temp));
+    } else if (to.IsSmi()) {
+      LOperand* value = UseRegister(instr->value());
+      return AssignEnvironment(
+          DefineAsRegister(new(zone()) LDoubleToSmi(value)));
     } else {
       ASSERT(to.IsInteger32());
       bool truncating = instr->CanTruncateToInt32();
@@ -1985,6 +2018,15 @@
         LNumberTagI* result = new(zone()) LNumberTagI(value);
         return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
       }
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      LInstruction* result =
+          DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
+      if (val->HasRange() && val->range()->IsInSmiRange()) {
+        return result;
+      }
+      return AssignEnvironment(result);
     } else {
       ASSERT(to.IsDouble());
       if (instr->value()->CheckFlag(HInstruction::kUint32)) {
@@ -2029,12 +2071,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoCheckSmiOrInt32(HCheckSmiOrInt32* instr) {
-  LOperand* value = UseAtStart(instr->value());
-  return AssignEnvironment(new(zone()) LCheckSmi(value));
-}
-
-
 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
   // If the target is in new space, we'll emit a global cell compare and so
   // want the value in a register.  If the target gets promoted before we
@@ -2105,7 +2141,7 @@
     } else {
       return DefineX87TOS(new(zone()) LConstantD(NULL));
     }
-  } else if (r.IsTagged()) {
+  } else if (r.IsSmiOrTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
@@ -2222,7 +2258,7 @@
 
 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
+         instr->key()->representation().IsSmi());
   ElementsKind elements_kind = instr->elements_kind();
   bool clobbers_key = ExternalArrayOpRequiresTemp(
       instr->key()->representation(), elements_kind);
@@ -2291,7 +2327,7 @@
   if (!instr->is_external()) {
     ASSERT(instr->elements()->representation().IsTagged());
     ASSERT(instr->key()->representation().IsInteger32() ||
-           instr->key()->representation().IsTagged());
+           instr->key()->representation().IsSmi());
 
     if (instr->value()->representation().IsDouble()) {
       LOperand* object = UseRegisterAtStart(instr->elements());
@@ -2304,7 +2340,7 @@
       LOperand* key = UseRegisterOrConstantAtStart(instr->key());
       return new(zone()) LStoreKeyed(object, key, val);
     } else {
-      ASSERT(instr->value()->representation().IsTagged());
+      ASSERT(instr->value()->representation().IsSmiOrTagged());
       bool needs_write_barrier = instr->NeedsWriteBarrier();
 
       LOperand* obj = UseRegister(instr->elements());
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index b32ead9..6712e76 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -70,6 +70,7 @@
   V(CheckNonSmi)                                \
   V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
+  V(CheckSmiAndReturn)                          \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
   V(ClampTToUint8)                              \
@@ -90,6 +91,7 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(DoubleToSmi)                                \
   V(DummyUse)                                   \
   V(ElementsKind)                               \
   V(FixedArrayBaseLength)                       \
@@ -106,6 +108,7 @@
   V(InstanceSize)                               \
   V(InstructionGap)                             \
   V(Integer32ToDouble)                          \
+  V(Integer32ToSmi)                             \
   V(Uint32ToDouble)                             \
   V(InvokeFunction)                             \
   V(IsConstructCallAndBranch)                   \
@@ -1593,7 +1596,7 @@
   // Operations that require the key to be divided by two to be converted into
   // an index cannot fold the scale operation into a load and need an extra
   // temp register to do the work.
-  return key_representation.IsTagged() &&
+  return key_representation.IsSmi() &&
       (elements_kind == EXTERNAL_BYTE_ELEMENTS ||
        elements_kind == EXTERNAL_UNSIGNED_BYTE_ELEMENTS ||
        elements_kind == EXTERNAL_PIXEL_ELEMENTS);
@@ -1998,6 +2001,19 @@
 };
 
 
+class LInteger32ToSmi: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LInteger32ToSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(Change)
+};
+
+
 class LUint32ToDouble: public LTemplateInstruction<1, 1, 1> {
  public:
   explicit LUint32ToDouble(LOperand* value, LOperand* temp) {
@@ -2069,6 +2085,19 @@
 };
 
 
+class LDoubleToSmi: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LDoubleToSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
+};
+
+
 // Truncating conversion from a tagged value to an int32.
 class LTaggedToI: public LTemplateInstruction<1, 1, 1> {
  public:
@@ -2153,6 +2182,7 @@
   LOperand* value() { return inputs_[0]; }
 
   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
+  DECLARE_HYDROGEN_ACCESSOR(Change);
 
   bool needs_check() const { return needs_check_; }
 
@@ -2444,6 +2474,18 @@
 };
 
 
+class LCheckSmiAndReturn: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCheckSmiAndReturn(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmiAndReturn, "check-smi-and-return")
+};
+
+
 class LClampDToUint8: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LClampDToUint8(LOperand* value) {
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 5c18cae..ec45eaa 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -580,38 +580,21 @@
 
 void MacroAssembler::CompareMap(Register obj,
                                 Handle<Map> map,
-                                Label* early_success,
-                                CompareMapMode mode) {
+                                Label* early_success) {
   cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
-  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
-    ElementsKind kind = map->elements_kind();
-    if (IsFastElementsKind(kind)) {
-      bool packed = IsFastPackedElementsKind(kind);
-      Map* current_map = *map;
-      while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
-        kind = GetNextMoreGeneralFastElementsKind(kind, packed);
-        current_map = current_map->LookupElementsTransitionMap(kind);
-        if (!current_map) break;
-        j(equal, early_success, Label::kNear);
-        cmp(FieldOperand(obj, HeapObject::kMapOffset),
-            Handle<Map>(current_map));
-      }
-    }
-  }
 }
 
 
 void MacroAssembler::CheckMap(Register obj,
                               Handle<Map> map,
                               Label* fail,
-                              SmiCheckType smi_check_type,
-                              CompareMapMode mode) {
+                              SmiCheckType smi_check_type) {
   if (smi_check_type == DO_SMI_CHECK) {
     JumpIfSmi(obj, fail);
   }
 
   Label success;
-  CompareMap(obj, map, &success, mode);
+  CompareMap(obj, map, &success);
   j(not_equal, fail);
   bind(&success);
 }
@@ -2521,6 +2504,18 @@
 }
 
 
+void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
+  ALLOW_HANDLE_DEREF(isolate(), "using raw address");
+  if (isolate()->heap()->InNewSpace(*object)) {
+    Handle<JSGlobalPropertyCell> cell =
+        isolate()->factory()->NewJSGlobalPropertyCell(object);
+    cmp(reg, Operand::Cell(cell));
+  } else {
+    cmp(reg, object);
+  }
+}
+
+
 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
   ALLOW_HANDLE_DEREF(isolate(), "using raw address");
   if (isolate()->heap()->InNewSpace(*object)) {
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index e7a075d..340055a 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -272,6 +272,7 @@
   void LoadFromSafepointRegisterSlot(Register dst, Register src);
 
   void LoadHeapObject(Register result, Handle<HeapObject> object);
+  void CmpHeapObject(Register reg, Handle<HeapObject> object);
   void PushHeapObject(Handle<HeapObject> object);
 
   void LoadObject(Register result, Handle<Object> object) {
@@ -283,6 +284,15 @@
     }
   }
 
+  void CmpObject(Register reg, Handle<Object> object) {
+    ALLOW_HANDLE_DEREF(isolate(), "heap object check");
+    if (object->IsHeapObject()) {
+      CmpHeapObject(reg, Handle<HeapObject>::cast(object));
+    } else {
+      cmp(reg, Immediate(object));
+    }
+  }
+
   // ---------------------------------------------------------------------------
   // JavaScript invokes
 
@@ -399,8 +409,7 @@
   // sequences branches to early_success.
   void CompareMap(Register obj,
                   Handle<Map> map,
-                  Label* early_success,
-                  CompareMapMode mode = REQUIRE_EXACT_MAP);
+                  Label* early_success);
 
   // Check if the map of an object is equal to a specified map and branch to
   // label if not. Skip the smi check if not required (object is known to be a
@@ -409,8 +418,7 @@
   void CheckMap(Register obj,
                 Handle<Map> map,
                 Label* fail,
-                SmiCheckType smi_check_type,
-                CompareMapMode mode = REQUIRE_EXACT_MAP);
+                SmiCheckType smi_check_type);
 
   // Check if the map of an object is equal to a specified map and branch to a
   // specified target if equal. Skip the smi check if not required (object is
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 88ea4b2..e1db7cd 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -783,7 +783,7 @@
                                            Label* slow) {
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, Handle<Map>(object->map()),
-              miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+              miss_label, DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -859,7 +859,7 @@
 
     __ bind(&heap_number);
     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(),
-                miss_restore_name, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+                miss_restore_name, DONT_DO_SMI_CHECK);
     if (CpuFeatures::IsSupported(SSE2)) {
       CpuFeatureScope use_sse2(masm, SSE2);
       __ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
@@ -918,6 +918,8 @@
   // object and the number of in-object properties is not going to change.
   index -= object->map()->inobject_properties();
 
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   // TODO(verwaest): Share this code as a code stub.
   if (index < 0) {
     // Set the property straight into the object.
@@ -940,7 +942,9 @@
                           offset,
                           name_reg,
                           scratch1,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   } else {
     // Write to the properties array.
@@ -965,7 +969,9 @@
                           offset,
                           name_reg,
                           receiver_reg,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   }
 
@@ -988,7 +994,7 @@
                                       Label* miss_label) {
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, Handle<Map>(object->map()),
-              miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+              miss_label, DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -1039,7 +1045,7 @@
     __ jmp(&do_store);
     __ bind(&heap_number);
     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(),
-                miss_label, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+                miss_label, DONT_DO_SMI_CHECK);
     if (CpuFeatures::IsSupported(SSE2)) {
       CpuFeatureScope use_sse2(masm, SSE2);
       __ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
@@ -1061,6 +1067,8 @@
 
   ASSERT(!FLAG_track_double_fields || !representation.IsDouble());
   // TODO(verwaest): Share this code as a code stub.
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index < 0) {
     // Set the property straight into the object.
     int offset = object->map()->instance_size() + (index * kPointerSize);
@@ -1074,7 +1082,9 @@
                           offset,
                           name_reg,
                           scratch1,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   } else {
     // Write to the properties array.
@@ -1091,7 +1101,9 @@
                           offset,
                           name_reg,
                           receiver_reg,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   }
 
@@ -1187,8 +1199,7 @@
       bool in_new_space = heap()->InNewSpace(*prototype);
       Handle<Map> current_map(current->map());
       if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) {
-        __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK,
-                    ALLOW_ELEMENT_TRANSITION_MAPS);
+        __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
       }
 
       // Check access rights to the global object.  This has to happen after
@@ -1229,8 +1240,7 @@
 
   if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) {
     // Check the holder map.
-    __ CheckMap(reg, Handle<Map>(holder->map()),
-                miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+    __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK);
   }
 
   // Perform security check for access to the global object.
@@ -2886,8 +2896,7 @@
   Label miss;
 
   // Check that the map of the object hasn't changed.
-  __ CheckMap(receiver(), Handle<Map>(object->map()),
-              &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+  __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
diff --git a/src/ic.cc b/src/ic.cc
index ea0c1fb..91e1c76 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -2892,7 +2892,7 @@
   if (target->ic_state() == UNINITIALIZED) return;
   Code::ExtraICState state = target->extended_extra_ic_state();
 
-  CompareNilICStub stub(state, CompareNilICStub::CODE_STUB_IS_MISS);
+  CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED);
   stub.ClearTypes();
 
   Code* code = NULL;
diff --git a/src/ic.h b/src/ic.h
index a044f0c..8fd96a6 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -811,6 +811,7 @@
 
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_MissLight);
 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
 
 
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index b67a9f6..f548a2e 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -773,9 +773,16 @@
           length);
     }
   } else {
-    String* string_location = *string;
-    Vector<const Char> vector = GetCharVector<Char>(string);
+    String* string_location = NULL;
+    Vector<const Char> vector(NULL, 0);
     for (int i = 0; i < length; i++) {
+      // If GC moved the string, we need to refresh the vector.
+      if (*string != string_location) {
+        AssertNoAllocation no_gc;
+        // This does not actually prevent the string from being relocated later.
+        vector = GetCharVector<Char>(string);
+        string_location = *string;
+      }
       Char c = vector[i];
       if (DoNotEscape(c)) {
         Append_<is_ascii, Char>(c);
@@ -783,11 +790,6 @@
         Append_<is_ascii, uint8_t>(reinterpret_cast<const uint8_t*>(
             &JsonEscapeTable[c * kJsonEscapeTableEntrySize]));
       }
-      // If GC moved the string, we need to refresh the vector.
-      if (*string != string_location) {
-        vector = GetCharVector<Char>(string);
-        string_location = *string;
-      }
     }
   }
 
@@ -825,17 +827,16 @@
 
 
 void BasicJsonStringifier::SerializeString(Handle<String> object) {
-  FlattenString(object);
-  String::FlatContent flat = object->GetFlatContent();
+  object = FlattenGetString(object);
   if (is_ascii_) {
-    if (flat.IsAscii()) {
+    if (object->IsOneByteRepresentation()) {
       SerializeString_<true, uint8_t>(object);
     } else {
       ChangeEncoding();
       SerializeString(object);
     }
   } else {
-    if (flat.IsAscii()) {
+    if (object->IsOneByteRepresentation()) {
       SerializeString_<false, uint8_t>(object);
     } else {
       SerializeString_<false, uc16>(object);
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index 74132b3..04113e1 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -1057,7 +1057,7 @@
       LInstruction* branch =
           InstructionAt(cur_block->last_instruction_index());
       if (branch->HasPointerMap()) {
-        if (phi->representation().IsTagged()) {
+        if (phi->representation().IsSmiOrTagged()) {
           branch->pointer_map()->RecordPointer(phi_operand, zone());
         } else if (!phi->representation().IsDouble()) {
           branch->pointer_map()->RecordUntagged(phi_operand, zone());
@@ -1640,7 +1640,7 @@
 bool LAllocator::HasTaggedValue(int virtual_register) const {
   HValue* value = graph_->LookupValue(virtual_register);
   if (value == NULL) return false;
-  return value->representation().IsTagged();
+  return value->representation().IsSmiOrTagged();
 }
 
 
diff --git a/src/lithium.cc b/src/lithium.cc
index 539f4ee..9f44b7e 100644
--- a/src/lithium.cc
+++ b/src/lithium.cc
@@ -455,10 +455,7 @@
   MarkEmptyBlocks();
 
   if (generator.GenerateCode()) {
-    if (FLAG_trace_codegen) {
-      PrintF("Crankshaft Compiler - ");
-    }
-    CodeGenerator::MakeCodePrologue(info());
+    CodeGenerator::MakeCodePrologue(info(), "optimized");
     Code::Flags flags = info()->flags();
     Handle<Code> code =
         CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
diff --git a/src/lithium.h b/src/lithium.h
index 388f565..85df95a 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -558,7 +558,7 @@
                 Representation representation,
                 bool is_uint32) {
     values_.Add(operand, zone());
-    if (representation.IsTagged()) {
+    if (representation.IsSmiOrTagged()) {
       ASSERT(!is_uint32);
       is_tagged_.Add(values_.length() - 1);
     }
diff --git a/src/messages.js b/src/messages.js
index 296965d..2ad68cb 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -906,8 +906,8 @@
 
 function CallSiteIsConstructor() {
   var receiver = this[CallSiteReceiverKey];
-  var constructor =
-      IS_OBJECT(receiver) ? %GetDataProperty(receiver, "constructor") : null;
+  var constructor = (receiver != null && IS_OBJECT(receiver))
+                        ? %GetDataProperty(receiver, "constructor") : null;
   if (!constructor) return false;
   return this[CallSiteFunctionKey] === constructor;
 }
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 7c09bb3..9b4170e 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -128,8 +128,8 @@
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(CompareNilIC_Miss);
-  descriptor->miss_handler_ =
-      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
 }
 
 
@@ -218,7 +218,7 @@
     for (int i = 0; i < param_count; ++i) {
       __ push(descriptor->register_params_[i]);
     }
-    ExternalReference miss = descriptor->miss_handler_;
+    ExternalReference miss = descriptor->miss_handler();
     __ CallExternalReference(miss, descriptor->register_param_count_);
   }
 
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index e874a08..72eb00b 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -514,50 +514,6 @@
 }
 
 
-void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
-                                         String::Encoding encoding,
-                                         Register string,
-                                         Register index,
-                                         Register value) {
-  if (FLAG_debug_code) {
-    __ And(at, index, Operand(kSmiTagMask));
-    __ Check(eq, "Non-smi index", at, Operand(zero_reg));
-    __ And(at, value, Operand(kSmiTagMask));
-    __ Check(eq, "Non-smi value", at, Operand(zero_reg));
-
-    __ lw(at, FieldMemOperand(string, String::kLengthOffset));
-    __ Check(lt, "Index is too large", index, Operand(at));
-
-    __ Check(ge, "Index is negative", index, Operand(zero_reg));
-
-    __ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
-    __ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
-
-    __ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ Subu(at, at, Operand(encoding == String::ONE_BYTE_ENCODING
-        ? one_byte_seq_type : two_byte_seq_type));
-    __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
-  }
-
-  __ Addu(at,
-          string,
-          Operand(SeqString::kHeaderSize - kHeapObjectTag));
-  __ SmiUntag(value);
-  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
-  if (encoding == String::ONE_BYTE_ENCODING) {
-    __ SmiUntag(index);
-    __ Addu(at, at, index);
-    __ sb(value, MemOperand(at));
-  } else {
-    // No need to untag a smi for two-byte addressing.
-    __ Addu(at, at, index);
-    __ sh(value, MemOperand(at));
-  }
-}
-
-
 static MemOperand ExpConstant(int index, Register base) {
   return MemOperand(base, index * kDoubleSize);
 }
diff --git a/src/mips/codegen-mips.h b/src/mips/codegen-mips.h
index d429443..240b02c 100644
--- a/src/mips/codegen-mips.h
+++ b/src/mips/codegen-mips.h
@@ -53,7 +53,7 @@
   static bool MakeCode(CompilationInfo* info);
 
   // Printing of AST, etc. as requested by flags.
-  static void MakeCodePrologue(CompilationInfo* info);
+  static void MakeCodePrologue(CompilationInfo* info, const char* kind);
 
   // Allocate and install the code.
   static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index bdfa43b..6a3b72d 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -3445,19 +3445,56 @@
 }
 
 
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+                                                  Register index,
+                                                  Register value,
+                                                  uint32_t encoding_mask) {
+  __ And(at, index, Operand(kSmiTagMask));
+  __ Check(eq, "Non-smi index", at, Operand(zero_reg));
+  __ And(at, value, Operand(kSmiTagMask));
+  __ Check(eq, "Non-smi value", at, Operand(zero_reg));
+
+  __ lw(at, FieldMemOperand(string, String::kLengthOffset));
+  __ Check(lt, "Index is too large", index, Operand(at));
+
+  __ Check(ge, "Index is negative", index, Operand(zero_reg));
+
+  __ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
+  __ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
+
+  __ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
+  __ Subu(at, at, Operand(encoding_mask));
+  __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
+}
+
+
 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = v0;
+  Register index = a1;
+  Register value = a2;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(a2);
-  __ pop(a1);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, v0, a1, a2);
-  context()->Plug(v0);
+  if (FLAG_debug_code) {
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
+  __ SmiUntag(value, value);
+  __ Addu(at,
+          string,
+          Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
+  __ SmiUntag(index);
+  __ Addu(at, at, index);
+  __ sb(value, MemOperand(at));
+  context()->Plug(string);
 }
 
 
@@ -3465,15 +3502,29 @@
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = v0;
+  Register index = a1;
+  Register value = a2;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(a2);
-  __ pop(a1);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, v0, a1, a2);
-  context()->Plug(v0);
+  if (FLAG_debug_code) {
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
+  __ SmiUntag(value, value);
+  __ Addu(at,
+          string,
+          Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
+  __ Addu(at, at, index);
+  STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
+  __ sh(value, MemOperand(at));
+    context()->Plug(string);
 }
 
 
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index ae0d628..1cdea12 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -500,7 +500,7 @@
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
   return constant->handle();
 }
 
@@ -510,6 +510,11 @@
 }
 
 
+bool LCodeGen::IsSmi(LConstantOperand* op) const {
+  return chunk_->LookupLiteralRepresentation(op).IsSmi();
+}
+
+
 int LCodeGen::ToInteger32(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
   return constant->Integer32Value();
@@ -1600,11 +1605,35 @@
 
 
 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
-  SeqStringSetCharGenerator::Generate(masm(),
-                                      instr->encoding(),
-                                      ToRegister(instr->string()),
-                                      ToRegister(instr->index()),
-                                      ToRegister(instr->value()));
+  Register string = ToRegister(instr->string());
+  Register index = ToRegister(instr->index());
+  Register value = ToRegister(instr->value());
+  Register scratch = scratch0();
+  String::Encoding encoding = instr->encoding();
+
+  if (FLAG_debug_code) {
+    __ lw(at, FieldMemOperand(string, HeapObject::kMapOffset));
+    __ lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset));
+
+    __ And(at, at, Operand(kStringRepresentationMask | kStringEncodingMask));
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    __ Subu(at, at, Operand(encoding == String::ONE_BYTE_ENCODING
+                                ? one_byte_seq_type : two_byte_seq_type));
+    __ Check(eq, "Unexpected string type", at, Operand(zero_reg));
+  }
+
+  __ Addu(scratch,
+          string,
+          Operand(SeqString::kHeaderSize - kHeapObjectTag));
+  if (encoding == String::ONE_BYTE_ENCODING) {
+    __ Addu(at, scratch, index);
+    __ sb(value, MemOperand(at));
+  } else {
+    __ sll(at, index, 1);
+    __ Addu(at, scratch, at);
+    __ sh(value, MemOperand(at));
+  }
 }
 
 
@@ -1837,7 +1866,7 @@
   int false_block = chunk_->LookupDestination(instr->false_block_id());
 
   Representation r = instr->hydrogen()->value()->representation();
-  if (r.IsInteger32()) {
+  if (r.IsInteger32() || r.IsSmi()) {
     Register reg = ToRegister(instr->value());
     EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg));
   } else if (r.IsDouble()) {
@@ -2758,9 +2787,7 @@
     bool last = (i == map_count - 1);
     Handle<Map> map = instr->hydrogen()->types()->at(i);
     Label check_passed;
-    __ CompareMapAndBranch(
-        object_map, map, &check_passed,
-        eq, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS);
+    __ CompareMapAndBranch(object_map, map, &check_passed, eq, &check_passed);
     if (last && !need_generic) {
       DeoptimizeIf(al, instr->environment());
       __ bind(&check_passed);
@@ -3898,13 +3925,7 @@
 
   Handle<Map> transition = instr->transition();
 
-  if (FLAG_track_fields && representation.IsSmi()) {
-    Register value = ToRegister(instr->value());
-    __ SmiTagCheckOverflow(value, value, scratch);
-    if (!instr->hydrogen()->value()->range()->IsInSmiRange()) {
-      DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
-    }
-  } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
+  if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
     Register value = ToRegister(instr->value());
     if (!instr->hydrogen()->value()->type().IsHeapObject()) {
       __ And(scratch, value, Operand(kSmiTagMask));
@@ -4407,6 +4428,21 @@
 }
 
 
+void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister());
+  LOperand* output = instr->result();
+  ASSERT(output->IsRegister());
+  Register scratch = scratch0();
+
+  __ SmiTagCheckOverflow(ToRegister(output), ToRegister(input), scratch);
+  if (!instr->hydrogen()->value()->HasRange() ||
+      !instr->hydrogen()->value()->range()->IsInSmiRange()) {
+    DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
+  }
+}
+
+
 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
   LOperand* input = instr->value();
   LOperand* output = instr->result();
@@ -4610,6 +4646,22 @@
     __ And(scratch, input, Operand(kHeapObjectTag));
     __ SmiUntag(result, input);
     DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg));
+  } else if (instr->hydrogen()->value()->IsLoadKeyed()) {
+    HLoadKeyed* load = HLoadKeyed::cast(instr->hydrogen()->value());
+    if (load->UsesMustHandleHole()) {
+      __ And(scratch, input, Operand(kHeapObjectTag));
+      __ SmiUntag(result, input);
+      if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+        Label done;
+        __ Branch(&done, eq, scratch, Operand(zero_reg));
+        __ li(result, Operand(Smi::FromInt(0)));
+        __ bind(&done);
+      } else {
+        DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg));
+      }
+    } else {
+      __ SmiUntag(result, input);
+    }
   } else {
     __ SmiUntag(result, input);
   }
@@ -4850,10 +4902,69 @@
 
     // Deopt if the operation did not succeed (except_flag != 0).
     DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
+
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      Label done;
+      __ Branch(&done, ne, result_reg, Operand(zero_reg));
+      __ mfc1(scratch1, double_input.high());
+      __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
+      DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
+      __ bind(&done);
+    }
   }
 }
 
 
+void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
+  Register result_reg = ToRegister(instr->result());
+  Register scratch1 = scratch0();
+  Register scratch2 = ToRegister(instr->temp());
+  DoubleRegister double_input = ToDoubleRegister(instr->value());
+
+  if (instr->truncating()) {
+    Register scratch3 = ToRegister(instr->temp2());
+    FPURegister single_scratch = double_scratch0().low();
+    __ EmitECMATruncate(result_reg,
+                        double_input,
+                        single_scratch,
+                        scratch1,
+                        scratch2,
+                        scratch3);
+  } else {
+    Register except_flag = scratch2;
+
+    __ EmitFPUTruncate(kRoundToMinusInf,
+                       result_reg,
+                       double_input,
+                       scratch1,
+                       double_scratch0(),
+                       except_flag,
+                       kCheckForInexactConversion);
+
+    // Deopt if the operation did not succeed (except_flag != 0).
+    DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg));
+
+    if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+      Label done;
+      __ Branch(&done, ne, result_reg, Operand(zero_reg));
+      __ mfc1(scratch1, double_input.high());
+      __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
+      DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg));
+      __ bind(&done);
+    }
+  }
+  __ SmiTagCheckOverflow(result_reg, result_reg, scratch1);
+  DeoptimizeIf(lt, instr->environment(), scratch1, Operand(zero_reg));
+}
+
+
+void LCodeGen::DoCheckSmiAndReturn(LCheckSmiAndReturn* instr) {
+  LOperand* input = instr->value();
+  __ And(at, ToRegister(input), Operand(kSmiTagMask));
+  DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
+}
+
+
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   LOperand* input = instr->value();
   __ And(at, ToRegister(input), Operand(kSmiTagMask));
@@ -4928,10 +5039,9 @@
 
 void LCodeGen::DoCheckMapCommon(Register map_reg,
                                 Handle<Map> map,
-                                CompareMapMode mode,
                                 LEnvironment* env) {
   Label success;
-  __ CompareMapAndBranch(map_reg, map, &success, eq, &success, mode);
+  __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
   DeoptimizeIf(al, env);
   __ bind(&success);
 }
@@ -4947,11 +5057,10 @@
   __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
-    __ CompareMapAndBranch(
-        map_reg, map, &success, eq, &success, REQUIRE_EXACT_MAP);
+    __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(map_reg, map, REQUIRE_EXACT_MAP, instr->environment());
+  DoCheckMapCommon(map_reg, map, instr->environment());
   __ bind(&success);
 }
 
@@ -5023,10 +5132,7 @@
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(prototype_reg, prototypes->at(i));
       __ lw(map_reg, FieldMemOperand(prototype_reg, HeapObject::kMapOffset));
-      DoCheckMapCommon(map_reg,
-                       maps->at(i),
-                       ALLOW_ELEMENT_TRANSITION_MAPS,
-                       instr->environment());
+      DoCheckMapCommon(map_reg, maps->at(i), instr->environment());
     }
   }
 }
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index 90e7bf6..a575f5d 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -125,6 +125,7 @@
   MemOperand ToHighMemOperand(LOperand* op) const;
 
   bool IsInteger32(LConstantOperand* op) const;
+  bool IsSmi(LConstantOperand* op) const;
   Handle<Object> ToHandle(LConstantOperand* op) const;
 
   // Try to generate code for the entire chunk, but it may fail if the
@@ -154,8 +155,7 @@
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
 
-  void DoCheckMapCommon(Register map_reg, Handle<Map> map,
-                        CompareMapMode mode, LEnvironment* env);
+  void DoCheckMapCommon(Register map_reg, Handle<Map> map, LEnvironment* env);
 
   // Parallel move support.
   void DoParallelMove(LParallelMove* move);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 5ca8cd9..3f96c39 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -373,8 +373,7 @@
 
 void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
-  stream->Add(".");
-  stream->Add(*String::cast(*name())->ToCString());
+  hydrogen()->access().PrintTo(stream);
   stream->Add(" <- ");
   value()->PrintTo(stream);
 }
@@ -1760,12 +1759,30 @@
 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   Representation from = instr->from();
   Representation to = instr->to();
+  if (from.IsSmi()) {
+    if (to.IsTagged()) {
+      LOperand* value = UseRegister(instr->value());
+      // For now, always deopt on hole.
+      if (instr->value()->IsLoadKeyed() &&
+          HLoadKeyed::cast(instr->value())->UsesMustHandleHole()) {
+        return AssignEnvironment(
+            DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
+      }
+      return DefineSameAsFirst(new(zone()) LDummyUse(value));
+    }
+    from = Representation::Tagged();
+  }
   if (from.IsTagged()) {
     if (to.IsDouble()) {
       info()->MarkAsDeferredCalling();
       LOperand* value = UseRegister(instr->value());
       LNumberUntagD* res = new(zone()) LNumberUntagD(value);
       return AssignEnvironment(DefineAsRegister(res));
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      return AssignEnvironment(
+          DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = NULL;
@@ -1773,6 +1790,13 @@
       if (instr->value()->type().IsSmi()) {
         value = UseRegisterAtStart(instr->value());
         res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
+        if (instr->value()->IsLoadKeyed()) {
+          HLoadKeyed* load_keyed = HLoadKeyed::cast(instr->value());
+          if (load_keyed->UsesMustHandleHole() &&
+              load_keyed->hole_mode() == NEVER_RETURN_HOLE) {
+            res = AssignEnvironment(res);
+          }
+        }
       } else {
         value = UseRegister(instr->value());
         LOperand* temp1 = TempRegister();
@@ -1800,6 +1824,10 @@
       LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
       Define(result, result_temp);
       return AssignPointerMap(result);
+    } else if (to.IsSmi()) {
+      LOperand* value = UseRegister(instr->value());
+      return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToSmi(value,
+          TempRegister(), TempRegister())));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
@@ -1822,6 +1850,15 @@
         LNumberTagI* result = new(zone()) LNumberTagI(value);
         return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
       }
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      LInstruction* result =
+          DefineSameAsFirst(new(zone()) LInteger32ToSmi(value));
+      if (val->HasRange() && val->range()->IsInSmiRange()) {
+        return result;
+      }
+      return AssignEnvironment(result);
     } else {
       ASSERT(to.IsDouble());
       if (instr->value()->CheckFlag(HInstruction::kUint32)) {
@@ -1916,7 +1953,7 @@
     return DefineAsRegister(new(zone()) LConstantI);
   } else if (r.IsDouble()) {
     return DefineAsRegister(new(zone()) LConstantD);
-  } else if (r.IsTagged()) {
+  } else if (r.IsTagged() || r.IsSmi()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
@@ -2038,7 +2075,7 @@
     if (instr->representation().IsDouble()) {
       obj = UseTempRegister(instr->elements());
     } else {
-      ASSERT(instr->representation().IsTagged());
+      ASSERT(instr->representation().IsSmiOrTagged());
       obj = UseRegisterAtStart(instr->elements());
     }
     result = new(zone()) LLoadKeyed(obj, key);
@@ -2088,7 +2125,7 @@
       key = UseRegisterOrConstantAtStart(instr->key());
       val = UseTempRegister(instr->value());
     } else {
-      ASSERT(instr->value()->representation().IsTagged());
+      ASSERT(instr->value()->representation().IsSmiOrTagged());
       object = UseTempRegister(instr->elements());
       val = needs_write_barrier ? UseTempRegister(instr->value())
           : UseRegisterAtStart(instr->value());
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index 1abea90..3156722 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -76,6 +76,7 @@
   V(CheckNonSmi)                                \
   V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
+  V(CheckSmiAndReturn)                          \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
   V(ClampTToUint8)                              \
@@ -95,6 +96,7 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(DoubleToSmi)                                \
   V(DummyUse)                                   \
   V(ElementsKind)                               \
   V(FixedArrayBaseLength)                       \
@@ -111,6 +113,7 @@
   V(InstanceSize)                               \
   V(InstructionGap)                             \
   V(Integer32ToDouble)                          \
+  V(Integer32ToSmi)                             \
   V(Uint32ToDouble)                             \
   V(InvokeFunction)                             \
   V(IsConstructCallAndBranch)                   \
@@ -1901,6 +1904,19 @@
 };
 
 
+class LInteger32ToSmi: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LInteger32ToSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(Change)
+};
+
+
 class LUint32ToDouble: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LUint32ToDouble(LOperand* value) {
@@ -1954,6 +1970,25 @@
 };
 
 
+class LDoubleToSmi: public LTemplateInstruction<1, 1, 2> {
+ public:
+  LDoubleToSmi(LOperand* value, LOperand* temp, LOperand* temp2) {
+    inputs_[0] = value;
+    temps_[0] = temp;
+    temps_[1] = temp2;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+  LOperand* temp() { return temps_[0]; }
+  LOperand* temp2() { return temps_[1]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
+
+  bool truncating() { return hydrogen()->CanTruncateToInt32(); }
+};
+
+
 // Sometimes truncating conversion from a tagged value to an int32.
 class LDoubleToI: public LTemplateInstruction<1, 1, 2> {
  public:
@@ -2034,6 +2069,7 @@
   LOperand* value() { return inputs_[0]; }
   bool needs_check() const { return needs_check_; }
 
+  DECLARE_HYDROGEN_ACCESSOR(Change);
   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
 
  private:
@@ -2305,6 +2341,18 @@
 };
 
 
+class LCheckSmiAndReturn: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCheckSmiAndReturn(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmiAndReturn, "check-smi-and-return")
+};
+
+
 class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
  public:
   explicit LCheckNonSmi(LOperand* value) {
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index cea4bc4..e3c8b33 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -3464,10 +3464,9 @@
                                          Handle<Map> map,
                                          Label* early_success,
                                          Condition cond,
-                                         Label* branch_to,
-                                         CompareMapMode mode) {
+                                         Label* branch_to) {
   lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
-  CompareMapAndBranch(scratch, map, early_success, cond, branch_to, mode);
+  CompareMapAndBranch(scratch, map, early_success, cond, branch_to);
 }
 
 
@@ -3475,25 +3474,8 @@
                                          Handle<Map> map,
                                          Label* early_success,
                                          Condition cond,
-                                         Label* branch_to,
-                                         CompareMapMode mode) {
-  Operand right = Operand(map);
-  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
-    ElementsKind kind = map->elements_kind();
-    if (IsFastElementsKind(kind)) {
-      bool packed = IsFastPackedElementsKind(kind);
-      Map* current_map = *map;
-      while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
-        kind = GetNextMoreGeneralFastElementsKind(kind, packed);
-        current_map = current_map->LookupElementsTransitionMap(kind);
-        if (!current_map) break;
-        Branch(early_success, eq, obj_map, right);
-        right = Operand(Handle<Map>(current_map));
-      }
-    }
-  }
-
-  Branch(branch_to, cond, obj_map, right);
+                                         Label* branch_to) {
+  Branch(branch_to, cond, obj_map, Operand(map));
 }
 
 
@@ -3501,13 +3483,12 @@
                               Register scratch,
                               Handle<Map> map,
                               Label* fail,
-                              SmiCheckType smi_check_type,
-                              CompareMapMode mode) {
+                              SmiCheckType smi_check_type) {
   if (smi_check_type == DO_SMI_CHECK) {
     JumpIfSmi(obj, fail);
   }
   Label success;
-  CompareMapAndBranch(obj, scratch, map, &success, ne, fail, mode);
+  CompareMapAndBranch(obj, scratch, map, &success, ne, fail);
   bind(&success);
 }
 
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index 6511223..3a7febe 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -1014,8 +1014,7 @@
                            Handle<Map> map,
                            Label* early_success,
                            Condition cond,
-                           Label* branch_to,
-                           CompareMapMode mode = REQUIRE_EXACT_MAP);
+                           Label* branch_to);
 
   // As above, but the map of the object is already loaded into the register
   // which is preserved by the code generated.
@@ -1023,8 +1022,7 @@
                            Handle<Map> map,
                            Label* early_success,
                            Condition cond,
-                           Label* branch_to,
-                           CompareMapMode mode = REQUIRE_EXACT_MAP);
+                           Label* branch_to);
 
   // Check if the map of an object is equal to a specified map and branch to
   // label if not. Skip the smi check if not required (object is known to be a
@@ -1034,8 +1032,7 @@
                 Register scratch,
                 Handle<Map> map,
                 Label* fail,
-                SmiCheckType smi_check_type,
-                CompareMapMode mode = REQUIRE_EXACT_MAP);
+                SmiCheckType smi_check_type);
 
 
   void CheckMap(Register obj,
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 4a73be2..d95f3be 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -453,7 +453,7 @@
 
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
-              DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+              DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -571,6 +571,8 @@
   index -= object->map()->inobject_properties();
 
   // TODO(verwaest): Share this code as a code stub.
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index < 0) {
     // Set the property straight into the object.
     int offset = object->map()->instance_size() + (index * kPointerSize);
@@ -596,7 +598,9 @@
                           name_reg,
                           scratch1,
                           kRAHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   } else {
     // Write to the properties array.
@@ -626,7 +630,9 @@
                           name_reg,
                           receiver_reg,
                           kRAHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   }
 
@@ -656,7 +662,7 @@
 
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
-              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+              DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -715,6 +721,8 @@
   }
 
   // TODO(verwaest): Share this code as a code stub.
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index < 0) {
     // Set the property straight into the object.
     int offset = object->map()->instance_size() + (index * kPointerSize);
@@ -732,7 +740,9 @@
                           name_reg,
                           scratch1,
                           kRAHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   } else {
     // Write to the properties array.
@@ -754,7 +764,9 @@
                           name_reg,
                           receiver_reg,
                           kRAHasNotBeenSaved,
-                          kDontSaveFPRegs);
+                          kDontSaveFPRegs,
+                          EMIT_REMEMBERED_SET,
+                          smi_check);
     }
   }
 
@@ -1249,8 +1261,7 @@
       if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) {
         Handle<Map> current_map(current->map());
         // CheckMap implicitly loads the map of |reg| into |map_reg|.
-        __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK,
-                    ALLOW_ELEMENT_TRANSITION_MAPS);
+        __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK);
       } else {
         __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
       }
@@ -1286,7 +1297,7 @@
   if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) {
     // Check the holder map.
     __ CheckMap(reg, scratch1, Handle<Map>(holder->map()), miss,
-                DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+                DONT_DO_SMI_CHECK);
   }
 
   // Perform security check for access to the global object.
@@ -2849,7 +2860,7 @@
 
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
-              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+              DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 95a0eca..3dd3fd6 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1542,6 +1542,13 @@
 }
 
 
+MaybeObject* JSObject::TryMigrateInstance() {
+  Map* new_map = map()->CurrentMapForDeprecated();
+  if (new_map == NULL) return Smi::FromInt(0);
+  return MigrateToMap(new_map);
+}
+
+
 Handle<String> JSObject::ExpectedTransitionKey(Handle<Map> map) {
   AssertNoAllocation no_gc;
   if (!map->HasTransitionArray()) return Handle<String>::null();
@@ -3592,6 +3599,16 @@
 }
 
 
+void Map::freeze() {
+  set_bit_field3(IsFrozen::update(bit_field3(), true));
+}
+
+
+bool Map::is_frozen() {
+  return IsFrozen::decode(bit_field3());
+}
+
+
 bool Map::CanBeDeprecated() {
   int descriptor = LastAdded();
   for (int i = 0; i <= descriptor; i++) {
@@ -5303,6 +5320,17 @@
 
 
 ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
+ACCESSORS_TO_SMI(JSArrayBuffer, flag, kFlagOffset)
+
+
+bool JSArrayBuffer::is_external() {
+  return BooleanBit::get(flag(), kIsExternalBit);
+}
+
+
+void JSArrayBuffer::set_is_external(bool value) {
+  set_flag(BooleanBit::set(flag(), kIsExternalBit, value));
+}
 
 
 ACCESSORS(JSTypedArray, buffer, Object, kBufferOffset)
@@ -5310,7 +5338,6 @@
 ACCESSORS(JSTypedArray, byte_length, Object, kByteLengthOffset)
 ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
 
-
 ACCESSORS(JSRegExp, data, Object, kDataOffset)
 
 
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index ddecae3..f312794 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -889,6 +889,8 @@
          has_only_simple_this_property_assignments());
   PrintF(out, "\n - this_property_assignments = ");
   this_property_assignments()->ShortPrint(out);
+  PrintF(out, "\n - optimized_code_map = ");
+  optimized_code_map()->ShortPrint(out);
   PrintF(out, "\n");
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index 31bbbdb..99fd8e2 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3644,6 +3644,19 @@
 }
 
 
+Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
+  if (FLAG_trace_migration) {
+    PrintF("migrating instance (no new maps) %p (%p)\n",
+           static_cast<void*>(*object),
+           static_cast<void*>(object->map()));
+  }
+  CALL_HEAP_FUNCTION(
+      object->GetIsolate(),
+      object->MigrateInstance(),
+      Object);
+}
+
+
 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map,
                                           int modify_index,
                                           Representation representation) {
@@ -4507,6 +4520,42 @@
 }
 
 
+static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary(
+    Isolate* isolate,
+    FixedArrayBase* array,
+    int length,
+    SeededNumberDictionary* dictionary) {
+  Heap* heap = isolate->heap();
+  bool has_double_elements = array->IsFixedDoubleArray();
+  for (int i = 0; i < length; i++) {
+    Object* value = NULL;
+    if (has_double_elements) {
+      FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
+      if (double_array->is_the_hole(i)) {
+        value = isolate->heap()->the_hole_value();
+      } else {
+        // Objects must be allocated in the old object space, since the
+        // overall number of HeapNumbers needed for the conversion might
+        // exceed the capacity of new space, and we would fail repeatedly
+        // trying to convert the FixedDoubleArray.
+        MaybeObject* maybe_value_object =
+            heap->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
+        if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
+      }
+    } else {
+      value = FixedArray::cast(array)->get(i);
+    }
+    if (!value->IsTheHole()) {
+      PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
+      MaybeObject* maybe_result =
+          dictionary->AddNumberEntry(i, value, details);
+      if (!maybe_result->To(&dictionary)) return maybe_result;
+    }
+  }
+  return dictionary;
+}
+
+
 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
     Handle<JSObject> object) {
   CALL_HEAP_FUNCTION(object->GetIsolate(),
@@ -4538,44 +4587,14 @@
   int old_capacity = 0;
   int used_elements = 0;
   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
-  SeededNumberDictionary* dictionary = NULL;
-  { Object* object;
-    MaybeObject* maybe =
-        SeededNumberDictionary::Allocate(GetHeap(), used_elements);
-    if (!maybe->ToObject(&object)) return maybe;
-    dictionary = SeededNumberDictionary::cast(object);
-  }
+  SeededNumberDictionary* dictionary;
+  MaybeObject* maybe_dictionary =
+      SeededNumberDictionary::Allocate(GetHeap(), used_elements);
+  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
 
-  // Copy the elements to the new backing store.
-  bool has_double_elements = array->IsFixedDoubleArray();
-  for (int i = 0; i < length; i++) {
-    Object* value = NULL;
-    if (has_double_elements) {
-      FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
-      if (double_array->is_the_hole(i)) {
-        value = GetIsolate()->heap()->the_hole_value();
-      } else {
-        // Objects must be allocated in the old object space, since the
-        // overall number of HeapNumbers needed for the conversion might
-        // exceed the capacity of new space, and we would fail repeatedly
-        // trying to convert the FixedDoubleArray.
-        MaybeObject* maybe_value_object =
-            GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
-        if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
-      }
-    } else {
-      ASSERT(old_map->has_fast_smi_or_object_elements());
-      value = FixedArray::cast(array)->get(i);
-    }
-    PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
-    if (!value->IsTheHole()) {
-      Object* result;
-      MaybeObject* maybe_result =
-          dictionary->AddNumberEntry(i, value, details);
-      if (!maybe_result->ToObject(&result)) return maybe_result;
-      dictionary = SeededNumberDictionary::cast(result);
-    }
-  }
+  maybe_dictionary = CopyFastElementsToDictionary(
+      GetIsolate(), array, length, dictionary);
+  if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
 
   // Switch to using the dictionary as the backing storage for elements.
   if (is_arguments) {
@@ -4583,11 +4602,11 @@
   } else {
     // Set the new map first to satify the elements type assert in
     // set_elements().
-    Object* new_map;
+    Map* new_map;
     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
                                                   DICTIONARY_ELEMENTS);
-    if (!maybe->ToObject(&new_map)) return maybe;
-    set_map(Map::cast(new_map));
+    if (!maybe->To(&new_map)) return maybe;
+    set_map(new_map);
     set_elements(dictionary);
   }
 
@@ -5331,6 +5350,7 @@
 
   // Do a map transition, other objects with this map may still
   // be extensible.
+  // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   Map* new_map;
   MaybeObject* maybe = map()->Copy();
   if (!maybe->To(&new_map)) return maybe;
@@ -5342,6 +5362,145 @@
 }
 
 
+template<typename Dictionary>
+static void FreezeDictionary(Dictionary* dictionary) {
+  int capacity = dictionary->Capacity();
+  for (int i = 0; i < capacity; i++) {
+    Object* k = dictionary->KeyAt(i);
+    if (dictionary->IsKey(k)) {
+      PropertyDetails details = dictionary->DetailsAt(i);
+      int attrs = DONT_DELETE;
+      // READ_ONLY is an invalid attribute for JS setters/getters.
+      if (details.type() != CALLBACKS ||
+          !dictionary->ValueAt(i)->IsAccessorPair()) {
+        attrs |= READ_ONLY;
+      }
+      details = details.CopyAddAttributes(
+          static_cast<PropertyAttributes>(attrs));
+      dictionary->DetailsAtPut(i, details);
+    }
+  }
+}
+
+
+MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) {
+  // Freezing non-strict arguments should be handled elsewhere.
+  ASSERT(!HasNonStrictArgumentsElements());
+
+  Heap* heap = isolate->heap();
+
+  if (map()->is_frozen()) return this;
+
+  if (IsAccessCheckNeeded() &&
+      !isolate->MayNamedAccess(this,
+                               heap->undefined_value(),
+                               v8::ACCESS_KEYS)) {
+    isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
+    return heap->false_value();
+  }
+
+  if (IsJSGlobalProxy()) {
+    Object* proto = GetPrototype();
+    if (proto->IsNull()) return this;
+    ASSERT(proto->IsJSGlobalObject());
+    return JSObject::cast(proto)->Freeze(isolate);
+  }
+
+  // It's not possible to freeze objects with external array elements
+  if (HasExternalArrayElements()) {
+    HandleScope scope(isolate);
+    Handle<Object> object(this, isolate);
+    Handle<Object> error  =
+        isolate->factory()->NewTypeError(
+            "cant_prevent_ext_external_array_elements",
+            HandleVector(&object, 1));
+    return isolate->Throw(*error);
+  }
+
+  SeededNumberDictionary* new_element_dictionary = NULL;
+  if (!elements()->IsDictionary()) {
+    int length = IsJSArray()
+        ? Smi::cast(JSArray::cast(this)->length())->value()
+        : elements()->length();
+    if (length > 0) {
+      int capacity = 0;
+      int used = 0;
+      GetElementsCapacityAndUsage(&capacity, &used);
+      MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used);
+      if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
+
+      // Move elements to a dictionary; avoid calling NormalizeElements to avoid
+      // unnecessary transitions.
+      maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length,
+                                                new_element_dictionary);
+      if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
+    } else {
+      // No existing elements, use a pre-allocated empty backing store
+      new_element_dictionary = heap->empty_slow_element_dictionary();
+    }
+  }
+
+  LookupResult result(isolate);
+  map()->LookupTransition(this, heap->frozen_symbol(), &result);
+  if (result.IsTransition()) {
+    Map* transition_map = result.GetTransitionTarget();
+    ASSERT(transition_map->has_dictionary_elements());
+    ASSERT(transition_map->is_frozen());
+    ASSERT(!transition_map->is_extensible());
+    set_map(transition_map);
+  } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) {
+    // Create a new descriptor array with fully-frozen properties
+    int num_descriptors = map()->NumberOfOwnDescriptors();
+    DescriptorArray* new_descriptors;
+    MaybeObject* maybe_descriptors =
+        map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors,
+                                                             FROZEN);
+    if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
+
+    Map* new_map;
+    MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(
+        new_descriptors, INSERT_TRANSITION, heap->frozen_symbol());
+    if (!maybe_new_map->To(&new_map)) return maybe_new_map;
+    new_map->freeze();
+    new_map->set_is_extensible(false);
+    new_map->set_elements_kind(DICTIONARY_ELEMENTS);
+    set_map(new_map);
+  } else {
+    // Slow path: need to normalize properties for safety
+    MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
+    if (maybe->IsFailure()) return maybe;
+
+    // Create a new map, since other objects with this map may be extensible.
+    // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
+    Map* new_map;
+    MaybeObject* maybe_copy = map()->Copy();
+    if (!maybe_copy->To(&new_map)) return maybe_copy;
+    new_map->freeze();
+    new_map->set_is_extensible(false);
+    new_map->set_elements_kind(DICTIONARY_ELEMENTS);
+    set_map(new_map);
+
+    // Freeze dictionary-mode properties
+    FreezeDictionary(property_dictionary());
+  }
+
+  ASSERT(map()->has_dictionary_elements());
+  if (new_element_dictionary != NULL) {
+    set_elements(new_element_dictionary);
+  }
+
+  if (elements() != heap->empty_slow_element_dictionary()) {
+    SeededNumberDictionary* dictionary = element_dictionary();
+    // Make sure we never go back to the fast case
+    dictionary->set_requires_slow_elements();
+    // Freeze all elements in the dictionary
+    FreezeDictionary(dictionary);
+  }
+
+  return this;
+}
+
+
 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
   StackLimitCheck check(isolate);
   if (check.HasOverflowed()) return isolate->StackOverflow();
@@ -6366,9 +6525,9 @@
 
 
 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
-                                         Name* name,
                                          TransitionFlag flag,
-                                         int descriptor_index) {
+                                         Name* name,
+                                         SimpleTransitionFlag simple_flag) {
   ASSERT(descriptors->IsSortedNoDuplicates());
 
   Map* result;
@@ -6379,14 +6538,8 @@
 
   if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
     TransitionArray* transitions;
-    SimpleTransitionFlag simple_flag =
-        (descriptor_index == descriptors->number_of_descriptors() - 1)
-         ? SIMPLE_TRANSITION
-         : FULL_TRANSITION;
-    ASSERT(name == descriptors->GetKey(descriptor_index));
     MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
-
     set_transitions(transitions);
     result->SetBackPointer(this);
   } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) {
@@ -6502,7 +6655,7 @@
       descriptors->CopyUpTo(number_of_own_descriptors);
   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
 
-  return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
+  return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
 }
 
 
@@ -6514,7 +6667,7 @@
       descriptors->CopyUpTo(number_of_own_descriptors);
   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
 
-  return CopyReplaceDescriptors(new_descriptors, NULL, OMIT_TRANSITION, 0);
+  return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
 }
 
 
@@ -6555,9 +6708,7 @@
   }
 
   Name* key = descriptor->GetKey();
-  int insertion_index = new_descriptors->number_of_descriptors() - 1;
-
-  return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
+  return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION);
 }
 
 
@@ -6578,7 +6729,8 @@
 }
 
 
-MaybeObject* DescriptorArray::CopyUpTo(int enumeration_index) {
+MaybeObject* DescriptorArray::CopyUpToAddAttributes(
+    int enumeration_index, PropertyAttributes attributes) {
   if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
 
   int size = enumeration_index;
@@ -6588,8 +6740,21 @@
   if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
   DescriptorArray::WhitenessWitness witness(descriptors);
 
-  for (int i = 0; i < size; ++i) {
-    descriptors->CopyFrom(i, this, i, witness);
+  if (attributes != NONE) {
+    for (int i = 0; i < size; ++i) {
+      Object* value = GetValue(i);
+      PropertyDetails details = GetDetails(i);
+      // READ_ONLY is an invalid attribute for JS setters/getters.
+      if (details.type() == CALLBACKS && value->IsAccessorPair()) {
+        attributes = static_cast<PropertyAttributes>(attributes & ~READ_ONLY);
+      }
+      Descriptor desc(GetKey(i), value, details.CopyAddAttributes(attributes));
+      descriptors->Set(i, &desc, witness);
+    }
+  } else {
+    for (int i = 0; i < size; ++i) {
+      descriptors->CopyFrom(i, this, i, witness);
+    }
   }
 
   if (number_of_descriptors() != enumeration_index) descriptors->Sort();
@@ -6630,7 +6795,11 @@
   // Re-sort if descriptors were removed.
   if (new_size != descriptors->length()) new_descriptors->Sort();
 
-  return CopyReplaceDescriptors(new_descriptors, key, flag, insertion_index);
+  SimpleTransitionFlag simple_flag =
+      (insertion_index == descriptors->number_of_descriptors() - 1)
+      ? SIMPLE_TRANSITION
+      : FULL_TRANSITION;
+  return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag);
 }
 
 
@@ -7672,6 +7841,7 @@
 
 
 String::FlatContent String::GetFlatContent() {
+  ASSERT(!GetHeap()->allow_allocation(false));
   int length = this->length();
   StringShape shape(this);
   String* string = this;
@@ -7898,6 +8068,8 @@
   if (str_ == NULL) return;
   Handle<String> str(str_);
   ASSERT(str->IsFlat());
+  AssertNoAllocation no_gc;
+  // This does not actually prevent the vector from being relocated later.
   String::FlatContent content = str->GetFlatContent();
   ASSERT(content.IsFlat());
   is_ascii_ = content.IsAscii();
@@ -8449,6 +8621,7 @@
 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
   int slen = length();
   if (str.length() != slen) return false;
+  AssertNoAllocation no_gc;
   FlatContent content = GetFlatContent();
   if (content.IsAscii()) {
     return CompareChars(content.ToOneByteVector().start(),
@@ -8464,6 +8637,7 @@
 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
   int slen = length();
   if (str.length() != slen) return false;
+  AssertNoAllocation no_gc;
   FlatContent content = GetFlatContent();
   if (content.IsTwoByte()) {
     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
@@ -9043,7 +9217,10 @@
     new_code_map->set(old_length + 1, code);
     new_code_map->set(old_length + 2, literals);
     // Zap the old map for the sake of the heap verifier.
-    if (Heap::ShouldZapGarbage()) ZapOptimizedCodeMap();
+    if (Heap::ShouldZapGarbage()) {
+      Object** data = old_code_map->data_start();
+      MemsetPointer(data, heap->the_hole_value(), old_length);
+    }
   }
 #ifdef DEBUG
   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
@@ -9137,14 +9314,6 @@
 }
 
 
-void SharedFunctionInfo::ZapOptimizedCodeMap() {
-  FixedArray* code_map = FixedArray::cast(optimized_code_map());
-  MemsetPointer(code_map->data_start(),
-                GetHeap()->the_hole_value(),
-                code_map->length());
-}
-
-
 bool JSFunction::CompileLazy(Handle<JSFunction> function,
                              ClearExceptionFlag flag) {
   bool result = true;
@@ -13388,13 +13557,13 @@
 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>;
 
 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
-    Allocate(Heap* heap, int at_least_space_for);
+    Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
 
 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
-    Allocate(Heap* heap, int at_least_space_for);
+    Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
 
 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
-    Allocate(Heap* heap, int n);
+    Allocate(Heap* heap, int n, PretenureFlag pretenure);
 
 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
     uint32_t, Object*);
@@ -14338,10 +14507,15 @@
 
 template<typename Shape, typename Key>
 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap,
-                                              int at_least_space_for) {
+                                              int at_least_space_for,
+                                              PretenureFlag pretenure) {
   Object* obj;
   { MaybeObject* maybe_obj =
-        HashTable<Shape, Key>::Allocate(heap, at_least_space_for);
+      HashTable<Shape, Key>::Allocate(
+          heap,
+          at_least_space_for,
+          HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY,
+          pretenure);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   }
   // Initialize the next enumeration index.
diff --git a/src/objects.h b/src/objects.h
index ac74162..34d0533 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -150,11 +150,6 @@
 namespace v8 {
 namespace internal {
 
-enum CompareMapMode {
-  REQUIRE_EXACT_MAP,
-  ALLOW_ELEMENT_TRANSITION_MAPS
-};
-
 enum KeyedAccessStoreMode {
   STANDARD_STORE,
   STORE_TRANSITION_SMI_TO_OBJECT,
@@ -1848,6 +1843,9 @@
   static void MigrateInstance(Handle<JSObject> instance);
   inline MUST_USE_RESULT MaybeObject* MigrateInstance();
 
+  static Handle<Object> TryMigrateInstance(Handle<JSObject> instance);
+  inline MUST_USE_RESULT MaybeObject* TryMigrateInstance();
+
   // Can cause GC.
   MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
       Name* key,
@@ -2297,6 +2295,9 @@
   static Handle<Object> PreventExtensions(Handle<JSObject> object);
   MUST_USE_RESULT MaybeObject* PreventExtensions();
 
+  // ES5 Object.freeze
+  MUST_USE_RESULT MaybeObject* Freeze(Isolate* isolate);
+
   // Copy object
   MUST_USE_RESULT MaybeObject* DeepCopy(Isolate* isolate);
 
@@ -2834,7 +2835,13 @@
                          int new_size,
                          DescriptorArray* other);
 
-  MUST_USE_RESULT MaybeObject* CopyUpTo(int enumeration_index);
+  MUST_USE_RESULT MaybeObject* CopyUpTo(int enumeration_index) {
+    return CopyUpToAddAttributes(enumeration_index, NONE);
+  }
+
+  MUST_USE_RESULT MaybeObject* CopyUpToAddAttributes(
+      int enumeration_index,
+      PropertyAttributes attributes);
 
   // Sort the instance descriptors by the hash codes of their keys.
   void Sort();
@@ -3369,8 +3376,10 @@
   }
 
   // Returns a new array for dictionary usage. Might return Failure.
-  MUST_USE_RESULT static MaybeObject* Allocate(Heap* heap,
-                                               int at_least_space_for);
+  MUST_USE_RESULT static MaybeObject* Allocate(
+      Heap* heap,
+      int at_least_space_for,
+      PretenureFlag pretenure = NOT_TENURED);
 
   // Ensure enough space for n additional elements.
   MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
@@ -5071,6 +5080,7 @@
   class OwnsDescriptors:            public BitField<bool, 25,  1> {};
   class IsObserved:                 public BitField<bool, 26,  1> {};
   class Deprecated:                 public BitField<bool, 27,  1> {};
+  class IsFrozen:                   public BitField<bool, 28,  1> {};
 
   // Tells whether the object in the prototype property will be used
   // for instances created from this function.  If the prototype
@@ -5373,6 +5383,8 @@
   inline void set_owns_descriptors(bool is_shared);
   inline bool is_observed();
   inline void set_is_observed(bool is_observed);
+  inline void freeze();
+  inline bool is_frozen();
   inline void deprecate();
   inline bool is_deprecated();
   inline bool CanBeDeprecated();
@@ -5387,9 +5399,9 @@
   MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
   MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
       DescriptorArray* descriptors,
-      Name* name,
       TransitionFlag flag,
-      int descriptor_index);
+      Name* name = NULL,
+      SimpleTransitionFlag simple_flag = FULL_TRANSITION);
   MUST_USE_RESULT MaybeObject* CopyInstallDescriptors(
       int new_descriptor,
       DescriptorArray* descriptors);
@@ -5829,9 +5841,6 @@
   // Trims the optimized code map after entries have been removed.
   void TrimOptimizedCodeMap(int shrink_by);
 
-  // Zaps the contents of backing optimized code map.
-  void ZapOptimizedCodeMap();
-
   // Add a new entry to the optimized code map.
   MUST_USE_RESULT MaybeObject* AddToOptimizedCodeMap(Context* native_context,
                                                      Code* code,
@@ -8757,6 +8766,12 @@
   // [byte_length]: length in bytes
   DECL_ACCESSORS(byte_length, Object)
 
+  // [flags]
+  DECL_ACCESSORS(flag, Smi)
+
+  inline bool is_external();
+  inline void set_is_external(bool value);
+
   // Casting.
   static inline JSArrayBuffer* cast(Object* obj);
 
@@ -8766,9 +8781,13 @@
 
   static const int kBackingStoreOffset = JSObject::kHeaderSize;
   static const int kByteLengthOffset = kBackingStoreOffset + kPointerSize;
-  static const int kSize = kByteLengthOffset + kPointerSize;
+  static const int kFlagOffset = kByteLengthOffset + kPointerSize;
+  static const int kSize = kFlagOffset + kPointerSize;
 
  private:
+  // Bit position in a flag
+  static const int kIsExternalBit = 0;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer);
 };
 
diff --git a/src/property-details.h b/src/property-details.h
index 674fc88..ac7ade4 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -39,7 +39,7 @@
   DONT_ENUM         = v8::DontEnum,
   DONT_DELETE       = v8::DontDelete,
 
-  SEALED            = DONT_ENUM | DONT_DELETE,
+  SEALED            = DONT_DELETE,
   FROZEN            = SEALED | READ_ONLY,
 
   SYMBOLIC          = 8,  // Used to filter symbol names
@@ -131,6 +131,7 @@
   bool IsNone() const { return kind_ == kNone; }
   bool IsTagged() const { return kind_ == kTagged; }
   bool IsSmi() const { return kind_ == kSmi; }
+  bool IsSmiOrTagged() const { return IsSmi() || IsTagged(); }
   bool IsInteger32() const { return kind_ == kInteger32; }
   bool IsDouble() const { return kind_ == kDouble; }
   bool IsHeapObject() const { return kind_ == kHeapObject; }
@@ -180,6 +181,11 @@
   PropertyDetails CopyWithRepresentation(Representation representation) {
     return PropertyDetails(value_, representation);
   }
+  PropertyDetails CopyAddAttributes(PropertyAttributes new_attributes) {
+    new_attributes =
+        static_cast<PropertyAttributes>(attributes() | new_attributes);
+    return PropertyDetails(value_, new_attributes);
+  }
 
   // Conversion for storing details as Object*.
   explicit inline PropertyDetails(Smi* smi);
@@ -237,6 +243,9 @@
     value_ = RepresentationField::update(
         value, EncodeRepresentation(representation));
   }
+  PropertyDetails(int value, PropertyAttributes attributes) {
+    value_ = AttributesField::update(value, attributes);
+  }
 
   uint32_t value_;
 };
diff --git a/src/runtime.cc b/src/runtime.cc
index 61b3549..1d0d262 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -658,28 +658,37 @@
   Isolate* isolate = reinterpret_cast<Isolate*>(external_isolate);
   HandleScope scope(isolate);
   Handle<Object> internal_object = Utils::OpenHandle(**object);
+  Handle<JSArrayBuffer> array_buffer(JSArrayBuffer::cast(*internal_object));
 
-  size_t allocated_length = NumberToSize(
-      isolate, JSArrayBuffer::cast(*internal_object)->byte_length());
-  isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
-      -static_cast<intptr_t>(allocated_length));
-  if (data != NULL)
+  if (!array_buffer->is_external()) {
+    size_t allocated_length = NumberToSize(
+        isolate, array_buffer->byte_length());
+    isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
+        -static_cast<intptr_t>(allocated_length));
     free(data);
+  }
   object->Dispose(external_isolate);
 }
 
 
-bool Runtime::SetupArrayBuffer(Isolate* isolate,
+void Runtime::SetupArrayBuffer(Isolate* isolate,
                                Handle<JSArrayBuffer> array_buffer,
+                               bool is_external,
                                void* data,
                                size_t allocated_length) {
+  ASSERT(array_buffer->GetInternalFieldCount() ==
+      v8::ArrayBuffer::kInternalFieldCount);
+  for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
+    array_buffer->SetInternalField(i, Smi::FromInt(0));
+  }
   array_buffer->set_backing_store(data);
+  array_buffer->set_flag(Smi::FromInt(0));
+  array_buffer->set_is_external(is_external);
 
   Handle<Object> byte_length =
       isolate->factory()->NewNumberFromSize(allocated_length);
   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
   array_buffer->set_byte_length(*byte_length);
-  return true;
 }
 
 
@@ -696,8 +705,7 @@
     data = NULL;
   }
 
-  if (!SetupArrayBuffer(isolate, array_buffer, data, allocated_length))
-    return false;
+  SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
 
   v8::Isolate* external_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   v8::Persistent<v8::Value> weak_handle = v8::Persistent<v8::Value>::New(
@@ -2692,6 +2700,14 @@
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
+  NoHandleAllocation ha(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_CHECKED(JSObject, object, 0);
+  return object->Freeze(isolate);
+}
+
+
 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
                                                  Object* char_code) {
   if (char_code->IsNumber()) {
@@ -5647,11 +5663,10 @@
   ASSERT(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
   Handle<String> string = FlattenGetString(source);
-  String::FlatContent content = string->GetFlatContent();
-  ASSERT(content.IsFlat());
-  Handle<String> result =
-      content.IsAscii() ? URIEscape::Escape<uint8_t>(isolate, source)
-                        : URIEscape::Escape<uc16>(isolate, source);
+  ASSERT(string->IsFlat());
+  Handle<String> result = string->IsOneByteRepresentationUnderneath()
+      ? URIEscape::Escape<uint8_t>(isolate, source)
+      : URIEscape::Escape<uc16>(isolate, source);
   if (result.is_null()) return Failure::OutOfMemoryException(0x12);
   return *result;
 }
@@ -5662,10 +5677,10 @@
   ASSERT(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
   Handle<String> string = FlattenGetString(source);
-  String::FlatContent content = string->GetFlatContent();
-  ASSERT(content.IsFlat());
-  return content.IsAscii() ? *URIUnescape::Unescape<uint8_t>(isolate, source)
-                           : *URIUnescape::Unescape<uc16>(isolate, source);
+  ASSERT(string->IsFlat());
+  return string->IsOneByteRepresentationUnderneath()
+      ? *URIUnescape::Unescape<uint8_t>(isolate, source)
+      : *URIUnescape::Unescape<uc16>(isolate, source);
 }
 
 
@@ -6194,6 +6209,7 @@
       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
     }
     elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
+    AssertNoAllocation no_gc;
     String::FlatContent content = s->GetFlatContent();
     if (content.IsAscii()) {
       Vector<const uint8_t> chars = content.ToOneByteVector();
@@ -7060,6 +7076,7 @@
     equal_prefix_result = Smi::FromInt(LESS);
   }
   int r;
+  AssertNoAllocation no_gc;
   String::FlatContent x_content = x->GetFlatContent();
   String::FlatContent y_content = y->GetFlatContent();
   if (x_content.IsAscii()) {
@@ -13279,6 +13296,7 @@
   ASSERT(args.length() == 2);
   CONVERT_ARG_CHECKED(String, format, 0);
   CONVERT_ARG_CHECKED(JSArray, elms, 1);
+  AssertNoAllocation no_gc;
   String::FlatContent format_content = format->GetFlatContent();
   RUNTIME_ASSERT(format_content.IsAscii());
   Vector<const uint8_t> chars = format_content.ToOneByteVector();
@@ -13305,6 +13323,7 @@
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
+ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
diff --git a/src/runtime.h b/src/runtime.h
index a37c851..f23c666 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -303,6 +303,9 @@
   F(ResumeJSGeneratorObject, 3, 1) \
   F(ThrowGeneratorStateError, 1, 1) \
   \
+  /* ES5 */ \
+  F(ObjectFreeze, 1, 1) \
+  \
   /* Harmony modules */ \
   F(IsJSModule, 1, 1) \
   \
@@ -423,6 +426,7 @@
   F(HasFastDoubleElements, 1, 1) \
   F(HasFastHoleyElements, 1, 1) \
   F(HasDictionaryElements, 1, 1) \
+  F(HasNonStrictArgumentsElements, 1, 1) \
   F(HasExternalPixelElements, 1, 1) \
   F(HasExternalArrayElements, 1, 1) \
   F(HasExternalByteElements, 1, 1) \
@@ -750,8 +754,9 @@
       Handle<Object> object,
       Handle<Object> key);
 
-  static bool SetupArrayBuffer(Isolate* isolate,
+  static void SetupArrayBuffer(Isolate* isolate,
                                Handle<JSArrayBuffer> array_buffer,
+                               bool is_external,
                                void* data,
                                size_t allocated_length);
 
diff --git a/src/string-stream.cc b/src/string-stream.cc
index ebe1b5b..ba4a65c 100644
--- a/src/string-stream.cc
+++ b/src/string-stream.cc
@@ -252,6 +252,14 @@
 }
 
 
+void StringStream::Add(const char* format, FmtElm arg0, FmtElm arg1,
+                       FmtElm arg2, FmtElm arg3, FmtElm arg4) {
+  const char argc = 5;
+  FmtElm argv[argc] = { arg0, arg1, arg2, arg3, arg4 };
+  Add(CStrVector(format), Vector<FmtElm>(argv, argc));
+}
+
+
 SmartArrayPointer<const char> StringStream::ToCString() const {
   char* str = NewArray<char>(length_ + 1);
   OS::MemCopy(str, buffer_, length_);
diff --git a/src/string-stream.h b/src/string-stream.h
index 88b4afe..2367994 100644
--- a/src/string-stream.h
+++ b/src/string-stream.h
@@ -137,6 +137,12 @@
            FmtElm arg1,
            FmtElm arg2,
            FmtElm arg3);
+  void Add(const char* format,
+           FmtElm arg0,
+           FmtElm arg1,
+           FmtElm arg2,
+           FmtElm arg3,
+           FmtElm arg4);
 
   // Getting the message out.
   void OutputToFile(FILE* out);
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 4e3a906..84e761f 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -341,6 +341,7 @@
                                               PropertyIndex field,
                                               Representation representation) {
   if (receiver.is_identical_to(holder)) {
+    // TODO(titzer): this should use an HObjectAccess
     KeyedLoadFieldStub stub(field.is_inobject(holder),
                             field.translate(holder),
                             representation);
@@ -918,6 +919,7 @@
   }
 
   Handle<Code> ic = stub.GetCode(isolate_);
+
   // For monomorphic maps, use the code as a template, copying and replacing
   // the monomorphic map that checks the object's type.
   ic = isolate_->factory()->CopyCode(ic);
diff --git a/src/v8natives.js b/src/v8natives.js
index b2ea749..f5ab122 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -1225,20 +1225,27 @@
   if (!IS_SPEC_OBJECT(obj)) {
     throw MakeTypeError("called_on_non_object", ["Object.freeze"]);
   }
-  if (%IsJSProxy(obj)) {
-    ProxyFix(obj);
-  }
-  var names = ObjectGetOwnPropertyNames(obj);
-  for (var i = 0; i < names.length; i++) {
-    var name = names[i];
-    var desc = GetOwnProperty(obj, name);
-    if (desc.isWritable() || desc.isConfigurable()) {
-      if (IsDataDescriptor(desc)) desc.setWritable(false);
-      desc.setConfigurable(false);
-      DefineOwnProperty(obj, name, desc, true);
+  var isProxy = %IsJSProxy(obj);
+  if (isProxy || %HasNonStrictArgumentsElements(obj)) {
+    if (isProxy) {
+      ProxyFix(obj);
     }
+    var names = ObjectGetOwnPropertyNames(obj);
+    for (var i = 0; i < names.length; i++) {
+      var name = names[i];
+      var desc = GetOwnProperty(obj, name);
+      if (desc.isWritable() || desc.isConfigurable()) {
+        if (IsDataDescriptor(desc)) desc.setWritable(false);
+        desc.setConfigurable(false);
+        DefineOwnProperty(obj, name, desc, true);
+      }
+    }
+    %PreventExtensions(obj);
+  } else {
+    // TODO(adamk): Is it worth going to this fast path if the
+    // object's properties are already in dictionary mode?
+    %ObjectFreeze(obj);
   }
-  %PreventExtensions(obj);
   return obj;
 }
 
diff --git a/src/version.cc b/src/version.cc
index 0aa2c79..42b11b7 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
 // system so their names cannot be changed without changing the scripts.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     19
-#define BUILD_NUMBER      3
-#define PATCH_LEVEL       1
+#define BUILD_NUMBER      4
+#define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index f87d952..e9f7e46 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -170,8 +170,8 @@
   descriptor->register_params_ = registers;
   descriptor->deoptimization_handler_ =
       FUNCTION_ADDR(CompareNilIC_Miss);
-  descriptor->miss_handler_ =
-      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate);
+  descriptor->SetMissHandler(
+      ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
 }
 
 
@@ -194,7 +194,7 @@
     for (int i = 0; i < param_count; ++i) {
       __ push(descriptor->register_params_[i]);
     }
-    ExternalReference miss = descriptor->miss_handler_;
+    ExternalReference miss = descriptor->miss_handler();
     __ CallExternalReference(miss, descriptor->register_param_count_);
   }
 
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 6f32f7c..2ac56a1 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -624,46 +624,6 @@
 }
 
 
-void SeqStringSetCharGenerator::Generate(MacroAssembler* masm,
-                                         String::Encoding encoding,
-                                         Register string,
-                                         Register index,
-                                         Register value) {
-  if (FLAG_debug_code) {
-    __ Check(masm->CheckSmi(index), "Non-smi index");
-    __ Check(masm->CheckSmi(value), "Non-smi value");
-
-    __ SmiCompare(index, FieldOperand(string, String::kLengthOffset));
-    __ Check(less, "Index is too large");
-
-    __ SmiCompare(index, Smi::FromInt(0));
-    __ Check(greater_equal, "Index is negative");
-
-    __ push(value);
-    __ movq(value, FieldOperand(string, HeapObject::kMapOffset));
-    __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset));
-
-    __ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
-    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
-    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
-    __ cmpq(value, Immediate(encoding == String::ONE_BYTE_ENCODING
-                                 ? one_byte_seq_type : two_byte_seq_type));
-    __ Check(equal, "Unexpected string type");
-    __ pop(value);
-  }
-
-  __ SmiToInteger32(value, value);
-  __ SmiToInteger32(index, index);
-  if (encoding == String::ONE_BYTE_ENCODING) {
-    __ movb(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
-            value);
-  } else {
-    __ movw(FieldOperand(string, index, times_2, SeqString::kHeaderSize),
-            value);
-  }
-}
-
-
 void MathExpGenerator::EmitMathExp(MacroAssembler* masm,
                                    XMMRegister input,
                                    XMMRegister result,
diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h
index 3a7646b..5747e0b 100644
--- a/src/x64/codegen-x64.h
+++ b/src/x64/codegen-x64.h
@@ -51,7 +51,7 @@
   static bool MakeCode(CompilationInfo* info);
 
   // Printing of AST, etc. as requested by flags.
-  static void MakeCodePrologue(CompilationInfo* info);
+  static void MakeCodePrologue(CompilationInfo* info, const char* kind);
 
   // Allocate and install the code.
   static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 22c6fae..e88e1a5 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -3345,19 +3345,54 @@
 }
 
 
+void FullCodeGenerator::EmitSeqStringSetCharCheck(Register string,
+                                                  Register index,
+                                                  Register value,
+                                                  uint32_t encoding_mask) {
+  __ Check(masm()->CheckSmi(index), "Non-smi index");
+  __ Check(masm()->CheckSmi(value), "Non-smi value");
+
+  __ SmiCompare(index, FieldOperand(string, String::kLengthOffset));
+  __ Check(less, "Index is too large");
+
+  __ SmiCompare(index, Smi::FromInt(0));
+  __ Check(greater_equal, "Index is negative");
+
+  __ push(value);
+  __ movq(value, FieldOperand(string, HeapObject::kMapOffset));
+  __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset));
+
+  __ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
+  __ cmpq(value, Immediate(encoding_mask));
+  __ Check(equal, "Unexpected string type");
+  __ pop(value);
+}
+
+
 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = rax;
+  Register index = rbx;
+  Register value = rcx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(rcx);
-  __ pop(rbx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::ONE_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, rax, rbx, rcx);
-  context()->Plug(rax);
+  if (FLAG_debug_code) {
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
+  }
+
+  __ SmiToInteger32(value, value);
+  __ SmiToInteger32(index, index);
+  __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize),
+          value);
+  context()->Plug(string);
 }
 
 
@@ -3365,14 +3400,25 @@
   ZoneList<Expression*>* args = expr->arguments();
   ASSERT_EQ(3, args->length());
 
+  Register string = rax;
+  Register index = rbx;
+  Register value = rcx;
+
   VisitForStackValue(args->at(1));  // index
   VisitForStackValue(args->at(2));  // value
-  __ pop(rcx);
-  __ pop(rbx);
+  __ pop(value);
+  __ pop(index);
   VisitForAccumulatorValue(args->at(0));  // string
 
-  static const String::Encoding encoding = String::TWO_BYTE_ENCODING;
-  SeqStringSetCharGenerator::Generate(masm_, encoding, rax, rbx, rcx);
+  if (FLAG_debug_code) {
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
+  }
+
+  __ SmiToInteger32(value, value);
+  __ SmiToInteger32(index, index);
+  __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize),
+          value);
   context()->Plug(rax);
 }
 
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 9a1ce98..44d056f 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -435,6 +435,12 @@
 }
 
 
+bool LCodeGen::IsSmiConstant(LConstantOperand* op) const {
+  return op->IsConstantOperand() &&
+      chunk_->LookupLiteralRepresentation(op).IsSmi();
+}
+
+
 bool LCodeGen::IsTaggedConstant(LConstantOperand* op) const {
   return op->IsConstantOperand() &&
       chunk_->LookupLiteralRepresentation(op).IsTagged();
@@ -456,7 +462,7 @@
 
 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
   HConstant* constant = chunk_->LookupConstant(op);
-  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
   return constant->handle();
 }
 
@@ -1666,11 +1672,32 @@
 
 
 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
-  SeqStringSetCharGenerator::Generate(masm(),
-                                      instr->encoding(),
-                                      ToRegister(instr->string()),
-                                      ToRegister(instr->index()),
-                                      ToRegister(instr->value()));
+  Register string = ToRegister(instr->string());
+  Register index = ToRegister(instr->index());
+  Register value = ToRegister(instr->value());
+  String::Encoding encoding = instr->encoding();
+
+  if (FLAG_debug_code) {
+    __ push(value);
+    __ movq(value, FieldOperand(string, HeapObject::kMapOffset));
+    __ movzxbq(value, FieldOperand(value, Map::kInstanceTypeOffset));
+
+    __ andb(value, Immediate(kStringRepresentationMask | kStringEncodingMask));
+    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
+    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
+    __ cmpq(value, Immediate(encoding == String::ONE_BYTE_ENCODING
+                                 ? one_byte_seq_type : two_byte_seq_type));
+    __ Check(equal, "Unexpected string type");
+    __ pop(value);
+  }
+
+  if (encoding == String::ONE_BYTE_ENCODING) {
+    __ movb(FieldOperand(string, index, times_1, SeqString::kHeaderSize),
+            value);
+  } else {
+    __ movw(FieldOperand(string, index, times_2, SeqString::kHeaderSize),
+            value);
+  }
 }
 
 
@@ -1877,6 +1904,10 @@
     Register reg = ToRegister(instr->value());
     __ testl(reg, reg);
     EmitBranch(true_block, false_block, not_zero);
+  } else if (r.IsSmi()) {
+    Register reg = ToRegister(instr->value());
+    __ testq(reg, reg);
+    EmitBranch(true_block, false_block, not_zero);
   } else if (r.IsDouble()) {
     XMMRegister reg = ToDoubleRegister(instr->value());
     __ xorps(xmm0, xmm0);
@@ -2072,9 +2103,11 @@
   int true_block = chunk_->LookupDestination(instr->true_block_id());
 
   if (instr->right()->IsConstantOperand()) {
-    __ Cmp(left, ToHandle(LConstantOperand::cast(instr->right())));
+    Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
+    __ CmpObject(left, right);
   } else {
-    __ cmpq(left, ToRegister(instr->right()));
+    Register right = ToRegister(instr->right());
+    __ cmpq(left, right);
   }
   EmitBranch(true_block, false_block, equal);
 }
@@ -2767,7 +2800,7 @@
     bool last = (i == map_count - 1);
     Handle<Map> map = instr->hydrogen()->types()->at(i);
     Label check_passed;
-    __ CompareMap(object, map, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS);
+    __ CompareMap(object, map, &check_passed);
     if (last && !need_generic) {
       DeoptimizeIf(not_equal, instr->environment());
       __ bind(&check_passed);
@@ -2889,7 +2922,7 @@
     // gets replaced during bound check elimination with the index argument
     // to the bounds check, which can be tagged, so that case must be
     // handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ SmiToInteger64(key_reg, key_reg);
     } else if (instr->hydrogen()->IsDehoisted()) {
       // Sign extend key because it could be a 32 bit negative value
@@ -2962,7 +2995,7 @@
     // representation for the key to be an integer, the input gets replaced
     // during bound check elimination with the index argument to the bounds
     // check, which can be tagged, so that case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ SmiToInteger64(key_reg, key_reg);
     } else if (instr->hydrogen()->IsDehoisted()) {
       // Sign extend key because it could be a 32 bit negative value
@@ -3004,7 +3037,7 @@
     // gets replaced during bound check elimination with the index
     // argument to the bounds check, which can be tagged, so that
     // case must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ SmiToInteger64(key_reg, key_reg);
     } else if (instr->hydrogen()->IsDehoisted()) {
       // Sign extend key because it could be a 32 bit negative value
@@ -3905,12 +3938,9 @@
   if (FLAG_track_fields && representation.IsSmi()) {
     if (instr->value()->IsConstantOperand()) {
       LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
-      if (!IsInteger32Constant(operand_value)) {
+      if (!IsSmiConstant(operand_value)) {
         DeoptimizeIf(no_condition, instr->environment());
       }
-    } else {
-      Register value = ToRegister(instr->value());
-      __ Integer32ToSmi(value, value);
     }
   } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
     if (instr->value()->IsConstantOperand()) {
@@ -3968,12 +3998,7 @@
 
   if (instr->value()->IsConstantOperand()) {
     LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
-    if (IsInteger32Constant(operand_value)) {
-      // In lithium register preparation, we made sure that the constant integer
-      // operand fits into smi range.
-      Smi* smi_value = Smi::FromInt(ToInteger32(operand_value));
-      __ Move(FieldOperand(write_register, offset), smi_value);
-    } else if (operand_value->IsRegister()) {
+    if (operand_value->IsRegister()) {
       __ movq(FieldOperand(write_register, offset),
               ToRegister(operand_value));
     } else {
@@ -4017,20 +4042,20 @@
 
   if (instr->length()->IsRegister()) {
     Register reg = ToRegister(instr->length());
-    if (!instr->hydrogen()->length()->representation().IsTagged()) {
+    if (!instr->hydrogen()->length()->representation().IsSmi()) {
       __ AssertZeroExtended(reg);
     }
     if (instr->index()->IsConstantOperand()) {
       int constant_index =
           ToInteger32(LConstantOperand::cast(instr->index()));
-      if (instr->hydrogen()->length()->representation().IsTagged()) {
+      if (instr->hydrogen()->length()->representation().IsSmi()) {
         __ Cmp(reg, Smi::FromInt(constant_index));
       } else {
         __ cmpq(reg, Immediate(constant_index));
       }
     } else {
       Register reg2 = ToRegister(instr->index());
-      if (!instr->hydrogen()->index()->representation().IsTagged()) {
+      if (!instr->hydrogen()->index()->representation().IsSmi()) {
         __ AssertZeroExtended(reg2);
       }
       __ cmpq(reg, reg2);
@@ -4040,7 +4065,7 @@
     if (instr->index()->IsConstantOperand()) {
       int constant_index =
           ToInteger32(LConstantOperand::cast(instr->index()));
-      if (instr->hydrogen()->length()->representation().IsTagged()) {
+      if (instr->hydrogen()->length()->representation().IsSmi()) {
         __ Cmp(length, Smi::FromInt(constant_index));
       } else {
         __ cmpq(length, Immediate(constant_index));
@@ -4063,7 +4088,7 @@
     // gets replaced during bound check elimination with the index
     // argument to the bounds check, which can be tagged, so that case
     // must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ SmiToInteger64(key_reg, key_reg);
     } else if (instr->hydrogen()->IsDehoisted()) {
       // Sign extend key because it could be a 32 bit negative value
@@ -4127,7 +4152,7 @@
     // input gets replaced during bound check elimination with the index
     // argument to the bounds check, which can be tagged, so that case
     // must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ SmiToInteger64(key_reg, key_reg);
     } else if (instr->hydrogen()->IsDehoisted()) {
       // Sign extend key because it could be a 32 bit negative value
@@ -4170,7 +4195,7 @@
     // input gets replaced during bound check elimination with the index
     // argument to the bounds check, which can be tagged, so that case
     // must be handled here, too.
-    if (instr->hydrogen()->key()->representation().IsTagged()) {
+    if (instr->hydrogen()->key()->representation().IsSmi()) {
       __ SmiToInteger64(key_reg, key_reg);
     } else if (instr->hydrogen()->IsDehoisted()) {
       // Sign extend key because it could be a 32 bit negative value
@@ -4434,6 +4459,18 @@
 }
 
 
+void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
+  LOperand* input = instr->value();
+  ASSERT(input->IsRegister());
+  LOperand* output = instr->result();
+  __ Integer32ToSmi(ToRegister(output), ToRegister(input));
+  if (!instr->hydrogen()->value()->HasRange() ||
+      !instr->hydrogen()->value()->range()->IsInSmiRange()) {
+    DeoptimizeIf(overflow, instr->environment());
+  }
+}
+
+
 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
   LOperand* input = instr->value();
   LOperand* output = instr->result();
@@ -4606,6 +4643,21 @@
   if (instr->needs_check()) {
     Condition is_smi = __ CheckSmi(input);
     DeoptimizeIf(NegateCondition(is_smi), instr->environment());
+  } else if (instr->hydrogen()->value()->IsLoadKeyed()) {
+    HLoadKeyed* load = HLoadKeyed::cast(instr->hydrogen()->value());
+    if (load->UsesMustHandleHole()) {
+      Condition cc = masm()->CheckSmi(input);
+      if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+        Label done;
+        __ j(cc, &done);
+        __ xor_(input, input);
+        __ bind(&done);
+      } else {
+        DeoptimizeIf(NegateCondition(cc), instr->environment());
+      }
+    } else {
+      __ AssertSmi(input);
+    }
   } else {
     __ AssertSmi(input);
   }
@@ -4826,6 +4878,48 @@
 }
 
 
+void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
+  LOperand* input = instr->value();
+  ASSERT(input->IsDoubleRegister());
+  LOperand* result = instr->result();
+  ASSERT(result->IsRegister());
+  CpuFeatureScope scope(masm(), SSE2);
+
+  XMMRegister input_reg = ToDoubleRegister(input);
+  Register result_reg = ToRegister(result);
+
+  Label done;
+  __ cvttsd2si(result_reg, input_reg);
+  __ cvtlsi2sd(xmm0, result_reg);
+  __ ucomisd(xmm0, input_reg);
+  DeoptimizeIf(not_equal, instr->environment());
+  DeoptimizeIf(parity_even, instr->environment());  // NaN.
+
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    // The integer converted back is equal to the original. We
+    // only have to test if we got -0 as an input.
+    __ testl(result_reg, result_reg);
+    __ j(not_zero, &done, Label::kNear);
+    __ movmskpd(result_reg, input_reg);
+    // Bit 0 contains the sign of the double in input_reg.
+    // If input was positive, we are ok and return 0, otherwise
+    // deoptimize.
+    __ andl(result_reg, Immediate(1));
+    DeoptimizeIf(not_zero, instr->environment());
+    __ bind(&done);
+  }
+  __ Integer32ToSmi(result_reg, result_reg);
+  DeoptimizeIf(overflow, instr->environment());
+}
+
+
+void LCodeGen::DoCheckSmiAndReturn(LCheckSmiAndReturn* instr) {
+  LOperand* input = instr->value();
+  Condition cc = masm()->CheckSmi(ToRegister(input));
+  DeoptimizeIf(NegateCondition(cc), instr->environment());
+}
+
+
 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
   LOperand* input = instr->value();
   Condition cc = masm()->CheckSmi(ToRegister(input));
@@ -4889,25 +4983,16 @@
 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
   Register reg = ToRegister(instr->value());
   Handle<JSFunction> target = instr->hydrogen()->target();
-  ALLOW_HANDLE_DEREF(isolate(), "using raw address");
-  if (isolate()->heap()->InNewSpace(*target)) {
-    Handle<JSGlobalPropertyCell> cell =
-        isolate()->factory()->NewJSGlobalPropertyCell(target);
-    __ movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
-    __ cmpq(reg, Operand(kScratchRegister, 0));
-  } else {
-    __ Cmp(reg, target);
-  }
+  __ CmpHeapObject(reg, target);
   DeoptimizeIf(not_equal, instr->environment());
 }
 
 
 void LCodeGen::DoCheckMapCommon(Register reg,
                                 Handle<Map> map,
-                                CompareMapMode mode,
                                 LInstruction* instr) {
   Label success;
-  __ CompareMap(reg, map, &success, mode);
+  __ CompareMap(reg, map, &success);
   DeoptimizeIf(not_equal, instr->environment());
   __ bind(&success);
 }
@@ -4922,11 +5007,11 @@
   SmallMapList* map_set = instr->hydrogen()->map_set();
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
-    __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP);
+    __ CompareMap(reg, map, &success);
     __ j(equal, &success);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr);
+  DoCheckMapCommon(reg, map, instr);
   __ bind(&success);
 }
 
@@ -4995,7 +5080,7 @@
   } else {
     for (int i = 0; i < prototypes->length(); i++) {
       __ LoadHeapObject(reg, prototypes->at(i));
-      DoCheckMapCommon(reg, maps->at(i), ALLOW_ELEMENT_TRANSITION_MAPS, instr);
+      DoCheckMapCommon(reg, maps->at(i), instr);
     }
   }
 }
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index d0dd90e..c47bb71 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -104,6 +104,7 @@
   Register ToRegister(LOperand* op) const;
   XMMRegister ToDoubleRegister(LOperand* op) const;
   bool IsInteger32Constant(LConstantOperand* op) const;
+  bool IsSmiConstant(LConstantOperand* op) const;
   int ToInteger32(LConstantOperand* op) const;
   double ToDouble(LConstantOperand* op) const;
   bool IsTaggedConstant(LConstantOperand* op) const;
@@ -133,8 +134,7 @@
   void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                        Label* map_check);
 
-  void DoCheckMapCommon(Register reg, Handle<Map> map,
-                        CompareMapMode mode, LInstruction* instr);
+  void DoCheckMapCommon(Register reg, Handle<Map> map, LInstruction* instr);
 
 // Parallel move support.
   void DoParallelMove(LParallelMove* move);
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 1217a40..db98f23 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -391,8 +391,7 @@
 
 void LStoreNamedField::PrintDataTo(StringStream* stream) {
   object()->PrintTo(stream);
-  stream->Add(".");
-  stream->Add(*String::cast(*name())->ToCString());
+  hydrogen()->access().PrintTo(stream);
   stream->Add(" <- ");
   value()->PrintTo(stream);
 }
@@ -1812,6 +1811,19 @@
 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   Representation from = instr->from();
   Representation to = instr->to();
+  if (from.IsSmi()) {
+    if (to.IsTagged()) {
+      LOperand* value = UseRegister(instr->value());
+      // For now, always deopt on hole.
+      if (instr->value()->IsLoadKeyed() &&
+          HLoadKeyed::cast(instr->value())->UsesMustHandleHole()) {
+        return AssignEnvironment(
+            DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
+      }
+      return DefineSameAsFirst(new(zone()) LDummyUse(value));
+    }
+    from = Representation::Tagged();
+  }
   // Only mark conversions that might need to allocate as calling rather than
   // all changes. This makes simple, non-allocating conversion not have to force
   // building a stack frame.
@@ -1821,11 +1833,28 @@
       LOperand* value = UseRegister(instr->value());
       LNumberUntagD* res = new(zone()) LNumberUntagD(value);
       return AssignEnvironment(DefineAsRegister(res));
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      if (val->type().IsSmi()) {
+        return DefineSameAsFirst(new(zone()) LDummyUse(value));
+      }
+      return AssignEnvironment(
+          DefineSameAsFirst(new(zone()) LCheckSmiAndReturn(value)));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
       if (instr->value()->type().IsSmi()) {
-        return DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
+        LInstruction* result =
+            DefineSameAsFirst(new(zone()) LSmiUntag(value, false));
+        if (instr->value()->IsLoadKeyed()) {
+          HLoadKeyed* load_keyed = HLoadKeyed::cast(instr->value());
+          if (load_keyed->UsesMustHandleHole() &&
+              load_keyed->hole_mode() == NEVER_RETURN_HOLE) {
+            return AssignEnvironment(result);
+          }
+        }
+        return result;
       } else {
         bool truncating = instr->CanTruncateToInt32();
         LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
@@ -1843,10 +1872,15 @@
       LUnallocated* result_temp = TempRegister();
       LNumberTagD* result = new(zone()) LNumberTagD(value, temp);
       return AssignPointerMap(Define(result, result_temp));
+    } else if (to.IsSmi()) {
+      LOperand* value = UseRegister(instr->value());
+      return AssignEnvironment(
+          DefineAsRegister(new(zone()) LDoubleToSmi(value)));
     } else {
       ASSERT(to.IsInteger32());
       LOperand* value = UseRegister(instr->value());
-      return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToI(value)));
+      return AssignEnvironment(
+          DefineAsRegister(new(zone()) LDoubleToI(value)));
     }
   } else if (from.IsInteger32()) {
     info()->MarkAsDeferredCalling();
@@ -1863,6 +1897,15 @@
         LNumberTagI* result = new(zone()) LNumberTagI(value);
         return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
       }
+    } else if (to.IsSmi()) {
+      HValue* val = instr->value();
+      LOperand* value = UseRegister(val);
+      LInstruction* result =
+          DefineAsRegister(new(zone()) LInteger32ToSmi(value));
+      if (val->HasRange() && val->range()->IsInSmiRange()) {
+        return result;
+      }
+      return AssignEnvironment(result);
     } else {
       if (instr->value()->CheckFlag(HInstruction::kUint32)) {
         LOperand* temp = FixedTemp(xmm1);
@@ -1906,12 +1949,6 @@
 }
 
 
-LInstruction* LChunkBuilder::DoCheckSmiOrInt32(HCheckSmiOrInt32* instr) {
-  LOperand* value = UseRegisterAtStart(instr->value());
-  return AssignEnvironment(new(zone()) LCheckSmi(value));
-}
-
-
 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
   LOperand* value = UseRegisterAtStart(instr->value());
   return AssignEnvironment(new(zone()) LCheckFunction(value));
@@ -1958,7 +1995,7 @@
   } else if (r.IsDouble()) {
     LOperand* temp = TempRegister();
     return DefineAsRegister(new(zone()) LConstantD(temp));
-  } else if (r.IsTagged()) {
+  } else if (r.IsSmiOrTagged()) {
     return DefineAsRegister(new(zone()) LConstantT);
   } else {
     UNREACHABLE();
@@ -2073,9 +2110,9 @@
 
 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   ASSERT(instr->key()->representation().IsInteger32() ||
-         instr->key()->representation().IsTagged());
+         instr->key()->representation().IsSmi());
   ElementsKind elements_kind = instr->elements_kind();
-  bool clobbers_key = instr->key()->representation().IsTagged();
+  bool clobbers_key = instr->key()->representation().IsSmi();
   LOperand* key = clobbers_key
       ? UseTempRegister(instr->key())
       : UseRegisterOrConstantAtStart(instr->key());
@@ -2116,7 +2153,7 @@
 
 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
   ElementsKind elements_kind = instr->elements_kind();
-  bool clobbers_key = instr->key()->representation().IsTagged();
+  bool clobbers_key = instr->key()->representation().IsSmi();
 
   if (!instr->is_external()) {
     ASSERT(instr->elements()->representation().IsTagged());
@@ -2131,7 +2168,7 @@
       key = clobbers_key ? UseTempRegister(instr->key())
           : UseRegisterOrConstantAtStart(instr->key());
     } else {
-      ASSERT(instr->value()->representation().IsTagged());
+      ASSERT(instr->value()->representation().IsSmiOrTagged());
       object = UseTempRegister(instr->elements());
       if (needs_write_barrier) {
         val = UseTempRegister(instr->value());
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 747d8e7..920ea0c 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -76,6 +76,7 @@
   V(CheckNonSmi)                                \
   V(CheckPrototypeMaps)                         \
   V(CheckSmi)                                   \
+  V(CheckSmiAndReturn)                          \
   V(ClampDToUint8)                              \
   V(ClampIToUint8)                              \
   V(ClampTToUint8)                              \
@@ -95,6 +96,7 @@
   V(Deoptimize)                                 \
   V(DivI)                                       \
   V(DoubleToI)                                  \
+  V(DoubleToSmi)                                \
   V(DummyUse)                                   \
   V(ElementsKind)                               \
   V(FixedArrayBaseLength)                       \
@@ -112,6 +114,7 @@
   V(InstanceSize)                               \
   V(InstructionGap)                             \
   V(Integer32ToDouble)                          \
+  V(Integer32ToSmi)                             \
   V(Uint32ToDouble)                             \
   V(InvokeFunction)                             \
   V(IsConstructCallAndBranch)                   \
@@ -1887,6 +1890,19 @@
 };
 
 
+class LInteger32ToSmi: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LInteger32ToSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(Change)
+};
+
+
 class LUint32ToDouble: public LTemplateInstruction<1, 1, 1> {
  public:
   explicit LUint32ToDouble(LOperand* value, LOperand* temp) {
@@ -1958,6 +1974,19 @@
 };
 
 
+class LDoubleToSmi: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LDoubleToSmi(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi")
+  DECLARE_HYDROGEN_ACCESSOR(UnaryOperation)
+};
+
+
 // Truncating conversion from a tagged value to an int32.
 class LTaggedToI: public LTemplateInstruction<1, 1, 1> {
  public:
@@ -2011,6 +2040,7 @@
   LOperand* value() { return inputs_[0]; }
   bool needs_check() const { return needs_check_; }
 
+  DECLARE_HYDROGEN_ACCESSOR(Change);
   DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
 
  private:
@@ -2277,6 +2307,18 @@
 };
 
 
+class LCheckSmiAndReturn: public LTemplateInstruction<1, 1, 0> {
+ public:
+  explicit LCheckSmiAndReturn(LOperand* value) {
+    inputs_[0] = value;
+  }
+
+  LOperand* value() { return inputs_[0]; }
+
+  DECLARE_CONCRETE_INSTRUCTION(CheckSmiAndReturn, "check-smi-and-return")
+};
+
+
 class LClampDToUint8: public LTemplateInstruction<1, 1, 0> {
  public:
   explicit LClampDToUint8(LOperand* unclamped) {
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 31796b1..dc30a6c 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -2299,6 +2299,7 @@
   if (source->IsSmi()) {
     Move(dst, Smi::cast(*source));
   } else {
+    ASSERT(source->IsHeapObject());
     movq(dst, source, RelocInfo::EMBEDDED_OBJECT);
   }
 }
@@ -2309,6 +2310,7 @@
   if (source->IsSmi()) {
     Move(dst, Smi::cast(*source));
   } else {
+    ASSERT(source->IsHeapObject());
     movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
     movq(dst, kScratchRegister);
   }
@@ -2320,7 +2322,8 @@
   if (source->IsSmi()) {
     Cmp(dst, Smi::cast(*source));
   } else {
-    Move(kScratchRegister, source);
+    ASSERT(source->IsHeapObject());
+    movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
     cmpq(dst, kScratchRegister);
   }
 }
@@ -2364,6 +2367,19 @@
 }
 
 
+void MacroAssembler::CmpHeapObject(Register reg, Handle<HeapObject> object) {
+  ALLOW_HANDLE_DEREF(isolate(), "using raw address");
+  if (isolate()->heap()->InNewSpace(*object)) {
+    Handle<JSGlobalPropertyCell> cell =
+        isolate()->factory()->NewJSGlobalPropertyCell(object);
+    movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+    cmpq(reg, Operand(kScratchRegister, 0));
+  } else {
+    Cmp(reg, object);
+  }
+}
+
+
 void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
   ALLOW_HANDLE_DEREF(isolate(), "using raw address");
   if (isolate()->heap()->InNewSpace(*object)) {
@@ -2853,38 +2869,21 @@
 
 void MacroAssembler::CompareMap(Register obj,
                                 Handle<Map> map,
-                                Label* early_success,
-                                CompareMapMode mode) {
+                                Label* early_success) {
   Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
-  if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
-    ElementsKind kind = map->elements_kind();
-    if (IsFastElementsKind(kind)) {
-      bool packed = IsFastPackedElementsKind(kind);
-      Map* current_map = *map;
-      while (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) {
-        kind = GetNextMoreGeneralFastElementsKind(kind, packed);
-        current_map = current_map->LookupElementsTransitionMap(kind);
-        if (!current_map) break;
-        j(equal, early_success, Label::kNear);
-        Cmp(FieldOperand(obj, HeapObject::kMapOffset),
-            Handle<Map>(current_map));
-      }
-    }
-  }
 }
 
 
 void MacroAssembler::CheckMap(Register obj,
                               Handle<Map> map,
                               Label* fail,
-                              SmiCheckType smi_check_type,
-                              CompareMapMode mode) {
+                              SmiCheckType smi_check_type) {
   if (smi_check_type == DO_SMI_CHECK) {
     JumpIfSmi(obj, fail);
   }
 
   Label success;
-  CompareMap(obj, map, &success, mode);
+  CompareMap(obj, map, &success);
   j(not_equal, fail);
   bind(&success);
 }
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 6c8d5ff..9cc496f 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -788,6 +788,7 @@
   // Load a heap object and handle the case of new-space objects by
   // indirecting via a global cell.
   void LoadHeapObject(Register result, Handle<HeapObject> object);
+  void CmpHeapObject(Register reg, Handle<HeapObject> object);
   void PushHeapObject(Handle<HeapObject> object);
 
   void LoadObject(Register result, Handle<Object> object) {
@@ -799,6 +800,15 @@
     }
   }
 
+  void CmpObject(Register reg, Handle<Object> object) {
+    ALLOW_HANDLE_DEREF(isolate(), "heap object check");
+    if (object->IsHeapObject()) {
+      CmpHeapObject(reg, Handle<HeapObject>::cast(object));
+    } else {
+      Cmp(reg, object);
+    }
+  }
+
   // Load a global cell into a register.
   void LoadGlobalCell(Register dst, Handle<JSGlobalPropertyCell> cell);
 
@@ -898,8 +908,7 @@
   // sequences branches to early_success.
   void CompareMap(Register obj,
                   Handle<Map> map,
-                  Label* early_success,
-                  CompareMapMode mode = REQUIRE_EXACT_MAP);
+                  Label* early_success);
 
   // Check if the map of an object is equal to a specified map and branch to
   // label if not. Skip the smi check if not required (object is known to be a
@@ -908,8 +917,7 @@
   void CheckMap(Register obj,
                 Handle<Map> map,
                 Label* fail,
-                SmiCheckType smi_check_type,
-                CompareMapMode mode = REQUIRE_EXACT_MAP);
+                SmiCheckType smi_check_type);
 
   // Check if the map of an object is equal to a specified map and branch to a
   // specified target if equal. Skip the smi check if not required (object is
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 148f65e..36fcb84 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -763,7 +763,7 @@
                                            Label* slow) {
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, Handle<Map>(object->map()),
-              miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+              miss_label, DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -830,7 +830,7 @@
 
     __ bind(&heap_number);
     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(),
-                miss_restore_name, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+                miss_restore_name, DONT_DO_SMI_CHECK);
     __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
 
     __ bind(&do_store);
@@ -880,6 +880,8 @@
   index -= object->map()->inobject_properties();
 
   // TODO(verwaest): Share this code as a code stub.
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index < 0) {
     // Set the property straight into the object.
     int offset = object->map()->instance_size() + (index * kPointerSize);
@@ -898,7 +900,8 @@
         ASSERT(storage_reg.is(name_reg));
       }
       __ RecordWriteField(
-          receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs);
+          receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs,
+          EMIT_REMEMBERED_SET, smi_check);
     }
   } else {
     // Write to the properties array.
@@ -920,7 +923,8 @@
         ASSERT(storage_reg.is(name_reg));
       }
       __ RecordWriteField(
-          scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs);
+          scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs,
+          EMIT_REMEMBERED_SET, smi_check);
     }
   }
 
@@ -943,7 +947,7 @@
                                       Label* miss_label) {
   // Check that the map of the object hasn't changed.
   __ CheckMap(receiver_reg, Handle<Map>(object->map()),
-              miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+              miss_label, DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {
@@ -988,9 +992,8 @@
 
     __ bind(&heap_number);
     __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(),
-                miss_label, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP);
+                miss_label, DONT_DO_SMI_CHECK);
     __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
-
     __ bind(&do_store);
     __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0);
     // Return the value (register rax).
@@ -1000,6 +1003,8 @@
   }
 
   // TODO(verwaest): Share this code as a code stub.
+  SmiCheck smi_check = representation.IsTagged()
+      ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
   if (index < 0) {
     // Set the property straight into the object.
     int offset = object->map()->instance_size() + (index * kPointerSize);
@@ -1010,7 +1015,8 @@
       // Pass the value being stored in the now unused name_reg.
       __ movq(name_reg, value_reg);
       __ RecordWriteField(
-          receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs);
+          receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs,
+          EMIT_REMEMBERED_SET, smi_check);
     }
   } else {
     // Write to the properties array.
@@ -1024,7 +1030,8 @@
       // Pass the value being stored in the now unused name_reg.
       __ movq(name_reg, value_reg);
       __ RecordWriteField(
-          scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs);
+          scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs,
+          EMIT_REMEMBERED_SET, smi_check);
     }
   }
 
@@ -1126,8 +1133,7 @@
         __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset));
       }
       if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) {
-        __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK,
-                    ALLOW_ELEMENT_TRANSITION_MAPS);
+        __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK);
       }
 
       // Check access rights to the global object.  This has to happen after
@@ -1162,8 +1168,7 @@
 
   if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) {
     // Check the holder map.
-    __ CheckMap(reg, Handle<Map>(holder->map()),
-                miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+    __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK);
   }
 
   // Perform security check for access to the global object.
@@ -2666,8 +2671,7 @@
   Label miss;
 
   // Check that the map of the object hasn't changed.
-  __ CheckMap(receiver(), Handle<Map>(object->map()), &miss,
-              DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
+  __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
 
   // Perform global security token check if needed.
   if (object->IsJSGlobalProxy()) {