Version 3.18.1

Removed SCons related files and deprecated test suite configurations.

Improved handling of unary plus (issue 2527).

Performance and stability improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@14336 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/SConscript b/src/SConscript
deleted file mode 100755
index 772ac4e..0000000
--- a/src/SConscript
+++ /dev/null
@@ -1,413 +0,0 @@
-# Copyright 2012 the V8 project authors. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#     * Neither the name of Google Inc. nor the names of its
-#       contributors may be used to endorse or promote products derived
-#       from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-import sys
-from os.path import join, dirname, abspath
-root_dir = dirname(File('SConstruct').rfile().abspath)
-sys.path.append(join(root_dir, 'tools'))
-import js2c
-Import('context')
-Import('tools')
-Import('d8_env')
-
-
-SOURCES = {
-  'all': Split("""
-    accessors.cc
-    allocation.cc
-    api.cc
-    assembler.cc
-    ast.cc
-    atomicops_internals_x86_gcc.cc
-    bignum-dtoa.cc
-    bignum.cc
-    bootstrapper.cc
-    builtins.cc
-    cached-powers.cc
-    checks.cc
-    circular-queue.cc
-    code-stubs.cc
-    codegen.cc
-    compilation-cache.cc
-    compiler.cc
-    contexts.cc
-    conversions.cc
-    counters.cc
-    cpu-profiler.cc
-    data-flow.cc
-    date.cc
-    dateparser.cc
-    debug-agent.cc
-    debug.cc
-    deoptimizer.cc
-    disassembler.cc
-    diy-fp.cc
-    dtoa.cc
-    elements-kind.cc
-    elements.cc
-    execution.cc
-    extensions/externalize-string-extension.cc
-    extensions/gc-extension.cc
-    extensions/statistics-extension.cc
-    factory.cc
-    fast-dtoa.cc
-    fixed-dtoa.cc
-    flags.cc
-    frames.cc
-    full-codegen.cc
-    func-name-inferrer.cc
-    gdb-jit.cc
-    global-handles.cc
-    handles.cc
-    heap-profiler.cc
-    heap-snapshot-generator.cc
-    heap.cc
-    hydrogen-instructions.cc
-    hydrogen.cc
-    ic.cc
-    incremental-marking.cc
-    interface.cc
-    interpreter-irregexp.cc
-    isolate.cc
-    jsregexp.cc
-    lithium-allocator.cc
-    lithium.cc
-    liveedit.cc
-    log-utils.cc
-    log.cc
-    mark-compact.cc
-    messages.cc
-    objects-printer.cc
-    objects-visiting.cc
-    objects.cc
-    once.cc
-    optimizing-compiler-thread.cc
-    parser.cc
-    preparse-data.cc
-    preparser.cc
-    profile-generator.cc
-    property.cc
-    regexp-macro-assembler-irregexp.cc
-    regexp-macro-assembler.cc
-    regexp-stack.cc
-    rewriter.cc
-    runtime-profiler.cc
-    runtime.cc
-    safepoint-table.cc
-    scanner-character-streams.cc
-    scanner.cc
-    scopeinfo.cc
-    scopes.cc
-    serialize.cc
-    snapshot-common.cc
-    spaces.cc
-    store-buffer.cc
-    string-search.cc
-    string-stream.cc
-    strtod.cc
-    stub-cache.cc
-    token.cc
-    transitions.cc
-    type-info.cc
-    unicode.cc
-    utils.cc
-    v8-counters.cc
-    v8.cc
-    v8conversions.cc
-    v8threads.cc
-    v8utils.cc
-    variables.cc
-    version.cc
-    zone.cc
-    """),
-  'arch:arm': Split("""
-    arm/builtins-arm.cc
-    arm/code-stubs-arm.cc
-    arm/codegen-arm.cc
-    arm/constants-arm.cc
-    arm/cpu-arm.cc
-    arm/debug-arm.cc
-    arm/deoptimizer-arm.cc
-    arm/disasm-arm.cc
-    arm/frames-arm.cc
-    arm/full-codegen-arm.cc
-    arm/ic-arm.cc
-    arm/lithium-arm.cc
-    arm/lithium-codegen-arm.cc
-    arm/lithium-gap-resolver-arm.cc
-    arm/macro-assembler-arm.cc
-    arm/regexp-macro-assembler-arm.cc
-    arm/stub-cache-arm.cc
-    arm/assembler-arm.cc
-    """),
-  'arch:mips': Split("""
-    mips/assembler-mips.cc
-    mips/builtins-mips.cc
-    mips/code-stubs-mips.cc
-    mips/codegen-mips.cc
-    mips/constants-mips.cc
-    mips/cpu-mips.cc
-    mips/debug-mips.cc
-    mips/deoptimizer-mips.cc
-    mips/disasm-mips.cc
-    mips/frames-mips.cc
-    mips/full-codegen-mips.cc
-    mips/ic-mips.cc
-    mips/lithium-codegen-mips.cc
-    mips/lithium-gap-resolver-mips.cc
-    mips/lithium-mips.cc
-    mips/macro-assembler-mips.cc
-    mips/regexp-macro-assembler-mips.cc
-    mips/stub-cache-mips.cc
-    """),
-  'arch:ia32': Split("""
-    ia32/assembler-ia32.cc
-    ia32/builtins-ia32.cc
-    ia32/code-stubs-ia32.cc
-    ia32/codegen-ia32.cc
-    ia32/cpu-ia32.cc
-    ia32/debug-ia32.cc
-    ia32/deoptimizer-ia32.cc
-    ia32/disasm-ia32.cc
-    ia32/frames-ia32.cc
-    ia32/full-codegen-ia32.cc
-    ia32/ic-ia32.cc
-    ia32/lithium-codegen-ia32.cc
-    ia32/lithium-gap-resolver-ia32.cc
-    ia32/lithium-ia32.cc
-    ia32/macro-assembler-ia32.cc
-    ia32/regexp-macro-assembler-ia32.cc
-    ia32/stub-cache-ia32.cc
-    """),
-  'arch:x64': Split("""
-    x64/assembler-x64.cc
-    x64/builtins-x64.cc
-    x64/code-stubs-x64.cc
-    x64/codegen-x64.cc
-    x64/cpu-x64.cc
-    x64/debug-x64.cc
-    x64/deoptimizer-x64.cc
-    x64/disasm-x64.cc
-    x64/frames-x64.cc
-    x64/full-codegen-x64.cc
-    x64/ic-x64.cc
-    x64/lithium-codegen-x64.cc
-    x64/lithium-gap-resolver-x64.cc
-    x64/lithium-x64.cc
-    x64/macro-assembler-x64.cc
-    x64/regexp-macro-assembler-x64.cc
-    x64/stub-cache-x64.cc
-    """),
-  'simulator:arm': ['arm/simulator-arm.cc'],
-  'simulator:mips': ['mips/simulator-mips.cc'],
-  'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
-  'os:openbsd': ['platform-openbsd.cc', 'platform-posix.cc'],
-  'os:linux':   ['platform-linux.cc', 'platform-posix.cc'],
-  'os:android': ['platform-linux.cc', 'platform-posix.cc'],
-  'os:macos':   ['platform-macos.cc', 'platform-posix.cc'],
-  'os:solaris': ['platform-solaris.cc', 'platform-posix.cc'],
-  'os:cygwin':  ['platform-cygwin.cc', 'platform-posix.cc'],
-  'os:nullos':  ['platform-nullos.cc'],
-  'os:win32':   ['platform-win32.cc', 'win32-math.cc'],
-  'mode:release': [],
-  'mode:debug': [
-    'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
-  ]
-}
-
-
-PREPARSER_SOURCES = {
-  'all': Split("""
-    allocation.cc
-    bignum.cc
-    bignum-dtoa.cc
-    cached-powers.cc
-    conversions.cc
-    diy-fp.cc
-    dtoa.cc
-    fast-dtoa.cc
-    fixed-dtoa.cc
-    preparse-data.cc
-    preparser.cc
-    preparser-api.cc
-    scanner.cc
-    strtod.cc
-    token.cc
-    unicode.cc
-    utils.cc
-    """),
-  'os:win32': ['win32-math.cc']
-}
-
-
-D8_LIGHT_FILES = {
-  'all': [
-    'd8.cc'
-  ]
-}
-
-
-D8_FULL_FILES = {
-  'all': [
-    'd8.cc', 'd8-debug.cc'
-  ],
-  'os:linux': [
-    'd8-posix.cc'
-  ],
-  'os:macos': [
-    'd8-posix.cc'
-  ],
-  'os:android': [
-    'd8-posix.cc'
-  ],
-  'os:freebsd': [
-    'd8-posix.cc'
-  ],
-  'os:openbsd': [
-    'd8-posix.cc'
-  ],
-  'os:solaris': [
-    'd8-posix.cc'
-  ],
-  'os:cygwin': [
-    'd8-posix.cc'
-  ],
-  'os:win32': [
-    'd8-windows.cc'
-  ],
-  'os:nullos': [
-    'd8-windows.cc'   # Empty implementation at the moment.
-  ],
-  'console:readline': [
-    'd8-readline.cc'
-  ]
-}
-
-
-LIBRARY_FILES = '''
-runtime.js
-v8natives.js
-array.js
-string.js
-uri.js
-math.js
-messages.js
-apinatives.js
-date.js
-regexp.js
-json.js
-liveedit-debugger.js
-mirror-debugger.js
-debug-debugger.js
-'''.split()
-
-
-EXPERIMENTAL_LIBRARY_FILES = '''
-symbol.js
-proxy.js
-collection.js
-'''.split()
-
-
-def Abort(message):
-  print message
-  sys.exit(1)
-
-
-def ConfigureObjectFiles():
-  env = Environment(tools=tools)
-  env.Replace(**context.flags['v8'])
-  context.ApplyEnvOverrides(env)
-  env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
-  env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET --logfile "$LOGFILE" --log-snapshot-positions')
-
-  def BuildJS2CEnv(type):
-    js2c_env = { 'TYPE': type, 'COMPRESSION': 'off' }
-    if 'COMPRESS_STARTUP_DATA_BZ2' in env['CPPDEFINES']:
-      js2c_env['COMPRESSION'] = 'bz2'
-    return js2c_env
-
-  # Build the standard platform-independent source files.
-  source_files = context.GetRelevantSources(SOURCES)
-  d8_js = env.JS2C('d8-js.cc', 'd8.js', **{'TYPE': 'D8', 'COMPRESSION': 'off'})
-  d8_js_obj = context.ConfigureObject(env, d8_js, CPPPATH=['.'])
-  if context.options['library'] == 'shared':
-    d8_files = context.GetRelevantSources(D8_LIGHT_FILES)
-    d8_objs = []
-  else:
-    d8_files = context.GetRelevantSources(D8_FULL_FILES)
-    d8_objs = [d8_js_obj]
-  d8_objs.append(context.ConfigureObject(d8_env, [d8_files]))
-
-  # Combine the JavaScript library files into a single C++ file and
-  # compile it.
-  library_files = [s for s in LIBRARY_FILES]
-  library_files.append('macros.py')
-  libraries_src = env.JS2C(
-    ['libraries.cc'], library_files, **BuildJS2CEnv('CORE'))
-  libraries_obj = context.ConfigureObject(env, libraries_src, CPPPATH=['.'])
-
-  # Combine the experimental JavaScript library files into a C++ file
-  # and compile it.
-  experimental_library_files = [ s for s in EXPERIMENTAL_LIBRARY_FILES ]
-  experimental_library_files.append('macros.py')
-  experimental_libraries_src = env.JS2C(['experimental-libraries.cc'],
-                                        experimental_library_files,
-                                        **BuildJS2CEnv('EXPERIMENTAL'))
-  experimental_libraries_obj = context.ConfigureObject(env, experimental_libraries_src, CPPPATH=['.'])
-
-  source_objs = context.ConfigureObject(env, source_files)
-  non_snapshot_files = [source_objs]
-
-  preparser_source_files = context.GetRelevantSources(PREPARSER_SOURCES)
-  preparser_objs = context.ConfigureObject(env, preparser_source_files)
-
-  # Create snapshot if necessary.  For cross compilation you should either
-  # do without snapshots and take the performance hit or you should build a
-  # host VM with the simulator=arm and snapshot=on options and then take the
-  # resulting snapshot.cc file from obj/release and put it in the src
-  # directory.  Then rebuild the VM with the cross compiler and specify
-  # snapshot=nobuild on the scons command line.
-  empty_snapshot_obj = context.ConfigureObject(env, 'snapshot-empty.cc')
-  mksnapshot_env = env.Copy()
-  mksnapshot_env.Replace(**context.flags['mksnapshot'])
-  mksnapshot_src = 'mksnapshot.cc'
-  mksnapshot = mksnapshot_env.Program('mksnapshot', [mksnapshot_src, libraries_obj, experimental_libraries_obj,  non_snapshot_files, empty_snapshot_obj], PDB='mksnapshot.exe.pdb')
-  if context.use_snapshot:
-    if context.build_snapshot:
-      snapshot_cc = env.Snapshot('snapshot.cc', mksnapshot, LOGFILE=File('snapshot.log').abspath)
-    else:
-      snapshot_cc = 'snapshot.cc'
-    snapshot_obj = context.ConfigureObject(env, snapshot_cc, CPPPATH=['.'])
-  else:
-    snapshot_obj = empty_snapshot_obj
-  library_objs = [non_snapshot_files, libraries_obj, experimental_libraries_obj, snapshot_obj]
-  return (library_objs, d8_objs, [mksnapshot], preparser_objs)
-
-
-(library_objs, d8_objs, mksnapshot, preparser_objs) = ConfigureObjectFiles()
-Return('library_objs d8_objs mksnapshot preparser_objs')
diff --git a/src/api.cc b/src/api.cc
index dddcd7d..15831ec 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -623,6 +623,9 @@
   if (IsDeadCheck(isolate, "V8::Persistent::New")) return NULL;
   LOG_API(isolate, "Persistent::New");
   i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
+#ifdef DEBUG
+  (*obj)->Verify();
+#endif  // DEBUG
   return result.location();
 }
 
diff --git a/src/arguments.h b/src/arguments.h
index 1423d56..f8fb00c 100644
--- a/src/arguments.h
+++ b/src/arguments.h
@@ -115,18 +115,15 @@
 
 
 #define DECLARE_RUNTIME_FUNCTION(Type, Name)    \
-Type Name(int args_length, Object** args_object, Isolate* isolate)
+Type Name(Arguments args, Isolate* isolate)
 
-#define RUNTIME_FUNCTION(Type, Name)                                  \
-static Type __RT_impl_##Name(Arguments args, Isolate* isolate);       \
-Type Name(int args_length, Object** args_object, Isolate* isolate) {  \
-  Arguments args(args_length, args_object);                           \
-  return __RT_impl_##Name(args, isolate);                             \
-}                                                                     \
-static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
 
-#define RUNTIME_ARGUMENTS(isolate, args) \
-  args.length(), args.arguments(), isolate
+#define RUNTIME_FUNCTION(Type, Name)            \
+Type Name(Arguments args, Isolate* isolate)
+
+
+#define RUNTIME_ARGUMENTS(isolate, args) args, isolate
+
 
 } }  // namespace v8::internal
 
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 0f9630b..1e0d5c1 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -266,19 +266,11 @@
 bool RelocInfo::IsPatchedReturnSequence() {
   Instr current_instr = Assembler::instr_at(pc_);
   Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize);
-#ifdef USE_BLX
   // A patched return sequence is:
   //  ldr ip, [pc, #0]
   //  blx ip
   return ((current_instr & kLdrPCMask) == kLdrPCPattern)
           && ((next_instr & kBlxRegMask) == kBlxRegPattern);
-#else
-  // A patched return sequence is:
-  //  mov lr, pc
-  //  ldr pc, [pc, #-4]
-  return (current_instr == kMovLrPc)
-          && ((next_instr & kLdrPCMask) == kLdrPCPattern);
-#endif
 }
 
 
@@ -408,14 +400,11 @@
     instr = Memory::int32_at(target_pc);
   }
 
-#ifdef USE_BLX
-  // If we have a blx instruction, the instruction before it is
-  // what needs to be patched.
+  // With a blx instruction, the instruction before is what needs to be patched.
   if ((instr & kBlxRegMask) == kBlxRegPattern) {
     target_pc -= kInstrSize;
     instr = Memory::int32_at(target_pc);
   }
-#endif
 
   ASSERT(IsLdrPcImmediateOffset(instr));
   int offset = instr & 0xfff;  // offset_12 is unsigned
@@ -442,7 +431,6 @@
 Address Assembler::target_address_from_return_address(Address pc) {
   // Returns the address of the call target from the return address that will
   // be returned to after a call.
-#ifdef USE_BLX
   // Call sequence on V7 or later is :
   //  movw  ip, #... @ call address low 16
   //  movt  ip, #... @ call address high 16
@@ -461,18 +449,10 @@
   ASSERT(IsMovW(Memory::int32_at(candidate)) &&
          IsMovT(Memory::int32_at(candidate + kInstrSize)));
   return candidate;
-#else
-  // Call sequence is:
-  //  mov  lr, pc
-  //  ldr  pc, [pc, #...] @ call address
-  //                      @ return address
-  return pc - kInstrSize;
-#endif
 }
 
 
 Address Assembler::return_address_from_call_start(Address pc) {
-#ifdef USE_BLX
   if (IsLdrPcImmediateOffset(Memory::int32_at(pc))) {
     return pc + kInstrSize * 2;
   } else {
@@ -480,9 +460,6 @@
     ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
     return pc + kInstrSize * 3;
   }
-#else
-  return pc + kInstrSize;
-#endif
 }
 
 
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index bc21b64..b473c6b 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -1683,7 +1683,6 @@
     emit(reinterpret_cast<Instr>(msg));
   }
 #else  // def __arm__
-#ifdef CAN_USE_ARMV5_INSTRUCTIONS
   if (cond != al) {
     Label skip;
     b(&skip, NegateCondition(cond));
@@ -1692,9 +1691,6 @@
   } else {
     bkpt(0);
   }
-#else  // ndef CAN_USE_ARMV5_INSTRUCTIONS
-  svc(0x9f0001, cond);
-#endif  // ndef CAN_USE_ARMV5_INSTRUCTIONS
 #endif  // def __arm__
 }
 
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 0aecbcd..0fd5186 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -663,37 +663,19 @@
 
   // Distance between start of patched return sequence and the emitted address
   // to jump to.
