Version 3.28.2 (based on bleeding_edge revision r21987)

Remove bogus assertions in HCompareObjectEqAndBranch (Chromium issue 387636).

Do not eagerly update allow_osr_at_loop_nesting_level (Chromium issue 387599).

Set host_arch to ia32 on machines with a 32bit userland but a 64bit kernel (Chromium issue 368384).

Map/Set: Implement constructor parameter handling (issue 3398).

Performance and stability improvements on all platforms.

git-svn-id: https://v8.googlecode.com/svn/trunk@21989 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/BUILD.gn b/BUILD.gn
index b2a2155..2cf0b0f 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -447,6 +447,8 @@
     "src/assembler.h",
     "src/assert-scope.h",
     "src/assert-scope.cc",
+    "src/ast-value-factory.cc",
+    "src/ast-value-factory.h",
     "src/ast.cc",
     "src/ast.h",
     "src/bignum-dtoa.cc",
@@ -986,7 +988,6 @@
     }
   } else if (is_android) {
     defines += [ "CAN_USE_VFP_INSTRUCTIONS" ]
-    sources += [ "src/platform-posix.cc" ]
 
     if (build_os == "mac") {
       if (current_toolchain == host_toolchain) {
diff --git a/ChangeLog b/ChangeLog
index d3ae718..9907d37 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2014-06-25: Version 3.28.2
+
+        Remove bogus assertions in HCompareObjectEqAndBranch (Chromium issue
+        387636).
+
+        Do not eagerly update allow_osr_at_loop_nesting_level (Chromium issue
+        387599).
+
+        Set host_arch to ia32 on machines with a 32bit userland but a 64bit
+        kernel (Chromium issue 368384).
+
+        Map/Set: Implement constructor parameter handling (issue 3398).
+
+        Performance and stability improvements on all platforms.
+
+
 2014-06-24: Version 3.28.1
 
         Support LiveEdit on Arm64 (Chromium issue 368580).
diff --git a/Makefile b/Makefile
index 9c170f6..eb73f5d 100644
--- a/Makefile
+++ b/Makefile
@@ -220,7 +220,7 @@
 
 # Architectures and modes to be compiled. Consider these to be internal
 # variables, don't override them (use the targets instead).
-ARCHES = ia32 x64 arm arm64 mips mipsel x87
+ARCHES = ia32 x64 x32 arm arm64 mips mipsel x87
 DEFAULT_ARCHES = ia32 x64 arm
 MODES = release debug optdebug
 DEFAULT_MODES = release debug
@@ -398,8 +398,7 @@
 # GYP file generation targets.
 OUT_MAKEFILES = $(addprefix $(OUTDIR)/Makefile.,$(BUILDS))
 $(OUT_MAKEFILES): $(GYPFILES) $(ENVFILE)
-	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
-	PYTHONPATH="$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
+	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH):$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
 	GYP_GENERATORS=make \
 	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
 	              -Ibuild/standalone.gypi --depth=. \
@@ -408,8 +407,7 @@
 	              -S$(suffix $(basename $@))$(suffix $@) $(GYPFLAGS)
 
 $(OUTDIR)/Makefile.native: $(GYPFILES) $(ENVFILE)
-	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
-	PYTHONPATH="$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
+	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH):$(shell pwd)/build/gyp/pylib:$(PYTHONPATH)" \
 	GYP_GENERATORS=make \
 	build/gyp/gyp --generator-output="$(OUTDIR)" build/all.gyp \
 	              -Ibuild/standalone.gypi --depth=. -S.native $(GYPFLAGS)
diff --git a/Makefile.android b/Makefile.android
index d3ed1f4..b06d9e5 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -119,7 +119,7 @@
 	GYP_DEFINES="${DEFINES}" \
 	CC="${ANDROID_TOOLCHAIN}/bin/${TOOLCHAIN_PREFIX}-gcc" \
 	CXX="${ANDROID_TOOLCHAIN}/bin/${TOOLCHAIN_PREFIX}-g++" \
-	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
+	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH)" \
 	build/gyp/gyp --generator-output="${OUTDIR}" build/all.gyp \
 	              -Ibuild/standalone.gypi --depth=. -Ibuild/android.gypi \
 	              -S$(suffix $(basename $@))$(suffix $@) ${GYPFLAGS}
diff --git a/Makefile.nacl b/Makefile.nacl
index 1d34a3b..34bd960 100644
--- a/Makefile.nacl
+++ b/Makefile.nacl
@@ -97,7 +97,7 @@
 	GYP_DEFINES="${GYPENV}" \
 	CC=${NACL_CC} \
 	CXX=${NACL_CXX} \
-	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(PYTHONPATH)" \
+	PYTHONPATH="$(shell pwd)/tools/generate_shim_headers:$(shell pwd)/build:$(PYTHONPATH)" \
 	build/gyp/gyp --generator-output="${OUTDIR}" build/all.gyp \
 	              -Ibuild/standalone.gypi --depth=. \
 	              -S$(suffix $(basename $@))$(suffix $@) $(GYPFLAGS) \
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 70f576a..430692f 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -41,6 +41,7 @@
         input_api.PresubmitLocalPath(), 'tools'))
   from presubmit import CppLintProcessor
   from presubmit import SourceProcessor
+  from presubmit import CheckGeneratedRuntimeTests
 
   results = []
   if not CppLintProcessor().Run(input_api.PresubmitLocalPath()):
@@ -49,6 +50,9 @@
     results.append(output_api.PresubmitError(
         "Copyright header, trailing whitespaces and two empty lines " \
         "between declarations check failed"))
+  if not CheckGeneratedRuntimeTests(input_api.PresubmitLocalPath()):
+    results.append(output_api.PresubmitError(
+        "Generated runtime tests check failed"))
   return results
 
 
diff --git a/build/detect_v8_host_arch.py b/build/detect_v8_host_arch.py
new file mode 100644
index 0000000..f66383b
--- /dev/null
+++ b/build/detect_v8_host_arch.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+# Copyright 2014 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+#       copyright notice, this list of conditions and the following
+#       disclaimer in the documentation and/or other materials provided
+#       with the distribution.
+#     * Neither the name of Google Inc. nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Outputs host CPU architecture in format recognized by gyp."""
+
+import platform
+import re
+import sys
+
+
+def main():
+  print DoMain([])
+  return 0
+
+def DoMain(_):
+  """Hook to be called from gyp without starting a separate python
+  interpreter."""
+  host_arch = platform.machine()
+
+  # Convert machine type to format recognized by gyp.
+  if re.match(r'i.86', host_arch) or host_arch == 'i86pc':
+    host_arch = 'ia32'
+  elif host_arch in ['x86_64', 'amd64']:
+    host_arch = 'x64'
+  elif host_arch.startswith('arm'):
+    host_arch = 'arm'
+  elif host_arch == 'aarch64':
+    host_arch = 'arm64'
+  elif host_arch.startswith('mips'):
+    host_arch = 'mipsel'
+
+  # platform.machine is based on running kernel. It's possible to use 64-bit
+  # kernel with 32-bit userland, e.g. to give linker slightly more memory.
+  # Distinguish between different userland bitness by querying
+  # the python binary.
+  if host_arch == 'x64' and platform.architecture()[0] == '32bit':
+    host_arch = 'ia32'
+
+  return host_arch
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/build/standalone.gypi b/build/standalone.gypi
index 7670e5b..7952bdc 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -51,13 +51,7 @@
               # Anything else gets passed through, which probably won't work
               # very well; such hosts should pass an explicit target_arch
               # to gyp.
-              'host_arch%':
-                '<!(uname -m | sed -e "s/i.86/ia32/;\
-                                       s/x86_64/x64/;\
-                                       s/amd64/x64/;\
-                                       s/arm.*/arm/;\
-                                       s/aarch64/arm64/;\
-                                       s/mips.*/mipsel/")',
+              'host_arch%': '<!pymod_do_main(detect_v8_host_arch)',
             }, {
               # OS!="linux" and OS!="freebsd" and OS!="openbsd" and
               # OS!="netbsd" and OS!="mac"
diff --git a/build/toolchain.gypi b/build/toolchain.gypi
index 4e6869b..0852eac 100644
--- a/build/toolchain.gypi
+++ b/build/toolchain.gypi
@@ -348,6 +348,21 @@
         },
         'msvs_configuration_platform': 'x64',
       }],  # v8_target_arch=="x64"
+      ['v8_target_arch=="x32"', {
+        'defines': [
+          # x32 port shares the source code with x64 port.
+          'V8_TARGET_ARCH_X64',
+          'V8_TARGET_ARCH_32_BIT',
+        ],
+        'cflags': [
+          '-mx32',
+          # Inhibit warning if long long type is used.
+          '-Wno-long-long',
+        ],
+        'ldflags': [
+          '-mx32',
+        ],
+      }],  # v8_target_arch=="x32"
       ['OS=="win"', {
         'defines': [
           'WIN32',
diff --git a/include/v8.h b/include/v8.h
index 5176566..7d27029 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -5586,7 +5586,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 163;
+  static const int kEmptyStringRootIndex = 160;
 
   // The external allocation limit should be below 256 MB on all architectures
   // to avoid that resource-constrained embedders run low on memory.
@@ -6214,7 +6214,7 @@
 String::ExternalStringResource* String::GetExternalStringResource() const {
   typedef internal::Object O;
   typedef internal::Internals I;
-  O* obj = *reinterpret_cast<O**>(const_cast<String*>(this));
+  O* obj = *reinterpret_cast<O* const*>(this);
   String::ExternalStringResource* result;
   if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
     void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
@@ -6233,7 +6233,7 @@
     String::Encoding* encoding_out) const {
   typedef internal::Object O;
   typedef internal::Internals I;
-  O* obj = *reinterpret_cast<O**>(const_cast<String*>(this));
+  O* obj = *reinterpret_cast<O* const*>(this);
   int type = I::GetInstanceType(obj) & I::kFullStringRepresentationMask;
   *encoding_out = static_cast<Encoding>(type & I::kStringEncodingMask);
   ExternalStringResourceBase* resource = NULL;
@@ -6260,7 +6260,7 @@
 bool Value::QuickIsUndefined() const {
   typedef internal::Object O;
   typedef internal::Internals I;
-  O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+  O* obj = *reinterpret_cast<O* const*>(this);
   if (!I::HasHeapObjectTag(obj)) return false;
   if (I::GetInstanceType(obj) != I::kOddballType) return false;
   return (I::GetOddballKind(obj) == I::kUndefinedOddballKind);
@@ -6278,7 +6278,7 @@
 bool Value::QuickIsNull() const {
   typedef internal::Object O;
   typedef internal::Internals I;
-  O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+  O* obj = *reinterpret_cast<O* const*>(this);
   if (!I::HasHeapObjectTag(obj)) return false;
   if (I::GetInstanceType(obj) != I::kOddballType) return false;
   return (I::GetOddballKind(obj) == I::kNullOddballKind);
@@ -6296,7 +6296,7 @@
 bool Value::QuickIsString() const {
   typedef internal::Object O;
   typedef internal::Internals I;
-  O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+  O* obj = *reinterpret_cast<O* const*>(this);
   if (!I::HasHeapObjectTag(obj)) return false;
   return (I::GetInstanceType(obj) < I::kFirstNonstringType);
 }
diff --git a/src/api.cc b/src/api.cc
index fc22929..92aa745 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3432,7 +3432,7 @@
       i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
       false);
   if (result->IsUndefined()) return false;
-  if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0);
+  if (fast) i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0);
   return true;
 }
 
@@ -3600,7 +3600,7 @@
 
   i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map()));
   new_map->set_is_access_check_needed(true);
-  obj->set_map(*new_map);
+  i::JSObject::MigrateToMap(obj, new_map);
 }
 
 
diff --git a/src/api.h b/src/api.h
index 7a688ca..ccede0d 100644
--- a/src/api.h
+++ b/src/api.h
@@ -370,8 +370,7 @@
     const v8::From* that, bool allow_empty_handle) {                        \
     EXTRA_CHECK(allow_empty_handle || that != NULL);                        \
     EXTRA_CHECK(that == NULL ||                                             \
-        (*reinterpret_cast<v8::internal::Object**>(                         \
-            const_cast<v8::From*>(that)))->Is##To());                       \
+        (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \
     return v8::internal::Handle<v8::internal::To>(                          \
         reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
   }
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index 6a35d93..814bd8b 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -400,10 +400,6 @@
 // -----------------------------------------------------------------------------
 // Specific instructions, constants, and masks.
 
-// add(sp, sp, 4) instruction (aka Pop())
-const Instr kPopInstruction =
-    al | PostIndex | 4 | LeaveCC | I | kRegister_sp_Code * B16 |
-        kRegister_sp_Code * B12;
 // str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
 // register r is not encoded.
 const Instr kPushRegPattern =
@@ -412,8 +408,6 @@
 // register r is not encoded.
 const Instr kPopRegPattern =
     al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16;
-// mov lr, pc
-const Instr kMovLrPc = al | MOV | kRegister_pc_Code | kRegister_lr_Code * B12;
 // ldr rd, [pc, #offset]
 const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
 const Instr kLdrPCImmedPattern = 5 * B24 | L | kRegister_pc_Code * B16;
@@ -437,8 +431,6 @@
 const Instr kMovMvnFlip = B22;
 const Instr kMovLeaveCCMask = 0xdff * B16;
 const Instr kMovLeaveCCPattern = 0x1a0 * B16;
-const Instr kMovwMask = 0xff * B20;
-const Instr kMovwPattern = 0x30 * B20;
 const Instr kMovwLeaveCCFlip = 0x5 * B21;
 const Instr kCmpCmnMask = 0xdd * B20 | 0xf * B12;
 const Instr kCmpCmnPattern = 0x15 * B20;
@@ -456,8 +448,6 @@
 const Instr kStrRegFpNegOffsetPattern =
     al | B26 | NegOffset | kRegister_fp_Code * B16;
 const Instr kLdrStrInstrTypeMask = 0xffff0000;
-const Instr kLdrStrInstrArgumentMask = 0x0000ffff;
-const Instr kLdrStrOffsetMask = 0x00000fff;
 
 
 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
diff --git a/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index 78ab5f7..6412366 100644
--- a/src/arm/cpu-arm.cc
+++ b/src/arm/cpu-arm.cc
@@ -52,7 +52,7 @@
                                   // r0 = beg
                                   // r1 = end
                                   // r2 = flags (0)
-    "  ldr r7, =%[scno]\n"        // r7 = syscall number
+    "  ldr r7, =%c[scno]\n"       // r7 = syscall number
     "  svc 0\n"
 
     "  pop {r7}\n"
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 2d2b31c..0392997 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -2369,9 +2369,7 @@
 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
   info()->MarkAsDeferredCalling();
   LOperand* context = UseAny(instr->context());
-  LOperand* size = instr->size()->IsConstant()
-      ? UseConstant(instr->size())
-      : UseTempRegister(instr->size());
+  LOperand* size = UseRegisterOrConstant(instr->size());
   LOperand* temp1 = TempRegister();
   LOperand* temp2 = TempRegister();
   LAllocate* result = new(zone()) LAllocate(context, size, temp1, temp2);
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 36aec45..14c34ca 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -5276,33 +5276,25 @@
     }
   } else {
     Register size = ToRegister(instr->size());
-    __ Allocate(size,
-                result,
-                scratch,
-                scratch2,
-                deferred->entry(),
-                flags);
+    __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
   }
 
   __ bind(deferred->exit());
 
   if (instr->hydrogen()->MustPrefillWithFiller()) {
+    STATIC_ASSERT(kHeapObjectTag == 1);
     if (instr->size()->IsConstantOperand()) {
       int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
-      __ mov(scratch, Operand(size));
+      __ mov(scratch, Operand(size - kHeapObjectTag));
     } else {
-      scratch = ToRegister(instr->size());
+      __ sub(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag));
     }
-    __ sub(scratch, scratch, Operand(kPointerSize));
-    __ sub(result, result, Operand(kHeapObjectTag));
+    __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
     Label loop;
     __ bind(&loop);
-    __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map()));
+    __ sub(scratch, scratch, Operand(kPointerSize), SetCC);
     __ str(scratch2, MemOperand(result, scratch));
-    __ sub(scratch, scratch, Operand(kPointerSize));
-    __ cmp(scratch, Operand(0));
     __ b(ge, &loop);
-    __ add(result, result, Operand(kHeapObjectTag));
   }
 }
 
diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc
index 484bf10..ee41875 100644
--- a/src/arm64/assembler-arm64.cc
+++ b/src/arm64/assembler-arm64.cc
@@ -455,7 +455,7 @@
   // + 1 is for the crash guard.
   // + 0/1 for alignment.
   int word_count = EntryCount() * 2 + 1 +
-                   (IsAligned(assm_->pc_offset(), 8)) ? 0 : 1;
+                   (IsAligned(assm_->pc_offset(), 8) ? 0 : 1);
   assm_->Emit(LDR_x_lit                          |
               Assembler::ImmLLiteral(word_count) |
               Assembler::Rt(xzr));
diff --git a/src/arm64/debug-arm64.cc b/src/arm64/debug-arm64.cc
index 43ebd36..1a29ffb 100644
--- a/src/arm64/debug-arm64.cc
+++ b/src/arm64/debug-arm64.cc
@@ -132,12 +132,10 @@
     FrameScope scope(masm, StackFrame::INTERNAL);
 
     // Load padding words on stack.
-    __ ldr(scratch, Smi::FromInt(LiveEdit::kFramePaddingValue));
-    for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) {
-      __ push(scratch);
-    }
-    __ ldr(scratch, Smi::FromInt(LiveEdit::kFramePaddingInitialSize));
-    __ push(scratch);
+    __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingValue));
+    __ PushMultipleTimes(scratch, LiveEdit::kFramePaddingInitialSize);
+    __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingInitialSize));
+    __ Push(scratch);
 
     // Any live values (object_regs and non_object_regs) in caller-saved
     // registers (or lr) need to be stored on the stack so that their values are
@@ -360,25 +358,28 @@
   ExternalReference restarter_frame_function_slot =
       ExternalReference::debug_restarter_frame_function_pointer_address(
           masm->isolate());
-  __ mov(x1, xzr);
-  __ Mov(ip0, restarter_frame_function_slot);
-  __ str(x1, MemOperand(ip0, 0));
+  UseScratchRegisterScope temps(masm);
+  Register scratch = temps.AcquireX();
+
+  __ Mov(scratch, restarter_frame_function_slot);
+  __ Str(xzr, MemOperand(scratch));
 
   // We do not know our frame height, but set sp based on fp.
-  __ sub(jssp, fp, Operand(kPointerSize));
+  __ Sub(masm->StackPointer(), fp, kPointerSize);
+  __ AssertStackConsistency();
 
   __ Pop(x1, fp, lr);  // Function, Frame, Return address.
 
   // Load context from the function.
-  __ ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
+  __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
 
   // Get function code.
-  __ ldr(ip0, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(ip0, FieldMemOperand(ip0, SharedFunctionInfo::kCodeOffset));
-  __ add(ip0, ip0, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ Ldr(scratch, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
+  __ Ldr(scratch, FieldMemOperand(scratch, SharedFunctionInfo::kCodeOffset));
+  __ Add(scratch, scratch, Code::kHeaderSize - kHeapObjectTag);
 
   // Re-run JSFunction, x1 is function, cp is context.
-  __ Jump(ip0);
+  __ Br(scratch);
 }
 
 
diff --git a/src/ast-value-factory.cc b/src/ast-value-factory.cc
new file mode 100644
index 0000000..cb37902
--- /dev/null
+++ b/src/ast-value-factory.cc
@@ -0,0 +1,409 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/ast-value-factory.h"
+
+#include "src/api.h"
+#include "src/objects.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+// For using StringToArrayIndex.
+class OneByteStringStream {
+ public:
+  explicit OneByteStringStream(Vector<const byte> lb) :
+      literal_bytes_(lb), pos_(0) {}
+
+  bool HasMore() { return pos_ < literal_bytes_.length(); }
+  uint16_t GetNext() { return literal_bytes_[pos_++]; }
+
+ private:
+  Vector<const byte> literal_bytes_;
+  int pos_;
+};
+
+}
+
+class AstRawStringInternalizationKey : public HashTableKey {
+ public:
+  explicit AstRawStringInternalizationKey(const AstRawString* string)
+      : string_(string) {}
+
+  virtual bool IsMatch(Object* other) V8_OVERRIDE {
+    if (string_->is_one_byte_)
+      return String::cast(other)->IsOneByteEqualTo(string_->literal_bytes_);
+    return String::cast(other)->IsTwoByteEqualTo(
+        Vector<const uint16_t>::cast(string_->literal_bytes_));
+  }
+
+  virtual uint32_t Hash() V8_OVERRIDE {
+    return string_->hash() >> Name::kHashShift;
+  }
+
+  virtual uint32_t HashForObject(Object* key) V8_OVERRIDE {
+    return String::cast(key)->Hash();
+  }
+
+  virtual Handle<Object> AsHandle(Isolate* isolate) V8_OVERRIDE {
+    if (string_->is_one_byte_)
+      return isolate->factory()->NewOneByteInternalizedString(
+          string_->literal_bytes_, string_->hash());
+    return isolate->factory()->NewTwoByteInternalizedString(
+        Vector<const uint16_t>::cast(string_->literal_bytes_), string_->hash());
+  }
+
+ private:
+  const AstRawString* string_;
+};
+
+
+void AstRawString::Internalize(Isolate* isolate) {
+  if (!string_.is_null()) return;
+  if (literal_bytes_.length() == 0) {
+    string_ = isolate->factory()->empty_string();
+  } else {
+    AstRawStringInternalizationKey key(this);
+    string_ = StringTable::LookupKey(isolate, &key);
+  }
+}
+
+
+bool AstRawString::AsArrayIndex(uint32_t* index) const {
+  if (!string_.is_null())
+    return string_->AsArrayIndex(index);
+  if (!is_one_byte_ || literal_bytes_.length() == 0 ||
+      literal_bytes_.length() > String::kMaxArrayIndexSize)
+    return false;
+  OneByteStringStream stream(literal_bytes_);
+  return StringToArrayIndex(&stream, index);
+}
+
+
+bool AstRawString::IsOneByteEqualTo(const char* data) const {
+  int length = static_cast<int>(strlen(data));
+  if (is_one_byte_ && literal_bytes_.length() == length) {
+    const char* token = reinterpret_cast<const char*>(literal_bytes_.start());
+    return !strncmp(token, data, length);
+  }
+  return false;
+}
+
+
+bool AstRawString::Compare(void* a, void* b) {
+  AstRawString* string1 = reinterpret_cast<AstRawString*>(a);
+  AstRawString* string2 = reinterpret_cast<AstRawString*>(b);
+  if (string1->is_one_byte_ != string2->is_one_byte_) return false;
+  if (string1->hash_ != string2->hash_) return false;
+  int length = string1->literal_bytes_.length();
+  if (string2->literal_bytes_.length() != length) return false;
+  return memcmp(string1->literal_bytes_.start(),
+                string2->literal_bytes_.start(), length) == 0;
+}
+
+
+void AstConsString::Internalize(Isolate* isolate) {
+  // AstRawStrings are internalized before AstConsStrings so left and right are
+  // already internalized.
+  string_ = isolate->factory()
+                ->NewConsString(left_->string(), right_->string())
+                .ToHandleChecked();
+}
+
+
+bool AstValue::IsPropertyName() const {
+  if (type_ == STRING) {
+    uint32_t index;
+    return !string_->AsArrayIndex(&index);
+  }
+  return false;
+}
+
+
+bool AstValue::BooleanValue() const {
+  switch (type_) {
+    case STRING:
+      ASSERT(string_ != NULL);
+      return !string_->IsEmpty();
+    case SYMBOL:
+      UNREACHABLE();
+      break;
+    case NUMBER:
+      return DoubleToBoolean(number_);
+    case SMI:
+      return smi_ != 0;
+    case STRING_ARRAY:
+      UNREACHABLE();
+      break;
+    case BOOLEAN:
+      return bool_;
+    case NULL_TYPE:
+      return false;
+    case THE_HOLE:
+      UNREACHABLE();
+      break;
+    case UNDEFINED:
+      return false;
+  }
+  UNREACHABLE();
+  return false;
+}
+
+
+void AstValue::Internalize(Isolate* isolate) {
+  switch (type_) {
+    case STRING:
+      ASSERT(string_ != NULL);
+      // Strings are already internalized.
+      ASSERT(!string_->string().is_null());
+      break;
+    case SYMBOL:
+      value_ = Object::GetProperty(
+                   isolate, handle(isolate->native_context()->builtins()),
+                   symbol_name_).ToHandleChecked();
+      break;
+    case NUMBER:
+      value_ = isolate->factory()->NewNumber(number_, TENURED);
+      break;
+    case SMI:
+      value_ = handle(Smi::FromInt(smi_), isolate);
+      break;
+    case BOOLEAN:
+      if (bool_) {
+        value_ = isolate->factory()->true_value();
+      } else {
+        value_ = isolate->factory()->false_value();
+      }
+      break;
+    case STRING_ARRAY: {
+      ASSERT(strings_ != NULL);
+      Factory* factory = isolate->factory();
+      int len = strings_->length();
+      Handle<FixedArray> elements = factory->NewFixedArray(len, TENURED);
+      for (int i = 0; i < len; i++) {
+        const AstRawString* string = (*strings_)[i];
+        Handle<Object> element = string->string();
+        // Strings are already internalized.
+        ASSERT(!element.is_null());
+        elements->set(i, *element);
+      }
+      value_ =
+          factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
+      break;
+    }
+    case NULL_TYPE:
+      value_ = isolate->factory()->null_value();
+      break;
+    case THE_HOLE:
+      value_ = isolate->factory()->the_hole_value();
+      break;
+    case UNDEFINED:
+      value_ = isolate->factory()->undefined_value();
+      break;
+  }
+}
+
+
+const AstRawString* AstValueFactory::GetOneByteString(
+    Vector<const uint8_t> literal) {
+  uint32_t hash = StringHasher::HashSequentialString<uint8_t>(
+      literal.start(), literal.length(), hash_seed_);
+  return GetString(hash, true, literal);
+}
+
+
+const AstRawString* AstValueFactory::GetTwoByteString(
+    Vector<const uint16_t> literal) {
+  uint32_t hash = StringHasher::HashSequentialString<uint16_t>(
+      literal.start(), literal.length(), hash_seed_);
+  return GetString(hash, false, Vector<const byte>::cast(literal));
+}
+
+
+const AstRawString* AstValueFactory::GetString(Handle<String> literal) {
+  DisallowHeapAllocation no_gc;
+  String::FlatContent content = literal->GetFlatContent();
+  if (content.IsAscii()) {
+    return GetOneByteString(content.ToOneByteVector());
+  }
+  ASSERT(content.IsTwoByte());
+  return GetTwoByteString(content.ToUC16Vector());
+}
+
+
+const AstConsString* AstValueFactory::NewConsString(
+    const AstString* left, const AstString* right) {
+  // This Vector will be valid as long as the Collector is alive (meaning that
+  // the AstRawString will not be moved).
+  AstConsString* new_string = new (zone_) AstConsString(left, right);
+  strings_.Add(new_string);
+  if (isolate_) {
+    new_string->Internalize(isolate_);
+  }
+  return new_string;
+}
+
+
+void AstValueFactory::Internalize(Isolate* isolate) {
+  if (isolate_) {
+    // Everything is already internalized.
+    return;
+  }
+  // Strings need to be internalized before values, because values refer to
+  // strings.
+  for (int i = 0; i < strings_.length(); ++i) {
+    strings_[i]->Internalize(isolate);
+  }
+  for (int i = 0; i < values_.length(); ++i) {
+    values_[i]->Internalize(isolate);
+  }
+  isolate_ = isolate;
+}
+
+
+const AstValue* AstValueFactory::NewString(const AstRawString* string) {
+  AstValue* value = new (zone_) AstValue(string);
+  ASSERT(string != NULL);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewSymbol(const char* name) {
+  AstValue* value = new (zone_) AstValue(name);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewNumber(double number) {
+  AstValue* value = new (zone_) AstValue(number);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewSmi(int number) {
+  AstValue* value =
+      new (zone_) AstValue(AstValue::SMI, number);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewBoolean(bool b) {
+  AstValue* value = new (zone_) AstValue(b);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewStringList(
+    ZoneList<const AstRawString*>* strings) {
+  AstValue* value = new (zone_) AstValue(strings);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewNull() {
+  AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewUndefined() {
+  AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstValue* AstValueFactory::NewTheHole() {
+  AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE);
+  if (isolate_) {
+    value->Internalize(isolate_);
+  }
+  values_.Add(value);
+  return value;
+}
+
+
+const AstRawString* AstValueFactory::GetString(
+    uint32_t hash, bool is_one_byte, Vector<const byte> literal_bytes) {
+  // literal_bytes here points to whatever the user passed, and this is OK
+  // because we use vector_compare (which checks the contents) to compare
+  // against the AstRawStrings which are in the string_table_. We should not
+  // return this AstRawString.
+  AstRawString key(is_one_byte, literal_bytes, hash);
+  HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
+  if (entry->value == NULL) {
+    // Copy literal contents for later comparison.
+    int length = literal_bytes.length();
+    byte* new_literal_bytes = zone_->NewArray<byte>(length);
+    memcpy(new_literal_bytes, literal_bytes.start(), length);
+    AstRawString* new_string = new (zone_) AstRawString(
+        is_one_byte, Vector<const byte>(new_literal_bytes, length), hash);
+    entry->key = new_string;
+    strings_.Add(new_string);
+    if (isolate_) {
+      new_string->Internalize(isolate_);
+    }
+    entry->value = reinterpret_cast<void*>(1);
+  }
+  return reinterpret_cast<AstRawString*>(entry->key);
+}
+
+
+} }  // namespace v8::internal
diff --git a/src/ast-value-factory.h b/src/ast-value-factory.h
new file mode 100644
index 0000000..51ee277
--- /dev/null
+++ b/src/ast-value-factory.h
@@ -0,0 +1,340 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_AST_VALUE_FACTORY_H_
+#define V8_AST_VALUE_FACTORY_H_
+
+#include "src/api.h"
+#include "src/hashmap.h"
+#include "src/utils.h"
+
+// AstString, AstValue and AstValueFactory are for storing strings and values
+// independent of the V8 heap and internalizing them later. During parsing,
+// AstStrings and AstValues are created and stored outside the heap, in
+// AstValueFactory. After parsing, the strings and values are internalized
+// (moved into the V8 heap).
+namespace v8 {
+namespace internal {
+
+class AstString : public ZoneObject {
+ public:
+  virtual ~AstString() {}
+
+  virtual int length() const = 0;
+  bool IsEmpty() const { return length() == 0; }
+
+  // Puts the string into the V8 heap.
+  virtual void Internalize(Isolate* isolate) = 0;
+
+  // This function can be called after internalizing.
+  V8_INLINE Handle<String> string() const {
+    ASSERT(!string_.is_null());
+    return string_;
+  }
+
+ protected:
+  // This is null until the string is internalized.
+  Handle<String> string_;
+};
+
+
+class AstRawString : public AstString {
+ public:
+  virtual int length() const V8_OVERRIDE {
+    if (is_one_byte_)
+      return literal_bytes_.length();
+    return literal_bytes_.length() / 2;
+  }
+
+  virtual void Internalize(Isolate* isolate) V8_OVERRIDE;
+
+  bool AsArrayIndex(uint32_t* index) const;
+
+  // The string is not null-terminated, use length() to find out the length.
+  const unsigned char* raw_data() const {
+    return literal_bytes_.start();
+  }
+  bool is_one_byte() const { return is_one_byte_; }
+  bool IsOneByteEqualTo(const char* data) const;
+  uint16_t FirstCharacter() const {
+    if (is_one_byte_)
+      return literal_bytes_[0];
+    const uint16_t* c =
+        reinterpret_cast<const uint16_t*>(literal_bytes_.start());
+    return *c;
+  }
+
+  // For storing AstRawStrings in a hash map.
+  uint32_t hash() const {
+    return hash_;
+  }
+  static bool Compare(void* a, void* b);
+
+ private:
+  friend class AstValueFactory;
+  friend class AstRawStringInternalizationKey;
+
+  AstRawString(bool is_one_byte, const Vector<const byte>& literal_bytes,
+            uint32_t hash)
+      : is_one_byte_(is_one_byte), literal_bytes_(literal_bytes), hash_(hash) {}
+
+  AstRawString()
+      : is_one_byte_(true),
+        hash_(0) {}
+
+  bool is_one_byte_;
+
+  // Points to memory owned by Zone.
+  Vector<const byte> literal_bytes_;
+  uint32_t hash_;
+};
+
+
+class AstConsString : public AstString {
+ public:
+  AstConsString(const AstString* left, const AstString* right)
+      : left_(left),
+        right_(right) {}
+
+  virtual int length() const V8_OVERRIDE {
+    return left_->length() + right_->length();
+  }
+
+  virtual void Internalize(Isolate* isolate) V8_OVERRIDE;
+
+ private:
+  friend class AstValueFactory;
+
+  const AstString* left_;
+  const AstString* right_;
+};
+
+
+// AstValue is either a string, a number, a string array, a boolean, or a
+// special value (null, undefined, the hole).
+class AstValue : public ZoneObject {
+ public:
+  bool IsString() const {
+    return type_ == STRING;
+  }
+
+  bool IsNumber() const {
+    return type_ == NUMBER || type_ == SMI;
+  }
+
+  const AstRawString* AsString() const {
+    if (type_ == STRING)
+      return string_;
+    UNREACHABLE();
+    return 0;
+  }
+
+  double AsNumber() const {
+    if (type_ == NUMBER)
+      return number_;
+    if (type_ == SMI)
+      return smi_;
+    UNREACHABLE();
+    return 0;
+  }
+
+  bool EqualsString(const AstRawString* string) const {
+    return type_ == STRING && string_ == string;
+  }
+
+  bool IsPropertyName() const;
+
+  bool BooleanValue() const;
+
+  void Internalize(Isolate* isolate);
+
+  // Can be called after Internalize has been called.
+  V8_INLINE Handle<Object> value() const {
+    if (type_ == STRING) {
+      return string_->string();
+    }
+    ASSERT(!value_.is_null());
+    return value_;
+  }
+
+ private:
+  friend class AstValueFactory;
+
+  enum Type {
+    STRING,
+    SYMBOL,
+    NUMBER,
+    SMI,
+    BOOLEAN,
+    STRING_ARRAY,
+    NULL_TYPE,
+    UNDEFINED,
+    THE_HOLE
+  };
+
+  explicit AstValue(const AstRawString* s) : type_(STRING) { string_ = s; }
+
+  explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; }
+
+  explicit AstValue(double n) : type_(NUMBER) { number_ = n; }
+
+  AstValue(Type t, int i) : type_(t) {
+    ASSERT(type_ == SMI);
+    smi_ = i;
+  }
+
+  explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; }
+
+  explicit AstValue(ZoneList<const AstRawString*>* s) : type_(STRING_ARRAY) {
+    strings_ = s;
+  }
+
+  explicit AstValue(Type t) : type_(t) {
+    ASSERT(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE);
+  }
+
+  Type type_;
+
+  // Uninternalized value.
+  union {
+    const AstRawString* string_;
+    double number_;
+    int smi_;
+    bool bool_;
+    ZoneList<const AstRawString*>* strings_;
+    const char* symbol_name_;
+  };
+
+  // Internalized value (empty before internalized).
+  Handle<Object> value_;
+};
+
+
+// For generating string constants.
+#define STRING_CONSTANTS(F) \
+  F(anonymous_function, "(anonymous function)") \
+  F(arguments, "arguments") \
+  F(done, "done") \
+  F(dot, ".") \
+  F(dot_for, ".for") \
+  F(dot_generator, ".generator") \
+  F(dot_generator_object, ".generator_object") \
+  F(dot_iterable, ".iterable") \
+  F(dot_iterator, ".iterator") \
+  F(dot_module, ".module") \
+  F(dot_result, ".result") \
+  F(empty, "") \
+  F(eval, "eval") \
+  F(initialize_const_global, "initializeConstGlobal") \
+  F(initialize_var_global, "initializeVarGlobal") \
+  F(make_reference_error, "MakeReferenceError") \
+  F(make_syntax_error, "MakeSyntaxError") \
+  F(make_type_error, "MakeTypeError") \
+  F(module, "module") \
+  F(native, "native") \
+  F(next, "next") \
+  F(proto, "__proto__") \
+  F(prototype, "prototype") \
+  F(this, "this") \
+  F(use_strict, "use strict") \
+  F(value, "value")
+
+
+class AstValueFactory {
+ public:
+  AstValueFactory(Zone* zone, uint32_t hash_seed)
+      : string_table_(AstRawString::Compare),
+        zone_(zone),
+        isolate_(NULL),
+        hash_seed_(hash_seed) {
+#define F(name, str) \
+    name##_string_ = NULL;
+    STRING_CONSTANTS(F)
+#undef F
+  }
+
+  const AstRawString* GetOneByteString(Vector<const uint8_t> literal);
+  const AstRawString* GetTwoByteString(Vector<const uint16_t> literal);
+  const AstRawString* GetString(Handle<String> literal);
+  const AstConsString* NewConsString(const AstString* left,
+                                     const AstString* right);
+
+  void Internalize(Isolate* isolate);
+  bool IsInternalized() {
+    return isolate_ != NULL;
+  }
+
+#define F(name, str) \
+  const AstRawString* name##_string() { \
+    if (name##_string_ == NULL) { \
+      const char* data = str; \
+      name##_string_ = GetOneByteString( \
+          Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), \
+                                static_cast<int>(strlen(data)))); \
+    } \
+    return name##_string_; \
+  }
+  STRING_CONSTANTS(F)
+#undef F
+
+  const AstValue* NewString(const AstRawString* string);
+  // A JavaScript symbol (ECMA-262 edition 6).
+  const AstValue* NewSymbol(const char* name);
+  const AstValue* NewNumber(double number);
+  const AstValue* NewSmi(int number);
+  const AstValue* NewBoolean(bool b);
+  const AstValue* NewStringList(ZoneList<const AstRawString*>* strings);
+  const AstValue* NewNull();
+  const AstValue* NewUndefined();
+  const AstValue* NewTheHole();
+
+ private:
+  const AstRawString* GetString(uint32_t hash, bool is_one_byte,
+                                Vector<const byte> literal_bytes);
+
+  // All strings are copied here, one after another (no NULLs inbetween).
+  HashMap string_table_;
+  // For keeping track of all AstValues and AstRawStrings we've created (so that
+  // they can be internalized later).
+  List<AstValue*> values_;
+  List<AstString*> strings_;
+  Zone* zone_;
+  Isolate* isolate_;
+
+  uint32_t hash_seed_;
+
+#define F(name, str) \
+  const AstRawString* name##_string_;
+  STRING_CONSTANTS(F)
+#undef F
+};
+
+} }  // namespace v8::internal
+
+#undef STRING_CONSTANTS
+
+#endif  // V8_AST_VALUE_FACTORY_H_
diff --git a/src/ast.cc b/src/ast.cc
index 3f19fbf..53d2799 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -55,14 +55,13 @@
   // The global identifier "undefined" is immutable. Everything
   // else could be reassigned.
   return var != NULL && var->location() == Variable::UNALLOCATED &&