-#ifdef USE_BLX
   // Patched return sequence is:
   //  ldr  ip, [pc, #0]   @ emited address and start
   //  blx  ip
   static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
-#else
-  // Patched return sequence is:
-  //  mov  lr, pc         @ start of sequence
-  //  ldr  pc, [pc, #-4]  @ emited address
-  static const int kPatchReturnSequenceAddressOffset =  kInstrSize;
-#endif
 
   // Distance between start of patched debug break slot and the emitted address
   // to jump to.
-#ifdef USE_BLX
   // Patched debug break slot code is:
   //  ldr  ip, [pc, #0]   @ emited address and start
   //  blx  ip
   static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
-#else
-  // Patched debug break slot code is:
-  //  mov  lr, pc         @ start of sequence
-  //  ldr  pc, [pc, #-4]  @ emited address
-  static const int kPatchDebugBreakSlotAddressOffset =  kInstrSize;
-#endif
 
-#ifdef USE_BLX
   static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
-#else
-  static const int kPatchDebugBreakSlotReturnOffset = kInstrSize;
-#endif
 
   // Difference between address of current opcode and value read from pc
   // register.
@@ -1130,16 +1112,8 @@
 
   static bool use_immediate_embedded_pointer_loads(
       const Assembler* assembler) {
-#ifdef USE_BLX
     return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
         (assembler == NULL || !assembler->predictable_code_size());
-#else
-    // If not using BLX, all loads from the constant pool cannot be immediate,
-    // because the ldr pc, [pc + #xxxx] used for calls must be a single
-    // instruction and cannot be easily distinguished out of context from
-    // other loads that could use movw/movt.
-    return false;
-#endif
   }
 
   // Check the code size generated from label to here.
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 1db4152..ef2dbb3 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -30,7 +30,6 @@
 #if defined(V8_TARGET_ARCH_ARM)
 
 #include "bootstrapper.h"
-#include "builtins-decls.h"
 #include "code-stubs.h"
 #include "regexp-macro-assembler.h"
 #include "stub-cache.h"
@@ -482,9 +481,7 @@
   __ Ret();
 
   __ bind(&not_special);
-  // Count leading zeros.  Uses mantissa for a scratch register on pre-ARM5.
-  // Gets the wrong answer for 0, but we already checked for that case above.
-  __ CountLeadingZeros(zeros_, source_, mantissa);
+  __ clz(zeros_, source_);
   // Compute exponent and or it into the exponent register.
   // We use mantissa as a scratch register here.  Use a fudge factor to
   // divide the constant 31 + HeapNumber::kExponentBias, 0x41d, into two parts
@@ -2032,7 +2029,7 @@
       }
 
       // Perform division by shifting.
-      __ CountLeadingZeros(scratch1, scratch1, scratch2);
+      __ clz(scratch1, scratch1);
       __ rsb(scratch1, scratch1, Operand(31));
       __ mov(right, Operand(left, LSR, scratch1));
       __ Ret();
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h
index 741ff9c..75cbf65 100644
--- a/src/arm/code-stubs-arm.h
+++ b/src/arm/code-stubs-arm.h
@@ -130,7 +130,7 @@
   void GenerateGenericStubBitNot(MacroAssembler* masm);
   void GenerateGenericCodeFallback(MacroAssembler* masm);
 
-  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
+  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
 
   virtual InlineCacheState GetICState() {
     return UnaryOpIC::ToState(operand_type_);
diff --git a/src/arm/constants-arm.h b/src/arm/constants-arm.h
index 747dc56..e21055f 100644
--- a/src/arm/constants-arm.h
+++ b/src/arm/constants-arm.h
@@ -33,13 +33,6 @@
 #error ARM EABI support is required.
 #endif
 
-// This means that interwork-compatible jump instructions are generated.  We
-// want to generate them on the simulator too so it makes snapshots that can
-// be used on real hardware.
-#if defined(__THUMB_INTERWORK__) || !defined(__arm__)
-# define USE_THUMB_INTERWORK 1
-#endif
-
 #if defined(__ARM_ARCH_7A__) || \
     defined(__ARM_ARCH_7R__) || \
     defined(__ARM_ARCH_7__)
@@ -49,39 +42,11 @@
 #endif
 #endif
 
-#if defined(__ARM_ARCH_6__)   ||   \
-    defined(__ARM_ARCH_6J__)  ||  \
-    defined(__ARM_ARCH_6K__)  ||  \
-    defined(__ARM_ARCH_6Z__)  ||  \
-    defined(__ARM_ARCH_6ZK__) || \
-    defined(__ARM_ARCH_6T2__) || \
-    defined(CAN_USE_ARMV7_INSTRUCTIONS)
-# define CAN_USE_ARMV6_INSTRUCTIONS 1
-#endif
-
-#if defined(__ARM_ARCH_5__)    || \
-    defined(__ARM_ARCH_5T__)   || \
-    defined(__ARM_ARCH_5TE__)  || \
-    defined(__ARM_ARCH_5TEJ__) || \
-    defined(CAN_USE_ARMV6_INSTRUCTIONS)
-# define CAN_USE_ARMV5_INSTRUCTIONS 1
-# define CAN_USE_THUMB_INSTRUCTIONS 1
-#endif
-
-// Simulator should support ARM5 instructions and unaligned access by default.
+// Simulator should support unaligned access by default.
 #if !defined(__arm__)
-# define CAN_USE_ARMV5_INSTRUCTIONS 1
-# define CAN_USE_THUMB_INSTRUCTIONS 1
-
 # ifndef CAN_USE_UNALIGNED_ACCESSES
 #  define CAN_USE_UNALIGNED_ACCESSES 1
 # endif
-
-#endif
-
-// Using blx may yield better code, so use it when required or when available
-#if defined(USE_THUMB_INTERWORK) || defined(CAN_USE_ARMV5_INSTRUCTIONS)
-#define USE_BLX 1
 #endif
 
 namespace v8 {
diff --git a/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index 7b08ed8..101cd9f 100644
--- a/src/arm/cpu-arm.cc
+++ b/src/arm/cpu-arm.cc
@@ -108,7 +108,7 @@
 
 
 void CPU::DebugBreak() {
-#if !defined (__arm__) || !defined(CAN_USE_ARMV5_INSTRUCTIONS)
+#if !defined (__arm__)
   UNIMPLEMENTED();  // when building ARM emulator target
 #else
   asm volatile("bkpt 0");
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index e9a65b2..848fae2 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -48,23 +48,13 @@
   //   add sp, sp, #4
   //   bx lr
   // to a call to the debug break return code.
-  // #ifdef USE_BLX
   //   ldr ip, [pc, #0]
   //   blx ip
-  // #else
-  //   mov lr, pc
-  //   ldr pc, [pc, #-4]
-  // #endif
   //   <debug break return code entry point address>
   //   bktp 0
   CodePatcher patcher(rinfo()->pc(), Assembler::kJSReturnSequenceInstructions);
-#ifdef USE_BLX
   patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
   patcher.masm()->blx(v8::internal::ip);
-#else
-  patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
-  patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
-#endif
   patcher.Emit(Isolate::Current()->debug()->debug_break_return()->entry());
   patcher.masm()->bkpt(0);
 }
@@ -99,22 +89,12 @@
   //   mov r2, r2
   //   mov r2, r2
   // to a call to the debug break slot code.
-  // #ifdef USE_BLX
   //   ldr ip, [pc, #0]
   //   blx ip
-  // #else
-  //   mov lr, pc
-  //   ldr pc, [pc, #-4]
-  // #endif
   //   <debug break slot code entry point address>
   CodePatcher patcher(rinfo()->pc(), Assembler::kDebugBreakSlotInstructions);
-#ifdef USE_BLX
   patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0));
   patcher.masm()->blx(v8::internal::ip);
-#else
-  patcher.masm()->mov(v8::internal::lr, v8::internal::pc);
-  patcher.masm()->ldr(v8::internal::pc, MemOperand(v8::internal::pc, -4));
-#endif
   patcher.Emit(Isolate::Current()->debug()->debug_break_slot()->entry());
 }
 
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index ba0f141..6a33234 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -3976,18 +3976,6 @@
       break;
     }
 
-    case Token::ADD: {
-      Comment cmt(masm_, "[ UnaryOperation (ADD)");
-      VisitForAccumulatorValue(expr->expression());
-      Label no_conversion;
-      __ JumpIfSmi(result_register(), &no_conversion);
-      ToNumberStub convert_stub;
-      __ CallStub(&convert_stub);
-      __ bind(&no_conversion);
-      context()->Plug(result_register());
-      break;
-    }
-
     case Token::SUB:
       EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
       break;
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index f6029b5..64083e8 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -823,11 +823,15 @@
     HEnvironment* last_environment = pred->last_environment();
     for (int i = 0; i < block->phis()->length(); ++i) {
       HPhi* phi = block->phis()->at(i);
-      last_environment->SetValueAt(phi->merged_index(), phi);
+      if (phi->merged_index() < last_environment->length()) {
+        last_environment->SetValueAt(phi->merged_index(), phi);
+      }
     }
     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
-      last_environment->SetValueAt(block->deleted_phis()->at(i),
-                                   graph_->GetConstantUndefined());
+      if (block->deleted_phis()->at(i) < last_environment->length()) {
+        last_environment->SetValueAt(block->deleted_phis()->at(i),
+                                     graph_->GetConstantUndefined());
+      }
     }
     block->UpdateEnvironment(last_environment);
     // Pick up the outgoing argument count of one of the predecessors.
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index a19015d..d2f44b0 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -304,7 +304,7 @@
       LDeferredCode* code = deferred_[i];
       __ bind(code->entry());
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred build frame",
+        Comment(";;; Deferred build frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(!frame_is_built_);
@@ -320,7 +320,7 @@
               code->instr()->Mnemonic());
       code->Generate();
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred destroy frame",
+        Comment(";;; Deferred destroy frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(frame_is_built_);
@@ -1043,11 +1043,9 @@
 
 
 void LCodeGen::DoLabel(LLabel* label) {
-  if (label->is_loop_header()) {
-    Comment(";;; B%d - LOOP entry", label->block_id());
-  } else {
-    Comment(";;; B%d", label->block_id());
-  }
+  Comment(";;; -------------------- B%d%s --------------------",
+          label->block_id(),
+          label->is_loop_header() ? " (loop header)" : "");
   __ bind(label->label());
   current_block_ = label->block_id();
   DoGap(label);
@@ -2055,33 +2053,38 @@
   LOperand* left = instr->left();
   LOperand* right = instr->right();
   HMathMinMax::Operation operation = instr->hydrogen()->operation();
-  Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
   if (instr->hydrogen()->representation().IsInteger32()) {
+    Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
     Register left_reg = ToRegister(left);
     Operand right_op = (right->IsRegister() || right->IsConstantOperand())
         ? ToOperand(right)
         : Operand(EmitLoadRegister(right, ip));
     Register result_reg = ToRegister(instr->result());
     __ cmp(left_reg, right_op);
-    if (!result_reg.is(left_reg)) {
-      __ mov(result_reg, left_reg, LeaveCC, condition);
-    }
+    __ Move(result_reg, left_reg, condition);
     __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition));
   } else {
     ASSERT(instr->hydrogen()->representation().IsDouble());
     DwVfpRegister left_reg = ToDoubleRegister(left);
     DwVfpRegister right_reg = ToDoubleRegister(right);
     DwVfpRegister result_reg = ToDoubleRegister(instr->result());
-    Label check_nan_left, check_zero, return_left, return_right, done;
+    Label result_is_nan, return_left, return_right, check_zero, done;
     __ VFPCompareAndSetFlags(left_reg, right_reg);
-    __ b(vs, &check_nan_left);
-    __ b(eq, &check_zero);
-    __ b(condition, &return_left);
-    __ b(al, &return_right);
-
-    __ bind(&check_zero);
+    if (operation == HMathMinMax::kMathMin) {
+      __ b(mi, &return_left);
+      __ b(gt, &return_right);
+    } else {
+      __ b(mi, &return_right);
+      __ b(gt, &return_left);
+    }
+    __ b(vs, &result_is_nan);
+    // Left equals right => check for -0.
     __ VFPCompareAndSetFlags(left_reg, 0.0);
-    __ b(ne, &return_left);  // left == right != 0.
+    if (left_reg.is(result_reg) || right_reg.is(result_reg)) {
+      __ b(ne, &done);  // left == right != 0.
+    } else {
+      __ b(ne, &return_left);  // left == right != 0.
+    }
     // At this point, both left and right are either 0 or -0.
     if (operation == HMathMinMax::kMathMin) {
       // We could use a single 'vorr' instruction here if we had NEON support.
@@ -2093,21 +2096,21 @@
       // the decision for vadd is easy because vand is a NEON instruction.
       __ vadd(result_reg, left_reg, right_reg);
     }
-    __ b(al, &done);
+    __ b(&done);
 
-    __ bind(&check_nan_left);
-    __ VFPCompareAndSetFlags(left_reg, left_reg);
-    __ b(vs, &return_left);  // left == NaN.
+    __ bind(&result_is_nan);
+    __ vadd(result_reg, left_reg, right_reg);
+    __ b(&done);
+
     __ bind(&return_right);
-    if (!right_reg.is(result_reg)) {
-      __ vmov(result_reg, right_reg);
+    __ Move(result_reg, right_reg);
+    if (!left_reg.is(result_reg)) {
+      __ b(&done);
     }
-    __ b(al, &done);
 
     __ bind(&return_left);
-    if (!left_reg.is(result_reg)) {
-      __ vmov(result_reg, left_reg);
-    }
+    __ Move(result_reg, left_reg);
+
     __ bind(&done);
   }
 }
@@ -2205,12 +2208,10 @@
     EmitBranch(true_block, false_block, ne);
   } else if (r.IsDouble()) {
     DwVfpRegister reg = ToDoubleRegister(instr->value());
-    Register scratch = scratch0();
-
     // Test the double value. Zero and NaN are false.
-    __ VFPCompareAndLoadFlags(reg, 0.0, scratch);
-    __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit));
-    EmitBranch(true_block, false_block, eq);
+    __ VFPCompareAndSetFlags(reg, 0.0);
+    __ cmp(r0, r0, vs);  // If NaN, set the Z flag.
+    EmitBranch(true_block, false_block, ne);
   } else {
     ASSERT(r.IsTagged());
     Register reg = ToRegister(instr->value());
@@ -2302,7 +2303,7 @@
         __ b(ne, &not_heap_number);
         __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset));
         __ VFPCompareAndSetFlags(dbl_scratch, 0.0);
-        __ b(vs, false_label);  // NaN -> false.
+        __ cmp(r0, r0, vs);  // NaN -> false.
         __ b(eq, false_label);  // +0, -0 -> false.
         __ b(true_label);
         __ bind(&not_heap_number);
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 3e24dae..c55558c 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -29,10 +29,12 @@
 #define V8_ARM_LITHIUM_CODEGEN_ARM_H_
 
 #include "arm/lithium-arm.h"
+
 #include "arm/lithium-gap-resolver-arm.h"
 #include "deoptimizer.h"
 #include "safepoint-table.h"
 #include "scopes.h"
+#include "v8utils.h"
 
 namespace v8 {
 namespace internal {
@@ -211,7 +213,7 @@
   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
 
   void Abort(const char* reason);
-  void Comment(const char* format, ...);
+  void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
 
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 7df0c0a..616d02d 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -51,44 +51,15 @@
 }
 
 
-// We always generate arm code, never thumb code, even if V8 is compiled to
-// thumb, so we require inter-working support
-#if defined(__thumb__) && !defined(USE_THUMB_INTERWORK)
-#error "flag -mthumb-interwork missing"
-#endif
-
-
-// We do not support thumb inter-working with an arm architecture not supporting
-// the blx instruction (below v5t).  If you know what CPU you are compiling for
-// you can use -march=armv7 or similar.
-#if defined(USE_THUMB_INTERWORK) && !defined(CAN_USE_THUMB_INSTRUCTIONS)
-# error "For thumb inter-working we require an architecture which supports blx"
-#endif
-
-
-// Using bx does not yield better code, so use it only when required
-#if defined(USE_THUMB_INTERWORK)
-#define USE_BX 1
-#endif
-
-
 void MacroAssembler::Jump(Register target, Condition cond) {
-#if USE_BX
   bx(target, cond);
-#else
-  mov(pc, Operand(target), LeaveCC, cond);
-#endif
 }
 
 
 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
                           Condition cond) {
-#if USE_BX
   mov(ip, Operand(target, rmode));
   bx(ip, cond);
-#else
-  mov(pc, Operand(target, rmode), LeaveCC, cond);
-#endif
 }
 
 
@@ -108,11 +79,7 @@
 
 
 int MacroAssembler::CallSize(Register target, Condition cond) {
-#ifdef USE_BLX
   return kInstrSize;
-#else
-  return 2 * kInstrSize;
-#endif
 }
 
 
@@ -121,13 +88,7 @@
   BlockConstPoolScope block_const_pool(this);
   Label start;
   bind(&start);
-#ifdef USE_BLX
   blx(target, cond);
-#else
-  // set lr for return at current pc + 8
-  mov(lr, Operand(pc), LeaveCC, cond);
-  mov(pc, Operand(target), LeaveCC, cond);
-#endif
   ASSERT_EQ(CallSize(target, cond), SizeOfCodeGeneratedSince(&start));
 }
 
@@ -170,7 +131,6 @@
     set_predictable_code_size(true);
   }
 
-#ifdef USE_BLX
   // Call sequence on V7 or later may be :
   //  movw  ip, #... @ call address low 16
   //  movt  ip, #... @ call address high 16
@@ -191,12 +151,6 @@
   mov(ip, Operand(reinterpret_cast<int32_t>(target), rmode));
   blx(ip, cond);
 
-#else
-  // Set lr for return at current pc + 8.
-  mov(lr, Operand(pc), LeaveCC, cond);
-  // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
-  mov(pc, Operand(reinterpret_cast<int32_t>(target), rmode), LeaveCC, cond);
-#endif
   ASSERT_EQ(CallSize(target, rmode, cond), SizeOfCodeGeneratedSince(&start));
   if (mode == NEVER_INLINE_TARGET_ADDRESS) {
     set_predictable_code_size(old_predictable_code_size);
@@ -230,11 +184,7 @@
 
 
 void MacroAssembler::Ret(Condition cond) {
-#if USE_BX
   bx(lr, cond);
-#else
-  mov(pc, Operand(lr), LeaveCC, cond);
-#endif
 }
 
 
@@ -3226,44 +3176,6 @@
 }
 
 
-void MacroAssembler::CountLeadingZeros(Register zeros,   // Answer.
-                                       Register source,  // Input.
-                                       Register scratch) {
-  ASSERT(!zeros.is(source) || !source.is(scratch));
-  ASSERT(!zeros.is(scratch));
-  ASSERT(!scratch.is(ip));
-  ASSERT(!source.is(ip));
-  ASSERT(!zeros.is(ip));
-#ifdef CAN_USE_ARMV5_INSTRUCTIONS
-  clz(zeros, source);  // This instruction is only supported after ARM5.
-#else
-  // Order of the next two lines is important: zeros register
-  // can be the same as source register.
-  Move(scratch, source);
-  mov(zeros, Operand::Zero());
-  // Top 16.
-  tst(scratch, Operand(0xffff0000));
-  add(zeros, zeros, Operand(16), LeaveCC, eq);
-  mov(scratch, Operand(scratch, LSL, 16), LeaveCC, eq);
-  // Top 8.
-  tst(scratch, Operand(0xff000000));
-  add(zeros, zeros, Operand(8), LeaveCC, eq);
-  mov(scratch, Operand(scratch, LSL, 8), LeaveCC, eq);
-  // Top 4.
-  tst(scratch, Operand(0xf0000000));
-  add(zeros, zeros, Operand(4), LeaveCC, eq);
-  mov(scratch, Operand(scratch, LSL, 4), LeaveCC, eq);
-  // Top 2.
-  tst(scratch, Operand(0xc0000000));
-  add(zeros, zeros, Operand(2), LeaveCC, eq);
-  mov(scratch, Operand(scratch, LSL, 2), LeaveCC, eq);
-  // Top bit.
-  tst(scratch, Operand(0x80000000u));
-  add(zeros, zeros, Operand(1), LeaveCC, eq);
-#endif
-}
-
-
 void MacroAssembler::CheckFor32DRegs(Register scratch) {
   mov(scratch, Operand(ExternalReference::cpu_features()));
   ldr(scratch, MemOperand(scratch));
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 86ae8f2..f9f672b 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -993,15 +993,6 @@
                    Register input_high,
                    Register input_low);
 
-  // Count leading zeros in a 32 bit word.  On ARM5 and later it uses the clz
-  // instruction.  On pre-ARM5 hardware this routine gives the wrong answer
-  // for 0 (31 instead of 32).  Source and scratch can be the same in which case
-  // the source is clobbered.  Source and zeros can also be the same in which
-  // case scratch should be a different register.
-  void CountLeadingZeros(Register zeros,
-                         Register source,
-                         Register scratch);
-
   // Check whether d16-d31 are available on the CPU. The result is given by the
   // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise.
   void CheckFor32DRegs(Register scratch);
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index ad4d77d..ea79310 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -975,14 +975,12 @@
 }
 
 
-// Runtime FP routines take up to two double arguments and zero
-// or one integer arguments. All are constructed here,
+// For use in calls that take two double values, constructed either
 // from r0-r3 or d0 and d1.
-void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
+void Simulator::GetFpArgs(double* x, double* y) {
   if (use_eabi_hardfloat()) {
     *x = vfp_registers_[0];
     *y = vfp_registers_[1];
-    *z = registers_[1];
   } else {
     // We use a char buffer to get around the strict-aliasing rules which
     // otherwise allow the compiler to optimize away the copy.
@@ -993,9 +991,41 @@
     // Registers 2 and 3 -> y.
     OS::MemCopy(buffer, registers_ + 2, sizeof(*y));
     OS::MemCopy(y, buffer, sizeof(*y));
-    // Register 2 -> z.
-    OS::MemCopy(buffer, registers_ + 2, sizeof(*z));
-    OS::MemCopy(z, buffer, sizeof(*z));
+  }
+}
+
+// For use in calls that take one double value, constructed either
+// from r0 and r1 or d0.
+void Simulator::GetFpArgs(double* x) {
+  if (use_eabi_hardfloat()) {
+    *x = vfp_registers_[0];
+  } else {
+    // We use a char buffer to get around the strict-aliasing rules which
+    // otherwise allow the compiler to optimize away the copy.
+    char buffer[sizeof(*x)];
+    // Registers 0 and 1 -> x.
+    OS::MemCopy(buffer, registers_, sizeof(*x));
+    OS::MemCopy(x, buffer, sizeof(*x));
+  }
+}
+
+
+// For use in calls that take one double value constructed either
+// from r0 and r1 or d0 and one integer value.
+void Simulator::GetFpArgs(double* x, int32_t* y) {
+  if (use_eabi_hardfloat()) {
+    *x = vfp_registers_[0];
+    *y = registers_[1];
+  } else {
+    // We use a char buffer to get around the strict-aliasing rules which
+    // otherwise allow the compiler to optimize away the copy.
+    char buffer[sizeof(*x)];
+    // Registers 0 and 1 -> x.
+    OS::MemCopy(buffer, registers_, sizeof(*x));
+    OS::MemCopy(x, buffer, sizeof(*x));
+    // Register 2 -> y.
+    OS::MemCopy(buffer, registers_ + 2, sizeof(*y));
+    OS::MemCopy(y, buffer, sizeof(*y));
   }
 }
 
@@ -1618,12 +1648,10 @@
                                         int32_t arg3,
                                         int32_t arg4,
                                         int32_t arg5);
-
-// These prototypes handle the four types of FP calls.
-typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
-typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
-typedef double (*SimulatorRuntimeFPCall)(double darg0);
-typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
+typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
+                                         int32_t arg1,
+                                         int32_t arg2,
+                                         int32_t arg3);
 
 // This signature supports direct call in to API function native callback
 // (refer to InvocationCallback in v8.h).
@@ -1689,27 +1717,27 @@
       intptr_t external =
           reinterpret_cast<intptr_t>(redirection->external_function());
       if (fp_call) {
-        double dval0, dval1;  // one or two double parameters
-        int32_t ival;         // zero or one integer parameters
-        int64_t iresult = 0;  // integer return value
-        double dresult = 0;   // double return value
-        GetFpArgs(&dval0, &dval1, &ival);
         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
-          SimulatorRuntimeCall generic_target =
-            reinterpret_cast<SimulatorRuntimeCall>(external);
+          SimulatorRuntimeFPCall target =
+              reinterpret_cast<SimulatorRuntimeFPCall>(external);
+          double dval0, dval1;
+          int32_t ival;
           switch (redirection->type()) {
           case ExternalReference::BUILTIN_FP_FP_CALL:
           case ExternalReference::BUILTIN_COMPARE_CALL:
+            GetFpArgs(&dval0, &dval1);
             PrintF("Call to host function at %p with args %f, %f",
-                   FUNCTION_ADDR(generic_target), dval0, dval1);
+                FUNCTION_ADDR(target), dval0, dval1);
             break;
           case ExternalReference::BUILTIN_FP_CALL:
+            GetFpArgs(&dval0);
             PrintF("Call to host function at %p with arg %f",
-                FUNCTION_ADDR(generic_target), dval0);
+                FUNCTION_ADDR(target), dval0);
             break;
           case ExternalReference::BUILTIN_FP_INT_CALL:
+            GetFpArgs(&dval0, &ival);
             PrintF("Call to host function at %p with args %f, %d",
-                   FUNCTION_ADDR(generic_target), dval0, ival);
+                FUNCTION_ADDR(target), dval0, ival);
             break;
           default:
             UNREACHABLE();
@@ -1721,54 +1749,22 @@
           PrintF("\n");
         }
         CHECK(stack_aligned);
-        switch (redirection->type()) {
-        case ExternalReference::BUILTIN_COMPARE_CALL: {
-          SimulatorRuntimeCompareCall target =
-            reinterpret_cast<SimulatorRuntimeCompareCall>(external);
-          iresult = target(dval0, dval1);
-          set_register(r0, static_cast<int32_t>(iresult));
-          set_register(r1, static_cast<int32_t>(iresult >> 32));
-          break;
-        }
-        case ExternalReference::BUILTIN_FP_FP_CALL: {
-          SimulatorRuntimeFPFPCall target =
-            reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
-          dresult = target(dval0, dval1);
-          SetFpResult(dresult);
-          break;
-        }
-        case ExternalReference::BUILTIN_FP_CALL: {
+        if (redirection->type() != ExternalReference::BUILTIN_COMPARE_CALL) {
           SimulatorRuntimeFPCall target =
-            reinterpret_cast<SimulatorRuntimeFPCall>(external);
-          dresult = target(dval0);
-          SetFpResult(dresult);
-          break;
-        }
-        case ExternalReference::BUILTIN_FP_INT_CALL: {
-          SimulatorRuntimeFPIntCall target =
-            reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
-          dresult = target(dval0, ival);
-          SetFpResult(dresult);
-          break;
-        }
-        default:
-          UNREACHABLE();
-          break;
-        }
-        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
-          switch (redirection->type()) {
-          case ExternalReference::BUILTIN_COMPARE_CALL:
-            PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
-            break;
-          case ExternalReference::BUILTIN_FP_FP_CALL:
-          case ExternalReference::BUILTIN_FP_CALL:
-          case ExternalReference::BUILTIN_FP_INT_CALL:
-            PrintF("Returned %f\n", dresult);
-            break;
-          default:
-            UNREACHABLE();
-            break;
+              reinterpret_cast<SimulatorRuntimeFPCall>(external);
+          double result = target(arg0, arg1, arg2, arg3);
+          SetFpResult(result);
+        } else {
+          SimulatorRuntimeCall target =
+              reinterpret_cast<SimulatorRuntimeCall>(external);
+          int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
+          int32_t lo_res = static_cast<int32_t>(result);
+          int32_t hi_res = static_cast<int32_t>(result >> 32);
+          if (::v8::internal::FLAG_trace_sim) {
+            PrintF("Returned %08x\n", lo_res);
           }
+          set_register(r0, lo_res);
+          set_register(r1, hi_res);
         }
       } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
         SimulatorRuntimeDirectApiCall target =
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index 45ae999..674ff42 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -348,8 +348,10 @@
       void* external_function,
       v8::internal::ExternalReference::Type type);
 
-  // Handle arguments and return value for runtime FP functions.
-  void GetFpArgs(double* x, double* y, int32_t* z);
+  // For use in calls that take double value arguments.
+  void GetFpArgs(double* x, double* y);
+  void GetFpArgs(double* x);
+  void GetFpArgs(double* x, int32_t* y);
   void SetFpResult(const double& result);
   void TrashCallerSaveRegisters();
 
diff --git a/src/atomicops_internals_x86_gcc.h b/src/atomicops_internals_x86_gcc.h
index e58d598..6e55b50 100644
--- a/src/atomicops_internals_x86_gcc.h
+++ b/src/atomicops_internals_x86_gcc.h
@@ -168,7 +168,7 @@
   return *ptr;
 }
 
-#if defined(__x86_64__) && defined(V8_HOST_ARCH_64_BIT)
+#if defined(__x86_64__)
 
 // 64-bit low-level operations on 64-bit platform.
 
diff --git a/src/builtins-decls.h b/src/builtins-decls.h
deleted file mode 100644
index beb5dd1..0000000
--- a/src/builtins-decls.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef V8_BUILTINS_DECLS_H_
-#define V8_BUILTINS_DECLS_H_
-
-#include "arguments.h"
-
-namespace v8 {
-namespace internal {
-
-DECLARE_RUNTIME_FUNCTION(MaybeObject*, ArrayConstructor_StubFailure);
-
-} }  // namespace v8::internal
-
-#endif  // V8_BUILTINS_DECLS_H_
diff --git a/src/builtins.cc b/src/builtins.cc
index 56c0501..30edf57 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -125,31 +125,23 @@
 
 #ifdef DEBUG
 
-#define BUILTIN(name)                                            \
-  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name(       \
-      name##ArgumentsType args, Isolate* isolate);               \
-  MUST_USE_RESULT static MaybeObject* Builtin_##name(            \
-      int args_length, Object** args_object, Isolate* isolate) { \
-    name##ArgumentsType args(args_length, args_object);          \
-    ASSERT(isolate == Isolate::Current());                       \
-    args.Verify();                                               \
-    return Builtin_Impl_##name(args, isolate);                   \
-  }                                                              \
-  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name(       \
+#define BUILTIN(name)                                      \
+  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
+      name##ArgumentsType args, Isolate* isolate);         \
+  MUST_USE_RESULT static MaybeObject* Builtin_##name(      \
+      name##ArgumentsType args, Isolate* isolate) {        \
+    ASSERT(isolate == Isolate::Current());                 \
+    args.Verify();                                         \
+    return Builtin_Impl_##name(args, isolate);             \
+  }                                                        \
+  MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
       name##ArgumentsType args, Isolate* isolate)
 
 #else  // For release mode.
 
-#define BUILTIN(name)                                            \
-  static MaybeObject* Builtin_impl##name(                        \
-      name##ArgumentsType args, Isolate* isolate);               \
-  static MaybeObject* Builtin_##name(                            \
-      int args_length, Object** args_object, Isolate* isolate) { \
-    name##ArgumentsType args(args_length, args_object);          \
-    return Builtin_impl##name(args, isolate);                    \
-  }                                                              \
-  static MaybeObject* Builtin_impl##name(                        \
-      name##ArgumentsType args, Isolate* isolate)
+#define BUILTIN(name)                                      \
+  static MaybeObject* Builtin_##name(name##ArgumentsType args, Isolate* isolate)
+
 #endif
 
 
diff --git a/src/builtins.h b/src/builtins.h
index ee607ad..12ed56a 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -274,6 +274,8 @@
   V(APPLY_PREPARE, 1)                    \
   V(APPLY_OVERFLOW, 1)
 
+MaybeObject* ArrayConstructor_StubFailure(Arguments args, Isolate* isolate);
+
 class BuiltinFunctionTable;
 class ObjectVisitor;
 
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 02c0091..60ddf9b 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -106,8 +106,7 @@
   Zone* zone = this->zone();
   int param_count = descriptor_->register_param_count_;
   HEnvironment* start_environment = graph()->start_environment();
-  HBasicBlock* next_block =
-      CreateBasicBlock(start_environment, BailoutId::StubEntry());
+  HBasicBlock* next_block = CreateBasicBlock(start_environment);
   current_block()->Goto(next_block);
   next_block->SetJoinId(BailoutId::StubEntry());
   set_current_block(next_block);
@@ -186,7 +185,7 @@
 static Handle<Code> DoGenerateCode(Stub* stub) {
   CodeStubGraphBuilder<Stub> builder(stub);
   LChunk* chunk = OptimizeGraph(builder.CreateGraph());
-  return chunk->Codegen(Code::COMPILED_STUB);
+  return chunk->Codegen();
 }
 
 
@@ -212,23 +211,24 @@
         AddInstruction(new(zone) HLoadElements(boilerplate, NULL));
 
     IfBuilder if_fixed_cow(this);
-    if_fixed_cow.BeginIfMapEquals(elements, factory->fixed_cow_array_map());
+    if_fixed_cow.IfCompareMap(elements, factory->fixed_cow_array_map());
+    if_fixed_cow.Then();
     environment()->Push(BuildCloneShallowArray(context(),
                                                boilerplate,
                                                alloc_site_mode,
                                                FAST_ELEMENTS,
                                                0/*copy-on-write*/));
-    if_fixed_cow.BeginElse();
+    if_fixed_cow.Else();
 
     IfBuilder if_fixed(this);
-    if_fixed.BeginIfMapEquals(elements, factory->fixed_array_map());
+    if_fixed.IfCompareMap(elements, factory->fixed_array_map());
+    if_fixed.Then();
     environment()->Push(BuildCloneShallowArray(context(),
                                                boilerplate,
                                                alloc_site_mode,
                                                FAST_ELEMENTS,
                                                length));
-    if_fixed.BeginElse();
-
+    if_fixed.Else();
     environment()->Push(BuildCloneShallowArray(context(),
                                                boilerplate,
                                                alloc_site_mode,
@@ -250,7 +250,7 @@
 Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
   CodeStubGraphBuilder<FastCloneShallowArrayStub> builder(this);
   LChunk* chunk = OptimizeGraph(builder.CreateGraph());
-  return chunk->Codegen(Code::COMPILED_STUB);
+  return chunk->Codegen();
 }
 
 
@@ -359,11 +359,12 @@
 
   IfBuilder if_builder(this);
 
-  if_builder.BeginIf(array_length, graph()->GetConstant0(), Token::EQ);
+  if_builder.IfCompare(array_length, graph()->GetConstant0(), Token::EQ);
+  if_builder.Then();
 
   // Nothing to do, just change the map.
 
-  if_builder.BeginElse();
+  if_builder.Else();
 
   HInstruction* elements =
       AddInstruction(new(zone) HLoadElements(js_array, js_array));
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index ad418d6..497dde5 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -67,7 +67,7 @@
 }
 
 