-         String::Equals(var_proxy->name(),
-                        isolate->factory()->undefined_string());
+         var_proxy->raw_name()->IsOneByteEqualTo("undefined");
 }
 
 
 VariableProxy::VariableProxy(Zone* zone, Variable* var, int position)
     : Expression(zone, position),
-      name_(var->name()),
+      name_(var->raw_name()),
       var_(NULL),  // Will be set by the call to BindTo.
       is_this_(var->is_this()),
       is_trivial_(false),
@@ -73,7 +72,7 @@
 
 
 VariableProxy::VariableProxy(Zone* zone,
-                             Handle<String> name,
+                             const AstRawString* name,
                              bool is_this,
                              Interface* interface,
                              int position)
@@ -84,8 +83,6 @@
       is_trivial_(false),
       is_lvalue_(false),
       interface_(interface) {
-  // Names must be canonicalized for fast equality checks.
-  ASSERT(name->IsInternalizedString());
 }
 
 
@@ -93,7 +90,7 @@
   ASSERT(var_ == NULL);  // must be bound only once
   ASSERT(var != NULL);  // must bind
   ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface()));
-  ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name()));
+  ASSERT((is_this() && var->is_this()) || name_ == var->raw_name());
   // Ideally CONST-ness should match. However, this is very hard to achieve
   // because we don't know the exact semantics of conflicting (const and
   // non-const) multiple variable declarations, const vars introduced via
@@ -180,15 +177,13 @@
 }
 
 
-ObjectLiteralProperty::ObjectLiteralProperty(
-    Zone* zone, Literal* key, Expression* value) {
+ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone,
+                                             AstValueFactory* ast_value_factory,
+                                             Literal* key, Expression* value) {
   emit_store_ = true;
   key_ = key;
   value_ = value;
-  Handle<Object> k = key->value();
-  if (k->IsInternalizedString() &&
-      String::Equals(Handle<String>::cast(k),
-                     zone->isolate()->factory()->proto_string())) {
+  if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) {
     kind_ = PROTOTYPE;
   } else if (value_->AsMaterializedLiteral() != NULL) {
     kind_ = MATERIALIZED_LITERAL;
@@ -1122,9 +1117,8 @@
     // optimize them.
     add_flag(kDontInline);
   } else if (node->function()->intrinsic_type == Runtime::INLINE &&
-      (node->name()->IsOneByteEqualTo(
-          STATIC_ASCII_VECTOR("_ArgumentsLength")) ||
-       node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
+             (node->raw_name()->IsOneByteEqualTo("_ArgumentsLength") ||
+              node->raw_name()->IsOneByteEqualTo("_Arguments"))) {
     // Don't inline the %_ArgumentsLength or %_Arguments because their
     // implementation will not work.  There is no stack frame to get them
     // from.
@@ -1139,17 +1133,17 @@
 
 
 Handle<String> Literal::ToString() {
-  if (value_->IsString()) return Handle<String>::cast(value_);
+  if (value_->IsString()) return value_->AsString()->string();
   ASSERT(value_->IsNumber());
   char arr[100];
   Vector<char> buffer(arr, ARRAY_SIZE(arr));
   const char* str;
-  if (value_->IsSmi()) {
+  if (value()->IsSmi()) {
     // Optimization only, the heap number case would subsume this.
-    SNPrintF(buffer, "%d", Smi::cast(*value_)->value());
+    SNPrintF(buffer, "%d", Smi::cast(*value())->value());
     str = arr;
   } else {
-    str = DoubleToCString(value_->Number(), buffer);
+    str = DoubleToCString(value()->Number(), buffer);
   }
   return isolate_->factory()->NewStringFromAsciiChecked(str);
 }
diff --git a/src/ast.h b/src/ast.h
index d56b972..23f9eef 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -8,6 +8,7 @@
 #include "src/v8.h"
 
 #include "src/assembler.h"
+#include "src/ast-value-factory.h"
 #include "src/factory.h"
 #include "src/feedback-slots.h"
 #include "src/interface.h"
@@ -367,11 +368,14 @@
  protected:
   Expression(Zone* zone, int pos)
       : AstNode(pos),
+        zone_(zone),
         bounds_(Bounds::Unbounded(zone)),
         id_(GetNextId(zone)),
         test_id_(GetNextId(zone)) {}
   void set_to_boolean_types(byte types) { to_boolean_types_ = types; }
 
+  Zone* zone_;
+
  private:
   Bounds bounds_;
   byte to_boolean_types_;
@@ -390,7 +394,7 @@
 
   // The labels associated with this statement. May be NULL;
   // if it is != NULL, guaranteed to contain at least one entry.
-  ZoneStringList* labels() const { return labels_; }
+  ZoneList<const AstRawString*>* labels() const { return labels_; }
 
   // Type testing & conversion.
   virtual BreakableStatement* AsBreakableStatement() V8_FINAL V8_OVERRIDE {
@@ -410,7 +414,7 @@
 
  protected:
   BreakableStatement(
-      Zone* zone, ZoneStringList* labels,
+      Zone* zone, ZoneList<const AstRawString*>* labels,
       BreakableType breakable_type, int position)
       : Statement(zone, position),
         labels_(labels),
@@ -422,7 +426,7 @@
 
 
  private:
-  ZoneStringList* labels_;
+  ZoneList<const AstRawString*>* labels_;
   BreakableType breakable_type_;
   Label break_target_;
   const BailoutId entry_id_;
@@ -453,7 +457,7 @@
 
  protected:
   Block(Zone* zone,
-        ZoneStringList* labels,
+        ZoneList<const AstRawString*>* labels,
         int capacity,
         bool is_initializer_block,
         int pos)
@@ -662,18 +666,15 @@
   DECLARE_NODE_TYPE(ModulePath)
 
   Module* module() const { return module_; }
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
 
  protected:
-  ModulePath(Zone* zone, Module* module, Handle<String> name, int pos)
-      : Module(zone, pos),
-        module_(module),
-        name_(name) {
-  }
+  ModulePath(Zone* zone, Module* module, const AstRawString* name, int pos)
+      : Module(zone, pos), module_(module), name_(name) {}
 
  private:
   Module* module_;
-  Handle<String> name_;
+  const AstRawString* name_;
 };
 
 
@@ -730,7 +731,7 @@
   Label* continue_target()  { return &continue_target_; }
 
  protected:
-  IterationStatement(Zone* zone, ZoneStringList* labels, int pos)
+  IterationStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
         body_(NULL),
         osr_entry_id_(GetNextId(zone)) {
@@ -764,7 +765,7 @@
   BailoutId BackEdgeId() const { return back_edge_id_; }
 
  protected:
-  DoWhileStatement(Zone* zone, ZoneStringList* labels, int pos)
+  DoWhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : IterationStatement(zone, labels, pos),
         cond_(NULL),
         continue_id_(GetNextId(zone)),
@@ -801,7 +802,7 @@
   BailoutId BodyId() const { return body_id_; }
 
  protected:
-  WhileStatement(Zone* zone, ZoneStringList* labels, int pos)
+  WhileStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : IterationStatement(zone, labels, pos),
         cond_(NULL),
         may_have_function_literal_(true),
@@ -852,7 +853,7 @@
   void set_loop_variable(Variable* var) { loop_variable_ = var; }
 
  protected:
-  ForStatement(Zone* zone, ZoneStringList* labels, int pos)
+  ForStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : IterationStatement(zone, labels, pos),
         init_(NULL),
         cond_(NULL),
@@ -894,11 +895,8 @@
   Expression* subject() const { return subject_; }
 
  protected:
-  ForEachStatement(Zone* zone, ZoneStringList* labels, int pos)
-      : IterationStatement(zone, labels, pos),
-        each_(NULL),
-        subject_(NULL) {
-  }
+  ForEachStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
+      : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {}
 
  private:
   Expression* each_;
@@ -934,7 +932,7 @@
   virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; }
 
  protected:
-  ForInStatement(Zone* zone, ZoneStringList* labels, int pos)
+  ForInStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : ForEachStatement(zone, labels, pos),
         for_in_type_(SLOW_FOR_IN),
         for_in_feedback_slot_(kInvalidFeedbackSlot),
@@ -1004,7 +1002,7 @@
   BailoutId BackEdgeId() const { return back_edge_id_; }
 
  protected:
-  ForOfStatement(Zone* zone, ZoneStringList* labels, int pos)
+  ForOfStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : ForEachStatement(zone, labels, pos),
         assign_iterator_(NULL),
         next_result_(NULL),
@@ -1165,7 +1163,7 @@
   ZoneList<CaseClause*>* cases() const { return cases_; }
 
  protected:
-  SwitchStatement(Zone* zone, ZoneStringList* labels, int pos)
+  SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
       : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
         tag_(NULL),
         cases_(NULL) { }
@@ -1345,26 +1343,28 @@
   DECLARE_NODE_TYPE(Literal)
 
   virtual bool IsPropertyName() const V8_OVERRIDE {
-    if (value_->IsInternalizedString()) {
-      uint32_t ignored;
-      return !String::cast(*value_)->AsArrayIndex(&ignored);
-    }
-    return false;
+    return value_->IsPropertyName();
   }
 
   Handle<String> AsPropertyName() {
     ASSERT(IsPropertyName());
-    return Handle<String>::cast(value_);
+    return Handle<String>::cast(value());
+  }
+
+  const AstRawString* AsRawPropertyName() {
+    ASSERT(IsPropertyName());
+    return value_->AsString();
   }
 
   virtual bool ToBooleanIsTrue() const V8_OVERRIDE {
-    return value_->BooleanValue();
+    return value()->BooleanValue();
   }
   virtual bool ToBooleanIsFalse() const V8_OVERRIDE {
-    return !value_->BooleanValue();
+    return !value()->BooleanValue();
   }
 
-  Handle<Object> value() const { return value_; }
+  Handle<Object> value() const { return value_->value(); }
+  const AstValue* raw_value() const { return value_; }
 
   // Support for using Literal as a HashMap key. NOTE: Currently, this works
   // only for string and number literals!
@@ -1379,7 +1379,7 @@
   TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }
 
  protected:
-  Literal(Zone* zone, Handle<Object> value, int position)
+  Literal(Zone* zone, const AstValue* value, int position)
       : Expression(zone, position),
         value_(value),
         isolate_(zone->isolate()) { }
@@ -1387,7 +1387,7 @@
  private:
   Handle<String> ToString();
 
-  Handle<Object> value_;
+  const AstValue* value_;
   // TODO(dcarney): remove.  this is only needed for Match and Hash.
   Isolate* isolate_;
 };
@@ -1458,7 +1458,8 @@
     PROTOTYPE              // Property is __proto__.
   };
 
-  ObjectLiteralProperty(Zone* zone, Literal* key, Expression* value);
+  ObjectLiteralProperty(Zone* zone, AstValueFactory* ast_value_factory,
+                        Literal* key, Expression* value);
 
   Literal* key() { return key_; }
   Expression* value() { return value_; }
@@ -1557,13 +1558,13 @@
  public:
   DECLARE_NODE_TYPE(RegExpLiteral)
 
-  Handle<String> pattern() const { return pattern_; }
-  Handle<String> flags() const { return flags_; }
+  Handle<String> pattern() const { return pattern_->string(); }
+  Handle<String> flags() const { return flags_->string(); }
 
  protected:
   RegExpLiteral(Zone* zone,
-                Handle<String> pattern,
-                Handle<String> flags,
+                const AstRawString* pattern,
+                const AstRawString* flags,
                 int literal_index,
                 int pos)
       : MaterializedLiteral(zone, literal_index, pos),
@@ -1573,8 +1574,8 @@
   }
 
  private:
-  Handle<String> pattern_;
-  Handle<String> flags_;
+  const AstRawString* pattern_;
+  const AstRawString* flags_;
 };
 
 
@@ -1625,15 +1626,12 @@
     return var_ == NULL ? true : var_->IsValidReference();
   }
 
-  bool IsVariable(Handle<String> n) const {
-    return !is_this() && name().is_identical_to(n);
-  }
-
   bool IsArguments() const { return var_ != NULL && var_->is_arguments(); }
 
   bool IsLValue() const { return is_lvalue_; }
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
+  const AstRawString* raw_name() const { return name_; }
   Variable* var() const { return var_; }
   bool is_this() const { return is_this_; }
   Interface* interface() const { return interface_; }
@@ -1649,12 +1647,12 @@
   VariableProxy(Zone* zone, Variable* var, int position);
 
   VariableProxy(Zone* zone,
-                Handle<String> name,
+                const AstRawString* name,
                 bool is_this,
                 Interface* interface,
                 int position);
 
-  Handle<String> name_;
+  const AstRawString* name_;
   Variable* var_;  // resolved variable, or NULL
   bool is_this_;
   bool is_trivial_;
@@ -1900,7 +1898,8 @@
  public:
   DECLARE_NODE_TYPE(CallRuntime)
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return raw_name_->string(); }
+  const AstRawString* raw_name() const { return raw_name_; }
   const Runtime::Function* function() const { return function_; }
   ZoneList<Expression*>* arguments() const { return arguments_; }
   bool is_jsruntime() const { return function_ == NULL; }
@@ -1909,17 +1908,17 @@
 
  protected:
   CallRuntime(Zone* zone,
-              Handle<String> name,
+              const AstRawString* name,
               const Runtime::Function* function,
               ZoneList<Expression*>* arguments,
               int pos)
       : Expression(zone, pos),
-        name_(name),
+        raw_name_(name),
         function_(function),
         arguments_(arguments) { }
 
  private:
-  Handle<String> name_;
+  const AstRawString* raw_name_;
   const Runtime::Function* function_;
   ZoneList<Expression*>* arguments_;
 };
@@ -2313,7 +2312,8 @@
 
   DECLARE_NODE_TYPE(FunctionLiteral)
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return raw_name_->string(); }
+  const AstRawString* raw_name() const { return raw_name_; }
   Scope* scope() const { return scope_; }
   ZoneList<Statement*>* body() const { return body_; }
   void set_function_token_position(int pos) { function_token_position_ = pos; }
@@ -2336,13 +2336,37 @@
   void InitializeSharedInfo(Handle<Code> code);
 
   Handle<String> debug_name() const {
-    if (name_->length() > 0) return name_;
+    if (raw_name_ != NULL && !raw_name_->IsEmpty()) {
+      return raw_name_->string();
+    }
     return inferred_name();
   }
 
-  Handle<String> inferred_name() const { return inferred_name_; }
+  Handle<String> inferred_name() const {
+    if (!inferred_name_.is_null()) {
+      ASSERT(raw_inferred_name_ == NULL);
+      return inferred_name_;
+    }
+    if (raw_inferred_name_ != NULL) {
+      return raw_inferred_name_->string();
+    }
+    UNREACHABLE();
+    return Handle<String>();
+  }
+
+  // Only one of {set_inferred_name, set_raw_inferred_name} should be called.
   void set_inferred_name(Handle<String> inferred_name) {
+    ASSERT(!inferred_name.is_null());
     inferred_name_ = inferred_name;
+    ASSERT(raw_inferred_name_== NULL || raw_inferred_name_->IsEmpty());
+    raw_inferred_name_ = NULL;
+  }
+
+  void set_raw_inferred_name(const AstString* raw_inferred_name) {
+    ASSERT(raw_inferred_name != NULL);
+    raw_inferred_name_ = raw_inferred_name;
+    ASSERT(inferred_name_.is_null());
+    inferred_name_ = Handle<String>();
   }
 
   // shared_info may be null if it's not cached in full code.
@@ -2389,7 +2413,8 @@
 
  protected:
   FunctionLiteral(Zone* zone,
-                  Handle<String> name,
+                  const AstRawString* name,
+                  AstValueFactory* ast_value_factory,
                   Scope* scope,
                   ZoneList<Statement*>* body,
                   int materialized_literal_count,
@@ -2403,10 +2428,10 @@
                   IsGeneratorFlag is_generator,
                   int position)
       : Expression(zone, position),
-        name_(name),
+        raw_name_(name),
         scope_(scope),
         body_(body),
-        inferred_name_(zone->isolate()->factory()->empty_string()),
+        raw_inferred_name_(ast_value_factory->empty_string()),
         dont_optimize_reason_(kNoReason),
         materialized_literal_count_(materialized_literal_count),
         expected_property_count_(expected_property_count),
@@ -2424,10 +2449,12 @@
   }
 
  private:
+  const AstRawString* raw_name_;
   Handle<String> name_;
   Handle<SharedFunctionInfo> shared_info_;
   Scope* scope_;
   ZoneList<Statement*>* body_;
+  const AstString* raw_inferred_name_;
   Handle<String> inferred_name_;
   AstProperties ast_properties_;
   BailoutReason dont_optimize_reason_;
@@ -2453,16 +2480,16 @@
  public:
   DECLARE_NODE_TYPE(NativeFunctionLiteral)
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
   v8::Extension* extension() const { return extension_; }
 
  protected:
-  NativeFunctionLiteral(
-      Zone* zone, Handle<String> name, v8::Extension* extension, int pos)
+  NativeFunctionLiteral(Zone* zone, const AstRawString* name,
+                        v8::Extension* extension, int pos)
       : Expression(zone, pos), name_(name), extension_(extension) {}
 
  private:
-  Handle<String> name_;
+  const AstRawString* name_;
   v8::Extension* extension_;
 };
 
@@ -2954,7 +2981,8 @@
 template<class Visitor>
 class AstNodeFactory V8_FINAL BASE_EMBEDDED {
  public:
-  explicit AstNodeFactory(Zone* zone) : zone_(zone) { }
+  explicit AstNodeFactory(Zone* zone, AstValueFactory* ast_value_factory)
+      : zone_(zone), ast_value_factory_(ast_value_factory) {}
 
   Visitor* visitor() { return &visitor_; }
 
@@ -3018,8 +3046,8 @@
     VISIT_AND_RETURN(ModuleVariable, module)
   }
 
-  ModulePath* NewModulePath(Module* origin, Handle<String> name, int pos) {
-    ModulePath* module = new(zone_) ModulePath(zone_, origin, name, pos);
+  ModulePath* NewModulePath(Module* origin, const AstRawString* name, int pos) {
+    ModulePath* module = new (zone_) ModulePath(zone_, origin, name, pos);
     VISIT_AND_RETURN(ModulePath, module)
   }
 
@@ -3028,7 +3056,7 @@
     VISIT_AND_RETURN(ModuleUrl, module)
   }
 
-  Block* NewBlock(ZoneStringList* labels,
+  Block* NewBlock(ZoneList<const AstRawString*>* labels,
                   int capacity,
                   bool is_initializer_block,
                   int pos) {
@@ -3038,7 +3066,7 @@
   }
 
 #define STATEMENT_WITH_LABELS(NodeType) \
-  NodeType* New##NodeType(ZoneStringList* labels, int pos) { \
+  NodeType* New##NodeType(ZoneList<const AstRawString*>* labels, int pos) { \
     NodeType* stmt = new(zone_) NodeType(zone_, labels, pos); \
     VISIT_AND_RETURN(NodeType, stmt); \
   }
@@ -3049,7 +3077,7 @@
 #undef STATEMENT_WITH_LABELS
 
   ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode,