-int CodeStub::GetCodeKind() {
+Code::Kind CodeStub::GetCodeKind() const {
   return Code::STUB;
 }
 
@@ -98,7 +98,7 @@
 
   // Copy the generated code into a heap object.
   Code::Flags flags = Code::ComputeFlags(
-      static_cast<Code::Kind>(GetCodeKind()),
+      GetCodeKind(),
       GetICState(),
       GetExtraICState(),
       GetStubType(),
@@ -308,7 +308,7 @@
 bool ICCompareStub::FindCodeInSpecialCache(Code** code_out, Isolate* isolate) {
   Factory* factory = isolate->factory();
   Code::Flags flags = Code::ComputeFlags(
-      static_cast<Code::Kind>(GetCodeKind()),
+      GetCodeKind(),
       UNINITIALIZED);
   ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
   Handle<Object> probe(
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 60c4fb9..56b5955 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -176,19 +176,19 @@
   virtual Major MajorKey() = 0;
   virtual int MinorKey() = 0;
 
- protected:
-  static bool CanUseFPRegisters();
-
-  // Generates the assembler code for the stub.
-  virtual Handle<Code> GenerateCode() = 0;
-
-  // BinaryOpStub needs to override this.
   virtual InlineCacheState GetICState() {
     return UNINITIALIZED;
   }
   virtual Code::ExtraICState GetExtraICState() {
     return Code::kNoExtraICState;
   }
+
+ protected:
+  static bool CanUseFPRegisters();
+
+  // Generates the assembler code for the stub.
+  virtual Handle<Code> GenerateCode() = 0;
+
   virtual Code::StubType GetStubType() {
     return Code::NORMAL;
   }
@@ -210,7 +210,7 @@
   virtual void Activate(Code* code) { }
 
   // BinaryOpStub needs to override this.
-  virtual int GetCodeKind();
+  virtual Code::Kind GetCodeKind() const;
 
   // Add the code to a specialized cache, specific to an individual
   // stub type. Please note, this method must add the code object to a
@@ -249,7 +249,7 @@
   // Retrieve the code for the stub. Generate the code if needed.
   virtual Handle<Code> GenerateCode();
 
-  virtual int GetCodeKind() { return Code::STUB; }
+  virtual Code::Kind GetCodeKind() const { return Code::STUB; }
   virtual int GetStubFlags() { return -1; }
 
  protected:
@@ -286,7 +286,7 @@
   // Retrieve the code for the stub. Generate the code if needed.
   virtual Handle<Code> GenerateCode() = 0;
 
-  virtual int GetCodeKind() { return Code::COMPILED_STUB; }
+  virtual Code::Kind GetCodeKind() const { return Code::STUB; }
 
   CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
     return isolate->code_stub_interface_descriptor(MajorKey());
@@ -606,7 +606,7 @@
 class ICStub: public PlatformCodeStub {
  public:
   explicit ICStub(Code::Kind kind) : kind_(kind) { }
-  virtual int GetCodeKind() { return kind_; }
+  virtual Code::Kind GetCodeKind() const { return kind_; }
   virtual InlineCacheState GetICState() { return MONOMORPHIC; }
 
   bool Describes(Code* code) {
@@ -692,7 +692,7 @@
 class HandlerStub: public ICStub {
  public:
   explicit HandlerStub(Code::Kind kind) : ICStub(kind) { }
-  virtual int GetCodeKind() { return Code::STUB; }
+  virtual Code::Kind GetCodeKind() const { return Code::STUB; }
   virtual int GetStubFlags() { return kind(); }
 };
 
@@ -830,7 +830,7 @@
   // Entirely platform-specific methods are defined as static helper
   // functions in the <arch>/code-stubs-<arch>.cc files.
 
-  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
+  virtual Code::Kind GetCodeKind() const { return Code::BINARY_OP_IC; }
 
   virtual InlineCacheState GetICState() {
     return BinaryOpIC::ToState(Max(left_type_, right_type_));
@@ -884,7 +884,7 @@
   virtual CodeStub::Major MajorKey() { return CompareIC; }
   virtual int MinorKey();
 
-  virtual int GetCodeKind() { return Code::COMPARE_IC; }
+  virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
 
   void GenerateSmis(MacroAssembler* masm);
   void GenerateNumbers(MacroAssembler* masm);
@@ -1548,7 +1548,7 @@
       : tos_(tos), types_(types) { }
 
   void Generate(MacroAssembler* masm);
-  virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; }
+  virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
   virtual void PrintName(StringStream* stream);
 
   virtual bool SometimesSetsUpAFrame() { return false; }
diff --git a/src/codegen.cc b/src/codegen.cc
index 90ab2b5..ff4003c 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -106,10 +106,13 @@
 
   // Allocate and install the code.
   CodeDesc desc;
+  bool is_crankshafted =
+      Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION ||
+      info->IsStub();
   masm->GetCode(&desc);
   Handle<Code> code =
-      isolate->factory()->NewCode(desc, flags, masm->CodeObject());
-
+      isolate->factory()->NewCode(desc, flags, masm->CodeObject(),
+                                  false, is_crankshafted);
   if (!code.is_null()) {
     isolate->counters()->total_compiled_code_size()->Increment(
         code->instruction_size());
@@ -129,7 +132,7 @@
   if (print_code) {
     // Print the source code if available.
     FunctionLiteral* function = info->function();
-    if (code->kind() != Code::COMPILED_STUB) {
+    if (code->kind() == Code::OPTIMIZED_FUNCTION) {
       Handle<Script> script = info->script();
       if (!script->IsUndefined() && !script->source()->IsUndefined()) {
         PrintF("--- Raw source ---\n");
diff --git a/src/compiler.cc b/src/compiler.cc
index 184429b..70ce6bc 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -144,7 +144,11 @@
 
 Code::Flags CompilationInfo::flags() const {
   if (IsStub()) {
-    return Code::ComputeFlags(Code::COMPILED_STUB);
+    return Code::ComputeFlags(code_stub()->GetCodeKind(),
+                              code_stub()->GetICState(),
+                              code_stub()->GetExtraICState(),
+                              Code::NORMAL,
+                              0);
   } else {
     return Code::ComputeFlags(Code::OPTIMIZED_FUNCTION);
   }
@@ -421,7 +425,7 @@
     Timer timer(this, &time_taken_to_codegen_);
     ASSERT(chunk_ != NULL);
     ASSERT(graph_ != NULL);
-    Handle<Code> optimized_code = chunk_->Codegen(Code::OPTIMIZED_FUNCTION);
+    Handle<Code> optimized_code = chunk_->Codegen();
     if (optimized_code.is_null()) {
       info()->set_bailout_reason("code generation failed");
       return AbortOptimization();
@@ -553,6 +557,7 @@
       isolate->factory()->NewSharedFunctionInfo(
           lit->name(),
           lit->materialized_literal_count(),
+          lit->is_generator(),
           info->code(),
           ScopeInfo::Create(info->scope(), info->zone()));
 
@@ -1074,6 +1079,7 @@
   Handle<SharedFunctionInfo> result =
       FACTORY->NewSharedFunctionInfo(literal->name(),
                                      literal->materialized_literal_count(),
+                                     literal->is_generator(),
                                      info.code(),
                                      scope_info);
   SetFunctionInfo(result, literal, false, script);
diff --git a/src/compiler.h b/src/compiler.h
index 5e69661..dae39db 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -79,7 +79,7 @@
   Handle<JSFunction> closure() const { return closure_; }
   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
   Handle<Script> script() const { return script_; }
-  HydrogenCodeStub* code_stub() {return code_stub_; }
+  HydrogenCodeStub* code_stub() const {return code_stub_; }
   v8::Extension* extension() const { return extension_; }
   ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
   Handle<Context> context() const { return context_; }
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 1af7365..92a2af2 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -1195,7 +1195,8 @@
   //                                         reg = JSFunction context
   //
 
-  ASSERT(compiled_code_->kind() == Code::COMPILED_STUB);
+  ASSERT(compiled_code_->is_crankshafted() &&
+         compiled_code_->kind() != Code::OPTIMIZED_FUNCTION);
   int major_key = compiled_code_->major_key();
   CodeStubInterfaceDescriptor* descriptor =
       isolate_->code_stub_interface_descriptor(major_key);
@@ -2133,7 +2134,7 @@
     // size matches with the stack height we can compute based on the
     // environment at the OSR entry. The code for that his built into
     // the DoComputeOsrOutputFrame function for now.
-  } else if (compiled_code_->kind() != Code::COMPILED_STUB) {
+  } else if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
     unsigned stack_slots = compiled_code_->stack_slots();
     unsigned outgoing_size = ComputeOutgoingArgumentSize();
     ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
diff --git a/src/disassembler.cc b/src/disassembler.cc
index b01b443..bbb1fb8 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -332,8 +332,7 @@
 // Called by Code::CodePrint.
 void Disassembler::Decode(FILE* f, Code* code) {
   Isolate* isolate = code->GetIsolate();
-  int decode_size = (code->kind() == Code::OPTIMIZED_FUNCTION ||
-                     code->kind() == Code::COMPILED_STUB)
+  int decode_size = code->is_crankshafted()
       ? static_cast<int>(code->safepoint_table_offset())
       : code->instruction_size();
   // If there might be a back edge table, stop before reaching it.
diff --git a/src/factory.cc b/src/factory.cc
index 5e2a2b1..77d2200 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1,4 +1,4 @@
-// Copyright 2012 the V8 project authors. All rights reserved.
+// Copyright 2013 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -916,10 +916,11 @@
 Handle<Code> Factory::NewCode(const CodeDesc& desc,
                               Code::Flags flags,
                               Handle<Object> self_ref,
-                              bool immovable) {
+                              bool immovable,
+                              bool crankshafted) {
   CALL_HEAP_FUNCTION(isolate(),
                      isolate()->heap()->CreateCode(
-                         desc, flags, self_ref, immovable),
+                         desc, flags, self_ref, immovable, crankshafted),
                      Code);
 }
 
@@ -1078,6 +1079,7 @@
 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
     Handle<String> name,
     int number_of_literals,
+    bool is_generator,
     Handle<Code> code,
     Handle<ScopeInfo> scope_info) {
   Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
@@ -1091,6 +1093,9 @@
     literals_array_size += JSFunction::kLiteralsPrefixSize;
   }
   shared->set_num_literals(literals_array_size);
+  if (is_generator) {
+    shared->set_instance_class_name(isolate()->heap()->Generator_string());
+  }
   return shared;
 }
 
diff --git a/src/factory.h b/src/factory.h
index 8695bcd..b6bfa8a 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -347,7 +347,8 @@
   Handle<Code> NewCode(const CodeDesc& desc,
                        Code::Flags flags,
                        Handle<Object> self_reference,
-                       bool immovable = false);
+                       bool immovable = false,
+                       bool crankshafted = false);
 
   Handle<Code> CopyCode(Handle<Code> code);
 
@@ -454,6 +455,7 @@
   Handle<SharedFunctionInfo> NewSharedFunctionInfo(
       Handle<String> name,
       int number_of_literals,
+      bool is_generator,
       Handle<Code> code,
       Handle<ScopeInfo> scope_info);
   Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
diff --git a/src/generator.js b/src/generator.js
index d579928..481d4d3 100644
--- a/src/generator.js
+++ b/src/generator.js
@@ -39,18 +39,38 @@
 // http://wiki.ecmascript.org/lib/exe/fetch.php?cache=cache&media=harmony:es6_generator_object_model_3-29-13.png
 
 function GeneratorObjectNext() {
+  if (!IS_GENERATOR(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['[Generator].prototype.next', this]);
+  }
+
   // TODO(wingo): Implement.
 }
 
 function GeneratorObjectSend(value) {
+  if (!IS_GENERATOR(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['[Generator].prototype.send', this]);
+  }
+
   // TODO(wingo): Implement.
 }
 
 function GeneratorObjectThrow(exn) {
+  if (!IS_GENERATOR(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['[Generator].prototype.throw', this]);
+  }
+
   // TODO(wingo): Implement.
 }
 
 function GeneratorObjectClose() {
+  if (!IS_GENERATOR(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['[Generator].prototype.close', this]);
+  }
+
   // TODO(wingo): Implement.
 }
 
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 28e50aa..43d4a99 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -623,6 +623,13 @@
   CALL_AND_RETRY(ISOLATE, FUNCTION_CALL, return, return)
 
 
+#define CALL_HEAP_FUNCTION_PASS_EXCEPTION(ISOLATE, FUNCTION_CALL) \
+  CALL_AND_RETRY(ISOLATE,                                         \
+                 FUNCTION_CALL,                                   \
+                 return __object__,                               \
+                 return __maybe_object__)
+
+
 #ifdef DEBUG
 
 inline bool Heap::allow_allocation(bool new_state) {
diff --git a/src/heap.cc b/src/heap.cc
index 453d985..0c83c3a 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -3752,7 +3752,8 @@
 MaybeObject* Heap::CreateCode(const CodeDesc& desc,
                               Code::Flags flags,
                               Handle<Object> self_reference,
-                              bool immovable) {
+                              bool immovable,
+                              bool crankshafted) {
   // Allocate ByteArray before the Code object, so that we do not risk
   // leaving uninitialized Code object (and breaking the heap).
   ByteArray* reloc_info;
@@ -3796,6 +3797,7 @@
   if (code->is_call_stub() || code->is_keyed_call_stub()) {
     code->set_check_type(RECEIVER_MAP_CHECK);
   }
+  code->set_is_crankshafted(crankshafted);
   code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER);
   code->InitializeTypeFeedbackInfoNoWriteBarrier(undefined_value());
   code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
@@ -4358,6 +4360,7 @@
     MaybeObject* maybe_map = AllocateInitialMap(function);
     if (!maybe_map->To(&map)) return maybe_map;
     function->set_initial_map(map);
+    map->set_constructor(function);
   }
   ASSERT(map->instance_type() == JS_GENERATOR_OBJECT_TYPE);
   return AllocateJSObjectFromMap(map);
diff --git a/src/heap.h b/src/heap.h
index 7b4b70d..66897ea 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -268,7 +268,8 @@
   V(infinity_string, "Infinity")                                         \
   V(minus_infinity_string, "-Infinity")                                  \
   V(hidden_stack_trace_string, "v8::hidden_stack_trace")                 \
-  V(query_colon_string, "(?:)")
+  V(query_colon_string, "(?:)")                                          \
+  V(Generator_string, "Generator")
 
 // Forward declarations.
 class GCTracer;
@@ -1141,7 +1142,8 @@
   MUST_USE_RESULT MaybeObject* CreateCode(const CodeDesc& desc,
                                           Code::Flags flags,
                                           Handle<Object> self_reference,
-                                          bool immovable = false);
+                                          bool immovable = false,
+                                          bool crankshafted = false);
 
   MUST_USE_RESULT MaybeObject* CopyCode(Code* code);
 
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 60a6912..e7060be 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -648,6 +648,11 @@
 }
 
 
+bool HValue::EqualsInteger32Constant(int32_t value) {
+  return IsInteger32Constant() && GetInteger32Constant() == value;
+}
+
+
 void HValue::SetOperandAt(int index, HValue* value) {
   RegisterUse(index, value);
   InternalSetOperandAt(index, value);
@@ -1393,15 +1398,11 @@
   if (!representation().IsInteger32()) return this;
   // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x.
   int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0;
-  if (left()->IsConstant() &&
-      HConstant::cast(left())->HasInteger32Value() &&
-      HConstant::cast(left())->Integer32Value() == nop_constant &&
+  if (left()->EqualsInteger32Constant(nop_constant) &&
       !right()->CheckFlag(kUint32)) {
     return right();
   }
-  if (right()->IsConstant() &&
-      HConstant::cast(right())->HasInteger32Value() &&
-      HConstant::cast(right())->Integer32Value() == nop_constant &&
+  if (right()->EqualsInteger32Constant(nop_constant) &&
       !left()->CheckFlag(kUint32)) {
     return left();
   }
@@ -1422,17 +1423,37 @@
 }
 
 
-HValue* HAdd::Canonicalize() {
-  if (!representation().IsInteger32()) return this;
-  if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
+HValue* HArithmeticBinaryOperation::Canonicalize() {
+  if (representation().IsInteger32() && CheckUsesForFlag(kTruncatingToInt32)) {
+    ClearFlag(kCanOverflow);
+  }
   return this;
 }
 
 
+static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
+  return arg1->representation().IsSpecialization() &&
+    arg2->EqualsInteger32Constant(identity);
+}
+
+
+HValue* HAdd::Canonicalize() {
+  if (IsIdentityOperation(left(), right(), 0)) return left();
+  if (IsIdentityOperation(right(), left(), 0)) return right();
+  return HArithmeticBinaryOperation::Canonicalize();
+}
+
+
 HValue* HSub::Canonicalize() {
-  if (!representation().IsInteger32()) return this;
-  if (CheckUsesForFlag(kTruncatingToInt32)) ClearFlag(kCanOverflow);
-  return this;
+  if (IsIdentityOperation(left(), right(), 0)) return left();
+  return HArithmeticBinaryOperation::Canonicalize();
+}
+
+
+HValue* HMul::Canonicalize() {
+  if (IsIdentityOperation(left(), right(), 1)) return left();
+  if (IsIdentityOperation(right(), left(), 1)) return right();
+  return HArithmeticBinaryOperation::Canonicalize();
 }
 
 
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 6853dfe..cfbcc13 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1001,6 +1001,7 @@
 
   bool IsInteger32Constant();
   int32_t GetInteger32Constant();
+  bool EqualsInteger32Constant(int32_t value);
 
   bool IsDefinedAfter(HBasicBlock* other) const;
 
@@ -3328,10 +3329,6 @@
 
   bool BooleanValue() const { return boolean_value_; }
 
-  bool IsUint32() {
-    return HasInteger32Value() && (Integer32Value() >= 0);
-  }
-
   virtual intptr_t Hashcode() {
     if (has_int32_value_) {
       return static_cast<intptr_t>(int32_value_);
@@ -3842,6 +3839,8 @@
         : representation();
   }
 
+  virtual HValue* Canonicalize();
+
  private:
   virtual bool IsDeletable() const { return true; }
 };
@@ -4401,6 +4400,8 @@
 
   virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
 
+  virtual HValue* Canonicalize();
+
   // Only commutative if it is certain that not two objects are multiplicated.
   virtual bool IsCommutative() const {
     return !representation().IsTagged();
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 127d7a9..e527057 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -113,11 +113,10 @@
   ASSERT(!IsStartBlock() || !IsFinished());
   ASSERT(!instr->IsLinked());
   ASSERT(!IsFinished());
-  // Make sure that we never add instructions without knowing
-  // what the previous ast id is.
-  ASSERT(instr->IsSimulate() || instr->IsGoto() ||
-         !last_environment()->previous_ast_id().IsNone());
+
   if (first_ == NULL) {
+    ASSERT(last_environment() != NULL);
+    ASSERT(!last_environment()->ast_id().IsNone());
     HBlockEntry* entry = new(zone()) HBlockEntry();
     entry->InitializeAsFirst(this);
     first_ = last_ = entry;
@@ -184,7 +183,9 @@
 }
 
 
-void HBasicBlock::Goto(HBasicBlock* block, FunctionState* state) {
+void HBasicBlock::Goto(HBasicBlock* block,
+                       FunctionState* state,
+                       bool add_simulate) {
   bool drop_extra = state != NULL &&
       state->inlining_kind() == DROP_EXTRA_ON_RETURN;
 
@@ -193,7 +194,7 @@
     last_environment_ = last_environment()->DiscardInlined(drop_extra);
   }
 
-  AddSimulate(BailoutId::None());
+  if (add_simulate) AddSimulate(BailoutId::None());
   HGoto* instr = new(zone()) HGoto(block);
   Finish(instr);
 }
@@ -215,12 +216,10 @@
 }
 
 
-void HBasicBlock::SetInitialEnvironment(HEnvironment* env,
-                                        BailoutId previous_ast_id) {
+void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
   ASSERT(!HasEnvironment());
   ASSERT(first() == NULL);
   UpdateEnvironment(env);
-  env->set_previous_ast_id(previous_ast_id);
 }
 
 
@@ -236,11 +235,7 @@
             predecessor->last_environment()->closure()->shared()
               ->VerifyBailoutId(ast_id)));
     simulate->set_ast_id(ast_id);
-  }
-  HEnvironment* last_environment = this->last_environment();
-  ASSERT(last_environment || IsFinished());
-  if (last_environment != NULL) {
-    last_environment->set_previous_ast_id(ast_id);
+    predecessor->last_environment()->set_ast_id(ast_id);
   }
 }
 
@@ -301,9 +296,7 @@
     }
   } else if (!HasEnvironment() && !IsFinished()) {
     ASSERT(!IsLoopHeader());
-    HEnvironment* new_env = pred->last_environment()->Copy();
-    SetInitialEnvironment(new_env,
-                          pred->last_environment()->previous_ast_id());
+    SetInitialEnvironment(pred->last_environment()->Copy());
   }
 
   predecessors_.Add(pred, zone());
@@ -553,6 +546,18 @@
       HPhi* phi = block->phis()->at(j);
       phi->Verify();
     }
+
+    // Check that all join blocks have predecessors that end with an
+    // unconditional goto and agree on their environment node id.
+    if (block->predecessors()->length() >= 2) {
+      BailoutId id =
+          block->predecessors()->first()->last_environment()->ast_id();
+      for (int k = 0; k < block->predecessors()->length(); k++) {
+        HBasicBlock* predecessor = block->predecessors()->at(k);
+        ASSERT(predecessor->end()->IsGoto());
+        ASSERT(predecessor->last_environment()->ast_id() == id);
+      }
+    }
   }
 
   // Check special property of first block to have no predecessors.
@@ -639,25 +644,24 @@
 
 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder)
     : builder_(builder),
-      finished_(false),
-      id_(builder->current_block()->last_environment()->previous_ast_id()) {
+      finished_(false) {
   HEnvironment* env = builder->environment();
-  failure_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory(), id_);
-  merge_block_ = builder->CreateBasicBlock(env->CopyWithoutHistory(), id_);
+  failure_block_ = builder->CreateBasicBlock(env->Copy());
+  merge_block_ = builder->CreateBasicBlock(env->Copy());
 }
 
 
 HValue* HGraphBuilder::CheckBuilder::CheckNotUndefined(HValue* value) {
   HEnvironment* env = builder_->environment();
-  HIsNilAndBranch* compare =
-      new(zone()) HIsNilAndBranch(value, kStrictEquality, kUndefinedValue);
-  HBasicBlock* success_block =
-      builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
-  HBasicBlock* failure_block =
-      builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
+  HCompareObjectEqAndBranch* compare =
+      new(zone()) HCompareObjectEqAndBranch(
+          value,
+          builder_->graph()->GetConstantUndefined());
+  HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy());
+  HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy());
   compare->SetSuccessorAt(0, failure_block);
   compare->SetSuccessorAt(1, success_block);
-  failure_block->Goto(failure_block_);
+  failure_block->GotoNoSimulate(failure_block_);
   builder_->current_block()->Finish(compare);
   builder_->set_current_block(success_block);
   return compare;
@@ -671,13 +675,11 @@
   HCompareIDAndBranch* compare =
       new(zone()) HCompareIDAndBranch(left, right, op);
   compare->AssumeRepresentation(Representation::Integer32());
-  HBasicBlock* success_block =
-      builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
-  HBasicBlock* failure_block =
-      builder_->CreateBasicBlock(env->CopyWithoutHistory(), id_);
+  HBasicBlock* success_block = builder_->CreateBasicBlock(env->Copy());
+  HBasicBlock* failure_block = builder_->CreateBasicBlock(env->Copy());
   compare->SetSuccessorAt(0, success_block);
   compare->SetSuccessorAt(1, failure_block);
-  failure_block->Goto(failure_block_);
+  failure_block->GotoNoSimulate(failure_block_);
   builder_->current_block()->Finish(compare);
   builder_->set_current_block(success_block);
   return compare;
@@ -692,11 +694,11 @@
 
 void HGraphBuilder::CheckBuilder::End() {
   ASSERT(!finished_);
-  builder_->current_block()->Goto(merge_block_);
-  failure_block_->SetJoinId(id_);
-  failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
+  builder_->current_block()->GotoNoSimulate(merge_block_);
+  if (failure_block_->HasPredecessor()) {
+    failure_block_->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
+  }
   builder_->set_current_block(merge_block_);
-  merge_block_->SetJoinId(id_);
   finished_ = true;
 }
 
@@ -706,19 +708,51 @@
 }
 
 
-HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
+HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder, int position)
     : builder_(builder),
+      position_(position),
       finished_(false),
+      did_then_(false),
       did_else_(false),
-      id_(builder->current_block()->last_environment()->previous_ast_id()) {
+      deopt_then_(false),
+      deopt_else_(false),
+      did_and_(false),
+      did_or_(false),
+      captured_(false),
+      needs_compare_(true),
+      split_edge_merge_block_(NULL) {
   HEnvironment* env = builder->environment();
-  first_true_block_ = builder->CreateBasicBlock(env->Copy(), id_);
+  first_true_block_ = builder->CreateBasicBlock(env->Copy());
   last_true_block_ = NULL;
-  first_false_block_ = builder->CreateBasicBlock(env->Copy(), id_);
+  first_false_block_ = builder->CreateBasicBlock(env->Copy());
 }
 
 
-HInstruction* HGraphBuilder::IfBuilder::BeginIf(
+HGraphBuilder::IfBuilder::IfBuilder(
+    HGraphBuilder* builder,
+    HIfContinuation* continuation)
+    : builder_(builder),
+      position_(RelocInfo::kNoPosition),
+      finished_(false),
+      did_then_(false),
+      did_else_(false),
+      deopt_then_(false),
+      deopt_else_(false),
+      did_and_(false),
+      did_or_(false),
+      captured_(false),
+      needs_compare_(false),
+      first_true_block_(NULL),
+      first_false_block_(NULL),
+      split_edge_merge_block_(NULL),
+      merge_block_(NULL) {
+  continuation->Continue(&first_true_block_,
+                         &first_false_block_,
+                         &position_);
+}
+
+
+HInstruction* HGraphBuilder::IfBuilder::IfCompare(
     HValue* left,
     HValue* right,
     Token::Value token,
@@ -728,58 +762,148 @@
   compare->set_observed_input_representation(input_representation,
                                              input_representation);
   compare->ChangeRepresentation(input_representation);
-  compare->SetSuccessorAt(0, first_true_block_);
-  compare->SetSuccessorAt(1, first_false_block_);
-  builder_->current_block()->Finish(compare);
-  builder_->set_current_block(first_true_block_);
+  AddCompare(compare);
   return compare;
 }
 
 
-HInstruction* HGraphBuilder::IfBuilder::BeginIfObjectsEqual(
-    HValue* left,
-    HValue* right) {
-  HCompareObjectEqAndBranch* compare =
-      new(zone()) HCompareObjectEqAndBranch(left, right);
-  compare->SetSuccessorAt(0, first_true_block_);
-  compare->SetSuccessorAt(1, first_false_block_);
-  builder_->current_block()->Finish(compare);
-  builder_->set_current_block(first_true_block_);
+HInstruction* HGraphBuilder::IfBuilder::IfCompareMap(HValue* left,
+                                                     Handle<Map> map) {
+  HCompareMap* compare =
+      new(zone()) HCompareMap(left, map,
+                              first_true_block_, first_false_block_);
+  AddCompare(compare);
   return compare;
 }
 
 
-HInstruction* HGraphBuilder::IfBuilder::BeginIfMapEquals(HValue* value,
-                                                         Handle<Map> map) {
-  HCompareMap* compare = new(zone())
-      HCompareMap(value, map, first_true_block_, first_false_block_);
+void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) {
+  if (split_edge_merge_block_ != NULL) {
+    HEnvironment* env = first_false_block_->last_environment();
+    HBasicBlock* split_edge =
+        builder_->CreateBasicBlock(env->Copy());
+    if (did_or_) {
+      compare->SetSuccessorAt(0, split_edge);
+      compare->SetSuccessorAt(1, first_false_block_);
+    } else {
+      compare->SetSuccessorAt(0, first_true_block_);
+      compare->SetSuccessorAt(1, split_edge);
+    }
+    split_edge->GotoNoSimulate(split_edge_merge_block_);
+  } else {
+    compare->SetSuccessorAt(0, first_true_block_);
+    compare->SetSuccessorAt(1, first_false_block_);
+  }
   builder_->current_block()->Finish(compare);
-  builder_->set_current_block(first_true_block_);
-  return compare;
+  needs_compare_ = false;
 }
 
 
-void HGraphBuilder::IfBuilder::BeginElse() {
+void HGraphBuilder::IfBuilder::Or() {
+  ASSERT(!did_and_);
+  did_or_ = true;
+  HEnvironment* env = first_false_block_->last_environment();
+  if (split_edge_merge_block_ == NULL) {
+    split_edge_merge_block_ =
+        builder_->CreateBasicBlock(env->Copy());
+    first_true_block_->GotoNoSimulate(split_edge_merge_block_);
+    first_true_block_ = split_edge_merge_block_;
+  }
+  builder_->set_current_block(first_false_block_);
+  first_false_block_ = builder_->CreateBasicBlock(env->Copy());
+}
+
+
+void HGraphBuilder::IfBuilder::And() {
+  ASSERT(!did_or_);
+  did_and_ = true;
+  HEnvironment* env = first_false_block_->last_environment();
+  if (split_edge_merge_block_ == NULL) {
+    split_edge_merge_block_ = builder_->CreateBasicBlock(env->Copy());
+    first_false_block_->GotoNoSimulate(split_edge_merge_block_);
+    first_false_block_ = split_edge_merge_block_;
+  }
+  builder_->set_current_block(first_true_block_);
+  first_true_block_ = builder_->CreateBasicBlock(env->Copy());
+}
+
+
+void HGraphBuilder::IfBuilder::CaptureContinuation(
+    HIfContinuation* continuation) {
+  ASSERT(!finished_);
+  ASSERT(!captured_);
+  HBasicBlock* true_block = last_true_block_ == NULL
+      ? first_true_block_
+      : last_true_block_;
+  HBasicBlock* false_block =
+      did_else_ ? builder_->current_block() : first_false_block_;
+  continuation->Capture(true_block, false_block, position_);
+  captured_ = true;
+  End();
+}
+
+
+void HGraphBuilder::IfBuilder::Then() {
+  ASSERT(!captured_);
+  ASSERT(!finished_);
+  did_then_ = true;
+  if (needs_compare_) {
+    // Handle if's without any expressions, they jump directly to the "else"
+    // branch.
+    builder_->current_block()->GotoNoSimulate(first_false_block_);
+    first_true_block_ = NULL;
+  }
+  builder_->set_current_block(first_true_block_);
+}
+
+
+void HGraphBuilder::IfBuilder::Else() {
+  ASSERT(did_then_);
+  ASSERT(!captured_);
+  ASSERT(!finished_);
   last_true_block_ = builder_->current_block();
-  ASSERT(!last_true_block_->IsFinished());
+  ASSERT(first_true_block_ == NULL || !last_true_block_->IsFinished());
   builder_->set_current_block(first_false_block_);
   did_else_ = true;
 }
 
 
+void HGraphBuilder::IfBuilder::Deopt() {
+  ASSERT(!(did_then_ ^ did_else_));
+  HBasicBlock* block = builder_->current_block();
+  block->FinishExitWithDeoptimization(HDeoptimize::kUseAll);
+  if (did_else_) {
+    first_false_block_ = NULL;
+    did_else_ = false;
+  } else {
+    first_true_block_ = NULL;
+  }
+}
+
+
 void HGraphBuilder::IfBuilder::End() {
-  ASSERT(!finished_);
-  if (!did_else_) BeginElse();
-  ASSERT(!last_true_block_->IsFinished());
-  HBasicBlock* last_false_block = builder_->current_block();
-  ASSERT(!last_false_block->IsFinished());
-  HEnvironment* merge_env =
-      last_true_block_->last_environment()->CopyWithoutHistory();
-  merge_block_ = builder_->CreateBasicBlock(merge_env, id_);
-  last_true_block_->Goto(merge_block_);
-  last_false_block->Goto(merge_block_);
-  merge_block_->SetJoinId(id_);
-  builder_->set_current_block(merge_block_);
+  if (!captured_) {
+    ASSERT(did_then_);
+    if (!did_else_) {
+      last_true_block_ = builder_->current_block();
+    }
+    if (first_true_block_ == NULL) {
+      // Deopt on true. Nothing to do, just continue the else block.
+    } else if (first_false_block_ == NULL) {
+      builder_->set_current_block(last_true_block_);
+    } else {
+      HEnvironment* merge_env = last_true_block_->last_environment()->Copy();
+      merge_block_ = builder_->CreateBasicBlock(merge_env);
+      ASSERT(!finished_);
+      if (!did_else_) Else();
+      ASSERT(!last_true_block_->IsFinished());
+      HBasicBlock* last_false_block = builder_->current_block();
+      ASSERT(!last_false_block->IsFinished());
+      last_true_block_->GotoNoSimulate(merge_block_);
+      last_false_block->GotoNoSimulate(merge_block_);
+      builder_->set_current_block(merge_block_);
+    }
+  }
   finished_ = true;
 }
 
@@ -790,9 +914,8 @@
     : builder_(builder),
       context_(context),
       direction_(direction),
-      id_(builder->current_block()->last_environment()->previous_ast_id()),
       finished_(false) {
-  header_block_ = builder->CreateLoopHeaderBlock(id_);
+  header_block_ = builder->CreateLoopHeaderBlock();
   body_block_ = NULL;
   exit_block_ = NULL;
 }
@@ -809,12 +932,12 @@
   phi_->AddInput(initial);
   phi_->ChangeRepresentation(Representation::Integer32());
   env->Push(initial);
-  builder_->current_block()->Goto(header_block_);
+  builder_->current_block()->GotoNoSimulate(header_block_);
 
   HEnvironment* body_env = env->Copy();
   HEnvironment* exit_env = env->Copy();
-  body_block_ = builder_->CreateBasicBlock(body_env, id_);
-  exit_block_ = builder_->CreateBasicBlock(exit_env, id_);
+  body_block_ = builder_->CreateBasicBlock(body_env);
+  exit_block_ = builder_->CreateBasicBlock(exit_env);
   // Remove the phi from the expression stack
   body_env->Pop();
 
@@ -863,9 +986,8 @@
 
   // Push the new increment value on the expression stack to merge into the phi.
   builder_->environment()->Push(increment_);
-  builder_->current_block()->Goto(header_block_);
+  builder_->current_block()->GotoNoSimulate(header_block_);
   header_block_->loop_information()->RegisterBackEdge(body_block_);
-  header_block_->SetJoinId(id_);
 
   builder_->set_current_block(exit_block_);
   // Pop the phi from the expression stack
@@ -900,7 +1022,6 @@
   ASSERT(current_block() != NULL);
   ASSERT(no_side_effects_scope_count_ == 0);
   current_block()->AddSimulate(id, removable);
-  environment()->set_previous_ast_id(id);
 }
 
 
@@ -935,23 +1056,37 @@
 }
 
 
-HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env,
-                                             BailoutId previous_ast_id) {
+HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   HBasicBlock* b = graph()->CreateBasicBlock();
-  b->SetInitialEnvironment(env, previous_ast_id);
+  b->SetInitialEnvironment(env);
   return b;
 }
 
 
-HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock(BailoutId previous_ast_id) {
+HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
   HBasicBlock* header = graph()->CreateBasicBlock();
   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
-  header->SetInitialEnvironment(entry_env, previous_ast_id);
+  header->SetInitialEnvironment(entry_env);
   header->AttachLoopInformation();
   return header;
 }
 
 
+HValue* HGraphBuilder::BuildCheckNonSmi(HValue* obj) {
+  HCheckNonSmi* check = new(zone()) HCheckNonSmi(obj);
+  AddInstruction(check);
+  return check;
+}
+
+
+HValue* HGraphBuilder::BuildCheckMap(HValue* obj,
+                                              Handle<Map> map) {
+  HCheckMaps* check = new(zone()) HCheckMaps(obj, map, zone());
+  AddInstruction(check);
+  return check;
+}
+
+
 HInstruction* HGraphBuilder::BuildExternalArrayElementAccess(
     HValue* external_elements,
     HValue* checked_key,
@@ -1049,14 +1184,16 @@
   Zone* zone = this->zone();
   IfBuilder length_checker(this);
 
-  length_checker.BeginIf(length, key, Token::EQ);
+  length_checker.IfCompare(length, key, Token::EQ);
+  length_checker.Then();
 
   HValue* current_capacity =
       AddInstruction(new(zone) HFixedArrayBaseLength(elements));
 
   IfBuilder capacity_checker(this);
 
-  capacity_checker.BeginIf(length, current_capacity, Token::EQ);
+  capacity_checker.IfCompare(length, current_capacity, Token::EQ);
+  capacity_checker.Then();
 
   HValue* context = environment()->LookupContext();
 
@@ -1068,7 +1205,7 @@
                                                    new_capacity);
 
   environment()->Push(new_elements);
-  capacity_checker.BeginElse();
+  capacity_checker.Else();
 
   environment()->Push(elements);
   capacity_checker.End();
@@ -1088,7 +1225,7 @@
     length_store->SetGVNFlag(kChangesArrayLengths);
   }
 
-  length_checker.BeginElse();
+  length_checker.Else();
 
   AddBoundsCheck(key, length, ALLOW_SMI_KEY);
   environment()->Push(elements);
@@ -1108,19 +1245,19 @@
 
   IfBuilder cow_checker(this);
 
-  cow_checker.BeginIfMapEquals(elements,
-                               Handle<Map>(heap->fixed_cow_array_map()));
+  cow_checker.IfCompareMap(elements,
+                           Handle<Map>(heap->fixed_cow_array_map()));
+  cow_checker.Then();
 
   HValue* capacity =
       AddInstruction(new(zone) HFixedArrayBaseLength(elements));
 
   HValue* new_elements = BuildGrowElementsCapacity(object, elements,
-                                                   kind, length,
-                                                   capacity);
+                                                   kind, length, capacity);
 
   environment()->Push(new_elements);
 