-                                        ZoneStringList* labels,
+                                        ZoneList<const AstRawString*>* labels,
                                         int pos) {
     switch (visit_mode) {
       case ForEachStatement::ENUMERATE: {
@@ -3146,14 +3174,60 @@
     VISIT_AND_RETURN(CaseClause, clause)
   }
 
-  Literal* NewLiteral(Handle<Object> handle, int pos) {
-    Literal* lit = new(zone_) Literal(zone_, handle, pos);
+  Literal* NewStringLiteral(const AstRawString* string, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewString(string), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  // A JavaScript symbol (ECMA-262 edition 6).
+  Literal* NewSymbolLiteral(const char* name, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos);
     VISIT_AND_RETURN(Literal, lit)
   }
 
   Literal* NewNumberLiteral(double number, int pos) {
-    return NewLiteral(
-        zone_->isolate()->factory()->NewNumber(number, TENURED), pos);
+    Literal* lit = new (zone_)
+        Literal(zone_, ast_value_factory_->NewNumber(number), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewSmiLiteral(int number, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewBooleanLiteral(bool b, int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewStringListLiteral(ZoneList<const AstRawString*>* strings,
+                                int pos) {
+    Literal* lit = new (zone_)
+        Literal(zone_, ast_value_factory_->NewStringList(strings), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewNullLiteral(int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewUndefinedLiteral(int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos);
+    VISIT_AND_RETURN(Literal, lit)
+  }
+
+  Literal* NewTheHoleLiteral(int pos) {
+    Literal* lit =
+        new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos);
+    VISIT_AND_RETURN(Literal, lit)
   }
 
   ObjectLiteral* NewObjectLiteral(
@@ -3170,7 +3244,8 @@
 
   ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key,
                                                     Expression* value) {
-    return new(zone_) ObjectLiteral::Property(zone_, key, value);
+    return new (zone_)
+        ObjectLiteral::Property(zone_, ast_value_factory_, key, value);
   }
 
   ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter,
@@ -3178,12 +3253,12 @@
                                                     int pos) {
     ObjectLiteral::Property* prop =
         new(zone_) ObjectLiteral::Property(zone_, is_getter, value);
-    prop->set_key(NewLiteral(value->name(), pos));
+    prop->set_key(NewStringLiteral(value->raw_name(), pos));
     return prop;  // Not an AST node, will not be visited.
   }
 
-  RegExpLiteral* NewRegExpLiteral(Handle<String> pattern,
-                                  Handle<String> flags,
+  RegExpLiteral* NewRegExpLiteral(const AstRawString* pattern,
+                                  const AstRawString* flags,
                                   int literal_index,
                                   int pos) {
     RegExpLiteral* lit =
@@ -3205,7 +3280,7 @@
     VISIT_AND_RETURN(VariableProxy, proxy)
   }
 
-  VariableProxy* NewVariableProxy(Handle<String> name,
+  VariableProxy* NewVariableProxy(const AstRawString* name,
                                   bool is_this,
                                   Interface* interface = Interface::NewValue(),
                                   int position = RelocInfo::kNoPosition) {
@@ -3233,7 +3308,7 @@
     VISIT_AND_RETURN(CallNew, call)
   }
 
-  CallRuntime* NewCallRuntime(Handle<String> name,
+  CallRuntime* NewCallRuntime(const AstRawString* name,
                               const Runtime::Function* function,
                               ZoneList<Expression*>* arguments,
                               int pos) {
@@ -3311,7 +3386,8 @@
   }
 
   FunctionLiteral* NewFunctionLiteral(
-      Handle<String> name,
+      const AstRawString* name,
+      AstValueFactory* ast_value_factory,
       Scope* scope,
       ZoneList<Statement*>* body,
       int materialized_literal_count,
@@ -3325,7 +3401,7 @@
       FunctionLiteral::IsGeneratorFlag is_generator,
       int position) {
     FunctionLiteral* lit = new(zone_) FunctionLiteral(
-        zone_, name, scope, body,
+        zone_, name, ast_value_factory, scope, body,
         materialized_literal_count, expected_property_count, handler_count,
         parameter_count, function_type, has_duplicate_parameters, is_function,
         is_parenthesized, is_generator, position);
@@ -3337,7 +3413,8 @@
   }
 
   NativeFunctionLiteral* NewNativeFunctionLiteral(
-      Handle<String> name, v8::Extension* extension, int pos) {
+      const AstRawString* name, v8::Extension* extension,
+      int pos) {
     NativeFunctionLiteral* lit =
         new(zone_) NativeFunctionLiteral(zone_, name, extension, pos);
     VISIT_AND_RETURN(NativeFunctionLiteral, lit)
@@ -3353,6 +3430,7 @@
  private:
   Zone* zone_;
   Visitor visitor_;
+  AstValueFactory* ast_value_factory_;
 };
 
 
diff --git a/src/base/build_config.h b/src/base/build_config.h
index e412b92d..bdee4b4 100644
--- a/src/base/build_config.h
+++ b/src/base/build_config.h
@@ -24,7 +24,11 @@
 #define V8_HOST_CAN_READ_UNALIGNED 1
 #else
 #define V8_HOST_ARCH_X64 1
+#if defined(__x86_64__) && !defined(__LP64__)
+#define V8_HOST_ARCH_32_BIT 1
+#else
 #define V8_HOST_ARCH_64_BIT 1
+#endif
 #define V8_HOST_CAN_READ_UNALIGNED 1
 #endif  // __native_client__
 #elif defined(_M_IX86) || defined(__i386__)
@@ -75,13 +79,41 @@
 #endif
 #endif
 
+// Determine architecture pointer size.
+#if V8_TARGET_ARCH_IA32
+#define V8_TARGET_ARCH_32_BIT 1
+#elif V8_TARGET_ARCH_X64
+#if !V8_TARGET_ARCH_32_BIT && !V8_TARGET_ARCH_64_BIT
+#if defined(__x86_64__) && !defined(__LP64__)
+#define V8_TARGET_ARCH_32_BIT 1
+#else
+#define V8_TARGET_ARCH_64_BIT 1
+#endif
+#endif
+#elif V8_TARGET_ARCH_ARM
+#define V8_TARGET_ARCH_32_BIT 1
+#elif V8_TARGET_ARCH_ARM64
+#define V8_TARGET_ARCH_64_BIT 1
+#elif V8_TARGET_ARCH_MIPS
+#define V8_TARGET_ARCH_32_BIT 1
+#elif V8_TARGET_ARCH_X87
+#define V8_TARGET_ARCH_32_BIT 1
+#else
+#error Unknown target architecture pointer size
+#endif
+
 // Check for supported combinations of host and target architectures.
 #if V8_TARGET_ARCH_IA32 && !V8_HOST_ARCH_IA32
 #error Target architecture ia32 is only supported on ia32 host
 #endif
-#if V8_TARGET_ARCH_X64 && !V8_HOST_ARCH_X64
+#if (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT && \
+     !(V8_HOST_ARCH_X64 && V8_HOST_ARCH_64_BIT))
 #error Target architecture x64 is only supported on x64 host
 #endif
+#if (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT && \
+     !(V8_HOST_ARCH_X64 && V8_HOST_ARCH_32_BIT))
+#error Target architecture x32 is only supported on x64 host with x32 support
+#endif
 #if (V8_TARGET_ARCH_ARM && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_ARM))
 #error Target architecture arm is only supported on arm and ia32 host
 #endif
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 7dc4100..771b5b2 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -342,10 +342,10 @@
 
 static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
   // object.__proto__ = proto;
-  Handle<Map> old_to_map = Handle<Map>(object->map());
-  Handle<Map> new_to_map = Map::Copy(old_to_map);
-  new_to_map->set_prototype(*proto);
-  object->set_map(*new_to_map);
+  Handle<Map> old_map = Handle<Map>(object->map());
+  Handle<Map> new_map = Map::Copy(old_map);
+  new_map->set_prototype(*proto);
+  JSObject::MigrateToMap(object, new_map);
 }
 
 
@@ -2540,10 +2540,8 @@
   TransferIndexedProperties(from, to);
 
   // Transfer the prototype (new map is needed).
-  Handle<Map> old_to_map = Handle<Map>(to->map());
-  Handle<Map> new_to_map = Map::Copy(old_to_map);
-  new_to_map->set_prototype(from->map()->prototype());
-  to->set_map(*new_to_map);
+  Handle<Object> proto(from->map()->prototype(), isolate());
+  SetObjectPrototype(to, proto);
 }
 
 
diff --git a/src/collection.js b/src/collection.js
index a1342a3..8ddf8e1 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -12,15 +12,64 @@
 var $Map = global.Map;
 
 
+// TODO(arv): Move these general functions to v8natives.js when Map and Set are
+// no longer experimental.
+
+
+// 7.4.1 CheckIterable ( obj )
+function ToIterable(obj) {
+  if (!IS_SPEC_OBJECT(obj)) {
+    return UNDEFINED;
+  }
+  return obj[symbolIterator];
+}
+
+
+// 7.4.2 GetIterator ( obj, method )
+function GetIterator(obj, method) {
+  if (IS_UNDEFINED(method)) {
+    method = ToIterable(obj);
+  }
+  if (!IS_SPEC_FUNCTION(method)) {
+    throw MakeTypeError('not_iterable', [obj]);
+  }
+  var iterator = %_CallFunction(obj, method);
+  if (!IS_SPEC_OBJECT(iterator)) {
+    throw MakeTypeError('not_an_iterator', [iterator]);
+  }
+  return iterator;
+}
+
+
 // -------------------------------------------------------------------
 // Harmony Set
 
-function SetConstructor() {
-  if (%_IsConstructCall()) {
-    %SetInitialize(this);
-  } else {
+function SetConstructor(iterable) {
+  if (!%_IsConstructCall()) {
     throw MakeTypeError('constructor_not_function', ['Set']);
   }
+
+  var iter, adder;
+
+  if (!IS_NULL_OR_UNDEFINED(iterable)) {
+    iter = GetIterator(iterable);
+    adder = this.add;
+    if (!IS_SPEC_FUNCTION(adder)) {
+      throw MakeTypeError('property_not_function', ['add', this]);
+    }
+  }
+
+  %SetInitialize(this);
+
+  if (IS_UNDEFINED(iter)) return;
+
+  var next, done;
+  while (!(next = iter.next()).done) {
+    if (!IS_SPEC_OBJECT(next)) {
+      throw MakeTypeError('iterator_result_not_an_object', [next]);
+    }
+    %_CallFunction(this, next.value, adder);
+  }
 }
 
 
@@ -117,12 +166,36 @@
 // -------------------------------------------------------------------
 // Harmony Map
 
-function MapConstructor() {
-  if (%_IsConstructCall()) {
-    %MapInitialize(this);
-  } else {
+function MapConstructor(iterable) {
+  if (!%_IsConstructCall()) {
     throw MakeTypeError('constructor_not_function', ['Map']);
   }
+
+  var iter, adder;
+
+  if (!IS_NULL_OR_UNDEFINED(iterable)) {
+    iter = GetIterator(iterable);
+    adder = this.set;
+    if (!IS_SPEC_FUNCTION(adder)) {
+      throw MakeTypeError('property_not_function', ['set', this]);
+    }
+  }
+
+  %MapInitialize(this);
+
+  if (IS_UNDEFINED(iter)) return;
+
+  var next, done, nextItem;
+  while (!(next = iter.next()).done) {
+    if (!IS_SPEC_OBJECT(next)) {
+      throw MakeTypeError('iterator_result_not_an_object', [next]);
+    }
+    nextItem = next.value;
+    if (!IS_SPEC_OBJECT(nextItem)) {
+      throw MakeTypeError('iterator_value_not_an_object', [nextItem]);
+    }
+    %_CallFunction(this, nextItem[0], nextItem[1], adder);
+  }
 }
 
 
diff --git a/src/compiler.cc b/src/compiler.cc
index 1d6fb1f..d9fb4a9 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -38,7 +38,9 @@
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL),
+      ast_value_factory_owned_(false) {
   Initialize(script->GetIsolate(), BASE, zone);
 }
 
@@ -51,7 +53,9 @@
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL),
+      ast_value_factory_owned_(false) {
   Initialize(script_->GetIsolate(), BASE, zone);
 }
 
@@ -66,7 +70,9 @@
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL),
+      ast_value_factory_owned_(false) {
   Initialize(script_->GetIsolate(), BASE, zone);
 }
 
@@ -78,7 +84,9 @@
       osr_ast_id_(BailoutId::None()),
       parameter_count_(0),
       this_has_uses_(true),
-      optimization_id_(-1) {
+      optimization_id_(-1),
+      ast_value_factory_(NULL),
+      ast_value_factory_owned_(false) {
   Initialize(isolate, STUB, zone);
   code_stub_ = stub;
 }
@@ -131,6 +139,7 @@
 CompilationInfo::~CompilationInfo() {
   delete deferred_handles_;
   delete no_frame_ranges_;
+  if (ast_value_factory_owned_) delete ast_value_factory_;
 #ifdef DEBUG
   // Check that no dependent maps have been added or added dependent maps have
   // been rolled back or committed.
diff --git a/src/compiler.h b/src/compiler.h
index 6531474..fdb7900 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -12,6 +12,7 @@
 namespace v8 {
 namespace internal {
 
+class AstValueFactory;
 class ScriptData;
 class HydrogenCodeStub;
 
@@ -321,6 +322,13 @@
 
   int optimization_id() const { return optimization_id_; }
 
+  AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
+  void SetAstValueFactory(AstValueFactory* ast_value_factory,
+                          bool owned = true) {
+    ast_value_factory_ = ast_value_factory;
+    ast_value_factory_owned_ = owned;
+  }
+
  protected:
   CompilationInfo(Handle<Script> script,
                   Zone* zone);
@@ -464,6 +472,9 @@
 
   int optimization_id_;
 
+  AstValueFactory* ast_value_factory_;
+  bool ast_value_factory_owned_;
+
   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
 };
 
diff --git a/src/execution.h b/src/execution.h
index 74d0feb..81fbbb8 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -227,7 +227,7 @@
   void EnableInterrupts();
   void DisableInterrupts();
 
-#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
+#if V8_TARGET_ARCH_64_BIT
   static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
   static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
 #else
diff --git a/src/factory.cc b/src/factory.cc
index 1996e73..6618357 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1818,8 +1818,15 @@
   // before object re-initialization is finished and filler object is installed.
   DisallowHeapAllocation no_allocation;
 
+  // Put in filler if the new object is smaller than the old.
+  if (size_difference > 0) {
+    Address address = object->address() + map->instance_size();
+    heap->CreateFillerObjectAt(address, size_difference);
+    heap->AdjustLiveBytes(address, -size_difference, Heap::FROM_MUTATOR);
+  }
+
   // Reset the map for the object.
-  object->set_map(*map);
+  object->synchronized_set_map(*map);
   Handle<JSObject> jsobj = Handle<JSObject>::cast(object);
 
   // Reinitialize the object from the constructor map.
@@ -1832,12 +1839,6 @@
     Handle<Context> context(isolate()->context()->native_context());
     InitializeFunction(js_function, shared.ToHandleChecked(), context);
   }
-
-  // Put in filler if the new object is smaller than the old.
-  if (size_difference > 0) {
-    heap->CreateFillerObjectAt(
-        object->address() + map->instance_size(), size_difference);
-  }
 }
 
 
@@ -1863,7 +1864,7 @@
   DisallowHeapAllocation no_allocation;
 
   // Reset the map for the object.
-  object->set_map(constructor->initial_map());
+  object->synchronized_set_map(*map);
 
   Heap* heap = isolate()->heap();
   // Reinitialize the object from the constructor map.
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 32241c2..088a9c9 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -328,7 +328,6 @@
   code->set_allow_osr_at_loop_nesting_level(0);
   code->set_profiler_ticks(0);
   code->set_back_edge_table_offset(table_offset);
-  code->set_back_edges_patched_for_osr(false);
   CodeGenerator::PrintCode(code, info);
   info->SetCode(code);
 #ifdef ENABLE_GDB_JIT_INTERFACE
@@ -348,7 +347,7 @@
   // The back edge table consists of a length (in number of entries)
   // field, and then a sequence of entries.  Each entry is a pair of AST id
   // and code-relative pc offset.
-  masm()->Align(kIntSize);
+  masm()->Align(kPointerSize);
   unsigned offset = masm()->pc_offset();
   unsigned length = back_edges_.length();
   __ dd(length);
@@ -1617,9 +1616,11 @@
   DisallowHeapAllocation no_gc;
   Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
 
-  // Iterate over the back edge table and patch every interrupt
+  // Increment loop nesting level by one and iterate over the back edge table
+  // to find the matching loops to patch the interrupt
   // call to an unconditional call to the replacement code.
-  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
+  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1;
+  if (loop_nesting_level > Code::kMaxLoopNestingMarker) return;
 
   BackEdgeTable back_edges(unoptimized, &no_gc);
   for (uint32_t i = 0; i < back_edges.length(); i++) {
@@ -1631,8 +1632,8 @@
     }
   }
 
-  unoptimized->set_back_edges_patched_for_osr(true);
-  ASSERT(Verify(isolate, unoptimized, loop_nesting_level));
+  unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level);
+  ASSERT(Verify(isolate, unoptimized));
 }
 
 
@@ -1641,7 +1642,6 @@
   Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);
 
   // Iterate over the back edge table and revert the patched interrupt calls.
-  ASSERT(unoptimized->back_edges_patched_for_osr());
   int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
 
   BackEdgeTable back_edges(unoptimized, &no_gc);
@@ -1654,10 +1654,9 @@
     }
   }
 
-  unoptimized->set_back_edges_patched_for_osr(false);
   unoptimized->set_allow_osr_at_loop_nesting_level(0);
   // Assert that none of the back edges are patched anymore.
-  ASSERT(Verify(isolate, unoptimized, -1));
+  ASSERT(Verify(isolate, unoptimized));
 }
 
 
@@ -1683,10 +1682,9 @@
 
 
 #ifdef DEBUG
-bool BackEdgeTable::Verify(Isolate* isolate,
-                           Code* unoptimized,
-                           int loop_nesting_level) {
+bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
   DisallowHeapAllocation no_gc;
+  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
   BackEdgeTable back_edges(unoptimized, &no_gc);
   for (uint32_t i = 0; i < back_edges.length(); i++) {
     uint32_t loop_depth = back_edges.loop_depth(i);
diff --git a/src/full-codegen.h b/src/full-codegen.h
index bd6aa13..cede9ac 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -890,10 +890,8 @@
     OSR_AFTER_STACK_CHECK
   };
 
-  // Patch all interrupts with allowed loop depth in the unoptimized code to
-  // unconditionally call replacement_code.
-  static void Patch(Isolate* isolate,
-                    Code* unoptimized_code);
+  // Increase allowed loop nesting level by one and patch those matching loops.
+  static void Patch(Isolate* isolate, Code* unoptimized_code);
 
   // Patch the back edge to the target state, provided the correct callee.
   static void PatchAt(Code* unoptimized_code,
@@ -919,9 +917,7 @@
 
 #ifdef DEBUG
   // Verify that all back edges of a certain loop depth are patched.
-  static bool Verify(Isolate* isolate,
-                     Code* unoptimized_code,
-                     int loop_nesting_level);
+  static bool Verify(Isolate* isolate, Code* unoptimized_code);
 #endif  // DEBUG
 
  private:
diff --git a/src/func-name-inferrer.cc b/src/func-name-inferrer.cc
index a3c2f08..b3a64b2 100644
--- a/src/func-name-inferrer.cc
+++ b/src/func-name-inferrer.cc
@@ -5,14 +5,16 @@
 #include "src/v8.h"
 
 #include "src/ast.h"
+#include "src/ast-value-factory.h"
 #include "src/func-name-inferrer.h"
 #include "src/list-inl.h"
 
 namespace v8 {
 namespace internal {
 
-FuncNameInferrer::FuncNameInferrer(Isolate* isolate, Zone* zone)
-    : isolate_(isolate),
+FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory,
+                                   Zone* zone)
+    : ast_value_factory_(ast_value_factory),
       entries_stack_(10, zone),
       names_stack_(5, zone),
       funcs_to_infer_(4, zone),
@@ -20,40 +22,36 @@
 }
 
 
-void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
+void FuncNameInferrer::PushEnclosingName(const AstRawString* name) {
   // Enclosing name is a name of a constructor function. To check
   // that it is really a constructor, we check that it is not empty
   // and starts with a capital letter.
-  if (name->length() > 0 && Runtime::IsUpperCaseChar(
-          isolate()->runtime_state(), name->Get(0))) {
+  if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) {
     names_stack_.Add(Name(name, kEnclosingConstructorName), zone());
   }
 }
 
 
-void FuncNameInferrer::PushLiteralName(Handle<String> name) {
-  if (IsOpen() &&
-      !String::Equals(isolate()->factory()->prototype_string(), name)) {
+void FuncNameInferrer::PushLiteralName(const AstRawString* name) {
+  if (IsOpen() && name != ast_value_factory_->prototype_string()) {
     names_stack_.Add(Name(name, kLiteralName), zone());
   }
 }
 
 
-void FuncNameInferrer::PushVariableName(Handle<String> name) {
-  if (IsOpen() &&
-      !String::Equals(isolate()->factory()->dot_result_string(), name)) {
+void FuncNameInferrer::PushVariableName(const AstRawString* name) {
+  if (IsOpen() && name != ast_value_factory_->dot_result_string()) {
     names_stack_.Add(Name(name, kVariableName), zone());
   }
 }
 
 
-Handle<String> FuncNameInferrer::MakeNameFromStack() {
-  return MakeNameFromStackHelper(0, isolate()->factory()->empty_string());
+const AstString* FuncNameInferrer::MakeNameFromStack() {
+  return MakeNameFromStackHelper(0, ast_value_factory_->empty_string());
 }
 
-
-Handle<String> FuncNameInferrer::MakeNameFromStackHelper(int pos,
-                                                         Handle<String> prev) {
+const AstString* FuncNameInferrer::MakeNameFromStackHelper(
+    int pos, const AstString* prev) {
   if (pos >= names_stack_.length()) return prev;
   if (pos < names_stack_.length() - 1 &&
       names_stack_.at(pos).type == kVariableName &&
@@ -62,12 +60,11 @@
     return MakeNameFromStackHelper(pos + 1, prev);
   } else {
     if (prev->length() > 0) {
-      Handle<String> name = names_stack_.at(pos).name;
+      const AstRawString* name = names_stack_.at(pos).name;
       if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
-      Factory* factory = isolate()->factory();
-      Handle<String> curr =
-          factory->NewConsString(factory->dot_string(), name).ToHandleChecked();
-      curr = factory->NewConsString(prev, curr).ToHandleChecked();
+      const AstConsString* curr = ast_value_factory_->NewConsString(
+          ast_value_factory_->dot_string(), name);
+      curr = ast_value_factory_->NewConsString(prev, curr);
       return MakeNameFromStackHelper(pos + 1, curr);
     } else {
       return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
@@ -77,9 +74,9 @@
 
 
 void FuncNameInferrer::InferFunctionsNames() {
-  Handle<String> func_name = MakeNameFromStack();
+  const AstString* func_name = MakeNameFromStack();
   for (int i = 0; i < funcs_to_infer_.length(); ++i) {
-    funcs_to_infer_[i]->set_inferred_name(func_name);
+    funcs_to_infer_[i]->set_raw_inferred_name(func_name);
   }
   funcs_to_infer_.Rewind(0);
 }
diff --git a/src/func-name-inferrer.h b/src/func-name-inferrer.h
index 0c5399c..43ef761 100644
--- a/src/func-name-inferrer.h
+++ b/src/func-name-inferrer.h
@@ -11,8 +11,10 @@
 namespace v8 {
 namespace internal {
 
+class AstRawString;
+class AstString;
+class AstValueFactory;
 class FunctionLiteral;
-class Isolate;
 
 // FuncNameInferrer is a stateful class that is used to perform name
 // inference for anonymous functions during static analysis of source code.
@@ -26,13 +28,13 @@
 // a name.
 class FuncNameInferrer : public ZoneObject {
  public:
-  FuncNameInferrer(Isolate* isolate, Zone* zone);
+  FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
 
   // Returns whether we have entered name collection state.
   bool IsOpen() const { return !entries_stack_.is_empty(); }
 
   // Pushes an enclosing the name of enclosing function onto names stack.
-  void PushEnclosingName(Handle<String> name);
+  void PushEnclosingName(const AstRawString* name);
 
   // Enters name collection state.
   void Enter() {
@@ -40,9 +42,9 @@
   }
 
   // Pushes an encountered name onto names stack when in collection state.
-  void PushLiteralName(Handle<String> name);
+  void PushLiteralName(const AstRawString* name);
 
-  void PushVariableName(Handle<String> name);
+  void PushVariableName(const AstRawString* name);
 
   // Adds a function to infer name for.
   void AddFunction(FunctionLiteral* func_to_infer) {
@@ -80,24 +82,24 @@
     kVariableName
   };
   struct Name {
-    Name(Handle<String> name, NameType type) : name(name), type(type) { }
-    Handle<String> name;
+    Name(const AstRawString* name, NameType type) : name(name), type(type) {}
+    const AstRawString* name;
     NameType type;
   };
 
-  Isolate* isolate() { return isolate_; }
   Zone* zone() const { return zone_; }
 
   // Constructs a full name in dotted notation from gathered names.
-  Handle<String> MakeNameFromStack();
+  const AstString* MakeNameFromStack();
 
   // A helper function for MakeNameFromStack.
-  Handle<String> MakeNameFromStackHelper(int pos, Handle<String> prev);
+  const AstString* MakeNameFromStackHelper(int pos,
+                                               const AstString* prev);
 
   // Performs name inferring for added functions.
   void InferFunctionsNames();
 
-  Isolate* isolate_;
+  AstValueFactory* ast_value_factory_;
   ZoneList<int> entries_stack_;
   ZoneList<Name> names_stack_;
   ZoneList<FunctionLiteral*> funcs_to_infer_;
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index 20e3f2a..09da388 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -649,10 +649,11 @@
   void WriteHeader(Writer* w) {
     ASSERT(w->position() == 0);
     Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87
+#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
+     (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
     const uint8_t ident[16] =
         { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-#elif V8_TARGET_ARCH_X64
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
     const uint8_t ident[16] =
         { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #else
@@ -762,7 +763,8 @@
   Binding binding() const {
     return static_cast<Binding>(info >> 4);
   }
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87
+#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
+     (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
   struct SerializedLayout {
     SerializedLayout(uint32_t name,
                      uintptr_t value,
@@ -785,7 +787,7 @@
     uint8_t other;
     uint16_t section;
   };
-#elif V8_TARGET_ARCH_X64
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
   struct SerializedLayout {
     SerializedLayout(uint32_t name,
                      uintptr_t value,
diff --git a/src/globals.h b/src/globals.h
index 595ecc3..c76dc85 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -138,7 +138,11 @@
 const int kDoubleSize    = sizeof(double);    // NOLINT
 const int kIntptrSize    = sizeof(intptr_t);  // NOLINT
 const int kPointerSize   = sizeof(void*);     // NOLINT
+#if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+const int kRegisterSize  = kPointerSize + kPointerSize;
+#else
 const int kRegisterSize  = kPointerSize;
+#endif
 const int kPCOnStackSize = kRegisterSize;
 const int kFPOnStackSize = kRegisterSize;
 
@@ -154,9 +158,17 @@
 const int kPointerSizeLog2 = 2;
 const intptr_t kIntptrSignBit = 0x80000000;
 const uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
+#if V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+// x32 port also requires code range.
+const bool kRequiresCodeRange = true;
+const size_t kMaximalCodeRangeSize = 256 * MB;
+#else
 const bool kRequiresCodeRange = false;
 const size_t kMaximalCodeRangeSize = 0 * MB;
 #endif
+#endif
+
+STATIC_ASSERT(kPointerSize == (1 << kPointerSizeLog2));
 
 const int kBitsPerByte = 8;
 const int kBitsPerByteLog2 = 3;
diff --git a/src/heap.cc b/src/heap.cc
index f8e6d49..4dea510 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2026,6 +2026,19 @@
     AllocationResult allocation =
         heap->new_space()->AllocateRaw(allocation_size);
     heap->promotion_queue()->SetNewLimit(heap->new_space()->top());
+
+    // Allocation in the other semi-space may fail due to fragmentation.
+    // In that case we allocate in the old generation.
+    if (allocation.IsRetry()) {
+      if (object_contents == DATA_OBJECT) {
+        ASSERT(heap->AllowedToBeMigrated(object, OLD_DATA_SPACE));
+        allocation = heap->old_data_space()->AllocateRaw(allocation_size);
+      } else {
+        ASSERT(heap->AllowedToBeMigrated(object, OLD_POINTER_SPACE));
+        allocation = heap->old_pointer_space()->AllocateRaw(allocation_size);
+      }
+    }
+
     HeapObject* target = HeapObject::cast(allocation.ToObjectChecked());
 
     if (alignment != kObjectAlignment) {
diff --git a/src/heap.h b/src/heap.h
index cf1d0ab..cb438b1 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -277,16 +277,11 @@
   V(constructor_string, "constructor")                                   \
   V(dot_result_string, ".result")                                        \
   V(dot_for_string, ".for.")                                             \
-  V(dot_iterable_string, ".iterable")                                    \
-  V(dot_iterator_string, ".iterator")                                    \
-  V(dot_generator_object_string, ".generator_object")                    \
   V(eval_string, "eval")                                                 \
   V(empty_string, "")                                                    \
   V(function_string, "function")                                         \
   V(length_string, "length")                                             \
-  V(module_string, "module")                                             \
   V(name_string, "name")                                                 \
-  V(native_string, "native")                                             \
   V(null_string, "null")                                                 \
   V(number_string, "number")                                             \
   V(Number_string, "Number")                                             \
@@ -312,7 +307,6 @@
   V(private_api_string, "private_api")                                   \
   V(private_intern_string, "private_intern")                             \
   V(Date_string, "Date")                                                 \
-  V(this_string, "this")                                                 \
   V(to_string_string, "toString")                                        \
   V(char_at_string, "CharAt")                                            \
   V(undefined_string, "undefined")                                       \
@@ -335,19 +329,13 @@
   V(cell_value_string, "%cell_value")                                    \
   V(function_class_string, "Function")                                   \
   V(illegal_argument_string, "illegal argument")                         \
-  V(MakeReferenceError_string, "MakeReferenceError")                     \
-  V(MakeSyntaxError_string, "MakeSyntaxError")                           \
-  V(MakeTypeError_string, "MakeTypeError")                               \
-  V(unknown_label_string, "unknown_label")                               \
   V(space_string, " ")                                                   \
   V(exec_string, "exec")                                                 \
   V(zero_string, "0")                                                    \
   V(global_eval_string, "GlobalEval")                                    \
   V(identity_hash_string, "v8::IdentityHash")                            \
   V(closure_string, "(closure)")                                         \
-  V(use_strict_string, "use strict")                                     \
   V(dot_string, ".")                                                     \
-  V(anonymous_function_string, "(anonymous function)")                   \
   V(compare_ic_string, "==")                                             \
   V(strict_compare_ic_string, "===")                                     \
   V(infinity_string, "Infinity")                                         \
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index d691cbe..ef42425 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -4383,12 +4383,6 @@
                             HBasicBlock* true_target = NULL,
                             HBasicBlock* false_target = NULL)
       : known_successor_index_(kNoKnownSuccessorIndex) {
-    ASSERT(!left->IsConstant() ||
-           (!HConstant::cast(left)->HasInteger32Value() ||
-            HConstant::cast(left)->HasSmiValue()));
-    ASSERT(!right->IsConstant() ||
-           (!HConstant::cast(right)->HasInteger32Value() ||
-            HConstant::cast(right)->HasSmiValue()));
     SetOperandAt(0, left);
     SetOperandAt(1, right);
     SetSuccessorAt(0, true_target);
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index a2f6320..339e0d3 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -7626,6 +7626,9 @@
 
   // Parse and allocate variables.
   CompilationInfo target_info(target, zone());
+  // Use the same AstValueFactory for creating strings in the sub-compilation
+  // step, but don't transfer ownership to target_info.
+  target_info.SetAstValueFactory(top_info()->ast_value_factory(), false);
   Handle<SharedFunctionInfo> target_shared(target->shared());
   if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
     if (target_info.isolate()->has_pending_exception()) {
diff --git a/src/interface.cc b/src/interface.cc
index d6e8406..364de39 100644
--- a/src/interface.cc
+++ b/src/interface.cc
@@ -9,15 +9,6 @@
 namespace v8 {
 namespace internal {
 
-static bool Match(void* key1, void* key2) {
-  String* name1 = *static_cast<String**>(key1);
-  String* name2 = *static_cast<String**>(key2);
-  ASSERT(name1->IsInternalizedString());
-  ASSERT(name2->IsInternalizedString());
-  return name1 == name2;
-}
-
-
 Interface* Interface::Lookup(Handle<String> name, Zone* zone) {
   ASSERT(IsModule());
   ZoneHashMap* map = Chase()->exports_;
@@ -47,8 +38,8 @@
 #endif
 
 
-void Interface::DoAdd(
-    void* name, uint32_t hash, Interface* interface, Zone* zone, bool* ok) {
+void Interface::DoAdd(const void* name, uint32_t hash, Interface* interface,
+                      Zone* zone, bool* ok) {
   MakeModule(ok);
   if (!*ok) return;
 
@@ -57,8 +48,9 @@
     PrintF("%*s# Adding...\n", Nesting::current(), "");
     PrintF("%*sthis = ", Nesting::current(), "");
     this->Print(Nesting::current());
-    PrintF("%*s%s : ", Nesting::current(), "",
-           (*static_cast<String**>(name))->ToAsciiArray());
+    const AstRawString* symbol = static_cast<const AstRawString*>(name);
+    PrintF("%*s%.*s : ", Nesting::current(), "", symbol->length(),
+           symbol->raw_data());
     interface->Print(Nesting::current());
   }
 #endif
@@ -68,10 +60,12 @@
 
   if (*map == NULL) {
     *map = new(zone->New(sizeof(ZoneHashMap)))
-        ZoneHashMap(Match, ZoneHashMap::kDefaultHashMapCapacity, allocator);
+        ZoneHashMap(ZoneHashMap::PointersMatch,
+                    ZoneHashMap::kDefaultHashMapCapacity, allocator);
   }
 
-  ZoneHashMap::Entry* p = (*map)->Lookup(name, hash, !IsFrozen(), allocator);
+  ZoneHashMap::Entry* p =
+      (*map)->Lookup(const_cast<void*>(name), hash, !IsFrozen(), allocator);
   if (p == NULL) {
     // This didn't have name but was frozen already, that's an error.
     *ok = false;
diff --git a/src/interface.h b/src/interface.h
index 086facf..2076364 100644
--- a/src/interface.h
+++ b/src/interface.h
@@ -5,6 +5,7 @@
 #ifndef V8_INTERFACE_H_
 #define V8_INTERFACE_H_
 
+#include "src/ast-value-factory.h"
 #include "src/zone-inl.h"  // For operator new.
 
 namespace v8 {
@@ -59,8 +60,9 @@
 
   // Add a name to the list of exports. If it already exists, unify with
   // interface, otherwise insert unless this is closed.
-  void Add(Handle<String> name, Interface* interface, Zone* zone, bool* ok) {
-    DoAdd(name.location(), name->Hash(), interface, zone, ok);
+  void Add(const AstRawString* name, Interface* interface, Zone* zone,
+           bool* ok) {
+    DoAdd(name, name->hash(), interface, zone, ok);
   }
 
   // Unify with another interface. If successful, both interface objects will
@@ -146,9 +148,9 @@
   class Iterator {
    public:
     bool done() const { return entry_ == NULL; }
-    Handle<String> name() const {
+    const AstRawString* name() const {
       ASSERT(!done());
-      return Handle<String>(*static_cast<String**>(entry_->key));
+      return static_cast<const AstRawString*>(entry_->key);
     }
     Interface* interface() const {
       ASSERT(!done());
@@ -207,7 +209,7 @@
     return result;
   }
 
-  void DoAdd(void* name, uint32_t hash, Interface* interface, Zone* zone,
+  void DoAdd(const void* name, uint32_t hash, Interface* interface, Zone* zone,
              bool* ok);
   void DoUnify(Interface* that, bool* ok, Zone* zone);
 };
diff --git a/src/list-inl.h b/src/list-inl.h
index 8a4cf56..fd1050e 100644
--- a/src/list-inl.h
+++ b/src/list-inl.h
@@ -219,7 +219,7 @@
   int low = 0;
   int high = list.length() - 1;
   while (low <= high) {
-    int mid = (low + high) / 2;
+    int mid = low + (high - low) / 2;
     T mid_elem = list[mid];
 
     if (cmp(&mid_elem) > 0) {
diff --git a/src/log.cc b/src/log.cc
index e8af5d0..9603fc1 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -554,14 +554,18 @@
 void LowLevelLogger::LogCodeInfo() {
 #if V8_TARGET_ARCH_IA32
   const char arch[] = "ia32";
-#elif V8_TARGET_ARCH_X64
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT
   const char arch[] = "x64";
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+  const char arch[] = "x32";
 #elif V8_TARGET_ARCH_ARM
   const char arch[] = "arm";
 #elif V8_TARGET_ARCH_MIPS
   const char arch[] = "mips";
 #elif V8_TARGET_ARCH_X87
   const char arch[] = "x87";
+#elif V8_TARGET_ARCH_ARM64
+  const char arch[] = "arm64";
 #else
   const char arch[] = "unknown";
 #endif
@@ -1711,7 +1715,7 @@
   if (overflow) {
     msg.Append(",overflow");
   }
-  for (int i = 0; i < sample->frames_count; ++i) {
+  for (unsigned i = 0; i < sample->frames_count; ++i) {
     msg.Append(',');
     msg.AppendAddress(sample->stack[i]);
   }
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index b31d6ae..b7575b3 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -2015,7 +2015,6 @@
         continue;
       }
 
-      // Promotion failed. Just migrate object to another semispace.
       AllocationResult allocation = new_space->AllocateRaw(size);
       if (allocation.IsRetry()) {
         if (!new_space->AddFreshPage()) {
diff --git a/src/messages.js b/src/messages.js
index 859bc0d..fd94cc0 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -89,6 +89,10 @@
   array_functions_on_frozen:     ["Cannot modify frozen array elements"],
   array_functions_change_sealed: ["Cannot add/remove sealed array elements"],
   first_argument_not_regexp:     ["First argument to ", "%0", " must not be a regular expression"],
+  not_iterable:                  ["%0", " is not iterable"],
+  not_an_iterator:               ["%0", " is not an iterator"],
+  iterator_result_not_an_object: ["Iterator result ", "%0", " is not an object"],
+  iterator_value_not_an_object:  ["Iterator value ", "%0", " is not an entry object"],
   // RangeError
   invalid_array_length:          ["Invalid array length"],
   invalid_array_buffer_length:   ["Invalid array buffer length"],
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 7640a76..a56792c 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -54,22 +54,19 @@
 
 
 #define TYPE_CHECKER(type, instancetype)                                \
-  bool Object::Is##type() {                                             \
+  bool Object::Is##type() const {                                       \
   return Object::IsHeapObject() &&                                      \
       HeapObject::cast(this)->map()->instance_type() == instancetype;   \
   }
 
 
-// TODO(svenpanne) We use const_cast here and at a few other places to break our
-// dependency cycle between the cast methods and the predicates. This can be
-// removed when the predicates are const-correct, too.
 #define CAST_ACCESSOR(type)                       \
   type* type::cast(Object* object) {              \
     SLOW_ASSERT(object->Is##type());              \
     return reinterpret_cast<type*>(object);       \
   }                                               \
   const type* type::cast(const Object* object) {  \
-    SLOW_ASSERT(const_cast<Object*>(object)->Is##type()); \
+    SLOW_ASSERT(object->Is##type());              \
     return reinterpret_cast<const type*>(object); \
   }
 
@@ -138,31 +135,31 @@
   }
 
 
-bool Object::IsFixedArrayBase() {
+bool Object::IsFixedArrayBase() const {
   return IsFixedArray() || IsFixedDoubleArray() || IsConstantPoolArray() ||
          IsFixedTypedArrayBase() || IsExternalArray();
 }
 
 
 // External objects are not extensible, so the map check is enough.
-bool Object::IsExternal() {
+bool Object::IsExternal() const {
   return Object::IsHeapObject() &&
       HeapObject::cast(this)->map() ==
       HeapObject::cast(this)->GetHeap()->external_map();
 }
 
 
-bool Object::IsAccessorInfo() {
+bool Object::IsAccessorInfo() const {
   return IsExecutableAccessorInfo() || IsDeclaredAccessorInfo();
 }
 
 
-bool Object::IsSmi() {
+bool Object::IsSmi() const {
   return HAS_SMI_TAG(this);
 }
 
 
-bool Object::IsHeapObject() {
+bool Object::IsHeapObject() const {
   return Internals::HasHeapObjectTag(this);
 }
 
@@ -171,41 +168,41 @@
 TYPE_CHECKER(Symbol, SYMBOL_TYPE)
 
 
-bool Object::IsString() {
+bool Object::IsString() const {
   return Object::IsHeapObject()
     && HeapObject::cast(this)->map()->instance_type() < FIRST_NONSTRING_TYPE;
 }
 
 
-bool Object::IsName() {
+bool Object::IsName() const {
   return IsString() || IsSymbol();
 }
 
 
-bool Object::IsUniqueName() {
+bool Object::IsUniqueName() const {
   return IsInternalizedString() || IsSymbol();
 }
 
 
-bool Object::IsSpecObject() {
+bool Object::IsSpecObject() const {
   return Object::IsHeapObject()
     && HeapObject::cast(this)->map()->instance_type() >= FIRST_SPEC_OBJECT_TYPE;
 }
 
 
-bool Object::IsSpecFunction() {
+bool Object::IsSpecFunction() const {
   if (!Object::IsHeapObject()) return false;
   InstanceType type = HeapObject::cast(this)->map()->instance_type();
   return type == JS_FUNCTION_TYPE || type == JS_FUNCTION_PROXY_TYPE;
 }
 
 
-bool Object::IsTemplateInfo() {
+bool Object::IsTemplateInfo() const {
   return IsObjectTemplateInfo() || IsFunctionTemplateInfo();
 }
 
 
-bool Object::IsInternalizedString() {
+bool Object::IsInternalizedString() const {
   if (!this->IsHeapObject()) return false;
   uint32_t type = HeapObject::cast(this)->map()->instance_type();
   STATIC_ASSERT(kNotInternalizedTag != 0);
@@ -214,52 +211,52 @@
 }
 
 
-bool Object::IsConsString() {
+bool Object::IsConsString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsCons();
 }
 
 
-bool Object::IsSlicedString() {
+bool Object::IsSlicedString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsSliced();
 }
 
 
-bool Object::IsSeqString() {
+bool Object::IsSeqString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsSequential();
 }
 
 
-bool Object::IsSeqOneByteString() {
+bool Object::IsSeqOneByteString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsSequential() &&
          String::cast(this)->IsOneByteRepresentation();
 }
 
 
-bool Object::IsSeqTwoByteString() {
+bool Object::IsSeqTwoByteString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsSequential() &&
          String::cast(this)->IsTwoByteRepresentation();
 }
 
 
-bool Object::IsExternalString() {
+bool Object::IsExternalString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsExternal();
 }
 
 
-bool Object::IsExternalAsciiString() {
+bool Object::IsExternalAsciiString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsExternal() &&
          String::cast(this)->IsOneByteRepresentation();
 }
 
 
-bool Object::IsExternalTwoByteString() {
+bool Object::IsExternalTwoByteString() const {
   if (!IsString()) return false;
   return StringShape(String::cast(this)).IsExternal() &&
          String::cast(this)->IsTwoByteRepresentation();
@@ -287,7 +284,7 @@
 }
 
 
-StringShape::StringShape(String* str)
+StringShape::StringShape(const String* str)
   : type_(str->map()->instance_type()) {
   set_valid();
   ASSERT((type_ & kIsNotStringMask) == kStringTag);
@@ -316,13 +313,13 @@
 }
 
 
-bool String::IsOneByteRepresentation() {
+bool String::IsOneByteRepresentation() const {
   uint32_t type = map()->instance_type();
   return (type & kStringEncodingMask) == kOneByteStringTag;
 }
 
 
-bool String::IsTwoByteRepresentation() {
+bool String::IsTwoByteRepresentation() const {
   uint32_t type = map()->instance_type();
   return (type & kStringEncodingMask) == kTwoByteStringTag;
 }
@@ -612,7 +609,7 @@
 };
 
 
-bool Object::IsNumber() {
+bool Object::IsNumber() const {
   return IsSmi() || IsHeapNumber();
 }
 
@@ -621,14 +618,14 @@
 TYPE_CHECKER(FreeSpace, FREE_SPACE_TYPE)
 
 
-bool Object::IsFiller() {
+bool Object::IsFiller() const {
   if (!Object::IsHeapObject()) return false;
   InstanceType instance_type = HeapObject::cast(this)->map()->instance_type();
   return instance_type == FREE_SPACE_TYPE || instance_type == FILLER_TYPE;
 }
 
 
-bool Object::IsExternalArray() {
+bool Object::IsExternalArray() const {
   if (!Object::IsHeapObject())
     return false;
   InstanceType instance_type =
@@ -646,7 +643,7 @@
 #undef TYPED_ARRAY_TYPE_CHECKER
 
 
-bool Object::IsFixedTypedArrayBase() {
+bool Object::IsFixedTypedArrayBase() const {
   if (!Object::IsHeapObject()) return false;
 
   InstanceType instance_type =
@@ -656,21 +653,21 @@
 }
 
 
-bool Object::IsJSReceiver() {
+bool Object::IsJSReceiver() const {
   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   return IsHeapObject() &&
       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_RECEIVER_TYPE;
 }
 
 
-bool Object::IsJSObject() {
+bool Object::IsJSObject() const {
   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
   return IsHeapObject() &&
       HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
 }
 
 
-bool Object::IsJSProxy() {
+bool Object::IsJSProxy() const {
   if (!Object::IsHeapObject()) return false;
   return  HeapObject::cast(this)->map()->IsJSProxyMap();
 }
@@ -690,22 +687,22 @@
 TYPE_CHECKER(ConstantPoolArray, CONSTANT_POOL_ARRAY_TYPE)
 
 
-bool Object::IsJSWeakCollection() {
+bool Object::IsJSWeakCollection() const {
   return IsJSWeakMap() || IsJSWeakSet();
 }
 
 
-bool Object::IsDescriptorArray() {
+bool Object::IsDescriptorArray() const {
   return IsFixedArray();
 }
 
 
-bool Object::IsTransitionArray() {
+bool Object::IsTransitionArray() const {
   return IsFixedArray();
 }
 
 
-bool Object::IsDeoptimizationInputData() {
+bool Object::IsDeoptimizationInputData() const {
   // Must be a fixed array.
   if (!IsFixedArray()) return false;
 
@@ -722,7 +719,7 @@
 }
 
 
-bool Object::IsDeoptimizationOutputData() {
+bool Object::IsDeoptimizationOutputData() const {
   if (!IsFixedArray()) return false;
   // There's actually no way to see the difference between a fixed array and
   // a deoptimization data array.  Since this is used for asserts we can check
@@ -732,7 +729,7 @@
 }
 
 
-bool Object::IsDependentCode() {
+bool Object::IsDependentCode() const {
   if (!IsFixedArray()) return false;
   // There's actually no way to see the difference between a fixed array and
   // a dependent codes array.
@@ -740,7 +737,7 @@
 }
 
 
-bool Object::IsContext() {
+bool Object::IsContext() const {
   if (!Object::IsHeapObject()) return false;
   Map* map = HeapObject::cast(this)->map();
   Heap* heap = map->GetHeap();
@@ -754,14 +751,14 @@
 }
 
 
-bool Object::IsNativeContext() {
+bool Object::IsNativeContext() const {
   return Object::IsHeapObject() &&
       HeapObject::cast(this)->map() ==
       HeapObject::cast(this)->GetHeap()->native_context_map();
 }
 
 
-bool Object::IsScopeInfo() {
+bool Object::IsScopeInfo() const {
   return Object::IsHeapObject() &&
       HeapObject::cast(this)->map() ==
       HeapObject::cast(this)->GetHeap()->scope_info_map();
@@ -788,7 +785,7 @@
 TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
 
 
-bool Object::IsStringWrapper() {
+bool Object::IsStringWrapper() const {
   return IsJSValue() && JSValue::cast(this)->value()->IsString();
 }
 
@@ -796,7 +793,7 @@
 TYPE_CHECKER(Foreign, FOREIGN_TYPE)
 
 
-bool Object::IsBoolean() {
+bool Object::IsBoolean() const {
   return IsOddball() &&
       ((Oddball::cast(this)->kind() & Oddball::kNotBooleanMask) == 0);
 }
@@ -808,7 +805,7 @@
 TYPE_CHECKER(JSDataView, JS_DATA_VIEW_TYPE)
 
 
-bool Object::IsJSArrayBufferView() {
+bool Object::IsJSArrayBufferView() const {
   return IsJSDataView() || IsJSTypedArray();
 }
 
@@ -821,47 +818,47 @@
 }
 
 
-bool Object::IsHashTable() {
+bool Object::IsHashTable() const {
   return Object::IsHeapObject() &&
       HeapObject::cast(this)->map() ==
       HeapObject::cast(this)->GetHeap()->hash_table_map();
 }
 
 
-bool Object::IsWeakHashTable() {
+bool Object::IsWeakHashTable() const {
   return IsHashTable();
 }
 
 
-bool Object::IsDictionary() {
+bool Object::IsDictionary() const {
   return IsHashTable() &&
       this != HeapObject::cast(this)->GetHeap()->string_table();
 }
 
 
-bool Object::IsNameDictionary() {
+bool Object::IsNameDictionary() const {
   return IsDictionary();
 }
 
 
-bool Object::IsSeededNumberDictionary() {
+bool Object::IsSeededNumberDictionary() const {
   return IsDictionary();
 }
 
 
-bool Object::IsUnseededNumberDictionary() {
+bool Object::IsUnseededNumberDictionary() const {
   return IsDictionary();
 }
 
 
-bool Object::IsStringTable() {
+bool Object::IsStringTable() const {
   return IsHashTable();
 }
 
 
-bool Object::IsJSFunctionResultCache() {
+bool Object::IsJSFunctionResultCache() const {
   if (!IsFixedArray()) return false;
-  FixedArray* self = FixedArray::cast(this);
+  const FixedArray* self = FixedArray::cast(this);
   int length = self->length();
   if (length < JSFunctionResultCache::kEntriesIndex) return false;
   if ((length - JSFunctionResultCache::kEntriesIndex)
@@ -870,7 +867,10 @@
   }
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) {
-    reinterpret_cast<JSFunctionResultCache*>(this)->
+    // TODO(svenpanne) We use const_cast here and below to break our dependency
+    // cycle between the predicates and the verifiers. This can be removed when
+    // the verifiers are const-correct, too.
+    reinterpret_cast<JSFunctionResultCache*>(const_cast<Object*>(this))->
         JSFunctionResultCacheVerify();
   }
 #endif
@@ -878,7 +878,7 @@
 }
 
 
-bool Object::IsNormalizedMapCache() {
+bool Object::IsNormalizedMapCache() const {
   return NormalizedMapCache::IsNormalizedMapCache(this);
 }
 
@@ -888,68 +888,69 @@
 }
 
 
-bool NormalizedMapCache::IsNormalizedMapCache(Object* obj) {
+bool NormalizedMapCache::IsNormalizedMapCache(const Object* obj) {
   if (!obj->IsFixedArray()) return false;
   if (FixedArray::cast(obj)->length() != NormalizedMapCache::kEntries) {
     return false;
   }
 #ifdef VERIFY_HEAP
   if (FLAG_verify_heap) {
-    reinterpret_cast<NormalizedMapCache*>(obj)->NormalizedMapCacheVerify();
+    reinterpret_cast<NormalizedMapCache*>(const_cast<Object*>(obj))->
+        NormalizedMapCacheVerify();
   }
 #endif
   return true;
 }
 
 
-bool Object::IsCompilationCacheTable() {
+bool Object::IsCompilationCacheTable() const {
   return IsHashTable();
 }
 
 
-bool Object::IsCodeCacheHashTable() {
+bool Object::IsCodeCacheHashTable() const {
   return IsHashTable();
 }
 
 
-bool Object::IsPolymorphicCodeCacheHashTable() {
+bool Object::IsPolymorphicCodeCacheHashTable() const {
   return IsHashTable();
 }
 
 
-bool Object::IsMapCache() {
+bool Object::IsMapCache() const {
   return IsHashTable();
 }
 
 
-bool Object::IsObjectHashTable() {
+bool Object::IsObjectHashTable() const {
   return IsHashTable();
 }
 
 
-bool Object::IsOrderedHashTable() {
+bool Object::IsOrderedHashTable() const {
   return IsHeapObject() &&
       HeapObject::cast(this)->map() ==
       HeapObject::cast(this)->GetHeap()->ordered_hash_table_map();
 }
 
 
-bool Object::IsOrderedHashSet() {
+bool Object::IsOrderedHashSet() const {
   return IsOrderedHashTable();
 }
 
 
-bool Object::IsOrderedHashMap() {
+bool Object::IsOrderedHashMap() const {
   return IsOrderedHashTable();
 }
 
 
-bool Object::IsPrimitive() {
+bool Object::IsPrimitive() const {
   return IsOddball() || IsNumber() || IsString();
 }
 
 
-bool Object::IsJSGlobalProxy() {
+bool Object::IsJSGlobalProxy() const {
   bool result = IsHeapObject() &&
                 (HeapObject::cast(this)->map()->instance_type() ==
                  JS_GLOBAL_PROXY_TYPE);
@@ -959,7 +960,7 @@
 }
 
 
-bool Object::IsGlobalObject() {
+bool Object::IsGlobalObject() const {
   if (!IsHeapObject()) return false;
 
   InstanceType type = HeapObject::cast(this)->map()->instance_type();
@@ -972,25 +973,24 @@
 TYPE_CHECKER(JSBuiltinsObject, JS_BUILTINS_OBJECT_TYPE)
 
 
-bool Object::IsUndetectableObject() {
+bool Object::IsUndetectableObject() const {
   return IsHeapObject()
     && HeapObject::cast(this)->map()->is_undetectable();
 }
 
 
-bool Object::IsAccessCheckNeeded() {
+bool Object::IsAccessCheckNeeded() const {
   if (!IsHeapObject()) return false;
   if (IsJSGlobalProxy()) {
-    JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
-    GlobalObject* global =
-        proxy->GetIsolate()->context()->global_object();
+    const JSGlobalProxy* proxy = JSGlobalProxy::cast(this);
+    GlobalObject* global = proxy->GetIsolate()->context()->global_object();
     return proxy->IsDetachedFrom(global);
   }
   return HeapObject::cast(this)->map()->is_access_check_needed();
 }
 
 
-bool Object::IsStruct() {
+bool Object::IsStruct() const {
   if (!IsHeapObject()) return false;
   switch (HeapObject::cast(this)->map()->instance_type()) {
 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return true;
@@ -1001,51 +1001,51 @@
 }
 
 
-#define MAKE_STRUCT_PREDICATE(NAME, Name, name)                  \
-  bool Object::Is##Name() {                                      \
-    return Object::IsHeapObject()                                \
+#define MAKE_STRUCT_PREDICATE(NAME, Name, name)                         \
+  bool Object::Is##Name() const {                                       \
+    return Object::IsHeapObject()                                       \
       && HeapObject::cast(this)->map()->instance_type() == NAME##_TYPE; \
   }
   STRUCT_LIST(MAKE_STRUCT_PREDICATE)
 #undef MAKE_STRUCT_PREDICATE
 
 
-bool Object::IsUndefined() {
+bool Object::IsUndefined() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUndefined;
 }
 
 
-bool Object::IsNull() {
+bool Object::IsNull() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kNull;
 }
 
 
-bool Object::IsTheHole() {
+bool Object::IsTheHole() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTheHole;
 }
 
 
-bool Object::IsException() {
+bool Object::IsException() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kException;
 }
 
 
-bool Object::IsUninitialized() {
+bool Object::IsUninitialized() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kUninitialized;
 }
 
 
-bool Object::IsTrue() {
+bool Object::IsTrue() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kTrue;
 }
 
 
-bool Object::IsFalse() {
+bool Object::IsFalse() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kFalse;
 }
 
 
-bool Object::IsArgumentsMarker() {
+bool Object::IsArgumentsMarker() const {
   return IsOddball() && Oddball::cast(this)->kind() == Oddball::kArgumentMarker;
 }
 
@@ -1058,7 +1058,7 @@
 }
 
 
-bool Object::IsNaN() {
+bool Object::IsNaN() const {
   return this->IsHeapNumber() && std::isnan(HeapNumber::cast(this)->value());
 }
 
@@ -1369,7 +1369,7 @@
 }
 
 
-Isolate* HeapObject::GetIsolate() {
+Isolate* HeapObject::GetIsolate() const {
   return GetHeap()->isolate();
 }
 
@@ -1478,7 +1478,7 @@
 }
 
 
-double HeapNumber::value() {
+double HeapNumber::value() const {
   return READ_DOUBLE_FIELD(this, kValueOffset);
 }
 
@@ -1849,7 +1849,7 @@
 ACCESSORS(Oddball, to_number, Object, kToNumberOffset)
 
 
-byte Oddball::kind() {
+byte Oddball::kind() const {
   return Smi::cast(READ_FIELD(this, kKindOffset))->value();
 }
 
@@ -3147,7 +3147,7 @@
 template <class Traits>
 const FixedTypedArray<Traits>*
 FixedTypedArray<Traits>::cast(const Object* object) {
-  SLOW_ASSERT(const_cast<Object*>(object)->IsHeapObject() &&
+  SLOW_ASSERT(object->IsHeapObject() &&
               HeapObject::cast(object)->map()->instance_type() ==
               Traits::kInstanceType);
   return reinterpret_cast<FixedTypedArray<Traits>*>(object);
@@ -3170,7 +3170,7 @@
 template <typename Derived, typename Shape, typename Key>
 const HashTable<Derived, Shape, Key>*
 HashTable<Derived, Shape, Key>::cast(const Object* obj) {
-  SLOW_ASSERT(const_cast<Object*>(obj)->IsHashTable());
+  SLOW_ASSERT(obj->IsHashTable());
   return reinterpret_cast<const HashTable*>(obj);
 }
 
@@ -4651,14 +4651,17 @@
 
 int Code::allow_osr_at_loop_nesting_level() {
   ASSERT_EQ(FUNCTION, kind());
-  return READ_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset);
+  int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
+  return AllowOSRAtLoopNestingLevelField::decode(fields);
 }
 
 
 void Code::set_allow_osr_at_loop_nesting_level(int level) {
   ASSERT_EQ(FUNCTION, kind());
   ASSERT(level >= 0 && level <= kMaxLoopNestingMarker);
-  WRITE_BYTE_FIELD(this, kAllowOSRAtLoopNestingLevelOffset, level);
+  int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
+  int updated = AllowOSRAtLoopNestingLevelField::update(previous, level);
+  WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
 }
 
 
@@ -4711,13 +4714,14 @@
 unsigned Code::back_edge_table_offset() {
   ASSERT_EQ(FUNCTION, kind());
   return BackEdgeTableOffsetField::decode(
-      READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
+      READ_UINT32_FIELD(this, kKindSpecificFlags2Offset)) << kPointerSizeLog2;
 }
 
 
 void Code::set_back_edge_table_offset(unsigned offset) {
   ASSERT_EQ(FUNCTION, kind());
-  ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
+  ASSERT(IsAligned(offset, static_cast<unsigned>(kPointerSize)));
+  offset = offset >> kPointerSizeLog2;
   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
   int updated = BackEdgeTableOffsetField::update(previous, offset);
   WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
@@ -4726,20 +4730,10 @@
 
 bool Code::back_edges_patched_for_osr() {
   ASSERT_EQ(FUNCTION, kind());
-  return BackEdgesPatchedForOSRField::decode(
-      READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
+  return allow_osr_at_loop_nesting_level() > 0;
 }
 
 
-void Code::set_back_edges_patched_for_osr(bool value) {
-  ASSERT_EQ(FUNCTION, kind());
-  int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
-  int updated = BackEdgesPatchedForOSRField::update(previous, value);
-  WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
-}
-
-
-
 byte Code::to_boolean_state() {
   return extra_ic_state();
 }
@@ -6438,7 +6432,7 @@
 }
 
 
-Object* JSReceiver::GetPrototype() {
+Object* JSReceiver::GetPrototype() const {
   return map()->prototype();
 }
 
@@ -6494,7 +6488,7 @@
 }
 
 
-bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) {
+bool JSGlobalProxy::IsDetachedFrom(GlobalObject* global) const {
   return GetPrototype() != global;
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index e9bedca..08a192f 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -92,8 +92,8 @@
 }
 
 
-bool Object::IsCallable() {
-  Object* fun = this;
+bool Object::IsCallable() const {
+  const Object* fun = this;
   while (fun->IsJSFunctionProxy()) {
     fun = JSFunctionProxy::cast(fun)->call_trap();
   }
@@ -761,7 +761,7 @@
         // the hole value.
         Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
         ASSERT(new_map->is_dictionary_map());
-        object->set_map(*new_map);
+        JSObject::MigrateToMap(object, new_map);
       }
       Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
       Handle<Object> value = isolate->factory()->the_hole_value();
@@ -1701,22 +1701,7 @@
 
 
 bool HeapNumber::HeapNumberBooleanValue() {
-  // NaN, +0, and -0 should return the false object
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  union IeeeDoubleLittleEndianArchType u;
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  union IeeeDoubleBigEndianArchType u;
-#endif
-  u.d = value();
-  if (u.bits.exp == 2047) {
-    // Detect NaN for IEEE double precision floating point.
-    if ((u.bits.man_low | u.bits.man_high) != 0) return false;
-  }
-  if (u.bits.exp == 0) {
-    // Detect +0, and -0 for IEEE double precision floating point.
-    if ((u.bits.man_low | u.bits.man_high) == 0) return false;
-  }
-  return true;
+  return DoubleToBoolean(value());
 }
 
 
@@ -2119,7 +2104,26 @@
 }
 
 
-// To migrate an instance to a map:
+void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
+  if (object->map() == *new_map) return;
+  if (object->HasFastProperties()) {
+    if (!new_map->is_dictionary_map()) {
+      MigrateFastToFast(object, new_map);
+    } else {
+      MigrateFastToSlow(object, new_map, 0);
+    }
+  } else {
+    // For slow-to-fast migrations JSObject::TransformToFastProperties()
+    // must be used instead.
+    CHECK(new_map->is_dictionary_map());
+
+    // Slow-to-slow migration is trivial.
+    object->set_map(*new_map);
+  }
+}
+
+
+// To migrate a fast instance to a fast map:
 // - First check whether the instance needs to be rewritten. If not, simply
 //   change the map.
 // - Otherwise, allocate a fixed array large enough to hold all fields, in
@@ -2134,7 +2138,7 @@
 //     to temporarily store the inobject properties.
 //   * If there are properties left in the backing store, install the backing
 //     store.
-void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
+void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
   Isolate* isolate = object->GetIsolate();
   Handle<Map> old_map(object->map());
   int number_of_fields = new_map->NumberOfFields();
@@ -2145,8 +2149,6 @@
   // converted to doubles.
   if (!old_map->InstancesNeedRewriting(
           *new_map, number_of_fields, inobject, unused)) {
-    // Writing the new map here does not require synchronization since it does
-    // not change the actual object size.
     object->synchronized_set_map(*new_map);
     return;
   }
@@ -2180,9 +2182,7 @@
 
     // Set the new property value and do the map transition.
     object->set_properties(*new_storage);
-    // Writing the new map here does not require synchronization since it does
-    // not change the actual object size.
-    object->set_map(*new_map);
+    object->synchronized_set_map(*new_map);
     return;
   }
   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
@@ -2254,24 +2254,21 @@
   ASSERT(instance_size_delta >= 0);
   Address address = object->address() + new_instance_size;
 
-  // The trimming is performed on a newly allocated object, which is on a
-  // freshly allocated page or on an already swept page. Hence, the sweeper
-  // thread can not get confused with the filler creation. No synchronization
-  // needed.
-  isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
+  Heap* heap = isolate->heap();
 
   // If there are properties in the new backing store, trim it to the correct
   // size and install the backing store into the object.
   if (external > 0) {
-    RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject);
+    RightTrimFixedArray<Heap::FROM_MUTATOR>(heap, *array, inobject);
     object->set_properties(*array);
   }
 
-  // The trimming is performed on a newly allocated object, which is on a
-  // freshly allocated page or on an already swept page. Hence, the sweeper
-  // thread can not get confused with the filler creation. No synchronization
-  // needed.
-  object->set_map(*new_map);
+  heap->CreateFillerObjectAt(address, instance_size_delta);
+  heap->AdjustLiveBytes(address, -instance_size_delta, Heap::FROM_MUTATOR);
+
+  // We are storing the new map using release store after creating a filler for
+  // the left-over space to avoid races with the sweeper thread.
+  object->synchronized_set_map(*new_map);
 }
 
 
@@ -2283,8 +2280,7 @@
   Handle<Map> new_map = Map::GeneralizeRepresentation(
       handle(object->map()), modify_index, new_representation,
       new_field_type, store_mode);
-  if (object->map() == *new_map) return;
-  return MigrateToMap(object, new_map);
+  MigrateToMap(object, new_map);
 }
 
 
@@ -3983,8 +3979,7 @@
 }
 
 
-static void SetPropertyToField(LookupResult* lookup,
-                               Handle<Object> value) {
+void JSObject::SetPropertyToField(LookupResult* lookup, Handle<Object> value) {
   if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) {
     Representation field_representation = value->OptimalRepresentation();
     Handle<HeapType> field_type = value->OptimalType(
@@ -3998,10 +3993,10 @@
 }
 
 
-static void ConvertAndSetOwnProperty(LookupResult* lookup,
-                                     Handle<Name> name,
-                                     Handle<Object> value,
-                                     PropertyAttributes attributes) {
+void JSObject::ConvertAndSetOwnProperty(LookupResult* lookup,
+                                        Handle<Name> name,
+                                        Handle<Object> value,
+                                        PropertyAttributes attributes) {
   Handle<JSObject> object(lookup->holder());
   if (object->TooManyFastProperties()) {
     JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
@@ -4028,10 +4023,10 @@
 }
 
 
-static void SetPropertyToFieldWithAttributes(LookupResult* lookup,
-                                             Handle<Name> name,
-                                             Handle<Object> value,
-                                             PropertyAttributes attributes) {
+void JSObject::SetPropertyToFieldWithAttributes(LookupResult* lookup,
+                                                Handle<Name> name,
+                                                Handle<Object> value,
+                                                PropertyAttributes attributes) {
   if (lookup->GetAttributes() == attributes) {
     if (value->IsUninitialized()) return;
     SetPropertyToField(lookup, value);
@@ -4577,6 +4572,16 @@
                                    int expected_additional_properties) {
   if (!object->HasFastProperties()) return;
 
+  Handle<Map> map(object->map());
+  Handle<Map> new_map = Map::Normalize(map, mode);
+
+  MigrateFastToSlow(object, new_map, expected_additional_properties);
+}
+
+
+void JSObject::MigrateFastToSlow(Handle<JSObject> object,
+                                 Handle<Map> new_map,
+                                 int expected_additional_properties) {
   // The global object is always normalized.
   ASSERT(!object->IsGlobalObject());
   // JSGlobalProxy must never be normalized
@@ -4585,7 +4590,6 @@
   Isolate* isolate = object->GetIsolate();
   HandleScope scope(isolate);
   Handle<Map> map(object->map());
-  Handle<Map> new_map = Map::Normalize(map, mode);
 
   // Allocate new content.
   int real_size = map->NumberOfOwnDescriptors();
@@ -4672,8 +4676,8 @@
 }
 
 
-void JSObject::TransformToFastProperties(Handle<JSObject> object,
-                                         int unused_property_fields) {
+void JSObject::MigrateSlowToFast(Handle<JSObject> object,
+                                 int unused_property_fields) {
   if (object->HasFastProperties()) return;
   ASSERT(!object->IsGlobalObject());
   Isolate* isolate = object->GetIsolate();
@@ -4718,7 +4722,7 @@
     ASSERT_LE(unused_property_fields, inobject_props);
     // Transform the object.
     new_map->set_unused_property_fields(inobject_props);
-    object->set_map(*new_map);
+    object->synchronized_set_map(*new_map);
     object->set_properties(isolate->heap()->empty_fixed_array());
     // Check that it really works.
     ASSERT(object->HasFastProperties());
@@ -4799,7 +4803,7 @@
   new_map->set_unused_property_fields(unused_property_fields);
 
   // Transform the object.
-  object->set_map(*new_map);
+  object->synchronized_set_map(*new_map);
 
   object->set_properties(*fields);
   ASSERT(object->IsJSObject());
@@ -6641,7 +6645,7 @@
   if (object->IsGlobalObject()) {
     Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
     ASSERT(new_map->is_dictionary_map());
-    object->set_map(*new_map);
+    JSObject::MigrateToMap(object, new_map);
 
     // When running crankshaft, changing the map is not enough. We
     // need to deoptimize all functions that rely on this global
@@ -9362,29 +9366,7 @@
   if (length == 0 || length > kMaxArrayIndexSize) return false;
   ConsStringIteratorOp op;
   StringCharacterStream stream(this, &op);
-  uint16_t ch = stream.GetNext();
-
-  // If the string begins with a '0' character, it must only consist
-  // of it to be a legal array index.
-  if (ch == '0') {
-    *index = 0;
-    return length == 1;
-  }
-
-  // Convert string to uint32 array index; character by character.
-  int d = ch - '0';
-  if (d < 0 || d > 9) return false;
-  uint32_t result = d;
-  while (stream.HasMore()) {
-    d = stream.GetNext() - '0';
-    if (d < 0 || d > 9) return false;
-    // Check that the new result is below the 32 bit limit.
-    if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
-    result = (result * 10) + d;
-  }
-
-  *index = result;
-  return true;
+  return StringToArrayIndex(&stream, index);
 }
 
 
@@ -9930,7 +9912,7 @@
   // Make sure prototypes are fast objects and their maps have the bit set
   // so they remain fast.
   if (!object->HasFastProperties()) {
-    TransformToFastProperties(object, 0);
+    MigrateSlowToFast(object, 0);
   }
 }
 
diff --git a/src/objects.h b/src/objects.h
index 23924ca..259f60d 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1350,48 +1350,49 @@
 class Object {
  public:
   // Type testing.
-  bool IsObject() { return true; }
+  bool IsObject() const { return true; }
 
-#define IS_TYPE_FUNCTION_DECL(type_)  inline bool Is##type_();
+#define IS_TYPE_FUNCTION_DECL(type_)  INLINE(bool Is##type_() const);
   OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
   HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
 #undef IS_TYPE_FUNCTION_DECL
 
-  inline bool IsFixedArrayBase();
-  inline bool IsExternal();
-  inline bool IsAccessorInfo();
+  INLINE(bool IsFixedArrayBase() const);
+  INLINE(bool IsExternal() const);
+  INLINE(bool IsAccessorInfo() const);
 
-  inline bool IsStruct();
-#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) inline bool Is##Name();
+  INLINE(bool IsStruct() const);
+#define DECLARE_STRUCT_PREDICATE(NAME, Name, name) \
+  INLINE(bool Is##Name() const);
   STRUCT_LIST(DECLARE_STRUCT_PREDICATE)
 #undef DECLARE_STRUCT_PREDICATE
 
-  INLINE(bool IsSpecObject());
-  INLINE(bool IsSpecFunction());
-  INLINE(bool IsTemplateInfo());
-  INLINE(bool IsNameDictionary());
-  INLINE(bool IsSeededNumberDictionary());
-  INLINE(bool IsUnseededNumberDictionary());
-  INLINE(bool IsOrderedHashSet());
-  INLINE(bool IsOrderedHashMap());
-  bool IsCallable();
+  INLINE(bool IsSpecObject()) const;
+  INLINE(bool IsSpecFunction()) const;
+  INLINE(bool IsTemplateInfo()) const;
+  INLINE(bool IsNameDictionary() const);
+  INLINE(bool IsSeededNumberDictionary() const);
+  INLINE(bool IsUnseededNumberDictionary() const);
+  INLINE(bool IsOrderedHashSet() const);
+  INLINE(bool IsOrderedHashMap() const);
+  bool IsCallable() const;
 
   // Oddball testing.
-  INLINE(bool IsUndefined());
-  INLINE(bool IsNull());
-  INLINE(bool IsTheHole());
-  INLINE(bool IsException());
-  INLINE(bool IsUninitialized());
-  INLINE(bool IsTrue());
-  INLINE(bool IsFalse());
-  inline bool IsArgumentsMarker();
+  INLINE(bool IsUndefined() const);
+  INLINE(bool IsNull() const);
+  INLINE(bool IsTheHole() const);
+  INLINE(bool IsException() const);
+  INLINE(bool IsUninitialized() const);
+  INLINE(bool IsTrue() const);
+  INLINE(bool IsFalse() const);
+  INLINE(bool IsArgumentsMarker() const);
 
   // Filler objects (fillers and free space objects).
-  inline bool IsFiller();
+  INLINE(bool IsFiller() const);
 
   // Extract the number.
   inline double Number();
-  inline bool IsNaN();
+  INLINE(bool IsNaN() const);
   bool ToInt32(int32_t* value);
   bool ToUint32(uint32_t* value);
 
@@ -1683,7 +1684,7 @@
   inline Heap* GetHeap() const;
 
   // Convenience method to get current isolate.
-  inline Isolate* GetIsolate();
+  inline Isolate* GetIsolate() const;
 
   // Converts an address to a HeapObject pointer.
   static inline HeapObject* FromAddress(Address address);
@@ -1813,7 +1814,7 @@
 class HeapNumber: public HeapObject {
  public:
   // [value]: number value.
-  inline double value();
+  inline double value() const;
   inline void set_value(double value);
 
   DECLARE_CAST(HeapNumber)
@@ -1969,7 +1970,7 @@
       uint32_t index);
 
   // Return the object's prototype (might be Heap::null_value()).
-  inline Object* GetPrototype();
+  inline Object* GetPrototype() const;
 
   // Return the constructor function (may be Heap::null_value()).
   inline Object* GetConstructor();
@@ -2425,13 +2426,7 @@
   static void TransitionElementsKind(Handle<JSObject> object,
                                      ElementsKind to_kind);
 
-  // TODO(mstarzinger): Both public because of ConvertAndSetOwnProperty().
   static void MigrateToMap(Handle<JSObject> object, Handle<Map> new_map);
-  static void GeneralizeFieldRepresentation(Handle<JSObject> object,
-                                            int modify_index,
-                                            Representation new_representation,
-                                            Handle<HeapType> new_field_type,
-                                            StoreMode store_mode);
 
   // Convert the object to use the canonical dictionary
   // representation. If the object is expected to have additional properties
@@ -2447,8 +2442,8 @@
       Handle<JSObject> object);
 
   // Transform slow named properties to fast variants.
-  static void TransformToFastProperties(Handle<JSObject> object,
-                                        int unused_property_fields);
+  static void MigrateSlowToFast(Handle<JSObject> object,
+                                int unused_property_fields);
 
   // Access fast-case object properties at index.
   static Handle<Object> FastPropertyAt(Handle<JSObject> object,
@@ -2632,6 +2627,28 @@
   friend class JSReceiver;
   friend class Object;
 
+  static void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map);
+  static void MigrateFastToSlow(Handle<JSObject> object,
+                                Handle<Map> new_map,
+                                int expected_additional_properties);
+
+  static void SetPropertyToField(LookupResult* lookup, Handle<Object> value);
+
+  static void ConvertAndSetOwnProperty(LookupResult* lookup,
+                                       Handle<Name> name,
+                                       Handle<Object> value,
+                                       PropertyAttributes attributes);
+
+  static void SetPropertyToFieldWithAttributes(LookupResult* lookup,
+                                               Handle<Name> name,
+                                               Handle<Object> value,
+                                               PropertyAttributes attributes);
+  static void GeneralizeFieldRepresentation(Handle<JSObject> object,
+                                            int modify_index,
+                                            Representation new_representation,
+                                            Handle<HeapType> new_field_type,
+                                            StoreMode store_mode);
+
   static void UpdateAllocationSite(Handle<JSObject> object,
                                    ElementsKind to_kind);
 
@@ -4770,7 +4787,7 @@
 
   DECLARE_CAST(NormalizedMapCache)
 
-  static inline bool IsNormalizedMapCache(Object* obj);
+  static inline bool IsNormalizedMapCache(const Object* obj);
 
   DECLARE_VERIFIER(NormalizedMapCache)
  private:
@@ -5569,7 +5586,6 @@
   inline void set_back_edge_table_offset(unsigned offset);
 
   inline bool back_edges_patched_for_osr();
-  inline void set_back_edges_patched_for_osr(bool value);
 
   // [to_boolean_foo]: For kind TO_BOOLEAN_IC tells what state the stub is in.
   inline byte to_boolean_state();
@@ -5814,8 +5830,7 @@
   class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
   class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
 
-  static const int kAllowOSRAtLoopNestingLevelOffset = kFullCodeFlags + 1;
-  static const int kProfilerTicksOffset = kAllowOSRAtLoopNestingLevelOffset + 1;
+  static const int kProfilerTicksOffset = kFullCodeFlags + 1;
 
   // Flags layout.  BitField<type, shift, size>.
   class ICStateField: public BitField<InlineCacheState, 0, 3> {};
@@ -5886,9 +5901,10 @@
 
   // KindSpecificFlags2 layout (FUNCTION)
   class BackEdgeTableOffsetField: public BitField<int,
-      kIsCrankshaftedBit + 1, 29> {};  // NOLINT
-  class BackEdgesPatchedForOSRField: public BitField<bool,
-      kIsCrankshaftedBit + 1 + 29, 1> {};  // NOLINT
+      kIsCrankshaftedBit + 1, 27> {};  // NOLINT
+  class AllowOSRAtLoopNestingLevelField: public BitField<int,
+      kIsCrankshaftedBit + 1 + 27, 4> {};  // NOLINT
+  STATIC_ASSERT(AllowOSRAtLoopNestingLevelField::kMax >= kMaxLoopNestingMarker);
 
   static const int kArgumentsBits = 16;
   static const int kMaxArguments = (1 << kArgumentsBits) - 1;
@@ -7809,7 +7825,7 @@
 
   DECLARE_CAST(JSGlobalProxy)
 
-  inline bool IsDetachedFrom(GlobalObject* global);
+  inline bool IsDetachedFrom(GlobalObject* global) const;
 
   // Dispatched behavior.
   DECLARE_PRINTER(JSGlobalProxy)
@@ -8805,7 +8821,7 @@
 // concrete performance benefit at that particular point in the code.
 class StringShape BASE_EMBEDDED {
  public:
-  inline explicit StringShape(String* s);
+  inline explicit StringShape(const String* s);
   inline explicit StringShape(Map* s);
   inline explicit StringShape(InstanceType t);
   inline bool IsSequential();
@@ -9064,8 +9080,8 @@
   // be ASCII encoded.  This might be the case even if the string is
   // two-byte.  Such strings may appear when the embedder prefers
   // two-byte external representations even for ASCII data.
-  inline bool IsOneByteRepresentation();
-  inline bool IsTwoByteRepresentation();
+  inline bool IsOneByteRepresentation() const;
+  inline bool IsTwoByteRepresentation() const;
 
   // Cons and slices have an encoding flag that may not represent the actual
   // encoding of the underlying string.  This is taken into account here.
@@ -9733,7 +9749,7 @@
   // [to_number]: Cached to_number computed at startup.
   DECL_ACCESSORS(to_number, Object)
 
-  inline byte kind();
+  inline byte kind() const;
   inline void set_kind(byte kind);
 
   DECLARE_CAST(Oddball)
diff --git a/src/parser.cc b/src/parser.cc
index 49e9a81..dd91b1a 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -326,7 +326,9 @@
 
 
 Scope* Parser::NewScope(Scope* parent, ScopeType scope_type) {
-  Scope* result = new(zone()) Scope(parent, scope_type, zone());
+  ASSERT(ast_value_factory_);
+  Scope* result =
+      new (zone()) Scope(parent, scope_type, ast_value_factory_, zone());
   result->Initialize();
   return result;
 }
@@ -399,10 +401,9 @@
 // ----------------------------------------------------------------------------
 // Implementation of Parser
 
-bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
-  Factory* factory = parser_->isolate()->factory();
-  return identifier.is_identical_to(factory->eval_string())
-      || identifier.is_identical_to(factory->arguments_string());
+bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
+  return identifier == parser_->ast_value_factory_->eval_string() ||
+         identifier == parser_->ast_value_factory_->arguments_string();
 }
 
 
@@ -424,10 +425,10 @@
 void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
                                     Expression* expression) {
   if (expression->IsPropertyName()) {
-    fni->PushLiteralName(expression->AsLiteral()->AsPropertyName());
+    fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
   } else {
     fni->PushLiteralName(
-        parser_->isolate()->factory()->anonymous_function_string());
+        parser_->ast_value_factory_->anonymous_function_string());
   }
 }
 
@@ -446,7 +447,7 @@
                                          Scope* scope) {
   VariableProxy* callee = expression->AsVariableProxy();
   if (callee != NULL &&
-      callee->IsVariable(parser_->isolate()->factory()->eval_string())) {
+      callee->raw_name() == parser_->ast_value_factory_->eval_string()) {
     scope->DeclarationScope()->RecordEvalCall();
   }
 }
@@ -464,10 +465,10 @@
 bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
     Expression** x, Expression* y, Token::Value op, int pos,
     AstNodeFactory<AstConstructionVisitor>* factory) {
-  if ((*x)->AsLiteral() && (*x)->AsLiteral()->value()->IsNumber() &&
-      y->AsLiteral() && y->AsLiteral()->value()->IsNumber()) {
-    double x_val = (*x)->AsLiteral()->value()->Number();
-    double y_val = y->AsLiteral()->value()->Number();
+  if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
+      y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
+    double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
+    double y_val = y->AsLiteral()->raw_value()->AsNumber();
     switch (op) {
       case Token::ADD:
         *x = factory->NewNumberLiteral(x_val + y_val, pos);
@@ -526,16 +527,14 @@
     AstNodeFactory<AstConstructionVisitor>* factory) {
   ASSERT(expression != NULL);
   if (expression->IsLiteral()) {
-    Handle<Object> literal = expression->AsLiteral()->value();
+    const AstValue* literal = expression->AsLiteral()->raw_value();
     if (op == Token::NOT) {
       // Convert the literal to a boolean condition and negate it.
       bool condition = literal->BooleanValue();
-      Handle<Object> result =
-          parser_->isolate()->factory()->ToBoolean(!condition);
-      return factory->NewLiteral(result, pos);
+      return factory->NewBooleanLiteral(!condition, pos);
     } else if (literal->IsNumber()) {
       // Compute some expressions involving only number literals.
-      double value = literal->Number();
+      double value = literal->AsNumber();
       switch (op) {
         case Token::ADD:
           return expression;
@@ -569,51 +568,41 @@
 
 Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) {
   return NewThrowError(
-      parser_->isolate()->factory()->MakeReferenceError_string(),
-      message, HandleVector<Object>(NULL, 0), pos);
+      parser_->ast_value_factory_->make_reference_error_string(), message, NULL,
+      pos);
 }
 
 
 Expression* ParserTraits::NewThrowSyntaxError(
-    const char* message, Handle<Object> arg, int pos) {
-  int argc = arg.is_null() ? 0 : 1;
-  Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
-  return NewThrowError(
-      parser_->isolate()->factory()->MakeSyntaxError_string(),
-      message, arguments, pos);
+    const char* message, const AstRawString* arg, int pos) {
+  return NewThrowError(parser_->ast_value_factory_->make_syntax_error_string(),
+                       message, arg, pos);
 }
 
 
 Expression* ParserTraits::NewThrowTypeError(
-    const char* message, Handle<Object> arg, int pos) {
-  int argc = arg.is_null() ? 0 : 1;
-  Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
-  return NewThrowError(
-      parser_->isolate()->factory()->MakeTypeError_string(),
-      message, arguments, pos);
+    const char* message, const AstRawString* arg, int pos) {
+  return NewThrowError(parser_->ast_value_factory_->make_type_error_string(),
+                       message, arg, pos);
 }
 
 
 Expression* ParserTraits::NewThrowError(
-    Handle<String> constructor, const char* message,
-    Vector<Handle<Object> > arguments, int pos) {
+    const AstRawString* constructor, const char* message,
+    const AstRawString* arg, int pos) {
   Zone* zone = parser_->zone();
-  Factory* factory = parser_->isolate()->factory();
-  int argc = arguments.length();
-  Handle<FixedArray> elements = factory->NewFixedArray(argc, TENURED);
-  for (int i = 0; i < argc; i++) {
-    Handle<Object> element = arguments[i];
-    if (!element.is_null()) {
-      elements->set(i, *element);
-    }
+  int argc = arg != NULL ? 1 : 0;
+  const AstRawString* type =
+      parser_->ast_value_factory_->GetOneByteString(Vector<const uint8_t>(
+          reinterpret_cast<const uint8_t*>(message), StrLength(message)));
+  ZoneList<const AstRawString*>* array =
+      new (zone) ZoneList<const AstRawString*>(argc, zone);
+  if (arg != NULL) {
+    array->Add(arg, zone);
   }
-  Handle<JSArray> array =
-      factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED);
-
-  ZoneList<Expression*>* args = new(zone) ZoneList<Expression*>(2, zone);
-  Handle<String> type = factory->InternalizeUtf8String(message);
-  args->Add(parser_->factory()->NewLiteral(type, pos), zone);
-  args->Add(parser_->factory()->NewLiteral(array, pos), zone);
+  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
+  args->Add(parser_->factory()->NewStringLiteral(type, pos), zone);
+  args->Add(parser_->factory()->NewStringListLiteral(array, pos), zone);
   CallRuntime* call_constructor =
       parser_->factory()->NewCallRuntime(constructor, NULL, args, pos);
   return parser_->factory()->NewThrow(call_constructor, pos);
@@ -634,13 +623,21 @@
   parser_->pending_error_location_ = source_location;
   parser_->pending_error_message_ = message;
   parser_->pending_error_char_arg_ = arg;
-  parser_->pending_error_arg_ = Handle<String>();
+  parser_->pending_error_arg_ = NULL;
   parser_->pending_error_is_reference_error_ = is_reference_error;
 }
 
 
 void ParserTraits::ReportMessage(const char* message,
-                                 MaybeHandle<String> arg,
+                                 const char* arg,
+                                 bool is_reference_error) {
+  Scanner::Location source_location = parser_->scanner()->location();
+  ReportMessageAt(source_location, message, arg, is_reference_error);
+}
+
+
+void ParserTraits::ReportMessage(const char* message,
+                                 const AstRawString* arg,
                                  bool is_reference_error) {
   Scanner::Location source_location = parser_->scanner()->location();
   ReportMessageAt(source_location, message, arg, is_reference_error);
@@ -649,7 +646,7 @@
 
 void ParserTraits::ReportMessageAt(Scanner::Location source_location,
                                    const char* message,
-                                   MaybeHandle<String> arg,
+                                   const AstRawString* arg,
                                    bool is_reference_error) {
   if (parser_->stack_overflow()) {
     // Suppress the error message (syntax error or such) in the presence of a
@@ -666,17 +663,16 @@
 }
 
 
-Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
-  Handle<String> result =
-      parser_->scanner()->AllocateInternalizedString(parser_->isolate());
-  ASSERT(!result.is_null());
+const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
+  const AstRawString* result =
+      parser_->scanner()->CurrentSymbol(parser_->ast_value_factory_);
+  ASSERT(result != NULL);
   return result;
 }
 
 
-Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
-                                               PretenureFlag tenured) {
-  return scanner->AllocateNextLiteralString(parser_->isolate(), tenured);
+const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
+  return parser_->scanner()->NextSymbol(parser_->ast_value_factory_);
 }
 
 
@@ -691,14 +687,13 @@
     Token::Value token, int pos,
     Scanner* scanner,
     AstNodeFactory<AstConstructionVisitor>* factory) {
-  Factory* isolate_factory = parser_->isolate()->factory();
   switch (token) {
     case Token::NULL_LITERAL:
-      return factory->NewLiteral(isolate_factory->null_value(), pos);
+      return factory->NewNullLiteral(pos);
     case Token::TRUE_LITERAL:
-      return factory->NewLiteral(isolate_factory->true_value(), pos);
+      return factory->NewBooleanLiteral(true, pos);
     case Token::FALSE_LITERAL:
-      return factory->NewLiteral(isolate_factory->false_value(), pos);
+      return factory->NewBooleanLiteral(false, pos);
     case Token::NUMBER: {
       double value = scanner->DoubleValue();
       return factory->NewNumberLiteral(value, pos);
@@ -711,13 +706,13 @@
 
 
 Expression* ParserTraits::ExpressionFromIdentifier(
-    Handle<String> name, int pos, Scope* scope,
+    const AstRawString* name, int pos, Scope* scope,
     AstNodeFactory<AstConstructionVisitor>* factory) {
   if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
   // The name may refer to a module instance object, so its type is unknown.
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Variable %s ", name->ToAsciiArray());
+    PrintF("# Variable %.*s ", name->length(), name->raw_data());
 #endif
   Interface* interface = Interface::NewUnknown(parser_->zone());
   return scope->NewUnresolved(factory, name, interface, pos);
@@ -727,16 +722,15 @@
 Expression* ParserTraits::ExpressionFromString(
     int pos, Scanner* scanner,
     AstNodeFactory<AstConstructionVisitor>* factory) {
-  Handle<String> symbol = GetSymbol(scanner);
+  const AstRawString* symbol = GetSymbol(scanner);
   if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
-  return factory->NewLiteral(symbol, pos);
+  return factory->NewStringLiteral(symbol, pos);
 }
 
 
 Literal* ParserTraits::GetLiteralTheHole(
     int position, AstNodeFactory<AstConstructionVisitor>* factory) {
-  return factory->NewLiteral(parser_->isolate()->factory()->the_hole_value(),
-                             RelocInfo::kNoPosition);
+  return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
 }
 
 
@@ -746,7 +740,7 @@
 
 
 FunctionLiteral* ParserTraits::ParseFunctionLiteral(
-    Handle<String> name,
+    const AstRawString* name,
     Scanner::Location function_name_location,
     bool name_is_strict_reserved,
     bool is_generator,
@@ -776,9 +770,11 @@
       target_stack_(NULL),
       cached_data_(NULL),
       cached_data_mode_(NO_CACHED_DATA),
+      ast_value_factory_(NULL),
       info_(info),
       has_pending_error_(false),
       pending_error_message_(NULL),
+      pending_error_arg_(NULL),
       pending_error_char_arg_(NULL) {
   ASSERT(!script_.is_null());
   isolate_->set_ast_node_id(0);
@@ -802,7 +798,7 @@
   if (FLAG_trace_parse) {
     timer.Start();
   }
-  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
+  fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone());
 
   // Initialize parser state.
   CompleteParserRecorder recorder;
@@ -857,13 +853,16 @@
   ASSERT(scope_ == NULL);
   ASSERT(target_stack_ == NULL);
 
-  Handle<String> no_name = isolate()->factory()->empty_string();
-
   FunctionLiteral* result = NULL;
   { Scope* scope = NewScope(scope_, GLOBAL_SCOPE);
     info->SetGlobalScope(scope);
     if (!info->context().is_null()) {
       scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
+      // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
+      // means the Parser cannot operate independent of the V8 heap. Tell the
+      // string table to internalize strings and values right after they're
+      // created.
+      ast_value_factory_->Internalize(isolate());
     }
     original_scope_ = scope;
     if (info->is_eval()) {
@@ -886,7 +885,8 @@
     ParsingModeScope parsing_mode(this, mode);
 
     // Enters 'scope'.
-    FunctionState function_state(&function_state_, &scope_, scope, zone());
+    FunctionState function_state(&function_state_, &scope_, scope, zone(),
+                                 ast_value_factory_);
 
     scope_->SetStrictMode(info->strict_mode());
     ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
@@ -911,9 +911,11 @@
       }
     }
 
+    ast_value_factory_->Internalize(isolate());
     if (ok) {
       result = factory()->NewFunctionLiteral(
-          no_name,
+          ast_value_factory_->empty_string(),
+          ast_value_factory_,
           scope_,
           body,
           function_state.materialized_literal_count(),
@@ -985,8 +987,10 @@
   ASSERT(target_stack_ == NULL);
 
   Handle<String> name(String::cast(shared_info->name()));
-  fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
-  fni_->PushEnclosingName(name);
+  ASSERT(ast_value_factory_);
+  fni_ = new(zone()) FuncNameInferrer(ast_value_factory_, zone());
+  const AstRawString* raw_name = ast_value_factory_->GetString(name);
+  fni_->PushEnclosingName(raw_name);
 
   ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
 
@@ -1002,7 +1006,8 @@
                                            zone());
     }
     original_scope_ = scope;
-    FunctionState function_state(&function_state_, &scope_, scope, zone());
+    FunctionState function_state(&function_state_, &scope_, scope, zone(),
+                                 ast_value_factory_);
     ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
     ASSERT(info()->strict_mode() == shared_info->strict_mode());
     scope->SetStrictMode(shared_info->strict_mode());
@@ -1012,7 +1017,7 @@
               : FunctionLiteral::NAMED_EXPRESSION)
         : FunctionLiteral::DECLARATION;
     bool ok = true;
-    result = ParseFunctionLiteral(name,
+    result = ParseFunctionLiteral(raw_name,
                                   Scanner::Location::invalid(),
                                   false,  // Strict mode name already checked.
                                   shared_info->is_generator(),
@@ -1027,6 +1032,7 @@
   // Make sure the target stack is empty.
   ASSERT(target_stack_ == NULL);
 
+  ast_value_factory_->Internalize(isolate());
   if (result == NULL) {
     if (stack_overflow()) {
       isolate()->StackOverflow();
@@ -1082,15 +1088,12 @@
       // Still processing directive prologue?
       if ((e_stat = stat->AsExpressionStatement()) != NULL &&
           (literal = e_stat->expression()->AsLiteral()) != NULL &&
-          literal->value()->IsString()) {
-        Handle<String> directive = Handle<String>::cast(literal->value());
-
+          literal->raw_value()->IsString()) {
         // Check "use strict" directive (ES5 14.1).
         if (strict_mode() == SLOPPY &&
-            String::Equals(isolate()->factory()->use_strict_string(),
-                           directive) &&
-            token_loc.end_pos - token_loc.beg_pos ==
-              isolate()->heap()->use_strict_string()->length() + 2) {
+            literal->raw_value()->AsString() ==
+                ast_value_factory_->use_strict_string() &&
+            token_loc.end_pos - token_loc.beg_pos == 12) {
           // TODO(mstarzinger): Global strict eval calls, need their own scope
           // as specified in ES5 10.4.2(3). The correct fix would be to always
           // add this scope in DoParseProgram(), but that requires adaptations
@@ -1121,7 +1124,7 @@
 }
 
 
-Statement* Parser::ParseModuleElement(ZoneStringList* labels,
+Statement* Parser::ParseModuleElement(ZoneList<const AstRawString*>* labels,
                                       bool* ok) {
   // (Ecma 262 5th Edition, clause 14):
   // SourceElement:
@@ -1155,10 +1158,9 @@
           !scanner()->HasAnyLineTerminatorBeforeNext() &&
           stmt != NULL) {
         ExpressionStatement* estmt = stmt->AsExpressionStatement();
-        if (estmt != NULL &&
-            estmt->expression()->AsVariableProxy() != NULL &&
-            String::Equals(isolate()->factory()->module_string(),
-                           estmt->expression()->AsVariableProxy()->name()) &&
+        if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
+            estmt->expression()->AsVariableProxy()->raw_name() ==
+                ast_value_factory_->module_string() &&
             !scanner()->literal_contains_escapes()) {
           return ParseModuleDeclaration(NULL, ok);
         }
@@ -1169,16 +1171,18 @@
 }
 
 
-Statement* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) {
+Statement* Parser::ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
+                                          bool* ok) {
   // ModuleDeclaration:
   //    'module' Identifier Module
 
   int pos = peek_position();
-  Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+  const AstRawString* name =
+      ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
 
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Module %s...\n", name->ToAsciiArray());
+    PrintF("# Module %.*s ", name->length(), name->raw_data());
 #endif
 
   Module* module = ParseModule(CHECK_OK);
@@ -1189,10 +1193,9 @@
 
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Module %s.\n", name->ToAsciiArray());
-
+    PrintF("# Module %.*s ", name->length(), name->raw_data());
   if (FLAG_print_interfaces) {
-    PrintF("module %s : ", name->ToAsciiArray());
+    PrintF("module %.*s: ", name->length(), name->raw_data());
     module->interface()->Print();
   }
 #endif
@@ -1293,17 +1296,17 @@
   int pos = peek_position();
   Module* result = ParseModuleVariable(CHECK_OK);
   while (Check(Token::PERIOD)) {
-    Handle<String> name = ParseIdentifierName(CHECK_OK);
+    const AstRawString* name = ParseIdentifierName(CHECK_OK);
 #ifdef DEBUG
     if (FLAG_print_interface_details)
-      PrintF("# Path .%s ", name->ToAsciiArray());
+      PrintF("# Path .%.*s ", name->length(), name->raw_data());
 #endif
     Module* member = factory()->NewModulePath(result, name, pos);
     result->interface()->Add(name, member->interface(), zone(), ok);
     if (!*ok) {
 #ifdef DEBUG
       if (FLAG_print_interfaces) {
-        PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray());
+        PrintF("PATH TYPE ERROR at '%.*s'\n", name->length(), name->raw_data());
         PrintF("result: ");
         result->interface()->Print();
         PrintF("member: ");
@@ -1325,10 +1328,11 @@
   //    Identifier
 
   int pos = peek_position();
-  Handle<String> name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
+  const AstRawString* name =
+      ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
 #ifdef DEBUG
   if (FLAG_print_interface_details)
-    PrintF("# Module variable %s ", name->ToAsciiArray());
+    PrintF("# Module variable %.*s ", name->length(), name->raw_data());
 #endif
   VariableProxy* proxy = scope_->NewUnresolved(
       factory(), name, Interface::NewModule(zone()),
@@ -1344,7 +1348,7 @@
 
   int pos = peek_position();
   Expect(Token::STRING, CHECK_OK);
-  Handle<String> symbol = GetSymbol();
+  const AstRawString* symbol = GetSymbol(scanner());
 
   // TODO(ES6): Request JS resource from environment...
 
@@ -1388,9 +1392,9 @@
 
   int pos = peek_position();
   Expect(Token::IMPORT, CHECK_OK);
-  ZoneStringList names(1, zone());
+  ZoneList<const AstRawString*> names(1, zone());
 
-  Handle<String> name = ParseIdentifierName(CHECK_OK);
+  const AstRawString* name = ParseIdentifierName(CHECK_OK);
   names.Add(name, zone());
   while (peek() == Token::COMMA) {
     Consume(Token::COMMA);
@@ -1408,14 +1412,15 @@
   for (int i = 0; i < names.length(); ++i) {
 #ifdef DEBUG
     if (FLAG_print_interface_details)
-      PrintF("# Import %s ", names[i]->ToAsciiArray());
+      PrintF("# Import %.*s ", name->length(), name->raw_data());
 #endif
     Interface* interface = Interface::NewUnknown(zone());
     module->interface()->Add(names[i], interface, zone(), ok);
     if (!*ok) {
 #ifdef DEBUG
       if (FLAG_print_interfaces) {
-        PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray());
+        PrintF("IMPORT TYPE ERROR at '%.*s'\n", name->length(),
+               name->raw_data());
         PrintF("module: ");
         module->interface()->Print();
       }
@@ -1446,14 +1451,14 @@
   Expect(Token::EXPORT, CHECK_OK);
 
   Statement* result = NULL;
-  ZoneStringList names(1, zone());
+  ZoneList<const AstRawString*> names(1, zone());
   switch (peek()) {
     case Token::IDENTIFIER: {
       int pos = position();
-      Handle<String> name =
+      const AstRawString* name =
           ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
       // Handle 'module' as a context-sensitive keyword.
-      if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
+      if (name != ast_value_factory_->module_string()) {
         names.Add(name, zone());
         while (peek() == Token::COMMA) {
           Consume(Token::COMMA);
@@ -1489,7 +1494,7 @@
   for (int i = 0; i < names.length(); ++i) {
 #ifdef DEBUG
     if (FLAG_print_interface_details)
-      PrintF("# Export %s ", names[i]->ToAsciiArray());
+      PrintF("# Export %.*s ", names[i]->length(), names[i]->raw_data());
 #endif
     Interface* inner = Interface::NewUnknown(zone());
     interface->Add(names[i], inner, zone(), CHECK_OK);
@@ -1509,7 +1514,7 @@
 }
 
 
-Statement* Parser::ParseBlockElement(ZoneStringList* labels,
+Statement* Parser::ParseBlockElement(ZoneList<const AstRawString*>* labels,
                                      bool* ok) {
   // (Ecma 262 5th Edition, clause 14):
   // SourceElement:
@@ -1534,7 +1539,8 @@
 }
 
 
-Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
+                                  bool* ok) {
   // Statement ::
   //   Block
   //   VariableStatement
@@ -1644,8 +1650,8 @@
 }
 
 
-VariableProxy* Parser::NewUnresolved(
-    Handle<String> name, VariableMode mode, Interface* interface) {
+VariableProxy* Parser::NewUnresolved(const AstRawString* name,
+                                     VariableMode mode, Interface* interface) {
   // If we are inside a function, a declaration of a var/const variable is a
   // truly local variable, and the scope of the variable is always the function
   // scope.
@@ -1658,7 +1664,8 @@
 
 void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
   VariableProxy* proxy = declaration->proxy();
-  Handle<String> name = proxy->name();
+  ASSERT(proxy->raw_name() != NULL);
+  const AstRawString* name = proxy->raw_name();
   VariableMode mode = declaration->mode();
   Scope* declaration_scope = DeclarationScope(mode);
   Variable* var = NULL;
@@ -1786,8 +1793,10 @@
     if (FLAG_harmony_modules) {
       bool ok;
 #ifdef DEBUG
-      if (FLAG_print_interface_details)
-        PrintF("# Declare %s\n", var->name()->ToAsciiArray());
+      if (FLAG_print_interface_details) {
+        PrintF("# Declare %.*s ", var->raw_name()->length(),
+               var->raw_name()->raw_data());
+      }
 #endif
       proxy->interface()->Unify(var->interface(), zone(), &ok);
       if (!ok) {
@@ -1815,7 +1824,7 @@
   int pos = peek_position();
   Expect(Token::FUNCTION, CHECK_OK);
   // Allow "eval" or "arguments" for backward compatibility.
-  Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
+  const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
   Expect(Token::LPAREN, CHECK_OK);
   bool done = (peek() == Token::RPAREN);
   while (!done) {
@@ -1850,7 +1859,8 @@
 }
 
 
-Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
+Statement* Parser::ParseFunctionDeclaration(
+    ZoneList<const AstRawString*>* names, bool* ok) {
   // FunctionDeclaration ::
   //   'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
   // GeneratorDeclaration ::
@@ -1860,7 +1870,7 @@
   int pos = position();
   bool is_generator = allow_generators() && Check(Token::MUL);
   bool is_strict_reserved = false;
-  Handle<String> name = ParseIdentifierOrStrictReservedWord(
+  const AstRawString* name = ParseIdentifierOrStrictReservedWord(
       &is_strict_reserved, CHECK_OK);
   FunctionLiteral* fun = ParseFunctionLiteral(name,
                                               scanner()->location(),
@@ -1887,7 +1897,7 @@
 }
 
 
-Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
+Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
   if (allow_harmony_scoping() && strict_mode() == STRICT) {
     return ParseScopedBlock(labels, ok);
   }
@@ -1914,7 +1924,8 @@
 }
 
 
-Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
+Block* Parser::ParseScopedBlock(ZoneList<const AstRawString*>* labels,
+                                bool* ok) {
   // The harmony mode uses block elements instead of statements.
   //
   // Block ::
@@ -1949,12 +1960,12 @@
 
 
 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
-                                      ZoneStringList* names,
+                                      ZoneList<const AstRawString*>* names,
                                       bool* ok) {
   // VariableStatement ::
   //   VariableDeclarations ';'
 
-  Handle<String> ignore;
+  const AstRawString* ignore;
   Block* result =
       ParseVariableDeclarations(var_context, NULL, names, &ignore, CHECK_OK);
   ExpectSemicolon(CHECK_OK);
@@ -1970,8 +1981,8 @@
 Block* Parser::ParseVariableDeclarations(
     VariableDeclarationContext var_context,
     VariableDeclarationProperties* decl_props,
-    ZoneStringList* names,
-    Handle<String>* out,
+    ZoneList<const AstRawString*>* names,
+    const AstRawString** out,
     bool* ok) {
   // VariableDeclarations ::
   //   ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
@@ -2079,7 +2090,7 @@
   // Create new block with one expected declaration.
   Block* block = factory()->NewBlock(NULL, 1, true, pos);
   int nvars = 0;  // the number of variables declared
-  Handle<String> name;
+  const AstRawString* name = NULL;
   do {
     if (fni_ != NULL) fni_->Enter();
 
@@ -2198,7 +2209,7 @@
       ZoneList<Expression*>* arguments =
           new(zone()) ZoneList<Expression*>(3, zone());
       // We have at least 1 parameter.
-      arguments->Add(factory()->NewLiteral(name, pos), zone());
+      arguments->Add(factory()->NewStringLiteral(name, pos), zone());
       CallRuntime* initialize;
 
       if (is_const) {
@@ -2210,7 +2221,7 @@
         // Note that the function does different things depending on
         // the number of arguments (1 or 2).
         initialize = factory()->NewCallRuntime(
-            isolate()->factory()->InitializeConstGlobal_string(),
+            ast_value_factory_->initialize_const_global_string(),
             Runtime::FunctionForId(Runtime::kHiddenInitializeConstGlobal),
             arguments, pos);
       } else {
@@ -2233,7 +2244,7 @@
         // Note that the function does different things depending on
         // the number of arguments (2 or 3).
         initialize = factory()->NewCallRuntime(
-            isolate()->factory()->InitializeVarGlobal_string(),
+            ast_value_factory_->initialize_var_global_string(),
             Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
             arguments, pos);
       }
@@ -2289,11 +2300,12 @@
 }
 
 
-static bool ContainsLabel(ZoneStringList* labels, Handle<String> label) {
-  ASSERT(!label.is_null());
+static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
+                          const AstRawString* label) {
+  ASSERT(label != NULL);
   if (labels != NULL) {
     for (int i = labels->length(); i-- > 0; ) {
-      if (labels->at(i).is_identical_to(label)) {
+      if (labels->at(i) == label) {
         return true;
       }
     }
@@ -2302,8 +2314,8 @@
 }
 
 
-Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
-                                                      bool* ok) {
+Statement* Parser::ParseExpressionOrLabelledStatement(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
   // ExpressionStatement | LabelledStatement ::
   //   Expression ';'
   //   Identifier ':' Statement
@@ -2316,7 +2328,7 @@
     // Expression is a single identifier, and not, e.g., a parenthesized
     // identifier.
     VariableProxy* var = expr->AsVariableProxy();
-    Handle<String> label = var->name();
+    const AstRawString* label = var->raw_name();
     // TODO(1240780): We don't check for redeclaration of labels
     // during preparsing since keeping track of the set of active
     // labels requires nontrivial changes to the way scopes are
@@ -2328,7 +2340,7 @@
       return NULL;
     }
     if (labels == NULL) {
-      labels = new(zone()) ZoneStringList(4, zone());
+      labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
     }
     labels->Add(label, zone());
     // Remove the "ghost" variable that turned out to be a label
@@ -2347,8 +2359,8 @@
       !scanner()->HasAnyLineTerminatorBeforeNext() &&
       expr != NULL &&
       expr->AsVariableProxy() != NULL &&
-      String::Equals(isolate()->factory()->native_string(),
-                     expr->AsVariableProxy()->name()) &&
+      expr->AsVariableProxy()->raw_name() ==
+          ast_value_factory_->native_string() &&
       !scanner()->literal_contains_escapes()) {
     return ParseNativeDeclaration(ok);
   }
@@ -2359,8 +2371,8 @@
       peek() != Token::IDENTIFIER ||
       scanner()->HasAnyLineTerminatorBeforeNext() ||
       expr->AsVariableProxy() == NULL ||
-      !String::Equals(isolate()->factory()->module_string(),
-                      expr->AsVariableProxy()->name()) ||
+      expr->AsVariableProxy()->raw_name() !=
+          ast_value_factory_->module_string() ||
       scanner()->literal_contains_escapes()) {
     ExpectSemicolon(CHECK_OK);
   }
@@ -2368,7 +2380,8 @@
 }
 
 
-IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
+IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
+                                      bool* ok) {
   // IfStatement ::
   //   'if' '(' Expression ')' Statement ('else' Statement)?
 
@@ -2396,19 +2409,18 @@
 
   int pos = peek_position();
   Expect(Token::CONTINUE, CHECK_OK);
-  Handle<String> label = Handle<String>::null();
+  const AstRawString* label = NULL;
   Token::Value tok = peek();
   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
     // ECMA allows "eval" or "arguments" as labels even in strict mode.
     label = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
   }
-  IterationStatement* target = NULL;
-  target = LookupContinueTarget(label, CHECK_OK);
+  IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
   if (target == NULL) {
     // Illegal continue statement.
     const char* message = "illegal_continue";
-    if (!label.is_null()) {
+    if (label != NULL) {
       message = "unknown_label";
     }
     ParserTraits::ReportMessage(message, label);
@@ -2420,13 +2432,14 @@
 }
 
 
-Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
+                                       bool* ok) {
   // BreakStatement ::
   //   'break' Identifier? ';'
 
   int pos = peek_position();
   Expect(Token::BREAK, CHECK_OK);
-  Handle<String> label;
+  const AstRawString* label = NULL;
   Token::Value tok = peek();
   if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
       tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
@@ -2435,7 +2448,7 @@
   }
   // Parse labeled break statements that target themselves into
   // empty statements, e.g. 'l1: l2: l3: break l2;'
-  if (!label.is_null() && ContainsLabel(labels, label)) {
+  if (label != NULL && ContainsLabel(labels, label)) {
     ExpectSemicolon(CHECK_OK);
     return factory()->NewEmptyStatement(pos);
   }
@@ -2444,7 +2457,7 @@
   if (target == NULL) {
     // Illegal break statement.
     const char* message = "illegal_break";
-    if (!label.is_null()) {
+    if (label != NULL) {
       message = "unknown_label";
     }
     ParserTraits::ReportMessage(message, label);
@@ -2498,7 +2511,8 @@
 }
 
 
-Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
+                                      bool* ok) {
   // WithStatement ::
   //   'with' '(' Expression ')' Statement
 
@@ -2560,8 +2574,8 @@
 }
 
 
-SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
-                                              bool* ok) {
+SwitchStatement* Parser::ParseSwitchStatement(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
   // SwitchStatement ::
   //   'switch' '(' Expression ')' '{' CaseClause* '}'
 
@@ -2644,7 +2658,7 @@
   Scope* catch_scope = NULL;
   Variable* catch_variable = NULL;
   Block* catch_block = NULL;
-  Handle<String> name;
+  const AstRawString* name = NULL;
   if (tok == Token::CATCH) {
     Consume(Token::CATCH);
 
@@ -2714,8 +2728,8 @@
 }
 
 
-DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
-                                                bool* ok) {
+DoWhileStatement* Parser::ParseDoWhileStatement(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
   // DoStatement ::
   //   'do' Statement 'while' '(' Expression ')' ';'
 
@@ -2742,7 +2756,8 @@
 }
 
 
-WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
+WhileStatement* Parser::ParseWhileStatement(
+    ZoneList<const AstRawString*>* labels, bool* ok) {
   // WhileStatement ::
   //   'while' '(' Expression ')' Statement
 
@@ -2781,13 +2796,12 @@
   ForOfStatement* for_of = stmt->AsForOfStatement();
 
   if (for_of != NULL) {
-    Factory* heap_factory = isolate()->factory();
     Variable* iterable = scope_->DeclarationScope()->NewTemporary(
-        heap_factory->dot_iterable_string());
+        ast_value_factory_->dot_iterable_string());
     Variable* iterator = scope_->DeclarationScope()->NewTemporary(
-        heap_factory->dot_iterator_string());
+        ast_value_factory_->dot_iterator_string());
     Variable* result = scope_->DeclarationScope()->NewTemporary(
-        heap_factory->dot_result_string());
+        ast_value_factory_->dot_result_string());
 
     Expression* assign_iterable;
     Expression* assign_iterator;
@@ -2805,10 +2819,8 @@
     // var iterator = iterable[Symbol.iterator]();
     {
       Expression* iterable_proxy = factory()->NewVariableProxy(iterable);
-      Handle<Symbol> iterator_symbol(
-          isolate()->native_context()->iterator_symbol(), isolate());
-      Expression* iterator_symbol_literal = factory()->NewLiteral(
-          iterator_symbol, RelocInfo::kNoPosition);
+      Expression* iterator_symbol_literal =
+          factory()->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition);
       // FIXME(wingo): Unhappily, it will be a common error that the RHS of a
       // for-of doesn't have a Symbol.iterator property.  We should do better
       // than informing the user that "undefined is not a function".
@@ -2827,8 +2839,8 @@
     // var result = iterator.next();
     {
       Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
-      Expression* next_literal = factory()->NewLiteral(
-          heap_factory->next_string(), RelocInfo::kNoPosition);
+      Expression* next_literal = factory()->NewStringLiteral(
+          ast_value_factory_->next_string(), RelocInfo::kNoPosition);
       Expression* next_property = factory()->NewProperty(
           iterator_proxy, next_literal, RelocInfo::kNoPosition);
       ZoneList<Expression*>* next_arguments =
@@ -2842,8 +2854,8 @@
 
     // result.done
     {
-      Expression* done_literal = factory()->NewLiteral(
-          heap_factory->done_string(), RelocInfo::kNoPosition);
+      Expression* done_literal = factory()->NewStringLiteral(
+          ast_value_factory_->done_string(), RelocInfo::kNoPosition);
       Expression* result_proxy = factory()->NewVariableProxy(result);
       result_done = factory()->NewProperty(
           result_proxy, done_literal, RelocInfo::kNoPosition);
@@ -2851,8 +2863,8 @@
 
     // each = result.value
     {
-      Expression* value_literal = factory()->NewLiteral(
-          heap_factory->value_string(), RelocInfo::kNoPosition);
+      Expression* value_literal = factory()->NewStringLiteral(
+          ast_value_factory_->value_string(), RelocInfo::kNoPosition);
       Expression* result_proxy = factory()->NewVariableProxy(result);
       Expression* result_value = factory()->NewProperty(
           result_proxy, value_literal, RelocInfo::kNoPosition);
@@ -2873,9 +2885,9 @@
 
 
 Statement* Parser::DesugarLetBindingsInForStatement(
-    Scope* inner_scope, ZoneStringList* names, ForStatement* loop,
-    Statement* init, Expression* cond, Statement* next, Statement* body,
-    bool* ok) {
+    Scope* inner_scope, ZoneList<const AstRawString*>* names,
+    ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+    Statement* body, bool* ok) {
   // ES6 13.6.3.4 specifies that on each loop iteration the let variables are
   // copied into a new environment. After copying, the "next" statement of the
   // loop is executed to update the loop variables. The loop condition is
@@ -2916,10 +2928,7 @@
                                            RelocInfo::kNoPosition);
   outer_block->AddStatement(init, zone());
 
-  Handle<String> temp_name = isolate()->factory()->dot_for_string();
-  Handle<Smi> smi0 = handle(Smi::FromInt(0), isolate());
-  Handle<Smi> smi1 = handle(Smi::FromInt(1), isolate());
-
+  const AstRawString* temp_name = ast_value_factory_->dot_for_string();
 
   // For each let variable x:
   //   make statement: temp_x = x.
@@ -2940,7 +2949,7 @@
   // Make statement: flag = 1.
   {
     VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
-    Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition);
+    Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
     Assignment* assignment = factory()->NewAssignment(
         Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
     Statement* assignment_statement = factory()->NewExpressionStatement(
@@ -2980,7 +2989,7 @@
     Expression* compare = NULL;
     // Make compare expresion: flag == 1.
     {
-      Expression* const1 = factory()->NewLiteral(smi1, RelocInfo::kNoPosition);
+      Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
       VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
       compare = factory()->NewCompareOperation(
           Token::EQ, flag_proxy, const1, pos);
@@ -2989,7 +2998,7 @@
     // Make statement: flag = 0.
     {
       VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
-      Expression* const0 = factory()->NewLiteral(smi0, RelocInfo::kNoPosition);
+      Expression* const0 = factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
       Assignment* assignment = factory()->NewAssignment(
           Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
       clear_flag = factory()->NewExpressionStatement(assignment, pos);
@@ -3003,7 +3012,7 @@
   // Make statement: if (cond) { } else { break; }.
   {
     Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
-    BreakableStatement* t = LookupBreakTarget(Handle<String>(), CHECK_OK);
+    BreakableStatement* t = LookupBreakTarget(NULL, CHECK_OK);
     Statement* stop = factory()->NewBreakStatement(t, RelocInfo::kNoPosition);
     Statement* if_not_cond_break = factory()->NewIfStatement(
         cond, empty, stop, cond->position());
@@ -3034,13 +3043,14 @@
 }
 
 
-Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
+Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
+                                     bool* ok) {
   // ForStatement ::
   //   'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement
 
   int pos = peek_position();
   Statement* init = NULL;
-  ZoneStringList let_bindings(1, zone());
+  ZoneList<const AstRawString*> let_bindings(1, zone());
 
   // Create an in-between scope for let-bound iteration variables.
   Scope* saved_scope = scope_;
@@ -3053,7 +3063,7 @@
   if (peek() != Token::SEMICOLON) {
     if (peek() == Token::VAR || peek() == Token::CONST) {
       bool is_const = peek() == Token::CONST;
-      Handle<String> name;
+      const AstRawString* name = NULL;
       VariableDeclarationProperties decl_props = kHasNoInitializers;
       Block* variable_statement =
           ParseVariableDeclarations(kForStatement, &decl_props, NULL, &name,
@@ -3061,7 +3071,7 @@
       bool accept_OF = decl_props == kHasNoInitializers;
       ForEachStatement::VisitMode mode;
 
-      if (!name.is_null() && CheckInOrOf(accept_OF, &mode)) {
+      if (name != NULL && CheckInOrOf(accept_OF, &mode)) {
         Interface* interface =
             is_const ? Interface::NewConst() : Interface::NewValue();
         ForEachStatement* loop =
@@ -3089,12 +3099,12 @@
         init = variable_statement;
       }
     } else if (peek() == Token::LET) {
-      Handle<String> name;
+      const AstRawString* name = NULL;
       VariableDeclarationProperties decl_props = kHasNoInitializers;
       Block* variable_statement =
-         ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
-                                   &name, CHECK_OK);
-      bool accept_IN = !name.is_null() && decl_props != kHasInitializers;
+          ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
+                                    &name, CHECK_OK);
+      bool accept_IN = name != NULL && decl_props != kHasInitializers;
       bool accept_OF = decl_props == kHasNoInitializers;
       ForEachStatement::VisitMode mode;
 
@@ -3114,14 +3124,8 @@
 
         // TODO(keuchel): Move the temporary variable to the block scope, after
         // implementing stack allocated block scoped variables.
-        Factory* heap_factory = isolate()->factory();
-        Handle<String> tempstr;
-        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
-            isolate(), tempstr,
-            heap_factory->NewConsString(heap_factory->dot_for_string(), name),
-            0);
-        Handle<String> tempname = heap_factory->InternalizeString(tempstr);
-        Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
+        Variable* temp = scope_->DeclarationScope()->NewTemporary(
+            ast_value_factory_->dot_for_string());
         VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
         ForEachStatement* loop =
             factory()->NewForEachStatement(mode, labels, pos);
@@ -3252,7 +3256,7 @@
 }
 
 
-void Parser::ReportInvalidCachedData(Handle<String> name, bool* ok) {
+void Parser::ReportInvalidCachedData(const AstRawString* name, bool* ok) {
   ParserTraits::ReportMessage("invalid_cached_data_function", name);
   *ok = false;
 }
@@ -3302,7 +3306,7 @@
 
 
 FunctionLiteral* Parser::ParseFunctionLiteral(
-    Handle<String> function_name,
+    const AstRawString* function_name,
     Scanner::Location function_name_location,
     bool name_is_strict_reserved,
     bool is_generator,
@@ -3325,11 +3329,11 @@
   // Anonymous functions were passed either the empty symbol or a null
   // handle as the function name.  Remember if we were passed a non-empty
   // handle to decide whether to invoke function name inference.
-  bool should_infer_name = function_name.is_null();
+  bool should_infer_name = function_name == NULL;
 
   // We want a non-null handle as the function name.
   if (should_infer_name) {
-    function_name = isolate()->factory()->empty_string();
+    function_name = ast_value_factory_->empty_string();
   }
 
   int num_parameters = 0;
@@ -3381,7 +3385,9 @@
   AstProperties ast_properties;
   BailoutReason dont_optimize_reason = kNoReason;
   // Parse function body.
-  { FunctionState function_state(&function_state_, &scope_, scope, zone());
+  {
+    FunctionState function_state(&function_state_, &scope_, scope, zone(),
+                                 ast_value_factory_);
     scope_->SetScopeName(function_name);
 
     if (is_generator) {
@@ -3394,7 +3400,7 @@
       // in a temporary variable, a definition that is used by "yield"
       // expressions. This also marks the FunctionState as a generator.
       Variable* temp = scope_->DeclarationScope()->NewTemporary(
-          isolate()->factory()->dot_generator_object_string());
+          ast_value_factory_->dot_generator_object_string());
       function_state.set_generator_object_variable(temp);
     }
 
@@ -3415,7 +3421,7 @@
          arity_restriction != FunctionLiteral::SETTER_ARITY);
     while (!done) {
       bool is_strict_reserved = false;
-      Handle<String> param_name =
+      const AstRawString* param_name =
           ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
 
       // Store locations for possible future error reports.
@@ -3460,6 +3466,7 @@
       VariableMode fvar_mode =
           allow_harmony_scoping() && strict_mode() == STRICT ? CONST
                                                              : CONST_LEGACY;
+      ASSERT(function_name != NULL);
       fvar = new(zone()) Variable(scope_,
          function_name, fvar_mode, true /* is valid LHS */,
          Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
@@ -3544,6 +3551,7 @@
       : FunctionLiteral::kNotGenerator;
   FunctionLiteral* function_literal =
       factory()->NewFunctionLiteral(function_name,
+                                    ast_value_factory_,
                                     scope,
                                     body,
                                     materialized_literal_count,
@@ -3565,7 +3573,7 @@
 }
 
 
-void Parser::SkipLazyFunctionBody(Handle<String> function_name,
+void Parser::SkipLazyFunctionBody(const AstRawString* function_name,
                                   int* materialized_literal_count,
                                   int* expected_property_count,
                                   bool* ok) {
@@ -3644,7 +3652,7 @@
 
 
 ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
-    Handle<String> function_name, int pos, Variable* fvar,
+    const AstRawString* function_name, int pos, Variable* fvar,
     Token::Value fvar_init_op, bool is_generator, bool* ok) {
   // Everything inside an eagerly parsed function will be parsed eagerly
   // (see comment above).
@@ -3667,7 +3675,7 @@
     ZoneList<Expression*>* arguments =
         new(zone()) ZoneList<Expression*>(0, zone());
     CallRuntime* allocation = factory()->NewCallRuntime(
-        isolate()->factory()->empty_string(),
+        ast_value_factory_->empty_string(),
         Runtime::FunctionForId(Runtime::kHiddenCreateJSGeneratorObject),
         arguments, pos);
     VariableProxy* init_proxy = factory()->NewVariableProxy(
@@ -3687,10 +3695,10 @@
   if (is_generator) {
     VariableProxy* get_proxy = factory()->NewVariableProxy(
         function_state_->generator_object_variable());
-    Expression *undefined = factory()->NewLiteral(
-        isolate()->factory()->undefined_value(), RelocInfo::kNoPosition);
-    Yield* yield = factory()->NewYield(
-        get_proxy, undefined, Yield::FINAL, RelocInfo::kNoPosition);
+    Expression* undefined =
+        factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
+    Yield* yield = factory()->NewYield(get_proxy, undefined, Yield::FINAL,
+                                       RelocInfo::kNoPosition);
     body->Add(factory()->NewExpressionStatement(
         yield, RelocInfo::kNoPosition), zone());
   }
@@ -3734,7 +3742,7 @@
   int pos = peek_position();
   Expect(Token::MOD, CHECK_OK);
   // Allow "eval" or "arguments" for backward compatibility.
-  Handle<String> name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
+  const AstRawString* name = ParseIdentifier(kAllowEvalOrArguments, CHECK_OK);
   ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
 
   if (extension_ != NULL) {
@@ -3743,7 +3751,7 @@
     scope_->DeclarationScope()->ForceEagerCompilation();
   }
 
-  const Runtime::Function* function = Runtime::FunctionForName(name);
+  const Runtime::Function* function = Runtime::FunctionForName(name->string());
 
   // Check for built-in IS_VAR macro.
   if (function != NULL &&
@@ -3771,7 +3779,7 @@
   }
 
   // Check that the function is defined if it's an inline runtime call.
-  if (function == NULL && name->Get(0) == '_') {
+  if (function == NULL && name->FirstCharacter() == '_') {
     ParserTraits::ReportMessage("not_defined", name);
     *ok = false;
     return NULL;
@@ -3783,8 +3791,7 @@
 
 
 Literal* Parser::GetLiteralUndefined(int position) {
-  return factory()->NewLiteral(
-      isolate()->factory()->undefined_value(), position);
+  return factory()->NewUndefinedLiteral(position);
 }
 
 
@@ -3793,7 +3800,7 @@
   if (decl != NULL) {
     // In harmony mode we treat conflicting variable bindinds as early
     // errors. See ES5 16 for a definition of early errors.
-    Handle<String> name = decl->proxy()->name();
+    const AstRawString* name = decl->proxy()->raw_name();
     int position = decl->proxy()->position();
     Scanner::Location location = position == RelocInfo::kNoPosition
         ? Scanner::Location::invalid()
@@ -3808,7 +3815,7 @@
 // Parser support
 
 
-bool Parser::TargetStackContainsLabel(Handle<String> label) {
+bool Parser::TargetStackContainsLabel(const AstRawString* label) {
   for (Target* t = target_stack_; t != NULL; t = t->previous()) {
     BreakableStatement* stat = t->node()->AsBreakableStatement();
     if (stat != NULL && ContainsLabel(stat->labels(), label))
@@ -3818,8 +3825,9 @@
 }
 
 
-BreakableStatement* Parser::LookupBreakTarget(Handle<String> label, bool* ok) {
-  bool anonymous = label.is_null();
+BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
+                                              bool* ok) {
+  bool anonymous = label == NULL;
   for (Target* t = target_stack_; t != NULL; t = t->previous()) {
     BreakableStatement* stat = t->node()->AsBreakableStatement();
     if (stat == NULL) continue;
@@ -3833,9 +3841,9 @@
 }
 
 
-IterationStatement* Parser::LookupContinueTarget(Handle<String> label,
+IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
                                                  bool* ok) {
-  bool anonymous = label.is_null();
+  bool anonymous = label == NULL;
   for (Target* t = target_stack_; t != NULL; t = t->previous()) {
     IterationStatement* stat = t->node()->AsIterationStatement();
     if (stat == NULL) continue;
@@ -3862,16 +3870,18 @@
 
 
 void Parser::ThrowPendingError() {
+  ASSERT(ast_value_factory_->IsInternalized());
   if (has_pending_error_) {
     MessageLocation location(script_,
                              pending_error_location_.beg_pos,
                              pending_error_location_.end_pos);
     Factory* factory = isolate()->factory();
     bool has_arg =
-        !pending_error_arg_.is_null() || pending_error_char_arg_ != NULL;
+        pending_error_arg_ != NULL || pending_error_char_arg_ != NULL;
     Handle<FixedArray> elements = factory->NewFixedArray(has_arg ? 1 : 0);
-    if (!pending_error_arg_.is_null()) {
-      elements->set(0, *(pending_error_arg_.ToHandleChecked()));
+    if (pending_error_arg_ != NULL) {
+      Handle<String> arg_string = pending_error_arg_->string();
+      elements->set(0, *arg_string);
     } else if (pending_error_char_arg_ != NULL) {
       Handle<String> arg_string =
           factory->NewStringFromUtf8(CStrVector(pending_error_char_arg_))
@@ -4785,6 +4795,18 @@
 bool Parser::Parse() {
   ASSERT(info()->function() == NULL);
   FunctionLiteral* result = NULL;
+  ast_value_factory_ = info()->ast_value_factory();
+  if (ast_value_factory_ == NULL) {
+    ast_value_factory_ =
+        new AstValueFactory(zone(), isolate()->heap()->HashSeed());
+  }
+  if (allow_natives_syntax() || extension_ != NULL) {
+    // If intrinsics are allowed, the Parser cannot operate independent of the
+    // V8 heap because of Rumtime. Tell the string table to internalize strings
+    // and values right after they're created.
+    ast_value_factory_->Internalize(isolate());
+  }
+
   if (info()->is_lazy()) {
     ASSERT(!info()->is_eval());
     if (info()->shared_info()->is_function()) {
@@ -4810,6 +4832,12 @@
     }
   }
   info()->SetFunction(result);
+  ASSERT(ast_value_factory_->IsInternalized());
+  // info takes ownership of ast_value_factory_.
+  if (info()->ast_value_factory() == NULL) {
+    info()->SetAstValueFactory(ast_value_factory_);
+  }
+  ast_value_factory_ = NULL;
   return (result != NULL);
 }
 
diff --git a/src/parser.h b/src/parser.h
index d011161..3d44d58 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -389,7 +389,7 @@
     typedef v8::internal::Zone Zone;
 
     // Return types for traversing functions.
-    typedef Handle<String> Identifier;
+    typedef const AstRawString* Identifier;
     typedef v8::internal::Expression* Expression;
     typedef Yield* YieldExpression;
     typedef v8::internal::FunctionLiteral* FunctionLiteral;
@@ -421,29 +421,29 @@
   }
 
   // Helper functions for recursive descent.
-  bool IsEvalOrArguments(Handle<String> identifier) const;
+  bool IsEvalOrArguments(const AstRawString* identifier) const;
 
   // Returns true if the expression is of type "this.foo".
   static bool IsThisProperty(Expression* expression);
 
   static bool IsIdentifier(Expression* expression);
 
-  static Handle<String> AsIdentifier(Expression* expression) {
+  static const AstRawString* AsIdentifier(Expression* expression) {
     ASSERT(IsIdentifier(expression));
-    return expression->AsVariableProxy()->name();
+    return expression->AsVariableProxy()->raw_name();
   }
 
   static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
     return ObjectLiteral::IsBoilerplateProperty(property);
   }
 
-  static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
-    return !string.is_null() && string->AsArrayIndex(index);
+  static bool IsArrayIndex(const AstRawString* string, uint32_t* index) {
+    return string->AsArrayIndex(index);
   }
 
   // Functions for encapsulating the differences between parsing and preparsing;
   // operations interleaved with the recursive descent.
-  static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
+  static void PushLiteralName(FuncNameInferrer* fni, const AstRawString* id) {
     fni->PushLiteralName(id);
   }
   void PushPropertyName(FuncNameInferrer* fni, Expression* expression);
@@ -501,16 +501,17 @@
   // type. The first argument may be null (in the handle sense) in
   // which case no arguments are passed to the constructor.
   Expression* NewThrowSyntaxError(
-      const char* type, Handle<Object> arg, int pos);
+      const char* type, const AstRawString* arg, int pos);
 
   // Generate AST node that throws a TypeError with the given
   // type. Both arguments must be non-null (in the handle sense).
-  Expression* NewThrowTypeError(const char* type, Handle<Object> arg, int pos);
+  Expression* NewThrowTypeError(const char* type, const AstRawString* arg,
+                                int pos);
 
   // Generic AST generator for throwing errors from compiled code.
   Expression* NewThrowError(
-      Handle<String> constructor, const char* type,
-      Vector<Handle<Object> > arguments, int pos);
+      const AstRawString* constructor, const char* type,
+      const AstRawString* arg, int pos);
 
   // Reporting errors.
   void ReportMessageAt(Scanner::Location source_location,
@@ -518,16 +519,19 @@
                        const char* arg = NULL,
                        bool is_reference_error = false);
   void ReportMessage(const char* message,
-                     MaybeHandle<String> arg,
+                     const char* arg = NULL,
+                     bool is_reference_error = false);
+  void ReportMessage(const char* message,
+                     const AstRawString* arg,
                      bool is_reference_error = false);
   void ReportMessageAt(Scanner::Location source_location,
                        const char* message,
-                       MaybeHandle<String> arg,
+                       const AstRawString* arg,
                        bool is_reference_error = false);
 
   // "null" return type creators.
-  static Handle<String> EmptyIdentifier() {
-    return Handle<String>();
+  static const AstRawString* EmptyIdentifier() {
+    return NULL;
   }
   static Expression* EmptyExpression() {
     return NULL;
@@ -545,16 +549,16 @@
                              AstNodeFactory<AstConstructionVisitor>* factory);
 
   // Producing data during the recursive descent.
-  Handle<String> GetSymbol(Scanner* scanner = NULL);
-  Handle<String> NextLiteralString(Scanner* scanner,
-                                   PretenureFlag tenured);
+  const AstRawString* GetSymbol(Scanner* scanner);
+  const AstRawString* GetNextSymbol(Scanner* scanner);
+
   Expression* ThisExpression(Scope* scope,
                              AstNodeFactory<AstConstructionVisitor>* factory);
   Literal* ExpressionFromLiteral(
       Token::Value token, int pos, Scanner* scanner,
       AstNodeFactory<AstConstructionVisitor>* factory);
   Expression* ExpressionFromIdentifier(
-      Handle<String> name, int pos, Scope* scope,
+      const AstRawString* name, int pos, Scope* scope,
       AstNodeFactory<AstConstructionVisitor>* factory);
   Expression* ExpressionFromString(
       int pos, Scanner* scanner,
@@ -572,7 +576,7 @@
   // Temporary glue; these functions will move to ParserBase.
   Expression* ParseV8Intrinsic(bool* ok);
   FunctionLiteral* ParseFunctionLiteral(
-      Handle<String> name,
+      const AstRawString* name,
       Scanner::Location function_name_location,
       bool name_is_strict_reserved,
       bool is_generator,
@@ -644,7 +648,7 @@
                                   Handle<String> source);
 
   // Report syntax error
-  void ReportInvalidCachedData(Handle<String> name, bool* ok);
+  void ReportInvalidCachedData(const AstRawString* name, bool* ok);
 
   void SetCachedData(ScriptData** data,
                      CachedDataMode cached_data_mode) {
@@ -671,8 +675,10 @@
   // for failure at the call sites.
   void* ParseSourceElements(ZoneList<Statement*>* processor, int end_token,
                             bool is_eval, bool is_global, bool* ok);
-  Statement* ParseModuleElement(ZoneStringList* labels, bool* ok);
-  Statement* ParseModuleDeclaration(ZoneStringList* names, bool* ok);
+  Statement* ParseModuleElement(ZoneList<const AstRawString*>* labels,
+                                bool* ok);
+  Statement* ParseModuleDeclaration(ZoneList<const AstRawString*>* names,
+                                    bool* ok);
   Module* ParseModule(bool* ok);
   Module* ParseModuleLiteral(bool* ok);
   Module* ParseModulePath(bool* ok);
@@ -681,38 +687,45 @@
   Module* ParseModuleSpecifier(bool* ok);
   Block* ParseImportDeclaration(bool* ok);
   Statement* ParseExportDeclaration(bool* ok);
-  Statement* ParseBlockElement(ZoneStringList* labels, bool* ok);
-  Statement* ParseStatement(ZoneStringList* labels, bool* ok);
-  Statement* ParseFunctionDeclaration(ZoneStringList* names, bool* ok);
+  Statement* ParseBlockElement(ZoneList<const AstRawString*>* labels, bool* ok);
+  Statement* ParseStatement(ZoneList<const AstRawString*>* labels, bool* ok);
+  Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
+                                      bool* ok);
   Statement* ParseNativeDeclaration(bool* ok);
-  Block* ParseBlock(ZoneStringList* labels, bool* ok);
+  Block* ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok);
   Block* ParseVariableStatement(VariableDeclarationContext var_context,
-                                ZoneStringList* names,
+                                ZoneList<const AstRawString*>* names,
                                 bool* ok);
   Block* ParseVariableDeclarations(VariableDeclarationContext var_context,
                                    VariableDeclarationProperties* decl_props,
-                                   ZoneStringList* names,
-                                   Handle<String>* out,
+                                   ZoneList<const AstRawString*>* names,
+                                   const AstRawString** out,
                                    bool* ok);
-  Statement* ParseExpressionOrLabelledStatement(ZoneStringList* labels,
-                                                bool* ok);
-  IfStatement* ParseIfStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseExpressionOrLabelledStatement(
+      ZoneList<const AstRawString*>* labels, bool* ok);
+  IfStatement* ParseIfStatement(ZoneList<const AstRawString*>* labels,
+                                bool* ok);
   Statement* ParseContinueStatement(bool* ok);
-  Statement* ParseBreakStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseBreakStatement(ZoneList<const AstRawString*>* labels,
+                                 bool* ok);
   Statement* ParseReturnStatement(bool* ok);
-  Statement* ParseWithStatement(ZoneStringList* labels, bool* ok);
+  Statement* ParseWithStatement(ZoneList<const AstRawString*>* labels,
+                                bool* ok);
   CaseClause* ParseCaseClause(bool* default_seen_ptr, bool* ok);
-  SwitchStatement* ParseSwitchStatement(ZoneStringList* labels, bool* ok);
-  DoWhileStatement* ParseDoWhileStatement(ZoneStringList* labels, bool* ok);
-  WhileStatement* ParseWhileStatement(ZoneStringList* labels, bool* ok);
-  Statement* ParseForStatement(ZoneStringList* labels, bool* ok);
+  SwitchStatement* ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
+                                        bool* ok);
+  DoWhileStatement* ParseDoWhileStatement(ZoneList<const AstRawString*>* labels,
+                                          bool* ok);
+  WhileStatement* ParseWhileStatement(ZoneList<const AstRawString*>* labels,
+                                      bool* ok);
+  Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok);
   Statement* ParseThrowStatement(bool* ok);
   Expression* MakeCatchContext(Handle<String> id, VariableProxy* value);
   TryStatement* ParseTryStatement(bool* ok);
   DebuggerStatement* ParseDebuggerStatement(bool* ok);
 
   // Support for hamony block scoped bindings.
-  Block* ParseScopedBlock(ZoneStringList* labels, bool* ok);
+  Block* ParseScopedBlock(ZoneList<const AstRawString*>* labels, bool* ok);
 
   // Initialize the components of a for-in / for-of statement.
   void InitializeForEachStatement(ForEachStatement* stmt,
@@ -720,12 +733,12 @@
                                   Expression* subject,
                                   Statement* body);
   Statement* DesugarLetBindingsInForStatement(
-      Scope* inner_scope, ZoneStringList* names, ForStatement* loop,
-      Statement* init, Expression* cond, Statement* next, Statement* body,
-      bool* ok);
+      Scope* inner_scope, ZoneList<const AstRawString*>* names,
+      ForStatement* loop, Statement* init, Expression* cond, Statement* next,
+      Statement* body, bool* ok);
 
   FunctionLiteral* ParseFunctionLiteral(
-      Handle<String> name,
+      const AstRawString* name,
       Scanner::Location function_name_location,
       bool name_is_strict_reserved,
       bool is_generator,
@@ -754,14 +767,14 @@
   void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
 
   // Parser support
-  VariableProxy* NewUnresolved(Handle<String> name,
+  VariableProxy* NewUnresolved(const AstRawString* name,
                                VariableMode mode,
                                Interface* interface);
   void Declare(Declaration* declaration, bool resolve, bool* ok);
 
-  bool TargetStackContainsLabel(Handle<String> label);
-  BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
-  IterationStatement* LookupContinueTarget(Handle<String> label, bool* ok);
+  bool TargetStackContainsLabel(const AstRawString* label);
+  BreakableStatement* LookupBreakTarget(const AstRawString* label, bool* ok);
+  IterationStatement* LookupContinueTarget(const AstRawString* label, bool* ok);
 
   void RegisterTargetUse(Label* target, Target* stop);
 
@@ -771,7 +784,7 @@
 
   // Skip over a lazy function, either using cached data if we have it, or
   // by parsing the function with PreParser. Consumes the ending }.
-  void SkipLazyFunctionBody(Handle<String> function_name,
+  void SkipLazyFunctionBody(const AstRawString* function_name,
                             int* materialized_literal_count,
                             int* expected_property_count,
                             bool* ok);
@@ -780,12 +793,9 @@
       SingletonLogger* logger);
 
   // Consumes the ending }.
-  ZoneList<Statement*>* ParseEagerFunctionBody(Handle<String> function_name,
-                                               int pos,
-                                               Variable* fvar,
-                                               Token::Value fvar_init_op,
-                                               bool is_generator,
-                                               bool* ok);
+  ZoneList<Statement*>* ParseEagerFunctionBody(
+      const AstRawString* function_name, int pos, Variable* fvar,
+      Token::Value fvar_init_op, bool is_generator, bool* ok);
 
   void ThrowPendingError();
 
@@ -798,6 +808,7 @@
   Target* target_stack_;  // for break, continue statements
   ScriptData** cached_data_;
   CachedDataMode cached_data_mode_;
+  AstValueFactory* ast_value_factory_;
 
   CompilationInfo* info_;
 
@@ -805,7 +816,7 @@
   bool has_pending_error_;
   Scanner::Location pending_error_location_;
   const char* pending_error_message_;
-  MaybeHandle<String> pending_error_arg_;
+  const AstRawString* pending_error_arg_;
   const char* pending_error_char_arg_;
   bool pending_error_is_reference_error_;
 };
diff --git a/src/preparser.h b/src/preparser.h
index f8e6203..753ff1b 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -150,7 +150,8 @@
         FunctionState** function_state_stack,
         typename Traits::Type::Scope** scope_stack,
         typename Traits::Type::Scope* scope,
-        typename Traits::Type::Zone* zone = NULL);
+        typename Traits::Type::Zone* zone = NULL,
+        AstValueFactory* ast_value_factory = NULL);
     ~FunctionState();
 
     int NextMaterializedLiteralIndex() {
@@ -395,7 +396,9 @@
 
   void ReportMessageAt(Scanner::Location location, const char* message,
                        bool is_reference_error = false) {
-    Traits::ReportMessageAt(location, message, NULL, is_reference_error);
+    Traits::ReportMessageAt(location, message,
+                            reinterpret_cast<const char*>(NULL),
+                            is_reference_error);
   }
 
   void ReportUnexpectedToken(Token::Value token);
@@ -782,9 +785,9 @@
 
 class PreParserFactory {
  public:
-  explicit PreParserFactory(void* extra_param) {}
-  PreParserExpression NewLiteral(PreParserIdentifier identifier,
-                                 int pos) {
+  explicit PreParserFactory(void* extra_param1, void* extra_param2) {}
+  PreParserExpression NewStringLiteral(PreParserIdentifier identifier,
+                                       int pos) {
     return PreParserExpression::Default();
   }
   PreParserExpression NewNumberLiteral(double number,
@@ -1036,8 +1039,8 @@
 
   // Producing data during the recursive descent.
   PreParserIdentifier GetSymbol(Scanner* scanner);
-  static PreParserIdentifier NextLiteralString(Scanner* scanner,
-                                               PretenureFlag tenured) {
+
+  static PreParserIdentifier GetNextSymbol(Scanner* scanner) {
     return PreParserIdentifier::Default();
   }
 
@@ -1225,7 +1228,8 @@
     FunctionState** function_state_stack,
     typename Traits::Type::Scope** scope_stack,
     typename Traits::Type::Scope* scope,
-    typename Traits::Type::Zone* extra_param)
+    typename Traits::Type::Zone* extra_param,
+    AstValueFactory* ast_value_factory)
     : next_materialized_literal_index_(JSFunction::kLiteralsPrefixSize),
       next_handler_index_(0),
       expected_property_count_(0),
@@ -1237,7 +1241,7 @@
       outer_scope_(*scope_stack),
       saved_ast_node_id_(0),
       extra_param_(extra_param),
-      factory_(extra_param) {
+      factory_(extra_param, ast_value_factory) {
   *scope_stack_ = scope;
   *function_state_stack = this;
   Traits::SetUpFunctionState(this, extra_param);
@@ -1363,14 +1367,14 @@
 
   int literal_index = function_state_->NextMaterializedLiteralIndex();
 
-  IdentifierT js_pattern = this->NextLiteralString(scanner(), TENURED);
+  IdentifierT js_pattern = this->GetNextSymbol(scanner());
   if (!scanner()->ScanRegExpFlags()) {
     Next();
     ReportMessage("invalid_regexp_flags");
     *ok = false;
     return Traits::EmptyExpression();
   }
-  IdentifierT js_flags = this->NextLiteralString(scanner(), TENURED);
+  IdentifierT js_flags = this->GetNextSymbol(scanner());
   Next();
   return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
 }
@@ -1615,7 +1619,7 @@
         }
         // Failed to parse as get/set property, so it's just a normal property
         // (which might be called "get" or "set" or something else).
-        key = factory()->NewLiteral(id, next_pos);
+        key = factory()->NewStringLiteral(id, next_pos);
         break;
       }
       case Token::STRING: {
@@ -1627,7 +1631,7 @@
           key = factory()->NewNumberLiteral(index, next_pos);
           break;
         }
-        key = factory()->NewLiteral(string, next_pos);
+        key = factory()->NewStringLiteral(string, next_pos);
         break;
       }
       case Token::NUMBER: {
@@ -1640,7 +1644,7 @@
         if (Token::IsKeyword(next)) {
           Consume(next);
           IdentifierT string = this->GetSymbol(scanner_);
-          key = factory()->NewLiteral(string, next_pos);
+          key = factory()->NewStringLiteral(string, next_pos);
         } else {
           Token::Value next = Next();
           ReportUnexpectedToken(next);
@@ -2009,7 +2013,7 @@
         int pos = position();
         IdentifierT name = ParseIdentifierName(CHECK_OK);
         result = factory()->NewProperty(
-            result, factory()->NewLiteral(name, pos), pos);
+            result, factory()->NewStringLiteral(name, pos), pos);
         if (fni_ != NULL) this->PushLiteralName(fni_, name);
         break;
       }
@@ -2132,7 +2136,7 @@
         int pos = position();
         IdentifierT name = ParseIdentifierName(CHECK_OK);
         expression = factory()->NewProperty(
-            expression, factory()->NewLiteral(name, pos), pos);
+            expression, factory()->NewStringLiteral(name, pos), pos);
         if (fni_ != NULL) {
           this->PushLiteralName(fni_, name);
         }
diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc
index ecfb015..c0961f2 100644
--- a/src/prettyprinter.cc
+++ b/src/prettyprinter.cc
@@ -6,6 +6,7 @@
 
 #include "src/v8.h"
 
+#include "src/ast-value-factory.h"
 #include "src/platform.h"
 #include "src/prettyprinter.h"
 #include "src/scopes.h"
@@ -133,7 +134,7 @@
 
 void PrettyPrinter::VisitContinueStatement(ContinueStatement* node) {
   Print("continue");
-  ZoneStringList* labels = node->target()->labels();
+  ZoneList<const AstRawString*>* labels = node->target()->labels();
   if (labels != NULL) {
     Print(" ");
     ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
@@ -145,7 +146,7 @@
 
 void PrettyPrinter::VisitBreakStatement(BreakStatement* node) {
   Print("break");
-  ZoneStringList* labels = node->target()->labels();
+  ZoneList<const AstRawString*>* labels = node->target()->labels();
   if (labels != NULL) {
     Print(" ");
     ASSERT(labels->length() > 0);  // guaranteed to have at least one entry
@@ -524,7 +525,7 @@
 }
 
 
-void PrettyPrinter::PrintLabels(ZoneStringList* labels) {
+void PrettyPrinter::PrintLabels(ZoneList<const AstRawString*>* labels) {
   if (labels != NULL) {
     for (int i = 0; i < labels->length(); i++) {
       PrintLiteral(labels->at(i), false);
@@ -582,6 +583,11 @@
 }
 
 
+void PrettyPrinter::PrintLiteral(const AstRawString* value, bool quote) {
+  PrintLiteral(value->string(), quote);
+}
+
+
 void PrettyPrinter::PrintParameters(Scope* scope) {
   Print("(");
   for (int i = 0; i < scope->num_parameters(); i++) {
@@ -676,7 +682,7 @@
 }
 
 
-void AstPrinter::PrintLabelsIndented(ZoneStringList* labels) {
+void AstPrinter::PrintLabelsIndented(ZoneList<const AstRawString*>* labels) {
   if (labels == NULL || labels->length() == 0) return;
   PrintIndented("LABELS ");
   PrintLabels(labels);
diff --git a/src/prettyprinter.h b/src/prettyprinter.h
index 585734e..de40aae 100644
--- a/src/prettyprinter.h
+++ b/src/prettyprinter.h
@@ -44,9 +44,10 @@
   const char* Output() const { return output_; }
 
   virtual void PrintStatements(ZoneList<Statement*>* statements);
-  void PrintLabels(ZoneStringList* labels);
+  void PrintLabels(ZoneList<const AstRawString*>* labels);
   virtual void PrintArguments(ZoneList<Expression*>* arguments);
   void PrintLiteral(Handle<Object> value, bool quote);
+  void PrintLiteral(const AstRawString* value, bool quote);
   void PrintParameters(Scope* scope);
   void PrintDeclarations(ZoneList<Declaration*>* declarations);
   void PrintFunctionLiteral(FunctionLiteral* function);
@@ -83,7 +84,7 @@
   void PrintLiteralWithModeIndented(const char* info,
                                     Variable* var,
                                     Handle<Object> value);
-  void PrintLabelsIndented(ZoneStringList* labels);
+  void PrintLabelsIndented(ZoneList<const AstRawString*>* labels);
 
   void inc_indent() { indent_++; }
   void dec_indent() { indent_--; }
diff --git a/src/rewriter.cc b/src/rewriter.cc
index c92ccda..8ec5c54 100644
--- a/src/rewriter.cc
+++ b/src/rewriter.cc
@@ -20,7 +20,9 @@
         result_assigned_(false),
         is_set_(false),
         in_try_(false),
-        factory_(zone) {
+        // Passing a null AstValueFactory is fine, because Processor doesn't
+        // need to create strings or literals.
+        factory_(zone, NULL) {
     InitializeAstVisitor(zone);
   }
 
@@ -234,8 +236,10 @@
 
   ZoneList<Statement*>* body = function->body();
   if (!body->is_empty()) {
-    Variable* result = scope->NewTemporary(
-        info->isolate()->factory()->dot_result_string());
+    Variable* result =
+        scope->NewTemporary(info->ast_value_factory()->dot_result_string());
+    // The name string must be internalized at this point.
+    ASSERT(!result->name().is_null());
     Processor processor(result, info->zone());
     processor.Process(body);
     if (processor.HasStackOverflow()) return false;
@@ -250,7 +254,7 @@
       // coincides with the end of the with scope which is the position of '1'.
       int pos = function->end_position();
       VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
-          result->name(), false, result->interface(), pos);
+          result->raw_name(), false, result->interface(), pos);
       result_proxy->BindTo(result);
       Statement* result_statement =
           processor.factory()->NewReturnStatement(result_proxy, pos);
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index dddcad0..cba563f 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -110,7 +110,9 @@
 }
 
 
-void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function) {
+void RuntimeProfiler::AttemptOnStackReplacement(JSFunction* function,
+                                                int loop_nesting_levels) {
+  SharedFunctionInfo* shared = function->shared();
   // See AlwaysFullCompiler (in compiler.cc) comment on why we need
   // Debug::has_break_points().
   if (!FLAG_use_osr ||
@@ -119,7 +121,6 @@
     return;
   }
 
-  SharedFunctionInfo* shared = function->shared();
   // If the code is not optimizable, don't try OSR.
   if (!shared->code()->optimizable()) return;
 
@@ -137,7 +138,9 @@
     PrintF("]\n");
   }
 
-  BackEdgeTable::Patch(isolate_, shared->code());
+  for (int i = 0; i < loop_nesting_levels; i++) {
+    BackEdgeTable::Patch(isolate_, shared->code());
+  }
 }
 
 
@@ -175,14 +178,8 @@
     if (shared_code->kind() != Code::FUNCTION) continue;
     if (function->IsInOptimizationQueue()) continue;
 
-    if (FLAG_always_osr &&
-        shared_code->allow_osr_at_loop_nesting_level() == 0) {
-      // Testing mode: always try an OSR compile for every function.
-      for (int i = 0; i < Code::kMaxLoopNestingMarker; i++) {
-        // TODO(titzer): fix AttemptOnStackReplacement to avoid this dumb loop.
-        shared_code->set_allow_osr_at_loop_nesting_level(i);
-        AttemptOnStackReplacement(function);
-      }
+    if (FLAG_always_osr) {
+      AttemptOnStackReplacement(function, Code::kMaxLoopNestingMarker);
       // Fall through and do a normal optimized compile as well.
     } else if (!frame->is_optimized() &&
         (function->IsMarkedForOptimization() ||
@@ -196,12 +193,7 @@
       if (shared_code->CodeSize() > allowance) {
         if (ticks < 255) shared_code->set_profiler_ticks(ticks + 1);
       } else {
-        int nesting = shared_code->allow_osr_at_loop_nesting_level();
-        if (nesting < Code::kMaxLoopNestingMarker) {
-          int new_nesting = nesting + 1;
-          shared_code->set_allow_osr_at_loop_nesting_level(new_nesting);
-          AttemptOnStackReplacement(function);
-        }
+        AttemptOnStackReplacement(function);
       }
       continue;
     }
diff --git a/src/runtime-profiler.h b/src/runtime-profiler.h
index fa8352d..14ced76 100644
--- a/src/runtime-profiler.h
+++ b/src/runtime-profiler.h
@@ -23,7 +23,7 @@
 
   void NotifyICChanged() { any_ic_changed_ = true; }
 
-  void AttemptOnStackReplacement(JSFunction* function);
+  void AttemptOnStackReplacement(JSFunction* function, int nesting_levels = 1);
 
  private:
   void Optimize(JSFunction* function, const char* reason);
diff --git a/src/runtime.cc b/src/runtime.cc
index 3cb6fe2..6d7fca9 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -310,7 +310,7 @@
   // computed properties have been assigned so that we can generate
   // constant function properties.
   if (should_transform && !has_function_literal) {
-    JSObject::TransformToFastProperties(
+    JSObject::MigrateSlowToFast(
         boilerplate, boilerplate->map()->unused_property_fields());
   }
 
@@ -5055,7 +5055,7 @@
   // DefineAccessor checks access rights.
   JSObject::DefineAccessor(obj, name, getter, setter, attr);
   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
-  if (fast) JSObject::TransformToFastProperties(obj, 0);
+  if (fast) JSObject::MigrateSlowToFast(obj, 0);
   return isolate->heap()->undefined_value();
 }
 
@@ -6036,7 +6036,7 @@
   ASSERT(args.length() == 1);
   CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
   if (object->IsJSObject() && !object->IsGlobalObject()) {
-    JSObject::TransformToFastProperties(Handle<JSObject>::cast(object), 0);
+    JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0);
   }
   return *object;
 }
@@ -8530,16 +8530,11 @@
   if (args.length() == 2 &&
       unoptimized->kind() == Code::FUNCTION) {
     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
-    if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
+    if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr")) && FLAG_use_osr) {
       // Start patching from the currently patched loop nesting level.
-      int current_level = unoptimized->allow_osr_at_loop_nesting_level();
-      ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
-      if (FLAG_use_osr) {
-        for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
-          unoptimized->set_allow_osr_at_loop_nesting_level(i);
-          isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
-        }
-      }
+      ASSERT(BackEdgeTable::Verify(isolate, unoptimized));
+      isolate->runtime_profiler()->AttemptOnStackReplacement(
+          *function, Code::kMaxLoopNestingMarker);
     } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent")) &&
                isolate->concurrent_recompilation_enabled()) {
       function->MarkForConcurrentOptimization();
@@ -9138,6 +9133,23 @@
   // In Win64 they are assigned to a hidden first argument.
   return result;
 }
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+// For x32 a 128-bit struct return is done as rax and rdx from the ObjectPair
+// are used in the full codegen and Crankshaft compiler. An alternative is
+// using uint64_t and modifying full codegen and Crankshaft compiler.
+struct ObjectPair {
+  Object* x;
+  uint32_t x_upper;
+  Object* y;
+  uint32_t y_upper;
+};
+
+
+static inline ObjectPair MakePair(Object* x, Object* y) {
+  ObjectPair result = {x, 0, y, 0};
+  // Pointers x and y returned in rax and rdx, in x32-abi.
+  return result;
+}
 #else
 typedef uint64_t ObjectPair;
 static inline ObjectPair MakePair(Object* x, Object* y) {
diff --git a/src/sampler.cc b/src/sampler.cc
index aedf75f..82fe27d 100644
--- a/src/sampler.cc
+++ b/src/sampler.cc
@@ -596,7 +596,7 @@
 
   SafeStackFrameIterator it(isolate, regs.fp, regs.sp, js_entry_sp);
   top_frame_type = it.top_frame_type();
-  int i = 0;
+  unsigned i = 0;
   while (!it.done() && i < TickSample::kMaxFramesCount) {
     stack[i++] = it.frame()->pc();
     it.Advance();
diff --git a/src/sampler.h b/src/sampler.h
index fe94a02..80fe5a9 100644
--- a/src/sampler.h
+++ b/src/sampler.h
@@ -44,10 +44,11 @@
     Address tos;   // Top stack value (*sp).
     Address external_callback;
   };
-  static const int kMaxFramesCount = 64;
+  static const unsigned kMaxFramesCountLog2 = 8;
+  static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
   Address stack[kMaxFramesCount];  // Call stack.
   TimeTicks timestamp;
-  int frames_count : 8;  // Number of captured frames.
+  unsigned frames_count : kMaxFramesCountLog2;  // Number of captured frames.
   bool has_external_callback : 1;
   StackFrame::Type top_frame_type : 4;
 };
diff --git a/src/scanner.cc b/src/scanner.cc
index 4e2e8fd..df19ee8 100644
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -9,6 +9,7 @@
 #include "src/v8.h"
 
 #include "include/v8stdint.h"
+#include "src/ast-value-factory.h"
 #include "src/char-predicates-inl.h"
 #include "src/conversions-inl.h"
 #include "src/list-inl.h"
@@ -1093,26 +1094,19 @@
 }
 
 
-Handle<String> Scanner::AllocateNextLiteralString(Isolate* isolate,
-                                                  PretenureFlag tenured) {
-  if (is_next_literal_one_byte()) {
-    return isolate->factory()->NewStringFromOneByte(
-        next_literal_one_byte_string(), tenured).ToHandleChecked();
-  } else {
-    return isolate->factory()->NewStringFromTwoByte(
-        next_literal_two_byte_string(), tenured).ToHandleChecked();
+const AstRawString* Scanner::CurrentSymbol(AstValueFactory* ast_value_factory) {
+  if (is_literal_one_byte()) {
+    return ast_value_factory->GetOneByteString(literal_one_byte_string());
   }
+  return ast_value_factory->GetTwoByteString(literal_two_byte_string());
 }
 
 
-Handle<String> Scanner::AllocateInternalizedString(Isolate* isolate) {
-  if (is_literal_one_byte()) {
-    return isolate->factory()->InternalizeOneByteString(
-        literal_one_byte_string());
-  } else {
-    return isolate->factory()->InternalizeTwoByteString(
-        literal_two_byte_string());
+const AstRawString* Scanner::NextSymbol(AstValueFactory* ast_value_factory) {
+  if (is_next_literal_one_byte()) {
+    return ast_value_factory->GetOneByteString(next_literal_one_byte_string());
   }
+  return ast_value_factory->GetTwoByteString(next_literal_two_byte_string());
 }
 
 
diff --git a/src/scanner.h b/src/scanner.h
index 2979082..8fee1b1 100644
--- a/src/scanner.h
+++ b/src/scanner.h
@@ -21,6 +21,8 @@
 namespace internal {
 
 
+class AstRawString;
+class AstValueFactory;
 class ParserRecorder;
 
 
@@ -376,9 +378,8 @@
     return next_.literal_chars->is_contextual_keyword(keyword);
   }
 
-  Handle<String> AllocateNextLiteralString(Isolate* isolate,
-                                           PretenureFlag tenured);
-  Handle<String> AllocateInternalizedString(Isolate* isolate);
+  const AstRawString* CurrentSymbol(AstValueFactory* ast_value_factory);
+  const AstRawString* NextSymbol(AstValueFactory* ast_value_factory);
 
   double DoubleValue();
   bool UnescapedLiteralMatches(const char* data, int length) {
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index d84c5bf..bce8244 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -540,7 +540,7 @@
   for (Interface::Iterator it = interface->iterator();
        !it.done(); it.Advance(), ++i) {
     Variable* var = scope->LookupLocal(it.name());
-    info->set_name(i, *it.name());
+    info->set_name(i, *(it.name()->string()));
     info->set_mode(i, var->mode());
     ASSERT((var->mode() == MODULE) == (it.interface()->IsModule()));
     if (var->mode() == MODULE) {
diff --git a/src/scopes.cc b/src/scopes.cc
index 497f794..2b3c07a 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -24,34 +24,28 @@
 //       use. Because a Variable holding a handle with the same location exists
 //       this is ensured.
 
-static bool Match(void* key1, void* key2) {
-  String* name1 = *reinterpret_cast<String**>(key1);
-  String* name2 = *reinterpret_cast<String**>(key2);
-  ASSERT(name1->IsInternalizedString());
-  ASSERT(name2->IsInternalizedString());
-  return name1 == name2;
-}
-
-
 VariableMap::VariableMap(Zone* zone)
-    : ZoneHashMap(Match, 8, ZoneAllocationPolicy(zone)),
+    : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)),
       zone_(zone) {}
 VariableMap::~VariableMap() {}
 
 
 Variable* VariableMap::Declare(
     Scope* scope,
-    Handle<String> name,
+    const AstRawString* name,
     VariableMode mode,
     bool is_valid_lhs,
     Variable::Kind kind,
     InitializationFlag initialization_flag,
     Interface* interface) {
-  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true,
-                                 ZoneAllocationPolicy(zone()));
+  // AstRawStrings are unambiguous, i.e., the same string is always represented
+  // by the same AstRawString*.
+  // FIXME(marja): fix the type of Lookup.
+  Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
+                                 true, ZoneAllocationPolicy(zone()));
   if (p->value == NULL) {
     // The variable has not been declared yet -> insert it.
-    ASSERT(p->key == name.location());
+    ASSERT(p->key == name);
     p->value = new(zone()) Variable(scope,
                                     name,
                                     mode,
@@ -64,11 +58,11 @@
 }
 
 
-Variable* VariableMap::Lookup(Handle<String> name) {
-  Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), false,
-                                 ZoneAllocationPolicy(NULL));
+Variable* VariableMap::Lookup(const AstRawString* name) {
+  Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(),
+                                 false, ZoneAllocationPolicy(NULL));
   if (p != NULL) {
-    ASSERT(*reinterpret_cast<String**>(p->key) == *name);
+    ASSERT(reinterpret_cast<const AstRawString*>(p->key) == name);
     ASSERT(p->value != NULL);
     return reinterpret_cast<Variable*>(p->value);
   }
@@ -79,7 +73,8 @@
 // ----------------------------------------------------------------------------
 // Implementation of Scope
 
-Scope::Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone)
+Scope::Scope(Scope* outer_scope, ScopeType scope_type,
+             AstValueFactory* ast_value_factory, Zone* zone)
     : isolate_(zone->isolate()),
       inner_scopes_(4, zone),
       variables_(zone),
@@ -92,6 +87,7 @@
                  (scope_type == MODULE_SCOPE || scope_type == GLOBAL_SCOPE)
                      ? Interface::NewModule(zone) : NULL),
       already_resolved_(false),
+      ast_value_factory_(ast_value_factory),
       zone_(zone) {
   SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null());
   // The outermost scope must be a global scope.
@@ -103,6 +99,7 @@
 Scope::Scope(Scope* inner_scope,
              ScopeType scope_type,
              Handle<ScopeInfo> scope_info,
+             AstValueFactory* value_factory,
              Zone* zone)
     : isolate_(zone->isolate()),
       inner_scopes_(4, zone),
@@ -114,6 +111,7 @@
       decls_(4, zone),
       interface_(NULL),
       already_resolved_(true),
+      ast_value_factory_(value_factory),
       zone_(zone) {
   SetDefaults(scope_type, NULL, scope_info);
   if (!scope_info.is_null()) {
@@ -126,7 +124,8 @@
 }
 
 
-Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone)
+Scope::Scope(Scope* inner_scope, const AstRawString* catch_variable_name,
+             AstValueFactory* value_factory, Zone* zone)
     : isolate_(zone->isolate()),
       inner_scopes_(1, zone),
       variables_(zone),
@@ -137,6 +136,7 @@
       decls_(0, zone),
       interface_(NULL),
       already_resolved_(true),
+      ast_value_factory_(value_factory),
       zone_(zone) {
   SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
   AddInnerScope(inner_scope);
@@ -157,7 +157,7 @@
                         Handle<ScopeInfo> scope_info) {
   outer_scope_ = outer_scope;
   scope_type_ = scope_type;
-  scope_name_ = isolate_->factory()->empty_string();
+  scope_name_ = ast_value_factory_->empty_string();
   dynamics_ = NULL;
   receiver_ = NULL;
   function_ = NULL;
@@ -199,6 +199,7 @@
       Scope* with_scope = new(zone) Scope(current_scope,
                                           WITH_SCOPE,
                                           Handle<ScopeInfo>::null(),
+                                          global_scope->ast_value_factory_,
                                           zone);
       current_scope = with_scope;
       // All the inner scopes are inside a with.
@@ -211,30 +212,36 @@
       current_scope = new(zone) Scope(current_scope,
                                       GLOBAL_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else if (context->IsModuleContext()) {
       ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
       current_scope = new(zone) Scope(current_scope,
                                       MODULE_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else if (context->IsFunctionContext()) {
       ScopeInfo* scope_info = context->closure()->shared()->scope_info();
       current_scope = new(zone) Scope(current_scope,
                                       FUNCTION_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else if (context->IsBlockContext()) {
       ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
       current_scope = new(zone) Scope(current_scope,
                                       BLOCK_SCOPE,
                                       Handle<ScopeInfo>(scope_info),
+                                      global_scope->ast_value_factory_,
                                       zone);
     } else {
       ASSERT(context->IsCatchContext());
       String* name = String::cast(context->extension());
-      current_scope = new(zone) Scope(
-          current_scope, Handle<String>(name), zone);
+      current_scope = new (zone) Scope(
+          current_scope,
+          global_scope->ast_value_factory_->GetString(Handle<String>(name)),
+          global_scope->ast_value_factory_, zone);
     }
     if (contains_with) current_scope->RecordWithStatement();
     if (innermost_scope == NULL) innermost_scope = current_scope;
@@ -266,7 +273,9 @@
 
   // Allocate the variables.
   {
-    AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone());
+    // Passing NULL as AstValueFactory is ok, because AllocateVariables doesn't
+    // need to create new strings or values.
+    AstNodeFactory<AstNullVisitor> ast_node_factory(info->zone(), NULL);
     if (!top->AllocateVariables(info, &ast_node_factory)) return false;
   }
 
@@ -310,7 +319,7 @@
   if (is_declaration_scope()) {
     Variable* var =
         variables_.Declare(this,
-                           isolate_->factory()->this_string(),
+                           ast_value_factory_->this_string(),
                            VAR,
                            false,
                            Variable::THIS,
@@ -327,7 +336,7 @@
     // Note that it might never be accessed, in which case it won't be
     // allocated during variable allocation.
     variables_.Declare(this,
-                       isolate_->factory()->arguments_string(),
+                       ast_value_factory_->arguments_string(),
                        VAR,
                        true,
                        Variable::ARGUMENTS,
@@ -366,23 +375,28 @@
 }
 
 
-Variable* Scope::LookupLocal(Handle<String> name) {
+Variable* Scope::LookupLocal(const AstRawString* name) {
   Variable* result = variables_.Lookup(name);
   if (result != NULL || scope_info_.is_null()) {
     return result;
   }
+  // The Scope is backed up by ScopeInfo. This means it cannot operate in a
+  // heap-independent mode, and all strings must be internalized immediately. So
+  // it's ok to get the Handle<String> here.
+  Handle<String> name_handle = name->string();
   // If we have a serialized scope info, we might find the variable there.
   // There should be no local slot with the given name.
-  ASSERT(scope_info_->StackSlotIndex(*name) < 0);
+  ASSERT(scope_info_->StackSlotIndex(*name_handle) < 0);
 
   // Check context slot lookup.
   VariableMode mode;
   Variable::Location location = Variable::CONTEXT;
   InitializationFlag init_flag;
-  int index = ScopeInfo::ContextSlotIndex(scope_info_, name, &mode, &init_flag);
+  int index =
+      ScopeInfo::ContextSlotIndex(scope_info_, name_handle, &mode, &init_flag);
   if (index < 0) {
     // Check parameters.
-    index = scope_info_->ParameterIndex(*name);
+    index = scope_info_->ParameterIndex(*name_handle);
     if (index < 0) return NULL;
 
     mode = DYNAMIC;
@@ -397,14 +411,14 @@
 }
 
 
-Variable* Scope::LookupFunctionVar(Handle<String> name,
+Variable* Scope::LookupFunctionVar(const AstRawString* name,
                                    AstNodeFactory<AstNullVisitor>* factory) {
-  if (function_ != NULL && function_->proxy()->name().is_identical_to(name)) {
+  if (function_ != NULL && function_->proxy()->raw_name() == name) {
     return function_->proxy()->var();
   } else if (!scope_info_.is_null()) {
     // If we are backed by a scope info, try to lookup the variable there.
     VariableMode mode;
-    int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
+    int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode);
     if (index < 0) return NULL;
     Variable* var = new(zone()) Variable(
         this, name, mode, true /* is valid LHS */,
@@ -421,7 +435,7 @@
 }
 
 
-Variable* Scope::Lookup(Handle<String> name) {
+Variable* Scope::Lookup(const AstRawString* name) {
   for (Scope* scope = this;
        scope != NULL;
        scope = scope->outer_scope()) {
@@ -432,7 +446,7 @@
 }
 
 
-void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
+void Scope::DeclareParameter(const AstRawString* name, VariableMode mode) {
   ASSERT(!already_resolved());
   ASSERT(is_function_scope());
   Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL,
@@ -441,7 +455,7 @@
 }
 
 
-Variable* Scope::DeclareLocal(Handle<String> name,
+Variable* Scope::DeclareLocal(const AstRawString* name,
                               VariableMode mode,
                               InitializationFlag init_flag,
                               Interface* interface) {
@@ -456,7 +470,7 @@
 }
 
 
-Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
+Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) {
   ASSERT(is_global_scope());
   return variables_.Declare(this,
                             name,
@@ -479,7 +493,7 @@
 }
 
 
-Variable* Scope::NewInternal(Handle<String> name) {
+Variable* Scope::NewInternal(const AstRawString* name) {
   ASSERT(!already_resolved());
   Variable* var = new(zone()) Variable(this,
                                        name,
@@ -492,7 +506,7 @@
 }
 
 
-Variable* Scope::NewTemporary(Handle<String> name) {
+Variable* Scope::NewTemporary(const AstRawString* name) {
   ASSERT(!already_resolved());
   Variable* var = new(zone()) Variable(this,
                                        name,
@@ -530,7 +544,7 @@
   for (int i = 0; i < length; i++) {
     Declaration* decl = decls_[i];
     if (decl->mode() != VAR) continue;
-    Handle<String> name = decl->proxy()->name();
+    const AstRawString* name = decl->proxy()->raw_name();
 
     // Iterate through all scopes until and including the declaration scope.
     Scope* previous = NULL;
@@ -773,9 +787,8 @@
 }
 
 
-static void PrintName(Handle<String> name) {
-  SmartArrayPointer<char> s = name->ToCString(DISALLOW_NULLS);
-  PrintF("%s", s.get());
+static void PrintName(const AstRawString* name) {
+  PrintF("%.*s", name->length(), name->raw_data());
 }
 
 
@@ -803,7 +816,7 @@
   if (var->is_used() || !var->IsUnallocated()) {
     Indent(indent, Variable::Mode2String(var->mode()));
     PrintF(" ");
-    PrintName(var->name());
+    PrintName(var->raw_name());
     PrintF(";  // ");
     PrintLocation(var);
     if (var->has_forced_context_allocation()) {
@@ -829,7 +842,7 @@
 
   // Print header.
   Indent(n0, Header(scope_type_));
-  if (scope_name_->length() > 0) {
+  if (!scope_name_->IsEmpty()) {
     PrintF(" ");
     PrintName(scope_name_);
   }
@@ -839,7 +852,7 @@
     PrintF(" (");
     for (int i = 0; i < params_.length(); i++) {
       if (i > 0) PrintF(", ");
-      PrintName(params_[i]->name());
+      PrintName(params_[i]->raw_name());
     }
     PrintF(")");
   }
@@ -849,7 +862,7 @@
   // Function name, if any (named function literals, only).
   if (function_ != NULL) {
     Indent(n1, "// (local) function name: ");
-    PrintName(function_->proxy()->name());
+    PrintName(function_->proxy()->raw_name());
     PrintF("\n");
   }
 
@@ -917,8 +930,8 @@
 #endif  // DEBUG
 
 
-Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
-  if (dynamics_ == NULL) dynamics_ = new(zone()) DynamicScopePart(zone());
+Variable* Scope::NonLocal(const AstRawString* name, VariableMode mode) {
+  if (dynamics_ == NULL) dynamics_ = new (zone()) DynamicScopePart(zone());
   VariableMap* map = dynamics_->GetMap(mode);
   Variable* var = map->Lookup(name);
   if (var == NULL) {
@@ -938,7 +951,7 @@
 }
 
 
-Variable* Scope::LookupRecursive(Handle<String> name,
+Variable* Scope::LookupRecursive(const AstRawString* name,
                                  BindingKind* binding_kind,
                                  AstNodeFactory<AstNullVisitor>* factory) {
   ASSERT(binding_kind != NULL);
@@ -1012,7 +1025,7 @@
 
   // Otherwise, try to resolve the variable.
   BindingKind binding_kind;
-  Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
+  Variable* var = LookupRecursive(proxy->raw_name(), &binding_kind, factory);
   switch (binding_kind) {
     case BOUND:
       // We found a variable binding.
@@ -1024,29 +1037,29 @@
       // scope which was not promoted to a context, this can happen if we use
       // debugger to evaluate arbitrary expressions at a break point).
       if (var->IsGlobalObjectProperty()) {
-        var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+        var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
       } else if (var->is_dynamic()) {
-        var = NonLocal(proxy->name(), DYNAMIC);
+        var = NonLocal(proxy->raw_name(), DYNAMIC);
       } else {
         Variable* invalidated = var;
-        var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
+        var = NonLocal(proxy->raw_name(), DYNAMIC_LOCAL);
         var->set_local_if_not_shadowed(invalidated);
       }
       break;
 
     case UNBOUND:
       // No binding has been found. Declare a variable on the global object.
-      var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
+      var = info->global_scope()->DeclareDynamicGlobal(proxy->raw_name());
       break;
 
     case UNBOUND_EVAL_SHADOWED:
       // No binding has been found. But some scope makes a sloppy 'eval' call.
-      var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
+      var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL);
       break;
 
     case DYNAMIC_LOOKUP:
       // The variable could not be resolved statically.
-      var = NonLocal(proxy->name(), DYNAMIC);
+      var = NonLocal(proxy->raw_name(), DYNAMIC);
       break;
   }
 
@@ -1069,8 +1082,10 @@
   if (FLAG_harmony_modules) {
     bool ok;
 #ifdef DEBUG
-    if (FLAG_print_interface_details)
-      PrintF("# Resolve %s:\n", var->name()->ToAsciiArray());
+    if (FLAG_print_interface_details) {
+      PrintF("# Resolve %.*s:\n", var->raw_name()->length(),
+             var->raw_name()->raw_data());
+    }
 #endif
     proxy->interface()->Unify(var->interface(), zone(), &ok);
     if (!ok) {
@@ -1150,7 +1165,7 @@
   // Give var a read/write use if there is a chance it might be accessed
   // via an eval() call.  This is only possible if the variable has a
   // visible name.
-  if ((var->is_this() || var->name()->length() > 0) &&
+  if ((var->is_this() || !var->raw_name()->IsEmpty()) &&
       (var->has_forced_context_allocation() ||
        scope_calls_eval_ ||
        inner_scope_calls_eval_ ||
@@ -1211,7 +1226,7 @@
 
 void Scope::AllocateParameterLocals() {
   ASSERT(is_function_scope());
-  Variable* arguments = LookupLocal(isolate_->factory()->arguments_string());
+  Variable* arguments = LookupLocal(ast_value_factory_->arguments_string());
   ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
 
   bool uses_sloppy_arguments = false;
@@ -1352,10 +1367,9 @@
   if (already_resolved()) return;
   if (is_module_scope()) {
     ASSERT(interface_->IsFrozen());
-    Handle<String> name = isolate_->factory()->InternalizeOneByteString(
-        STATIC_ASCII_VECTOR(".module"));
     ASSERT(module_var_ == NULL);
-    module_var_ = host_scope->NewInternal(name);
+    module_var_ =
+        host_scope->NewInternal(ast_value_factory_->dot_module_string());
     ++host_scope->num_modules_;
   }
 
diff --git a/src/scopes.h b/src/scopes.h
index 4486921..c313a40 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -22,14 +22,14 @@
   virtual ~VariableMap();
 
   Variable* Declare(Scope* scope,
-                    Handle<String> name,
+                    const AstRawString* name,
                     VariableMode mode,
                     bool is_valid_lhs,
                     Variable::Kind kind,
                     InitializationFlag initialization_flag,
                     Interface* interface = Interface::NewValue());
 
-  Variable* Lookup(Handle<String> name);
+  Variable* Lookup(const AstRawString* name);
 
   Zone* zone() const { return zone_; }
 
@@ -74,7 +74,8 @@
   // ---------------------------------------------------------------------------
   // Construction
 
-  Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone);
+  Scope(Scope* outer_scope, ScopeType scope_type,
+        AstValueFactory* value_factory, Zone* zone);
 
   // Compute top scope and allocate variables. For lazy compilation the top
   // scope only contains the single lazily compiled function, so this
@@ -85,7 +86,9 @@
                                       Zone* zone);
 
   // The scope name is only used for printing/debugging.
-  void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
+  void SetScopeName(const AstRawString* scope_name) {
+    scope_name_ = scope_name;
+  }
 
   void Initialize();
 
@@ -100,18 +103,18 @@
   // Declarations
 
   // Lookup a variable in this scope. Returns the variable or NULL if not found.
-  Variable* LookupLocal(Handle<String> name);
+  Variable* LookupLocal(const AstRawString* name);
 
   // This lookup corresponds to a lookup in the "intermediate" scope sitting
   // between this scope and the outer scope. (ECMA-262, 3rd., requires that
   // the name of named function literal is kept in an intermediate scope
   // in between this scope and the next outer scope.)
-  Variable* LookupFunctionVar(Handle<String> name,
+  Variable* LookupFunctionVar(const AstRawString* name,
                               AstNodeFactory<AstNullVisitor>* factory);
 
   // Lookup a variable in this scope or outer scopes.
   // Returns the variable or NULL if not found.
-  Variable* Lookup(Handle<String> name);
+  Variable* Lookup(const AstRawString* name);
 
   // Declare the function variable for a function literal. This variable
   // is in an intermediate scope between this function scope and the the
@@ -124,11 +127,11 @@
   // Declare a parameter in this scope.  When there are duplicated
   // parameters the rightmost one 'wins'.  However, the implementation
   // expects all parameters to be declared and from left to right.
-  void DeclareParameter(Handle<String> name, VariableMode mode);
+  void DeclareParameter(const AstRawString* name, VariableMode mode);
 
   // Declare a local variable in this scope. If the variable has been
   // declared before, the previously declared variable is returned.
-  Variable* DeclareLocal(Handle<String> name,
+  Variable* DeclareLocal(const AstRawString* name,
                          VariableMode mode,
                          InitializationFlag init_flag,
                          Interface* interface = Interface::NewValue());
@@ -137,12 +140,12 @@
   // global scope.  The variable was introduced (possibly from an inner
   // scope) by a reference to an unresolved variable with no intervening
   // with statements or eval calls.
-  Variable* DeclareDynamicGlobal(Handle<String> name);
+  Variable* DeclareDynamicGlobal(const AstRawString* name);
 
   // Create a new unresolved variable.
   template<class Visitor>
   VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory,
-                               Handle<String> name,
+                               const AstRawString* name,
                                Interface* interface = Interface::NewValue(),
                                int position = RelocInfo::kNoPosition) {
     // Note that we must not share the unresolved variables with
@@ -167,13 +170,13 @@
   // for printing and cannot be used to find the variable.  In particular,
   // the only way to get hold of the temporary is by keeping the Variable*
   // around.
-  Variable* NewInternal(Handle<String> name);
+  Variable* NewInternal(const AstRawString* name);
 
   // Creates a new temporary variable in this scope.  The name is only used
   // for printing and cannot be used to find the variable.  In particular,
   // the only way to get hold of the temporary is by keeping the Variable*
   // around.  The name should not clash with a legitimate variable names.
-  Variable* NewTemporary(Handle<String> name);
+  Variable* NewTemporary(const AstRawString* name);
 
   // Adds the specific declaration node to the list of declarations in
   // this scope. The declarations are processed as part of entering
@@ -390,7 +393,7 @@
 
   // ---------------------------------------------------------------------------
   // Strict mode support.
-  bool IsDeclared(Handle<String> name) {
+  bool IsDeclared(const AstRawString* name) {
     // During formal parameter list parsing the scope only contains
     // two variables inserted at initialization: "this" and "arguments".
     // "this" is an invalid parameter name and "arguments" is invalid parameter
@@ -421,7 +424,7 @@
   ScopeType scope_type_;
 
   // Debugging support.
-  Handle<String> scope_name_;
+  const AstRawString* scope_name_;
 
   // The variables declared in this scope:
   //
@@ -497,7 +500,7 @@
 
   // Create a non-local variable with a given name.
   // These variables are looked up dynamically at runtime.
-  Variable* NonLocal(Handle<String> name, VariableMode mode);
+  Variable* NonLocal(const AstRawString* name, VariableMode mode);
 
   // Variable resolution.
   // Possible results of a recursive variable lookup telling if and how a
@@ -548,7 +551,7 @@
   // Lookup a variable reference given by name recursively starting with this
   // scope. If the code is executed because of a call to 'eval', the context
   // parameter should be set to the calling context of 'eval'.
-  Variable* LookupRecursive(Handle<String> name,
+  Variable* LookupRecursive(const AstRawString* name,
                             BindingKind* binding_kind,
                             AstNodeFactory<AstNullVisitor>* factory);
   MUST_USE_RESULT
@@ -592,10 +595,12 @@
  private:
   // Construct a scope based on the scope info.
   Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info,
-        Zone* zone);
+        AstValueFactory* value_factory, Zone* zone);
 
   // Construct a catch scope with a binding for the name.
-  Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone);
+  Scope(Scope* inner_scope,
+        const AstRawString* catch_variable_name,
+        AstValueFactory* value_factory, Zone* zone);
 
   void AddInnerScope(Scope* inner_scope) {
     if (inner_scope != NULL) {
@@ -608,6 +613,7 @@
                    Scope* outer_scope,
                    Handle<ScopeInfo> scope_info);
 
+  AstValueFactory* ast_value_factory_;
   Zone* zone_;
 };
 
diff --git a/src/utils.cc b/src/utils.cc
index 52b0d48..df1f280 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -394,4 +394,24 @@
 }
 
 
+bool DoubleToBoolean(double d) {
+  // NaN, +0, and -0 should return the false object
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+  union IeeeDoubleLittleEndianArchType u;
+#elif __BYTE_ORDER == __BIG_ENDIAN
+  union IeeeDoubleBigEndianArchType u;
+#endif
+  u.d = d;
+  if (u.bits.exp == 2047) {
+    // Detect NaN for IEEE double precision floating point.
+    if ((u.bits.man_low | u.bits.man_high) != 0) return false;
+  }
+  if (u.bits.exp == 0) {
+    // Detect +0, and -0 for IEEE double precision floating point.
+    if ((u.bits.man_low | u.bits.man_high) == 0) return false;
+  }
+  return true;
+}
+
+
 } }  // namespace v8::internal
diff --git a/src/utils.h b/src/utils.h
index 5422985..da5d0fc 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -1318,8 +1318,12 @@
 #if V8_HOST_ARCH_IA32
 #define STOS "stosl"
 #elif V8_HOST_ARCH_X64
+#if V8_HOST_ARCH_32_BIT
+#define STOS "addr32 stosl"
+#else
 #define STOS "stosq"
 #endif
+#endif
 #if defined(__native_client__)
   // This STOS sequence does not validate for x86_64 Native Client.
   // Here we #undef STOS to force use of the slower C version.
@@ -1578,6 +1582,36 @@
 };
 
 
+bool DoubleToBoolean(double d);
+
+template <typename Stream>
+bool StringToArrayIndex(Stream* stream, uint32_t* index) {
+  uint16_t ch = stream->GetNext();
+
+  // If the string begins with a '0' character, it must only consist
+  // of it to be a legal array index.
+  if (ch == '0') {
+    *index = 0;
+    return !stream->HasMore();
+  }
+
+  // Convert string to uint32 array index; character by character.
+  int d = ch - '0';
+  if (d < 0 || d > 9) return false;
+  uint32_t result = d;
+  while (stream->HasMore()) {
+    d = stream->GetNext() - '0';
+    if (d < 0 || d > 9) return false;
+    // Check that the new result is below the 32 bit limit.
+    if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
+    result = (result * 10) + d;
+  }
+
+  *index = result;
+  return true;
+}
+
+
 } }  // namespace v8::internal
 
 #endif  // V8_UTILS_H_
diff --git a/src/variables.cc b/src/variables.cc
index 906b6ab..3013938 100644
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -33,7 +33,7 @@
 
 
 Variable::Variable(Scope* scope,
-                   Handle<String> name,
+                   const AstRawString* name,
                    VariableMode mode,
                    bool is_valid_ref,
                    Kind kind,
@@ -52,8 +52,6 @@
     is_used_(false),
     initialization_flag_(initialization_flag),
     interface_(interface) {
-  // Names must be canonicalized for fast equality checks.
-  ASSERT(name->IsInternalizedString());
   // Var declared variables never need initialization.
   ASSERT(!(mode == VAR && initialization_flag == kNeedsInitialization));
 }
diff --git a/src/variables.h b/src/variables.h
index acec910..fdea0ee 100644
--- a/src/variables.h
+++ b/src/variables.h
@@ -5,6 +5,7 @@
 #ifndef V8_VARIABLES_H_
 #define V8_VARIABLES_H_
 
+#include "src/ast-value-factory.h"
 #include "src/interface.h"
 #include "src/zone.h"
 
@@ -52,7 +53,7 @@
   };
 
   Variable(Scope* scope,
-           Handle<String> name,
+           const AstRawString* name,
            VariableMode mode,
            bool is_valid_ref,
            Kind kind,
@@ -70,7 +71,8 @@
   // scope is only used to follow the context chain length.
   Scope* scope() const { return scope_; }
 
-  Handle<String> name() const { return name_; }
+  Handle<String> name() const { return name_->string(); }
+  const AstRawString* raw_name() const { return name_; }
   VariableMode mode() const { return mode_; }
   bool has_forced_context_allocation() const {
     return force_context_allocation_;
@@ -136,7 +138,7 @@
 
  private:
   Scope* scope_;
-  Handle<String> name_;
+  const AstRawString* name_;
   VariableMode mode_;
   Kind kind_;
   Location location_;
diff --git a/src/version.cc b/src/version.cc
index 6a4f90b..b0004fe 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     28
-#define BUILD_NUMBER      1
-#define PATCH_LEVEL       2
+#define BUILD_NUMBER      2
+#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 0bc5739..b6aadc7 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -2375,10 +2375,10 @@
   __ SmiToInteger32(rdx, rdx);
 
   __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rcx);
-  __ cmpq(rdi, rcx);
+  __ cmpp(rdi, rcx);
   __ j(not_equal, &miss);
 
-  __ movq(rax, Immediate(arg_count()));
+  __ movp(rax, Immediate(arg_count()));
   __ movp(rbx, FieldOperand(rbx, rdx, times_pointer_size,
                             FixedArray::kHeaderSize));
 
@@ -2417,7 +2417,7 @@
 
   // The checks. First, does rdi match the recorded monomorphic target?
   __ SmiToInteger32(rdx, rdx);
-  __ cmpq(rdi, FieldOperand(rbx, rdx, times_pointer_size,
+  __ cmpp(rdi, FieldOperand(rbx, rdx, times_pointer_size,
                             FixedArray::kHeaderSize));
   __ j(not_equal, &extra_checks_or_miss);
 
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 3190e5a..46d91a0 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -2939,7 +2939,8 @@
   // rcx: valid entries in the descriptor array.
   // Calculate the end of the descriptor array.
   __ imulp(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize));
-  __ leap(rcx, Operand(r8, rcx, times_8, DescriptorArray::kFirstOffset));
+  __ leap(rcx,
+          Operand(r8, rcx, times_pointer_size, DescriptorArray::kFirstOffset));
   // Calculate location of the first key name.
   __ addp(r8, Immediate(DescriptorArray::kFirstOffset));
   // Loop through all the keys in the descriptor array. If one of these is the
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index b9b1b8e..a2ff91b 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -167,7 +167,7 @@
 #endif
       __ Push(rax);
       __ Set(rax, slots);
-      __ movq(kScratchRegister, kSlotsZapValue);
+      __ Set(kScratchRegister, kSlotsZapValue);
       Label loop;
       __ bind(&loop);
       __ movp(MemOperand(rsp, rax, times_pointer_size, 0),
@@ -744,7 +744,7 @@
     ExternalReference count = ExternalReference::stress_deopt_count(isolate());
     Label no_deopt;
     __ pushfq();
-    __ Push(rax);
+    __ pushq(rax);
     Operand count_operand = masm()->ExternalOperand(count, kScratchRegister);
     __ movl(rax, count_operand);
     __ subl(rax, Immediate(1));
@@ -752,13 +752,13 @@
     if (FLAG_trap_on_deopt) __ int3();
     __ movl(rax, Immediate(FLAG_deopt_every_n_times));
     __ movl(count_operand, rax);
-    __ Pop(rax);
+    __ popq(rax);
     __ popfq();
     ASSERT(frame_is_built_);
     __ call(entry, RelocInfo::RUNTIME_ENTRY);
     __ bind(&no_deopt);
     __ movl(count_operand, rax);
-    __ Pop(rax);
+    __ popq(rax);
     __ popfq();
   }
 
@@ -2746,7 +2746,7 @@
     __ Push(ToRegister(instr->value()));
     __ Push(instr->function());
 
-    static const int kAdditionalDelta = 10;
+    static const int kAdditionalDelta = kPointerSize == kInt64Size ? 10 : 16;
     int delta =
         masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
     ASSERT(delta >= 0);
@@ -4715,7 +4715,7 @@
 
   if (FLAG_inline_new) {
     __ AllocateHeapNumber(reg, tmp, &slow);
-    __ jmp(&done, Label::kNear);
+    __ jmp(&done, kPointerSize == kInt64Size ? Label::kNear : Label::kFar);
   }
 
   // Slow case: Call the runtime system to do the number allocation.
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 919df87..6d772c0 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -331,6 +331,16 @@
 
 
 int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
+  if (kind == DOUBLE_REGISTERS && kDoubleSize == 2 * kPointerSize) {
+    // Skip a slot if for a double-width slot for x32 port.
+    spill_slot_count_++;
+    // The spill slot's address is at rbp - (index + 1) * kPointerSize -
+    // StandardFrameConstants::kFixedFrameSizeFromFp. kFixedFrameSizeFromFp is
+    // 2 * kPointerSize, if rbp is aligned at 8-byte boundary, the below "|= 1"
+    // will make sure the spilled doubles are aligned at 8-byte boundary.
+    // TODO(haitao): make sure rbp is aligned at 8-byte boundary for x32 port.
+    spill_slot_count_ |= 1;
+  }
   return spill_slot_count_++;
 }
 
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index d42756a..e0fa23c 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -1100,7 +1100,7 @@
   if (emit_debug_code()) {
     Move(dst, Smi::FromInt(kSmiConstantRegisterValue),
          Assembler::RelocInfoNone());
-    cmpq(dst, kSmiConstantRegister);
+    cmpp(dst, kSmiConstantRegister);
     Assert(equal, kUninitializedKSmiConstantRegister);
   }
   int value = source->value();
diff --git a/test/cctest/test-ast.cc b/test/cctest/test-ast.cc
index 2285d0c..a25ae69 100644
--- a/test/cctest/test-ast.cc
+++ b/test/cctest/test-ast.cc
@@ -41,7 +41,7 @@
 
   Isolate* isolate = CcTest::i_isolate();
   Zone zone(isolate);
-  AstNodeFactory<AstNullVisitor> factory(&zone);
+  AstNodeFactory<AstNullVisitor> factory(&zone, NULL);
   AstNode* node = factory.NewEmptyStatement(RelocInfo::kNoPosition);
   list->Add(node);
   CHECK_EQ(1, list->length());
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 77b5bd8..6e5e23b 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -283,7 +283,7 @@
   sample->pc = code->address();
   sample->tos = 0;
   sample->frames_count = i::TickSample::kMaxFramesCount;
-  for (int i = 0; i < sample->frames_count; ++i) {
+  for (unsigned i = 0; i < sample->frames_count; ++i) {
     sample->stack[i] = code->address();
   }
   processor->FinishTickSample();
@@ -1248,6 +1248,72 @@
 }
 
 
+static const char* cpu_profiler_deep_stack_test_source =
+"function foo(n) {\n"
+"  if (n)\n"
+"    foo(n - 1);\n"
+"  else\n"
+"    startProfiling('my_profile');\n"
+"}\n"
+"function start() {\n"
+"  foo(250);\n"
+"}\n";
+
+
+// Check a deep stack
+//
+// [Top down]:
+//    0  (root) 0 #1
+//    2    (program) 0 #2
+//    0    start 21 #3 no reason
+//    0      foo 21 #4 no reason
+//    0        foo 21 #5 no reason
+//                ....
+//    0          foo 21 #253 no reason
+//    1            startProfiling 0 #254
+TEST(CpuProfileDeepStack) {
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
+
+  v8::Script::Compile(v8::String::NewFromUtf8(
+      env->GetIsolate(), cpu_profiler_deep_stack_test_source))->Run();
+  v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+      env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
+
+  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+  v8::Local<v8::String> profile_name =
+      v8::String::NewFromUtf8(env->GetIsolate(), "my_profile");
+  function->Call(env->Global(), 0, NULL);
+  v8::CpuProfile* profile = cpu_profiler->StopProfiling(profile_name);
+  CHECK_NE(NULL, profile);
+  // Dump collected profile to have a better diagnostic in case of failure.
+  reinterpret_cast<i::CpuProfile*>(profile)->Print();
+
+  const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+  {
+    ScopedVector<v8::Handle<v8::String> > names(3);
+    names[0] = v8::String::NewFromUtf8(
+        env->GetIsolate(), ProfileGenerator::kGarbageCollectorEntryName);
+    names[1] = v8::String::NewFromUtf8(env->GetIsolate(),
+                                       ProfileGenerator::kProgramEntryName);
+    names[2] = v8::String::NewFromUtf8(env->GetIsolate(), "start");
+    CheckChildrenNames(root, names);
+  }
+
+  const v8::CpuProfileNode* node =
+      GetChild(env->GetIsolate(), root, "start");
+  for (int i = 0; i < 250; ++i) {
+    node = GetChild(env->GetIsolate(), node, "foo");
+  }
+  // TODO(alph):
+  // In theory there must be one more 'foo' and a 'startProfiling' nodes,
+  // but due to unstable top frame extraction these might be missing.
+
+  profile->Delete();
+}
+
+
 static const char* js_native_js_test_source =
 "var is_profiling = false;\n"
 "function foo(iterations) {\n"
diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc
index f92a81e..0e6f14a 100644
--- a/test/cctest/test-lockers.cc
+++ b/test/cctest/test-lockers.cc
@@ -247,6 +247,8 @@
 TEST(MultithreadedParallelIsolates) {
 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
   const int kNThreads = 10;
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+  const int kNThreads = 4;
 #else
   const int kNThreads = 50;
 #endif
@@ -713,6 +715,8 @@
 TEST(ExtensionsRegistration) {
 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
   const int kNThreads = 10;
+#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
+  const int kNThreads = 4;
 #else
   const int kNThreads = 40;
 #endif
diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 3f9d0b3..334a201 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -172,7 +172,7 @@
   CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace), sample.external_callback);
 
   // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
-  int base = 0;
+  unsigned base = 0;
   CHECK_GT(sample.frames_count, base + 1);
 
   CHECK(IsAddressWithinFuncCode(
@@ -225,7 +225,7 @@
   CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace), sample.external_callback);
 
   // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
-  int base = 0;
+  unsigned base = 0;
   CHECK_GT(sample.frames_count, base + 1);
   CHECK(IsAddressWithinFuncCode(context, "JSTrace", sample.stack[base + 0]));
   CHECK(IsAddressWithinFuncCode(
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index c484663..858354d 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -31,6 +31,7 @@
 
 #include "src/v8.h"
 
+#include "src/ast-value-factory.h"
 #include "src/compiler.h"
 #include "src/execution.h"
 #include "src/isolate.h"
@@ -796,8 +797,12 @@
   CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
   CHECK(scanner.ScanRegExpPattern(start == i::Token::ASSIGN_DIV));
   scanner.Next();  // Current token is now the regexp literal.
+  i::Zone zone(CcTest::i_isolate());
+  i::AstValueFactory ast_value_factory(&zone,
+                                       CcTest::i_isolate()->heap()->HashSeed());
+  ast_value_factory.Internalize(CcTest::i_isolate());
   i::Handle<i::String> val =
-      scanner.AllocateInternalizedString(CcTest::i_isolate());
+      scanner.CurrentSymbol(&ast_value_factory)->string();
   i::DisallowHeapAllocation no_alloc;
   i::String::FlatContent content = val->GetFlatContent();
   CHECK(content.IsAscii());
@@ -2587,3 +2592,20 @@
   i::DeleteArray(two_byte_source);
   i::DeleteArray(two_byte_name);
 }
+
+
+TEST(RegressionLazyFunctionWithErrorWithArg) {
+  // The bug occurred when a lazy function had an error which requires a
+  // parameter (such as "unknown label" here). The error message was processed
+  // before the AstValueFactory containing the error message string was
+  // internalized.
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::HandleScope scope(isolate);
+  LocalContext env;
+  i::FLAG_lazy = true;
+  i::FLAG_min_preparse_length = 0;
+  CompileRun("function this_is_lazy() {\n"
+             "  break p;\n"
+             "}\n"
+             "this_is_lazy();\n");
+}
diff --git a/test/mjsunit/harmony/collections.js b/test/mjsunit/harmony/collections.js
index edbdd41..1dd7f0d 100644
--- a/test/mjsunit/harmony/collections.js
+++ b/test/mjsunit/harmony/collections.js
@@ -25,7 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --harmony-collections
+// Flags: --harmony-collections --harmony-iteration
 // Flags: --expose-gc --allow-natives-syntax
 
 
@@ -987,3 +987,261 @@
 
   assertArrayEquals([0, 1, 2, 3, 4], buffer);
 })();
+
+
+(function TestSetConstructor() {
+  var s = new Set(null);
+  assertEquals(s.size, 0);
+
+  s = new Set(undefined);
+  assertEquals(s.size, 0);
+
+  // No @@iterator
+  assertThrows(function() {
+    new Set({});
+  }, TypeError);
+
+  // @@iterator not callable
+  assertThrows(function() {
+    var object = {};
+    object[Symbol.iterator] = 42;
+    new Set(object);
+  }, TypeError);
+
+  // @@iterator result not object
+  assertThrows(function() {
+    var object = {};
+    object[Symbol.iterator] = function() {
+      return 42;
+    };
+    new Set(object);
+  }, TypeError);
+
+  var s2 = new Set();
+  s2.add('a');
+  s2.add('b');
+  s2.add('c');
+  s = new Set(s2.values());
+  assertEquals(s.size, 3);
+  assertTrue(s.has('a'));
+  assertTrue(s.has('b'));
+  assertTrue(s.has('c'));
+})();
+
+
+(function TestSetConstructorAddNotCallable() {
+  var originalSetPrototypeAdd = Set.prototype.add;
+  assertThrows(function() {
+    Set.prototype.add = 42;
+    new Set([1, 2].values());
+  }, TypeError);
+  Set.prototype.add = originalSetPrototypeAdd;
+})();
+
+
+(function TestSetConstructorGetAddOnce() {
+  var originalSetPrototypeAdd = Set.prototype.add;
+  var getAddCount = 0;
+  Object.defineProperty(Set.prototype, 'add', {
+    get: function() {
+      getAddCount++;
+      return function() {};
+    }
+  });
+  var s = new Set([1, 2].values());
+  assertEquals(getAddCount, 1);
+  assertEquals(s.size, 0);
+  Object.defineProperty(Set.prototype, 'add', {
+    value: originalSetPrototypeAdd,
+    writable: true
+  });
+})();
+
+
+(function TestSetConstructorAddReplaced() {
+  var originalSetPrototypeAdd = Set.prototype.add;
+  var addCount = 0;
+  Set.prototype.add = function(value) {
+    addCount++;
+    originalSetPrototypeAdd.call(this, value);
+    Set.prototype.add = null;
+  };
+  var s = new Set([1, 2].values());
+  assertEquals(addCount, 2);
+  assertEquals(s.size, 2);
+  Set.prototype.add = originalSetPrototypeAdd;
+})();
+
+
+(function TestSetConstructorOrderOfDoneValue() {
+  var valueCount = 0, doneCount = 0;
+  var iterator = {
+    next: function() {
+      return {
+        get value() {
+          valueCount++;
+        },
+        get done() {
+          doneCount++;
+          throw new Error();
+        }
+      };
+    }
+  };
+  iterator[Symbol.iterator] = function() {
+    return this;
+  };
+  assertThrows(function() {
+    new Set(iterator);
+  });
+  assertEquals(doneCount, 1);
+  assertEquals(valueCount, 0);
+})();
+
+
+(function TestSetConstructorNextNotAnObject() {
+  var iterator = {
+    next: function() {
+      return 'abc';
+    }
+  };
+  iterator[Symbol.iterator] = function() {
+    return this;
+  };
+  assertThrows(function() {
+    new Set(iterator);
+  }, TypeError);
+})();
+
+
+(function TestMapConstructor() {
+  var m = new Map(null);
+  assertEquals(m.size, 0);
+
+  m = new Map(undefined);
+  assertEquals(m.size, 0);
+
+  // No @@iterator
+  assertThrows(function() {
+    new Map({});
+  }, TypeError);
+
+  // @@iterator not callable
+  assertThrows(function() {
+    var object = {};
+    object[Symbol.iterator] = 42;
+    new Map(object);
+  }, TypeError);
+
+  // @@iterator result not object
+  assertThrows(function() {
+    var object = {};
+    object[Symbol.iterator] = function() {
+      return 42;
+    };
+    new Map(object);
+  }, TypeError);
+
+  var m2 = new Map();
+  m2.set(0, 'a');
+  m2.set(1, 'b');
+  m2.set(2, 'c');
+  m = new Map(m2.entries());
+  assertEquals(m.size, 3);
+  assertEquals(m.get(0), 'a');
+  assertEquals(m.get(1), 'b');
+  assertEquals(m.get(2), 'c');
+})();
+
+
+(function TestMapConstructorSetNotCallable() {
+  var originalMapPrototypeSet = Map.prototype.set;
+  assertThrows(function() {
+    Map.prototype.set = 42;
+    new Map([1, 2].entries());
+  }, TypeError);
+  Map.prototype.set = originalMapPrototypeSet;
+})();
+
+
+(function TestMapConstructorGetAddOnce() {
+  var originalMapPrototypeSet = Map.prototype.set;
+  var getSetCount = 0;
+  Object.defineProperty(Map.prototype, 'set', {
+    get: function() {
+      getSetCount++;
+      return function() {};
+    }
+  });
+  var m = new Map([1, 2].entries());
+  assertEquals(getSetCount, 1);
+  assertEquals(m.size, 0);
+  Object.defineProperty(Map.prototype, 'set', {
+    value: originalMapPrototypeSet,
+    writable: true
+  });
+})();
+
+
+(function TestMapConstructorSetReplaced() {
+  var originalMapPrototypeSet = Map.prototype.set;
+  var setCount = 0;
+  Map.prototype.set = function(key, value) {
+    setCount++;
+    originalMapPrototypeSet.call(this, key, value);
+    Map.prototype.set = null;
+  };
+  var m = new Map([1, 2].entries());
+  assertEquals(setCount, 2);
+  assertEquals(m.size, 2);
+  Map.prototype.set = originalMapPrototypeSet;
+})();
+
+
+(function TestMapConstructorOrderOfDoneValue() {
+  var valueCount = 0, doneCount = 0;
+  function FakeError() {}
+  var iterator = {
+    next: function() {
+      return {
+        get value() {
+          valueCount++;
+        },
+        get done() {
+          doneCount++;
+          throw new FakeError();
+        }
+      };
+    }
+  };
+  iterator[Symbol.iterator] = function() {
+    return this;
+  };
+  assertThrows(function() {
+    new Map(iterator);
+  }, FakeError);
+  assertEquals(doneCount, 1);
+  assertEquals(valueCount, 0);
+})();
+
+
+(function TestMapConstructorNextNotAnObject() {
+  var iterator = {
+    next: function() {
+      return 'abc';
+    }
+  };
+  iterator[Symbol.iterator] = function() {
+    return this;
+  };
+  assertThrows(function() {
+    new Map(iterator);
+  }, TypeError);
+})();
+
+
+(function TestMapConstructorIteratorNotObjectValues() {
+  assertThrows(function() {
+    new Map([1, 2].values());
+  }, TypeError);
+})();
diff --git a/test/mjsunit/regress/regress-crbug-387599.js b/test/mjsunit/regress/regress-crbug-387599.js
new file mode 100644
index 0000000..98750aa
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-387599.js
@@ -0,0 +1,19 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --expose-debug-as debug
+
+Debug = debug.Debug;
+Debug.setListener(function() {});
+
+function f() {
+  for (var i = 0; i < 100; i++) {
+    %OptimizeFunctionOnNextCall(f, "osr");
+  }
+}
+
+Debug.setBreakPoint(f, 0, 0);
+f();
+f();
+Debug.setListener(null);
diff --git a/test/mjsunit/regress/regress-crbug-387636.js b/test/mjsunit/regress/regress-crbug-387636.js
new file mode 100644
index 0000000..1e50ace
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-387636.js
@@ -0,0 +1,14 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f() {
+  [].indexOf(0x40000000);
+}
+
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
diff --git a/tools/disasm.py b/tools/disasm.py
index 6fa81ca..cc7ef06 100644
--- a/tools/disasm.py
+++ b/tools/disasm.py
@@ -49,7 +49,8 @@
   "ia32": "-m i386",
   "x64": "-m i386 -M x86-64",
   "arm": "-m arm",  # Not supported by our objdump build.
-  "mips": "-m mips"  # Not supported by our objdump build.
+  "mips": "-m mips",  # Not supported by our objdump build.
+  "arm64": "-m aarch64"
 }
 
 
diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py
index a604cd3..e8d4c64 100755
--- a/tools/generate-runtime-tests.py
+++ b/tools/generate-runtime-tests.py
@@ -51,7 +51,7 @@
 EXPECTED_FUZZABLE_COUNT = 326
 EXPECTED_CCTEST_COUNT = 6
 EXPECTED_UNKNOWN_COUNT = 4
-EXPECTED_BUILTINS_COUNT = 798
+EXPECTED_BUILTINS_COUNT = 800
 
 
 # Don't call these at all.
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index c6dcf69..c7d04c6 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -343,6 +343,8 @@
         '../../src/assembler.h',
         '../../src/assert-scope.h',
         '../../src/assert-scope.cc',
+        '../../src/ast-value-factory.cc',
+        '../../src/ast-value-factory.h',
         '../../src/ast.cc',
         '../../src/ast.h',
         '../../src/bignum-dtoa.cc',
@@ -870,7 +872,7 @@
             '../../src/mips/stub-cache-mips.cc',
           ],
         }],
-        ['v8_target_arch=="x64"', {
+        ['v8_target_arch=="x64" or v8_target_arch=="x32"', {
           'sources': [  ### gcmole(arch:x64) ###
             '../../src/x64/assembler-x64-inl.h',
             '../../src/x64/assembler-x64.cc',
diff --git a/tools/ll_prof.py b/tools/ll_prof.py
index 216929d..409b396 100755
--- a/tools/ll_prof.py
+++ b/tools/ll_prof.py
@@ -351,7 +351,8 @@
     "ia32": ctypes.c_uint32,
     "arm": ctypes.c_uint32,
     "mips": ctypes.c_uint32,
-    "x64": ctypes.c_uint64
+    "x64": ctypes.c_uint64,
+    "arm64": ctypes.c_uint64
   }
 
   _CODE_CREATE_TAG = "C"
diff --git a/tools/parser-shell.cc b/tools/parser-shell.cc
index c229185..f14c000 100644
--- a/tools/parser-shell.cc
+++ b/tools/parser-shell.cc
@@ -44,6 +44,18 @@
 
 using namespace v8::internal;
 
+class StringResource8 : public v8::String::ExternalAsciiStringResource {
+ public:
+  StringResource8(const char* data, int length)
+      : data_(data), length_(length) { }
+  virtual size_t length() const { return length_; }
+  virtual const char* data() const { return data_; }
+
+ private:
+  const char* data_;
+  int length_;
+};
+
 std::pair<TimeDelta, TimeDelta> RunBaselineParser(
     const char* fname, Encoding encoding, int repeat, v8::Isolate* isolate,
     v8::Handle<v8::Context> context) {
@@ -63,7 +75,9 @@
       break;
     }
     case LATIN1: {
-      source_handle = v8::String::NewFromOneByte(isolate, source);
+      StringResource8* string_resource =
+          new StringResource8(reinterpret_cast<const char*>(source), length);
+      source_handle = v8::String::NewExternal(isolate, string_resource);
       break;
     }
   }
diff --git a/tools/run-tests.py b/tools/run-tests.py
index 794c864..fbbe416 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -86,6 +86,7 @@
                    "nacl_ia32",
                    "nacl_x64",
                    "x64",
+                   "x32",
                    "arm64"]
 # Double the timeout for these:
 SLOW_ARCHS = ["android_arm",
diff --git a/tools/whitespace.txt b/tools/whitespace.txt
index 4517663..69793d0 100644
--- a/tools/whitespace.txt
+++ b/tools/whitespace.txt
@@ -3,3 +3,4 @@
 
 
 
+