-  cow_checker.BeginElse();
+  cow_checker.Else();
 
   environment()->Push(elements);
 
@@ -1175,11 +1312,13 @@
   HValue* checked_key = NULL;
   if (IsExternalArrayElementsKind(elements_kind)) {
     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
+      NoObservableSideEffectsScope no_effects(this);
       HLoadExternalArrayPointer* external_elements =
           new(zone) HLoadExternalArrayPointer(elements);
       AddInstruction(external_elements);
       IfBuilder length_checker(this);
-      length_checker.BeginIf(key, length, Token::LT);
+      length_checker.IfCompare(key, length, Token::LT);
+      length_checker.Then();
       CheckBuilder negative_checker(this);
       HValue* bounds_check = negative_checker.CheckIntegerCompare(
           key, graph()->GetConstant0(), Token::GTE);
@@ -1216,7 +1355,11 @@
 
     elements = BuildCheckForCapacityGrow(object, elements, elements_kind,
                                          length, key, is_js_array);
-    checked_key = key;
+    if (!key->type().IsSmi()) {
+      checked_key = AddInstruction(new(zone) HCheckSmiOrInt32(key));
+    } else {
+      checked_key = key;
+    }
   } else {
     checked_key = AddBoundsCheck(
         key, length, ALLOW_SMI_KEY, checked_index_representation);
@@ -1307,8 +1450,7 @@
 HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context,
                                                           ElementsKind kind,
                                                           HValue* capacity) {
-  HValue* new_elements =
-      BuildAllocateElements(context, kind, capacity);
+  HValue* new_elements = BuildAllocateElements(context, kind, capacity);
   BuildInitializeElements(new_elements, kind, capacity);
   return new_elements;
 }
@@ -1684,9 +1826,9 @@
     start_environment_ =
         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
   }
+  start_environment_->set_ast_id(BailoutId::FunctionEntry());
   entry_block_ = CreateBasicBlock();
-  entry_block_->SetInitialEnvironment(start_environment_,
-                                      BailoutId::FunctionEntry());
+  entry_block_->SetInitialEnvironment(start_environment_);
 }
 
 
@@ -3839,8 +3981,8 @@
     HValue* operand = phi->OperandAt(j);
     if (!operand->CheckFlag(HInstruction::kUint32)) {
       // Lazyly mark constants that fit into uint32 range with kUint32 flag.
-      if (operand->IsConstant() &&
-          HConstant::cast(operand)->IsUint32()) {
+      if (operand->IsInteger32Constant() &&
+          operand->GetInteger32Constant() >= 0) {
         operand->SetFlag(HInstruction::kUint32);
         continue;
       }
@@ -4099,6 +4241,22 @@
 }
 
 
+void EffectContext::ReturnContinuation(HIfContinuation* continuation,
+                                       BailoutId ast_id) {
+  HBasicBlock* true_branch = NULL;
+  HBasicBlock* false_branch = NULL;
+  continuation->Continue(&true_branch, &false_branch, NULL);
+  if (!continuation->IsTrueReachable()) {
+    owner()->set_current_block(false_branch);
+  } else if (!continuation->IsFalseReachable()) {
+    owner()->set_current_block(true_branch);
+  } else {
+    HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
+    owner()->set_current_block(join);
+  }
+}
+
+
 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   ASSERT(!instr->IsControlInstruction());
   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
@@ -4132,6 +4290,29 @@
 }
 
 
+void ValueContext::ReturnContinuation(HIfContinuation* continuation,
+                                      BailoutId ast_id) {
+  HBasicBlock* materialize_true = NULL;
+  HBasicBlock* materialize_false = NULL;
+  continuation->Continue(&materialize_true, &materialize_false, NULL);
+  if (continuation->IsTrueReachable()) {
+    owner()->set_current_block(materialize_true);
+    owner()->Push(owner()->graph()->GetConstantTrue());
+    owner()->set_current_block(materialize_true);
+  }
+  if (continuation->IsFalseReachable()) {
+    owner()->set_current_block(materialize_false);
+    owner()->Push(owner()->graph()->GetConstantFalse());
+    owner()->set_current_block(materialize_false);
+  }
+  if (continuation->TrueAndFalseReachable()) {
+    HBasicBlock* join =
+        owner()->CreateJoin(materialize_true, materialize_false, ast_id);
+    owner()->set_current_block(join);
+  }
+}
+
+
 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   ASSERT(!instr->IsControlInstruction());
   HOptimizedGraphBuilder* builder = owner();
@@ -4160,6 +4341,21 @@
 }
 
 
+void TestContext::ReturnContinuation(HIfContinuation* continuation,
+                                     BailoutId ast_id) {
+  HBasicBlock* true_branch = NULL;
+  HBasicBlock* false_branch = NULL;
+  continuation->Continue(&true_branch, &false_branch, NULL);
+  if (continuation->IsTrueReachable()) {
+    true_branch->Goto(if_true(), owner()->function_state());
+  }
+  if (continuation->IsFalseReachable()) {
+    false_branch->Goto(if_false(), owner()->function_state());
+  }
+  owner()->set_current_block(NULL);
+}
+
+
 void TestContext::BuildBranch(HValue* value) {
   // We expect the graph to be in edge-split form: there is no edge that
   // connects a branch node to a join node.  We conservatively ensure that
@@ -4296,8 +4492,7 @@
   // values (but not instructions), present in the initial environment and
   // not replayed by the Lithium translation.
   HEnvironment* initial_env = environment()->CopyWithoutHistory();
-  HBasicBlock* body_entry = CreateBasicBlock(initial_env,
-                                             BailoutId::FunctionEntry());
+  HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   current_block()->Goto(body_entry);
   body_entry->SetJoinId(BailoutId::FunctionEntry());
   set_current_block(body_entry);
@@ -5541,7 +5736,7 @@
   ASSERT(current_block()->HasPredecessor());
   ASSERT(current_block() != NULL);
   bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   current_block()->Goto(loop_entry);
   set_current_block(loop_entry);
   if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -5584,7 +5779,7 @@
   ASSERT(current_block()->HasPredecessor());
   ASSERT(current_block() != NULL);
   bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   current_block()->Goto(loop_entry);
   set_current_block(loop_entry);
   if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -5631,7 +5826,7 @@
   }
   ASSERT(current_block() != NULL);
   bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   current_block()->Goto(loop_entry);
   set_current_block(loop_entry);
   if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -5726,7 +5921,7 @@
       HForInCacheArray::cast(index_cache));
 
   bool osr_entry = PreProcessOsrEntry(stmt);
-  HBasicBlock* loop_entry = CreateLoopHeaderBlock(stmt->EntryId());
+  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   current_block()->Goto(loop_entry);
   set_current_block(loop_entry);
   if (osr_entry) graph()->set_osr_loop_entry(loop_entry);
@@ -6804,7 +6999,6 @@
                              true,  // is_store
                              &has_side_effects);
     Push(value);
-    ASSERT(has_side_effects);  // Stores always have side effects.
     AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE);
     return ast_context()->ReturnValue(Pop());
   }
@@ -8279,7 +8473,6 @@
 
   AddSimulate(return_id);
   current_block()->UpdateEnvironment(inner_env);
-  inner_env->set_previous_ast_id(BailoutId::FunctionEntry());
   ZoneList<HValue*>* arguments_values = NULL;
 
   // If the function uses arguments copy current arguments values
@@ -8547,6 +8740,18 @@
         return true;
       }
       break;
+    case kStringFromCharCode:
+      if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) {
+        AddCheckConstantFunction(expr->holder(), receiver, receiver_map);
+        HValue* argument = Pop();
+        HValue* context = environment()->LookupContext();
+        Drop(1);  // Receiver.
+        HInstruction* result =
+            HStringCharFromCode::New(zone(), context, argument);
+        ast_context()->ReturnInstruction(result, expr->id());
+        return true;
+      }
+      break;
     case kMathExp:
       if (!FLAG_fast_math) break;
       // Fall through if FLAG_fast_math.
@@ -8600,9 +8805,7 @@
           } else if (exponent == 2.0) {
             result = HMul::New(zone(), context, left, left);
           }
-        } else if (right->IsConstant() &&
-                   HConstant::cast(right)->HasInteger32Value() &&
-                   HConstant::cast(right)->Integer32Value() == 2) {
+        } else if (right->EqualsInteger32Constant(2)) {
           result = HMul::New(zone(), context, left, left);
         }
 
@@ -9160,7 +9363,6 @@
     case Token::DELETE: return VisitDelete(expr);
     case Token::VOID: return VisitVoid(expr);
     case Token::TYPEOF: return VisitTypeof(expr);
-    case Token::ADD: return VisitAdd(expr);
     case Token::SUB: return VisitSub(expr);
     case Token::BIT_NOT: return VisitBitNot(expr);
     case Token::NOT: return VisitNot(expr);
@@ -9218,21 +9420,6 @@
 }
 
 
-void HOptimizedGraphBuilder::VisitAdd(UnaryOperation* expr) {
-  CHECK_ALIVE(VisitForValue(expr->expression()));
-  HValue* value = Pop();
-  HValue* context = environment()->LookupContext();
-  HInstruction* instr =
-      HMul::New(zone(), context, value, graph()->GetConstant1());
-  if (instr->IsBinaryOperation()) {
-    // Since we don't have type feedback, we must be cautious/pessimistic.
-    HBinaryOperation::cast(instr)->set_observed_input_representation(
-        Representation::Tagged(), Representation::Tagged());
-  }
-  return ast_context()->ReturnInstruction(instr, expr->id());
-}
-
-
 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
   CHECK_ALIVE(VisitForValue(expr->expression()));
   HValue* value = Pop();
@@ -11033,7 +11220,6 @@
       pop_count_(0),
       push_count_(0),
       ast_id_(BailoutId::None()),
-      previous_ast_id_(BailoutId::None()),
       zone_(zone) {
   Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
 }
@@ -11050,7 +11236,6 @@
       pop_count_(0),
       push_count_(0),
       ast_id_(BailoutId::None()),
-      previous_ast_id_(BailoutId::None()),
       zone_(zone) {
   Initialize(parameter_count, 0, 0);
 }
@@ -11067,7 +11252,6 @@
       pop_count_(0),
       push_count_(0),
       ast_id_(other->ast_id()),
-      previous_ast_id_(BailoutId::None()),
       zone_(zone) {
   Initialize(other);
 }
@@ -11088,7 +11272,6 @@
       pop_count_(0),
       push_count_(0),
       ast_id_(BailoutId::None()),
-      previous_ast_id_(BailoutId::None()),
       zone_(zone) {
 }
 
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 3dbca3c..809942b 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -108,7 +108,7 @@
   bool Dominates(HBasicBlock* other) const;
   int LoopNestingDepth() const;
 
-  void SetInitialEnvironment(HEnvironment* env, BailoutId previous_id);
+  void SetInitialEnvironment(HEnvironment* env);
   void ClearEnvironment() { last_environment_ = NULL; }
   bool HasEnvironment() const { return last_environment_ != NULL; }
   void UpdateEnvironment(HEnvironment* env) { last_environment_ = env; }
@@ -125,7 +125,12 @@
 
   void Finish(HControlInstruction* last);
   void FinishExit(HControlInstruction* instruction);
-  void Goto(HBasicBlock* block, FunctionState* state = NULL);
+  void Goto(HBasicBlock* block,
+            FunctionState* state = NULL,
+            bool add_simulate = true);
+  void GotoNoSimulate(HBasicBlock* block) {
+    Goto(block, NULL, false);
+  }
 
   int PredecessorIndexOf(HBasicBlock* predecessor) const;
   void AddSimulate(BailoutId ast_id,
@@ -484,8 +489,6 @@
 
   BailoutId ast_id() const { return ast_id_; }
   void set_ast_id(BailoutId id) { ast_id_ = id; }
-  BailoutId previous_ast_id() const { return previous_ast_id_; }
-  void set_previous_ast_id(BailoutId id) { previous_ast_id_ = id; }
 
   HEnterInlined* entry() const { return entry_; }
   void set_entry(HEnterInlined* entry) { entry_ = entry; }
@@ -647,7 +650,6 @@
   int pop_count_;
   int push_count_;
   BailoutId ast_id_;
-  BailoutId previous_ast_id_;
   Zone* zone_;
 };
 
@@ -678,6 +680,9 @@
   ARGUMENTS_ALLOWED
 };
 
+
+class HIfContinuation;
+
 // This class is not BASE_EMBEDDED because our inlining implementation uses
 // new and delete.
 class AstContext {
@@ -703,6 +708,13 @@
   // expressions.
   virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0;
 
+  // Finishes the current basic block and materialize a boolean for
+  // value context, nothing for effect, generate a branch for test context.
+  // Call this function in tail position in the Visit functions for
+  // expressions that use an IfBuilder.
+  virtual void ReturnContinuation(HIfContinuation* continuation,
+                                  BailoutId ast_id) = 0;
+
   void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; }
   bool is_for_typeof() { return for_typeof_; }
 
@@ -738,6 +750,8 @@
   virtual void ReturnValue(HValue* value);
   virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
   virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
+  virtual void ReturnContinuation(HIfContinuation* continuation,
+                                  BailoutId ast_id);
 };
 
 
@@ -751,6 +765,8 @@
   virtual void ReturnValue(HValue* value);
   virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
   virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
+  virtual void ReturnContinuation(HIfContinuation* continuation,
+                                  BailoutId ast_id);
 
   bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
 
@@ -776,6 +792,8 @@
   virtual void ReturnValue(HValue* value);
   virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id);
   virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id);
+  virtual void ReturnContinuation(HIfContinuation* continuation,
+                                  BailoutId ast_id);
 
   static TestContext* cast(AstContext* context) {
     ASSERT(context->IsTest());
@@ -863,6 +881,45 @@
 };
 
 
+class HIfContinuation {
+ public:
+  HIfContinuation() { continuation_captured_ = false; }
+  ~HIfContinuation() { ASSERT(!continuation_captured_); }
+
+  void Capture(HBasicBlock* true_branch,
+               HBasicBlock* false_branch,
+               int position) {
+    ASSERT(!continuation_captured_);
+    ASSERT(true_branch != NULL || false_branch != NULL);
+    true_branch_ = true_branch;
+    false_branch_ = false_branch;
+    position_ = position;
+    continuation_captured_ = true;
+  }
+
+  void Continue(HBasicBlock** true_branch,
+                HBasicBlock** false_branch,
+                int* position) {
+    ASSERT(continuation_captured_);
+    *true_branch = true_branch_;
+    *false_branch = false_branch_;
+    if (position != NULL) *position = position_;
+    continuation_captured_ = false;
+  }
+
+  bool IsTrueReachable() { return true_branch_ != NULL; }
+  bool IsFalseReachable() { return false_branch_ != NULL; }
+  bool TrueAndFalseReachable() {
+    return IsTrueReachable() || IsFalseReachable();
+  }
+
+  bool continuation_captured_;
+  HBasicBlock* true_branch_;
+  HBasicBlock* false_branch_;
+  int position_;
+};
+
+
 class HGraphBuilder {
  public:
   explicit HGraphBuilder(CompilationInfo* info)
@@ -906,9 +963,11 @@
  protected:
   virtual bool BuildGraph() = 0;
 
-  HBasicBlock* CreateBasicBlock(HEnvironment* envy,
-                                BailoutId previous_ast_id);
-  HBasicBlock* CreateLoopHeaderBlock(BailoutId previous_ast_id);
+  HBasicBlock* CreateBasicBlock(HEnvironment* env);
+  HBasicBlock* CreateLoopHeaderBlock();
+
+  HValue* BuildCheckNonSmi(HValue* object);
+  HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
 
   // Building common constructs
   HInstruction* BuildExternalArrayElementAccess(
@@ -973,37 +1032,127 @@
     bool finished_;
     HBasicBlock* failure_block_;
     HBasicBlock* merge_block_;
-    BailoutId id_;
   };
 
   class IfBuilder {
    public:
-    explicit IfBuilder(HGraphBuilder* builder);
+    explicit IfBuilder(HGraphBuilder* builder,
+                       int position = RelocInfo::kNoPosition);
+    IfBuilder(HGraphBuilder* builder,
+              HIfContinuation* continuation);
+
     ~IfBuilder() {
       if (!finished_) End();
     }
 
-    HInstruction* BeginIf(
+    HInstruction* IfCompare(
         HValue* left,
         HValue* right,
         Token::Value token,
         Representation input_representation = Representation::Integer32());
-    HInstruction* BeginIfObjectsEqual(HValue* left, HValue* right);
-    HInstruction* BeginIfMapEquals(HValue* value, Handle<Map> map);
-    void BeginElse();
+
+    HInstruction* IfCompareMap(HValue* left, Handle<Map> map);
+
+    template<class Condition>
+    HInstruction* If(HValue *p) {
+      HControlInstruction* compare = new(zone()) Condition(p);
+      AddCompare(compare);
+      return compare;
+    }
+
+    template<class Condition, class P2>
+    HInstruction* If(HValue* p1, P2 p2) {
+      HControlInstruction* compare = new(zone()) Condition(p1, p2);
+      AddCompare(compare);
+      return compare;
+    }
+
+    template<class Condition>
+    HInstruction* OrIfCompare(
+        HValue* p1,
+        HValue* p2,
+        Token::Value token,
+        Representation input_representation = Representation::Integer32()) {
+      Or();
+      return IfCompare(p1, p2, token, input_representation);
+    }
+
+    HInstruction* OrIfCompareMap(HValue* left, Handle<Map> map) {
+      Or();
+      return IfCompareMap(left, map);
+    }
+
+    template<class Condition>
+    HInstruction* OrIf(HValue *p) {
+      Or();
+      return If<Condition>(p);
+    }
+
+    template<class Condition, class P2>
+    HInstruction* OrIf(HValue* p1, P2 p2) {
+      Or();
+      return If<Condition>(p1, p2);
+    }
+
+    template<class Condition>
+    HInstruction* AndIfCompare(
+        HValue* p1,
+        HValue* p2,
+        Token::Value token,
+        Representation input_representation = Representation::Integer32()) {
+      And();
+      return IfCompare(p1, p2, token, input_representation);
+    }
+
+    HInstruction* AndIfCompareMap(HValue* left, Handle<Map> map) {
+      And();
+      return IfCompareMap(left, map);
+    }
+
+    template<class Condition>
+    HInstruction* AndIf(HValue *p) {
+      And();
+      return If<Condition>(p);
+    }
+
+    template<class Condition, class P2>
+    HInstruction* AndIf(HValue* p1, P2 p2) {
+      And();
+      return If<Condition>(p1, p2);
+    }
+
+    void Or();
+    void And();
+
+    void CaptureContinuation(HIfContinuation* continuation);
+
+    void Then();
+    void Else();
     void End();
 
+    void Deopt();
+
    private:
+    void AddCompare(HControlInstruction* compare);
+
     Zone* zone() { return builder_->zone(); }
 
     HGraphBuilder* builder_;
-    bool finished_;
-    bool did_else_;
+    int position_;
+    bool finished_ : 1;
+    bool did_then_ : 1;
+    bool did_else_ : 1;
+    bool deopt_then_ : 1;
+    bool deopt_else_ : 1;
+    bool did_and_ : 1;
+    bool did_or_ : 1;
+    bool captured_ : 1;
+    bool needs_compare_ : 1;
     HBasicBlock* first_true_block_;
     HBasicBlock* last_true_block_;
     HBasicBlock* first_false_block_;
+    HBasicBlock* split_edge_merge_block_;
     HBasicBlock* merge_block_;
-    BailoutId id_;
   };
 
   class LoopBuilder {
@@ -1040,7 +1189,6 @@
     HBasicBlock* body_block_;
     HBasicBlock* exit_block_;
     Direction direction_;
-    BailoutId id_;
     bool finished_;
   };
 
@@ -1267,7 +1415,6 @@
   void VisitDelete(UnaryOperation* expr);
   void VisitVoid(UnaryOperation* expr);
   void VisitTypeof(UnaryOperation* expr);
-  void VisitAdd(UnaryOperation* expr);
   void VisitSub(UnaryOperation* expr);
   void VisitBitNot(UnaryOperation* expr);
   void VisitNot(UnaryOperation* expr);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 05dceb7..84fe688 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -30,7 +30,6 @@
 #if defined(V8_TARGET_ARCH_IA32)
 
 #include "bootstrapper.h"
-#include "builtins-decls.h"
 #include "code-stubs.h"
 #include "isolate.h"
 #include "jsregexp.h"
diff --git a/src/ia32/code-stubs-ia32.h b/src/ia32/code-stubs-ia32.h
index c2ae5f0..07563cd 100644
--- a/src/ia32/code-stubs-ia32.h
+++ b/src/ia32/code-stubs-ia32.h
@@ -144,7 +144,7 @@
   void GenerateGenericStubBitNot(MacroAssembler* masm);
   void GenerateGenericCodeFallback(MacroAssembler* masm);
 
-  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
+  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
 
   virtual InlineCacheState GetICState() {
     return UnaryOpIC::ToState(operand_type_);
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 19989b1..a35f12d 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -3967,18 +3967,6 @@
       break;
     }
 
-    case Token::ADD: {
-      Comment cmt(masm_, "[ UnaryOperation (ADD)");
-      VisitForAccumulatorValue(expr->expression());
-      Label no_conversion;
-      __ JumpIfSmi(result_register(), &no_conversion);
-      ToNumberStub convert_stub;
-      __ CallStub(&convert_stub);
-      __ bind(&no_conversion);
-      context()->Plug(result_register());
-      break;
-    }
-
     case Token::SUB:
       EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
       break;
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 1dcad04..665c85e 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -467,7 +467,7 @@
       LDeferredCode* code = deferred_[i];
       __ bind(code->entry());
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred build frame",
+        Comment(";;; Deferred build frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(!frame_is_built_);
@@ -484,7 +484,7 @@
               code->instr()->Mnemonic());
       code->Generate();
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred destroy frame",
+        Comment(";;; Deferred destroy frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(frame_is_built_);
@@ -1126,11 +1126,9 @@
 
 
 void LCodeGen::DoLabel(LLabel* label) {
-  if (label->is_loop_header()) {
-    Comment(";;; B%d - LOOP entry", label->block_id());
-  } else {
-    Comment(";;; B%d", label->block_id());
-  }
+  Comment(";;; -------------------- B%d%s --------------------",
+          label->block_id(),
+          label->is_loop_header() ? " (loop header)" : "");
   __ bind(label->label());
   current_block_ = label->block_id();
   DoGap(label);
@@ -2287,11 +2285,15 @@
 
 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
   Register left = ToRegister(instr->left());
-  Operand right = ToOperand(instr->right());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
   int true_block = chunk_->LookupDestination(instr->true_block_id());
 
-  __ cmp(left, Operand(right));
+  if (instr->right()->IsConstantOperand()) {
+    __ cmp(left, ToHandle(LConstantOperand::cast(instr->right())));
+  } else {
+    Operand right = ToOperand(instr->right());
+    __ cmp(left, Operand(right));
+  }
   EmitBranch(true_block, false_block, equal);
 }
 
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index 362f091..b268456 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -32,9 +32,10 @@
 
 #include "checks.h"
 #include "deoptimizer.h"
+#include "ia32/lithium-gap-resolver-ia32.h"
 #include "safepoint-table.h"
 #include "scopes.h"
-#include "ia32/lithium-gap-resolver-ia32.h"
+#include "v8utils.h"
 
 namespace v8 {
 namespace internal {
@@ -201,7 +202,7 @@
   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
 
   void Abort(const char* reason);
-  void Comment(const char* format, ...);
+  void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
 
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index a7bb2d9..c4a8be1 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -884,11 +884,15 @@
     HEnvironment* last_environment = pred->last_environment();
     for (int i = 0; i < block->phis()->length(); ++i) {
       HPhi* phi = block->phis()->at(i);
-      last_environment->SetValueAt(phi->merged_index(), phi);
+      if (phi->merged_index() < last_environment->length()) {
+        last_environment->SetValueAt(phi->merged_index(), phi);
+      }
     }
     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
-      last_environment->SetValueAt(block->deleted_phis()->at(i),
-                                   graph_->GetConstantUndefined());
+      if (block->deleted_phis()->at(i) < last_environment->length()) {
+        last_environment->SetValueAt(block->deleted_phis()->at(i),
+                                     graph_->GetConstantUndefined());
+      }
     }
     block->UpdateEnvironment(last_environment);
     // Pick up the outgoing argument count of one of the predecessors.
@@ -1693,7 +1697,7 @@
 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
     HCompareObjectEqAndBranch* instr) {
   LOperand* left = UseRegisterAtStart(instr->left());
-  LOperand* right = UseAtStart(instr->right());
+  LOperand* right = UseOrConstantAtStart(instr->right());
   return new(zone()) LCmpObjectEqAndBranch(left, right);
 }
 
diff --git a/src/ic.cc b/src/ic.cc
index 3c33e4f..78fb297 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1384,7 +1384,7 @@
   }
 
 
-  return Runtime::GetObjectProperty(isolate(), object, key);
+  return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
 }
 
 
@@ -1972,7 +1972,7 @@
     TRACE_IC("KeyedStoreIC", key, state, target());
   }
 
-  return Runtime::SetObjectProperty(
+  return Runtime::SetObjectPropertyOrFail(
       isolate(), object , key, value, NONE, strict_mode);
 }
 
diff --git a/src/lithium.cc b/src/lithium.cc
index 09c0f44..b4a57f5 100644
--- a/src/lithium.cc
+++ b/src/lithium.cc
@@ -442,7 +442,7 @@
 }
 
 
-Handle<Code> LChunk::Codegen(Code::Kind kind) {
+Handle<Code> LChunk::Codegen() {
   MacroAssembler assembler(info()->isolate(), NULL, 0);
   LOG_CODE_EVENT(info()->isolate(),
                  CodeStartLinePosInfoRecordEvent(
@@ -456,11 +456,11 @@
       PrintF("Crankshaft Compiler - ");
     }
     CodeGenerator::MakeCodePrologue(info());
-    Code::Flags flags = Code::ComputeFlags(kind);
+    Code::Flags flags = info()->flags();
     Handle<Code> code =
         CodeGenerator::MakeCodeEpilogue(&assembler, flags, info());
     generator.FinishCode(code);
-
+    code->set_is_crankshafted(true);
     if (!code.is_null()) {
       void* jit_handler_data =
           assembler.positions_recorder()->DetachJITHandlerData();
diff --git a/src/lithium.h b/src/lithium.h
index 9d5b0b9..2418274 100644
--- a/src/lithium.h
+++ b/src/lithium.h
@@ -685,7 +685,7 @@
 
   Zone* zone() const { return info_->zone(); }
 
-  Handle<Code> Codegen(Code::Kind kind);
+  Handle<Code> Codegen();
 
   void set_allocated_double_registers(BitVector* allocated_registers);
   BitVector* allocated_double_registers() {
diff --git a/src/log.cc b/src/log.cc
index 1538894..55f5637 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1590,7 +1590,6 @@
       case Code::BINARY_OP_IC:   // fall through
       case Code::COMPARE_IC:  // fall through
       case Code::TO_BOOLEAN_IC:  // fall through
-      case Code::COMPILED_STUB:  // fall through
       case Code::STUB:
         description =
             CodeStub::MajorName(CodeStub::GetMajorKey(code_object), true);
diff --git a/src/macros.py b/src/macros.py
index 92ed437..0c52f38 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -117,6 +117,7 @@
 macro IS_ARGUMENTS(arg)         = (%_ClassOf(arg) === 'Arguments');
 macro IS_GLOBAL(arg)            = (%_ClassOf(arg) === 'global');
 macro IS_ARRAYBUFFER(arg)       = (%_ClassOf(arg) === '__ArrayBuffer');
+macro IS_GENERATOR(arg)         = (%_ClassOf(arg) === 'Generator');
 macro IS_UNDETECTABLE(arg)      = (%_IsUndetectableObject(arg));
 macro FLOOR(arg)                = $floor(arg);
 
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index cbe2048..27fd732 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -30,7 +30,6 @@
 #if defined(V8_TARGET_ARCH_MIPS)
 
 #include "bootstrapper.h"
-#include "builtins-decls.h"
 #include "code-stubs.h"
 #include "codegen.h"
 #include "regexp-macro-assembler.h"
diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h
index 0ebfe59..2370d45 100644
--- a/src/mips/code-stubs-mips.h
+++ b/src/mips/code-stubs-mips.h
@@ -131,7 +131,7 @@
   void GenerateGenericStubBitNot(MacroAssembler* masm);
   void GenerateGenericCodeFallback(MacroAssembler* masm);
 
-  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
+  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
 
   virtual InlineCacheState GetICState() {
     return UnaryOpIC::ToState(operand_type_);
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 8e2d5ab..bc0d855 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -3995,19 +3995,6 @@
       break;
     }
 
-    case Token::ADD: {
-      Comment cmt(masm_, "[ UnaryOperation (ADD)");
-      VisitForAccumulatorValue(expr->expression());
-      Label no_conversion;
-      __ JumpIfSmi(result_register(), &no_conversion);
-      __ mov(a0, result_register());
-      ToNumberStub convert_stub;
-      __ CallStub(&convert_stub);
-      __ bind(&no_conversion);
-      context()->Plug(result_register());
-      break;
-    }
-
     case Token::SUB:
       EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
       break;
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 59cfcd9..7794931 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -301,7 +301,7 @@
       LDeferredCode* code = deferred_[i];
       __ bind(code->entry());
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred build frame",
+        Comment(";;; Deferred build frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(!frame_is_built_);
@@ -317,7 +317,7 @@
               code->instr()->Mnemonic());
       code->Generate();
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred destroy frame",
+        Comment(";;; Deferred destroy frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(frame_is_built_);
@@ -1024,11 +1024,9 @@
 
 
 void LCodeGen::DoLabel(LLabel* label) {
-  if (label->is_loop_header()) {
-    Comment(";;; B%d - LOOP entry", label->block_id());
-  } else {
-    Comment(";;; B%d", label->block_id());
-  }
+  Comment(";;; -------------------- B%d%s --------------------",
+          label->block_id(),
+          label->is_loop_header() ? " (loop header)" : "");
   __ bind(label->label());
   current_block_ = label->block_id();
   DoGap(label);
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index a1bc4ba..01d0ffc 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -28,11 +28,12 @@
 #ifndef V8_MIPS_LITHIUM_CODEGEN_MIPS_H_
 #define V8_MIPS_LITHIUM_CODEGEN_MIPS_H_
 
-#include "mips/lithium-mips.h"
-#include "mips/lithium-gap-resolver-mips.h"
 #include "deoptimizer.h"
+#include "mips/lithium-gap-resolver-mips.h"
+#include "mips/lithium-mips.h"
 #include "safepoint-table.h"
 #include "scopes.h"
+#include "v8utils.h"
 
 namespace v8 {
 namespace internal {
@@ -207,7 +208,7 @@
   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
 
   void Abort(const char* reason);
-  void Comment(const char* format, ...);
+  void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index efc1764..f3a029e 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -3645,9 +3645,21 @@
 }
 
 
+inline bool Code::is_crankshafted() {
+  return IsCrankshaftedField::decode(
+      READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
+}
+
+
+inline void Code::set_is_crankshafted(bool value) {
+  int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
+  int updated = IsCrankshaftedField::update(previous, value);
+  WRITE_UINT32_FIELD(this, kKindSpecificFlags2Offset, updated);
+}
+
+
 int Code::major_key() {
   ASSERT(kind() == STUB ||
-         kind() == COMPILED_STUB ||
          kind() == UNARY_OP_IC ||
          kind() == BINARY_OP_IC ||
          kind() == COMPARE_IC ||
@@ -3661,7 +3673,6 @@
 
 void Code::set_major_key(int major) {
   ASSERT(kind() == STUB ||
-         kind() == COMPILED_STUB ||
          kind() == UNARY_OP_IC ||
          kind() == BINARY_OP_IC ||
          kind() == COMPARE_IC ||
@@ -3774,7 +3785,7 @@
 
 
 unsigned Code::stack_slots() {
-  ASSERT(kind() == OPTIMIZED_FUNCTION || kind() == COMPILED_STUB);
+  ASSERT(is_crankshafted());
   return StackSlotsField::decode(
       READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
 }
@@ -3782,7 +3793,7 @@
 
 void Code::set_stack_slots(unsigned slots) {
   CHECK(slots <= (1 << kStackSlotsBitCount));
-  ASSERT(kind() == OPTIMIZED_FUNCTION || kind() == COMPILED_STUB);
+  ASSERT(is_crankshafted());
   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
   int updated = StackSlotsField::update(previous, slots);
   WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
@@ -3790,7 +3801,7 @@
 
 
 unsigned Code::safepoint_table_offset() {
-  ASSERT(kind() == OPTIMIZED_FUNCTION || kind() == COMPILED_STUB);
+  ASSERT(is_crankshafted());
   return SafepointTableOffsetField::decode(
       READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
 }
@@ -3798,7 +3809,7 @@
 
 void Code::set_safepoint_table_offset(unsigned offset) {
   CHECK(offset <= (1 << kSafepointTableOffsetBitCount));
-  ASSERT(kind() == OPTIMIZED_FUNCTION || kind() == COMPILED_STUB);
+  ASSERT(is_crankshafted());
   ASSERT(IsAligned(offset, static_cast<unsigned>(kIntSize)));
   int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
   int updated = SafepointTableOffsetField::update(previous, offset);
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index aa71a96..f21481a 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -187,8 +187,10 @@
       break;
     case JS_ARRAY_BUFFER_TYPE:
       JSArrayBuffer::cast(this)->JSArrayBufferPrint(out);
+      break;
     case JS_TYPED_ARRAY_TYPE:
       JSTypedArray::cast(this)->JSTypedArrayPrint(out);
+      break;
 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   case NAME##_TYPE:                        \
     Name::cast(this)->Name##Print(out);    \
diff --git a/src/objects.cc b/src/objects.cc
index 33be173..2092859 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -9313,7 +9313,6 @@
   switch (kind) {
     case FUNCTION: return "FUNCTION";
     case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
-    case COMPILED_STUB: return "COMPILED_STUB";
     case STUB: return "STUB";
     case BUILTIN: return "BUILTIN";
     case LOAD_IC: return "LOAD_IC";
@@ -9613,7 +9612,7 @@
   }
   PrintF("\n");
 
-  if (kind() == OPTIMIZED_FUNCTION || kind() == COMPILED_STUB) {
+  if (is_crankshafted()) {
     SafepointTable table(this);
     PrintF(out, "Safepoints (size = %u)\n", table.size());
     for (unsigned i = 0; i < table.length(); i++) {
diff --git a/src/objects.h b/src/objects.h
index 898b176..3ca89f0 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4327,7 +4327,6 @@
   V(FUNCTION)             \
   V(OPTIMIZED_FUNCTION)   \
   V(STUB)                 \
-  V(COMPILED_STUB)        \
   V(BUILTIN)              \
   V(LOAD_IC)              \
   V(KEYED_LOAD_IC)        \
@@ -4470,6 +4469,11 @@
   inline int major_key();
   inline void set_major_key(int value);
 
+  // For kind STUB or ICs, tells whether or not a code object was generated by
+  // the optimizing compiler (but it may not be an optimized function).
+  bool is_crankshafted();
+  inline void set_is_crankshafted(bool value);
+
   // For stubs, tells whether they should always exist, so that they can be
   // called from other stubs.
   inline bool is_pregenerated();
@@ -4785,15 +4789,22 @@
       kMarkedForDeoptimizationFirstBit,
       kMarkedForDeoptimizationBitCount> {};  // NOLINT
 
+  // KindSpecificFlags2 layout (ALL)
+  static const int kIsCrankshaftedBit = 0;
+  class IsCrankshaftedField: public BitField<bool,
+      kIsCrankshaftedBit, 1> {};  // NOLINT
+
   // KindSpecificFlags2 layout (STUB and OPTIMIZED_FUNCTION)
-  static const int kStubMajorKeyFirstBit = 0;
+  static const int kStubMajorKeyFirstBit = kIsCrankshaftedBit + 1;
   static const int kSafepointTableOffsetFirstBit =
       kStubMajorKeyFirstBit + kStubMajorKeyBits;
-  static const int kSafepointTableOffsetBitCount = 26;
+  static const int kSafepointTableOffsetBitCount = 25;
 
   STATIC_ASSERT(kStubMajorKeyFirstBit + kStubMajorKeyBits <= 32);
   STATIC_ASSERT(kSafepointTableOffsetFirstBit +
                 kSafepointTableOffsetBitCount <= 32);
+  STATIC_ASSERT(1 + kStubMajorKeyBits +
+                kSafepointTableOffsetBitCount <= 32);
 
   class SafepointTableOffsetField: public BitField<int,
       kSafepointTableOffsetFirstBit,
@@ -4802,8 +4813,10 @@
       kStubMajorKeyFirstBit, kStubMajorKeyBits> {};  // NOLINT
 
   // KindSpecificFlags2 layout (FUNCTION)
-  class BackEdgeTableOffsetField: public BitField<int, 0, 31> {};
-  class BackEdgesPatchedForOSRField: public BitField<bool, 31, 1> {};
+  class BackEdgeTableOffsetField: public BitField<int,
+      kIsCrankshaftedBit + 1, 29> {};  // NOLINT
+  class BackEdgesPatchedForOSRField: public BitField<bool,
+      kIsCrankshaftedBit + 1 + 29, 1> {};  // NOLINT
 
   // Signed field cannot be encoded using the BitField class.
   static const int kArgumentsCountShift = 17;
diff --git a/src/parser.cc b/src/parser.cc
index b4ab623..b63911b 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1872,9 +1872,10 @@
   const int literals = fun->NumberOfLiterals();
   Handle<Code> code = Handle<Code>(fun->shared()->code());
   Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
+  bool is_generator = false;
   Handle<SharedFunctionInfo> shared =
-      isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
-          Handle<ScopeInfo>(fun->shared()->scope_info()));
+      isolate()->factory()->NewSharedFunctionInfo(name, literals, is_generator,
+          code, Handle<ScopeInfo>(fun->shared()->scope_info()));
   shared->set_construct_stub(*construct_stub);
 
   // Copy the function data to the shared function info.
@@ -3286,6 +3287,16 @@
       }
     }
 
+    // Desugar '+foo' into 'foo*1', this enables the collection of type feedback
+    // without any special stub and the multiplication is removed later in
+    // Crankshaft's canonicalization pass.
+    if (op == Token::ADD) {
+      return factory()->NewBinaryOperation(Token::MUL,
+                                           expression,
+                                           factory()->NewNumberLiteral(1),
+                                           position);
+    }
+
     return factory()->NewUnaryOperation(op, expression, position);
 
   } else if (Token::IsCountOp(op)) {
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 735f078..eadcf55 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -194,9 +194,7 @@
 
 void OS::DebugBreak() {
 #if (defined(__arm__) || defined(__thumb__))
-# if defined(CAN_USE_ARMV5_INSTRUCTIONS)
   asm("bkpt 0");
-# endif
 #else
   asm("int $3");
 #endif
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 38f7c67..a6402d7 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -419,9 +419,7 @@
 // TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x,
 //  which is the architecture of generated code).
 #if (defined(__arm__) || defined(__thumb__))
-# if defined(CAN_USE_ARMV5_INSTRUCTIONS)
   asm("bkpt 0");
-# endif
 #elif defined(__mips__)
   asm("break");
 #elif defined(__native_client__)
diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc
index 752d79c..95e86b1 100644
--- a/src/runtime-profiler.cc
+++ b/src/runtime-profiler.cc
@@ -30,6 +30,7 @@
 #include "runtime-profiler.h"
 
 #include "assembler.h"
+#include "bootstrapper.h"
 #include "code-stubs.h"
 #include "compilation-cache.h"
 #include "deoptimizer.h"
@@ -134,7 +135,7 @@
     PrintF("]\n");
   }
 
-  if (FLAG_parallel_recompilation) {
+  if (FLAG_parallel_recompilation && !isolate_->bootstrapper()->IsActive()) {
     ASSERT(!function->IsMarkedForInstallingRecompiledCode());
     ASSERT(!function->IsInRecompileQueue());
     function->MarkForParallelRecompilation();
diff --git a/src/runtime.cc b/src/runtime.cc
index 7e7d6d5..c0213d2 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -706,9 +706,8 @@
   holder->set_byte_length(byte_length);
 
   v8::Isolate* external_isolate = reinterpret_cast<v8::Isolate*>(isolate);
-  v8::Handle<Object> external_holder(*holder);
-  Persistent<Object> weak_handle = Persistent<Object>::New(
-      external_isolate, external_holder);
+  v8::Persistent<v8::Value> weak_handle = v8::Persistent<v8::Value>::New(
+      external_isolate, v8::Utils::ToLocal(Handle<Object>::cast(holder)));
   weak_handle.MakeWeak(external_isolate, data, ArrayBufferWeakCallback);
   weak_handle.MarkIndependent(external_isolate);
   isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
@@ -734,8 +733,7 @@
   size_t start = static_cast<size_t>(first);
   size_t target_length = NumberToSize(isolate, target->byte_length());
 
-  if (target_length == 0)
-    return isolate->heap()->undefined_value();
+  if (target_length == 0) return isolate->heap()->undefined_value();
 
   ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
   uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
@@ -2417,11 +2415,9 @@
 
 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
                                                  Object* char_code) {
-  uint32_t code;
-  if (char_code->ToArrayIndex(&code)) {
-    if (code <= 0xffff) {
-      return isolate->heap()->LookupSingleCharacterStringFromCode(code);
-    }
+  if (char_code->IsNumber()) {
+    return isolate->heap()->LookupSingleCharacterStringFromCode(
+        NumberToUint32(char_code) & 0xffff);
   }
   return isolate->heap()->empty_string();
 }
@@ -4096,6 +4092,13 @@
   return isolate->heap()->ToBoolean(object->HasProperty(*name));
 }
 
+MaybeObject* Runtime::GetObjectPropertyOrFail(
+    Isolate* isolate,
+    Handle<Object> object,
+    Handle<Object> key) {
+  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
+      GetObjectProperty(isolate, object, key));
+}
 
 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
                                         Handle<Object> object,
@@ -4380,6 +4383,18 @@
 }
 
 
+MaybeObject* Runtime::SetObjectPropertyOrFail(
+    Isolate* isolate,
+    Handle<Object> object,
+    Handle<Object> key,
+    Handle<Object> value,
+    PropertyAttributes attr,
+    StrictModeFlag strict_mode) {
+  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
+      SetObjectProperty(isolate, object, key, value, attr, strict_mode));
+}
+
+
 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
                                         Handle<Object> object,
                                         Handle<Object> key,
@@ -7636,7 +7651,6 @@
   ASSERT(args.length() == 0);
   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
   ASSERT(isolate->heap()->IsAllocationAllowed());
-  ASSERT(deoptimizer->compiled_code_kind() == Code::COMPILED_STUB);
   delete deoptimizer;
   return isolate->heap()->undefined_value();
 }
@@ -7651,7 +7665,7 @@
   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
   ASSERT(isolate->heap()->IsAllocationAllowed());
 
-  ASSERT(deoptimizer->compiled_code_kind() != Code::COMPILED_STUB);
+  ASSERT(deoptimizer->compiled_code_kind() == Code::OPTIMIZED_FUNCTION);
 
   // Make sure to materialize objects before causing any allocation.
   JavaScriptFrameIterator it(isolate);
diff --git a/src/runtime.h b/src/runtime.h
index cbf70e9..1413351 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -702,6 +702,14 @@
       PropertyAttributes attr,
       StrictModeFlag strict_mode);
 
+  MUST_USE_RESULT static MaybeObject* SetObjectPropertyOrFail(
+      Isolate* isolate,
+      Handle<Object> object,
+      Handle<Object> key,
+      Handle<Object> value,
+      PropertyAttributes attr,
+      StrictModeFlag strict_mode);
+
   MUST_USE_RESULT static MaybeObject* ForceSetObjectProperty(
       Isolate* isolate,
       Handle<JSObject> object,
@@ -725,6 +733,11 @@
       Handle<Object> object,
       Handle<Object> key);
 
+  MUST_USE_RESULT static MaybeObject* GetObjectPropertyOrFail(
+      Isolate* isolate,
+      Handle<Object> object,
+      Handle<Object> key);
+
   // Helper functions used stubs.
   static void PerformGC(Object* result);
 
diff --git a/src/safepoint-table.cc b/src/safepoint-table.cc
index 9e42304..b565565 100644
--- a/src/safepoint-table.cc
+++ b/src/safepoint-table.cc
@@ -59,8 +59,7 @@
 
 
 SafepointTable::SafepointTable(Code* code) {
-  ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION ||
-         code->kind() == Code::COMPILED_STUB);
+  ASSERT(code->is_crankshafted());
   code_ = code;
   Address header = code->instruction_start() + code->safepoint_table_offset();
   length_ = Memory::uint32_at(header + kLengthOffset);
diff --git a/src/spaces.cc b/src/spaces.cc
index e413bf1..7202e1b 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -1807,7 +1807,6 @@
       CASE(FUNCTION);
       CASE(OPTIMIZED_FUNCTION);
       CASE(STUB);
-      CASE(COMPILED_STUB);
       CASE(BUILTIN);
       CASE(LOAD_IC);
       CASE(KEYED_LOAD_IC);
diff --git a/src/version.cc b/src/version.cc
index 933e254..8a1b8b7 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     18
-#define BUILD_NUMBER      0
+#define BUILD_NUMBER      1
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 787c7fb..3958cf0 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -30,7 +30,6 @@
 #if defined(V8_TARGET_ARCH_X64)
 
 #include "bootstrapper.h"
-#include "builtins-decls.h"
 #include "code-stubs.h"
 #include "regexp-macro-assembler.h"
 #include "stub-cache.h"
@@ -4273,10 +4272,6 @@
   Label invoke, handler_entry, exit;
   Label not_outermost_js, not_outermost_js_2;
 
-#ifdef _WIN64
-  const int kCalleeSaveXMMRegisters = 10;
-  const int kFullXMMRegisterSize = 16;
-#endif
   {  // NOLINT. Scope block confuses linter.
     MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
     // Set up frame.
@@ -4306,17 +4301,17 @@
 
 #ifdef _WIN64
     // On Win64 XMM6-XMM15 are callee-save
-    __ subq(rsp, Immediate(kCalleeSaveXMMRegisters * kFullXMMRegisterSize));
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 0), xmm6);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 1), xmm7);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 2), xmm8);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 3), xmm9);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 4), xmm10);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 5), xmm11);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 6), xmm12);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 7), xmm13);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 8), xmm14);
-    __ movdqu(Operand(rsp, kFullXMMRegisterSize * 9), xmm15);
+    __ subq(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize));
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0), xmm6);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1), xmm7);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2), xmm8);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3), xmm9);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4), xmm10);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5), xmm11);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6), xmm12);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7), xmm13);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8), xmm14);
+    __ movdqu(Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9), xmm15);
 #endif
 
     // Set up the roots and smi constant registers.
@@ -4409,17 +4404,17 @@
   // Restore callee-saved registers (X64 conventions).
 #ifdef _WIN64
   // On Win64 XMM6-XMM15 are callee-save
-  __ movdqu(xmm6, Operand(rsp, kFullXMMRegisterSize * 0));
-  __ movdqu(xmm7, Operand(rsp, kFullXMMRegisterSize * 1));
-  __ movdqu(xmm8, Operand(rsp, kFullXMMRegisterSize * 2));
-  __ movdqu(xmm8, Operand(rsp, kFullXMMRegisterSize * 3));
-  __ movdqu(xmm10, Operand(rsp, kFullXMMRegisterSize * 4));
-  __ movdqu(xmm11, Operand(rsp, kFullXMMRegisterSize * 5));
-  __ movdqu(xmm12, Operand(rsp, kFullXMMRegisterSize * 6));
-  __ movdqu(xmm13, Operand(rsp, kFullXMMRegisterSize * 7));
-  __ movdqu(xmm14, Operand(rsp, kFullXMMRegisterSize * 8));
-  __ movdqu(xmm15, Operand(rsp, kFullXMMRegisterSize * 9));
-  __ addq(rsp, Immediate(kCalleeSaveXMMRegisters * kFullXMMRegisterSize));
+  __ movdqu(xmm6, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 0));
+  __ movdqu(xmm7, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 1));
+  __ movdqu(xmm8, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 2));
+  __ movdqu(xmm9, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 3));
+  __ movdqu(xmm10, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 4));
+  __ movdqu(xmm11, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 5));
+  __ movdqu(xmm12, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 6));
+  __ movdqu(xmm13, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 7));
+  __ movdqu(xmm14, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 8));
+  __ movdqu(xmm15, Operand(rsp, EntryFrameConstants::kXMMRegisterSize * 9));
+  __ addq(rsp, Immediate(EntryFrameConstants::kXMMRegistersBlockSize));
 #endif
 
   __ pop(rbx);
diff --git a/src/x64/code-stubs-x64.h b/src/x64/code-stubs-x64.h
index 5dd4064..72a3a95 100644
--- a/src/x64/code-stubs-x64.h
+++ b/src/x64/code-stubs-x64.h
@@ -138,7 +138,7 @@
   void GenerateGenericStubBitNot(MacroAssembler* masm);
   void GenerateGenericCodeFallback(MacroAssembler* masm);
 
-  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
+  virtual Code::Kind GetCodeKind() const { return Code::UNARY_OP_IC; }
 
   virtual InlineCacheState GetICState() {
     return UnaryOpIC::ToState(operand_type_);
diff --git a/src/x64/frames-x64.h b/src/x64/frames-x64.h
index 14cc5b8..a24ab53 100644
--- a/src/x64/frames-x64.h
+++ b/src/x64/frames-x64.h
@@ -51,7 +51,12 @@
 class EntryFrameConstants : public AllStatic {
  public:
 #ifdef _WIN64
-  static const int kCallerFPOffset      = -10 * kPointerSize;
+  static const int kCalleeSaveXMMRegisters = 10;
+  static const int kXMMRegisterSize = 16;
+  static const int kXMMRegistersBlockSize =
+      kXMMRegisterSize * kCalleeSaveXMMRegisters;
+  static const int kCallerFPOffset =
+      -10 * kPointerSize - kXMMRegistersBlockSize;
 #else
   static const int kCallerFPOffset      = -8 * kPointerSize;
 #endif
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 564c3de..8ca173b 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -3968,18 +3968,6 @@
       break;
     }
 
-    case Token::ADD: {
-      Comment cmt(masm_, "[ UnaryOperation (ADD)");
-      VisitForAccumulatorValue(expr->expression());
-      Label no_conversion;
-      __ JumpIfSmi(result_register(), &no_conversion);
-      ToNumberStub convert_stub;
-      __ CallStub(&convert_stub);
-      __ bind(&no_conversion);
-      context()->Plug(result_register());
-      break;
-    }
-
     case Token::SUB:
       EmitUnaryOperation(expr, "[ UnaryOperation (SUB)");
       break;
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 6fc56ed..3e8fd5c 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -370,7 +370,7 @@
       LDeferredCode* code = deferred_[i];
       __ bind(code->entry());
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred build frame",
+        Comment(";;; Deferred build frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(!frame_is_built_);
@@ -387,7 +387,7 @@
               code->instr()->Mnemonic());
       code->Generate();
       if (NeedsDeferredFrame()) {
-        Comment(";;; Deferred destroy frame",
+        Comment(";;; Deferred destroy frame @%d: %s.",
                 code->instruction_index(),
                 code->instr()->Mnemonic());
         ASSERT(frame_is_built_);
@@ -926,11 +926,9 @@
 
 
 void LCodeGen::DoLabel(LLabel* label) {
-  if (label->is_loop_header()) {
-    Comment(";;; B%d - LOOP entry", label->block_id());
-  } else {
-    Comment(";;; B%d", label->block_id());
-  }
+  Comment(";;; -------------------- B%d%s --------------------",
+          label->block_id(),
+          label->is_loop_header() ? " (loop header)" : "");
   __ bind(label->label());
   current_block_ = label->block_id();
   DoGap(label);
@@ -2055,11 +2053,14 @@
 
 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
   Register left = ToRegister(instr->left());
-  Register right = ToRegister(instr->right());
   int false_block = chunk_->LookupDestination(instr->false_block_id());
   int true_block = chunk_->LookupDestination(instr->true_block_id());
 
-  __ cmpq(left, right);
+  if (instr->right()->IsConstantOperand()) {
+    __ Cmp(left, ToHandle(LConstantOperand::cast(instr->right())));
+  } else {
+    __ cmpq(left, ToRegister(instr->right()));
+  }
   EmitBranch(true_block, false_block, equal);
 }
 
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index e857606..adcc3e5 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -34,6 +34,7 @@
 #include "deoptimizer.h"
 #include "safepoint-table.h"
 #include "scopes.h"
+#include "v8utils.h"
 #include "x64/lithium-gap-resolver-x64.h"
 
 namespace v8 {
@@ -172,7 +173,7 @@
   int GetStackSlotCount() const { return chunk()->spill_slot_count(); }
 
   void Abort(const char* reason);
-  void Comment(const char* format, ...);
+  void FPRINTF_CHECKING Comment(const char* format, ...);
 
   void AddDeferredCode(LDeferredCode* code) { deferred_.Add(code, zone()); }
 
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index ba29ed9..1d42455 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -831,11 +831,15 @@
     HEnvironment* last_environment = pred->last_environment();
     for (int i = 0; i < block->phis()->length(); ++i) {
       HPhi* phi = block->phis()->at(i);
-      last_environment->SetValueAt(phi->merged_index(), phi);
+      if (phi->merged_index() < last_environment->length()) {
+        last_environment->SetValueAt(phi->merged_index(), phi);
+      }
     }
     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
-      last_environment->SetValueAt(block->deleted_phis()->at(i),
-                                   graph_->GetConstantUndefined());
+      if (block->deleted_phis()->at(i) < last_environment->length()) {
+        last_environment->SetValueAt(block->deleted_phis()->at(i),
+                                     graph_->GetConstantUndefined());
+      }
     }
     block->UpdateEnvironment(last_environment);
     // Pick up the outgoing argument count of one of the predecessors.
@@ -1610,7 +1614,7 @@
 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
     HCompareObjectEqAndBranch* instr) {
   LOperand* left = UseRegisterAtStart(instr->left());
-  LOperand* right = UseRegisterAtStart(instr->right());
+  LOperand* right = UseRegisterOrConstantAtStart(instr->right());
   return new(zone()) LCmpObjectEqAndBranch(left, right);
 }