Upgrade V8 to version 4.9.385.28

https://chromium.googlesource.com/v8/v8/+/4.9.385.28

FPIIM-449

Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/assembler.cc b/src/assembler.cc
index c73b470..4aac08d 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -40,22 +40,26 @@
 #include "src/base/functional.h"
 #include "src/base/lazy-instance.h"
 #include "src/base/platform/platform.h"
+#include "src/base/utils/random-number-generator.h"
 #include "src/builtins.h"
 #include "src/codegen.h"
 #include "src/counters.h"
-#include "src/cpu-profiler.h"
-#include "src/debug.h"
+#include "src/debug/debug.h"
 #include "src/deoptimizer.h"
+#include "src/disassembler.h"
 #include "src/execution.h"
 #include "src/ic/ic.h"
 #include "src/ic/stub-cache.h"
-#include "src/isolate-inl.h"
-#include "src/jsregexp.h"
-#include "src/regexp-macro-assembler.h"
-#include "src/regexp-stack.h"
+#include "src/ostreams.h"
+#include "src/parsing/token.h"
+#include "src/profiler/cpu-profiler.h"
+#include "src/regexp/jsregexp.h"
+#include "src/regexp/regexp-macro-assembler.h"
+#include "src/regexp/regexp-stack.h"
+#include "src/register-configuration.h"
 #include "src/runtime/runtime.h"
-#include "src/serialize.h"
-#include "src/token.h"
+#include "src/simulator.h"  // For flushing instruction cache.
+#include "src/snapshot/serialize.h"
 
 #if V8_TARGET_ARCH_IA32
 #include "src/ia32/assembler-ia32-inl.h"  // NOLINT
@@ -65,6 +69,8 @@
 #include "src/arm64/assembler-arm64-inl.h"  // NOLINT
 #elif V8_TARGET_ARCH_ARM
 #include "src/arm/assembler-arm-inl.h"  // NOLINT
+#elif V8_TARGET_ARCH_PPC
+#include "src/ppc/assembler-ppc-inl.h"  // NOLINT
 #elif V8_TARGET_ARCH_MIPS
 #include "src/mips/assembler-mips-inl.h"  // NOLINT
 #elif V8_TARGET_ARCH_MIPS64
@@ -78,19 +84,21 @@
 // Include native regexp-macro-assembler.
 #ifndef V8_INTERPRETED_REGEXP
 #if V8_TARGET_ARCH_IA32
-#include "src/ia32/regexp-macro-assembler-ia32.h"  // NOLINT
+#include "src/regexp/ia32/regexp-macro-assembler-ia32.h"  // NOLINT
 #elif V8_TARGET_ARCH_X64
-#include "src/x64/regexp-macro-assembler-x64.h"  // NOLINT
+#include "src/regexp/x64/regexp-macro-assembler-x64.h"  // NOLINT
 #elif V8_TARGET_ARCH_ARM64
-#include "src/arm64/regexp-macro-assembler-arm64.h"  // NOLINT
+#include "src/regexp/arm64/regexp-macro-assembler-arm64.h"  // NOLINT
 #elif V8_TARGET_ARCH_ARM
-#include "src/arm/regexp-macro-assembler-arm.h"  // NOLINT
+#include "src/regexp/arm/regexp-macro-assembler-arm.h"  // NOLINT
+#elif V8_TARGET_ARCH_PPC
+#include "src/regexp/ppc/regexp-macro-assembler-ppc.h"  // NOLINT
 #elif V8_TARGET_ARCH_MIPS
-#include "src/mips/regexp-macro-assembler-mips.h"  // NOLINT
+#include "src/regexp/mips/regexp-macro-assembler-mips.h"  // NOLINT
 #elif V8_TARGET_ARCH_MIPS64
-#include "src/mips64/regexp-macro-assembler-mips64.h"  // NOLINT
+#include "src/regexp/mips64/regexp-macro-assembler-mips64.h"  // NOLINT
 #elif V8_TARGET_ARCH_X87
-#include "src/x87/regexp-macro-assembler-x87.h"  // NOLINT
+#include "src/regexp/x87/regexp-macro-assembler-x87.h"  // NOLINT
 #else  // Unknown architecture.
 #error "Unknown architecture."
 #endif  // Target architecture.
@@ -100,6 +108,39 @@
 namespace internal {
 
 // -----------------------------------------------------------------------------
+// Common register code.
+
+const char* Register::ToString() {
+  // This is the mapping of allocation indices to registers.
+  DCHECK(reg_code >= 0 && reg_code < kNumRegisters);
+  return RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
+      ->GetGeneralRegisterName(reg_code);
+}
+
+
+bool Register::IsAllocatable() const {
+  return ((1 << reg_code) &
+          RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
+              ->allocatable_general_codes_mask()) != 0;
+}
+
+
+const char* DoubleRegister::ToString() {
+  // This is the mapping of allocation indices to registers.
+  DCHECK(reg_code >= 0 && reg_code < kMaxNumRegisters);
+  return RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
+      ->GetDoubleRegisterName(reg_code);
+}
+
+
+bool DoubleRegister::IsAllocatable() const {
+  return ((1 << reg_code) &
+          RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT)
+              ->allocatable_double_codes_mask()) != 0;
+}
+
+
+// -----------------------------------------------------------------------------
 // Common double constants.
 
 struct DoubleConstant BASE_EMBEDDED {
@@ -107,7 +148,6 @@
 double one_half;
 double minus_one_half;
 double negative_infinity;
-double canonical_non_hole_nan;
 double the_hole_nan;
 double uint32_bias;
 };
@@ -132,8 +172,9 @@
       predictable_code_size_(false),
       // We may use the assembler without an isolate.
       serializer_enabled_(isolate && isolate->serializer_enabled()),
-      ool_constant_pool_available_(false) {
-  if (FLAG_mask_constants_with_cookie && isolate != NULL)  {
+      constant_pool_available_(false) {
+  DCHECK_NOT_NULL(isolate);
+  if (FLAG_mask_constants_with_cookie) {
     jit_cookie_ = isolate->random_number_generator()->NextInt();
   }
   own_buffer_ = buffer == NULL;
@@ -152,9 +193,31 @@
 }
 
 
+void AssemblerBase::FlushICache(Isolate* isolate, void* start, size_t size) {
+  if (size == 0) return;
+  if (CpuFeatures::IsSupported(COHERENT_CACHE)) return;
+
+#if defined(USE_SIMULATOR)
+  Simulator::FlushICache(isolate->simulator_i_cache(), start, size);
+#else
+  CpuFeatures::FlushICache(start, size);
+#endif  // USE_SIMULATOR
+}
+
+
+void AssemblerBase::Print() {
+  OFStream os(stdout);
+  v8::internal::Disassembler::Decode(isolate(), &os, buffer_, pc_, nullptr);
+}
+
+
 // -----------------------------------------------------------------------------
 // Implementation of PredictableCodeSizeScope
 
+PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler)
+    : PredictableCodeSizeScope(assembler, -1) {}
+
+
 PredictableCodeSizeScope::PredictableCodeSizeScope(AssemblerBase* assembler,
                                                    int expected_size)
     : assembler_(assembler),
@@ -245,97 +308,61 @@
 //   10: short_data_record:    [6-bit pc delta] 10 followed by
 //                             [6-bit data delta] [2-bit data type tag]
 //
-//   11: long_record           [2-bit high tag][4 bit middle_tag] 11
-//                             followed by variable data depending on type.
+//   11: long_record           [6 bit reloc mode] 11
+//                             followed by pc delta
+//                             followed by optional data depending on type.
 //
 //  2-bit data type tags, used in short_data_record and data_jump long_record:
 //   code_target_with_id: 00
 //   position:            01
 //   statement_position:  10
-//   comment:             11 (not used in short_data_record)
+//   deopt_reason:        11
 //
-//  Long record format:
-//    4-bit middle_tag:
-//      0000 - 1100 : Short record for RelocInfo::Mode middle_tag + 2
-//         (The middle_tag encodes rmode - RelocInfo::LAST_COMPACT_ENUM,
-//          and is between 0000 and 1100)
-//        The format is:
-//                              00 [4 bit middle_tag] 11 followed by
-//                              00 [6 bit pc delta]
-//
-//      1101: constant or veneer pool. Used only on ARM and ARM64 for now.
-//        The format is:       [2-bit sub-type] 1101 11
-//                             signed int (size of the pool).
-//          The 2-bit sub-types are:
-//            00: constant pool
-//            01: veneer pool
-//      1110: long_data_record
-//        The format is:       [2-bit data_type_tag] 1110 11
-//                             signed intptr_t, lowest byte written first
-//                             (except data_type code_target_with_id, which
-//                             is followed by a signed int, not intptr_t.)
-//
-//      1111: long_pc_jump
-//        The format is:
-//          pc-jump:             00 1111 11,
-//                               00 [6 bits pc delta]
-//        or
-//          pc-jump (variable length):
-//                               01 1111 11,
+//  If a pc delta exceeds 6 bits, it is split into a remainder that fits into
+//  6 bits and a part that does not. The latter is encoded as a long record
+//  with PC_JUMP as pseudo reloc info mode. The former is encoded as part of
+//  the following record in the usual way. The long pc jump record has variable
+//  length:
+//               pc-jump:        [PC_JUMP] 11
 //                               [7 bits data] 0
 //                                  ...
 //                               [7 bits data] 1
 //               (Bits 6..31 of pc delta, with leading zeroes
 //                dropped, and last non-zero chunk tagged with 1.)
 
-
-#ifdef DEBUG
-const int kMaxStandardNonCompactModes = 14;
-#endif
-
 const int kTagBits = 2;
 const int kTagMask = (1 << kTagBits) - 1;
-const int kExtraTagBits = 4;
-const int kLocatableTypeTagBits = 2;
-const int kSmallDataBits = kBitsPerByte - kLocatableTypeTagBits;
+const int kLongTagBits = 6;
+const int kShortDataTypeTagBits = 2;
+const int kShortDataBits = kBitsPerByte - kShortDataTypeTagBits;
 
 const int kEmbeddedObjectTag = 0;
 const int kCodeTargetTag = 1;
 const int kLocatableTag = 2;
 const int kDefaultTag = 3;
 
-const int kPCJumpExtraTag = (1 << kExtraTagBits) - 1;
-
 const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
 const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
 const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;
 
-const int kVariableLengthPCJumpTopTag = 1;
 const int kChunkBits = 7;
 const int kChunkMask = (1 << kChunkBits) - 1;
 const int kLastChunkTagBits = 1;
 const int kLastChunkTagMask = 1;
 const int kLastChunkTag = 1;
 
-
-const int kDataJumpExtraTag = kPCJumpExtraTag - 1;
-
 const int kCodeWithIdTag = 0;
 const int kNonstatementPositionTag = 1;
 const int kStatementPositionTag = 2;
-const int kCommentTag = 3;
-
-const int kPoolExtraTag = kPCJumpExtraTag - 2;
-const int kConstPoolTag = 0;
-const int kVeneerPoolTag = 1;
+const int kDeoptReasonTag = 3;
 
 
-uint32_t RelocInfoWriter::WriteVariableLengthPCJump(uint32_t pc_delta) {
+uint32_t RelocInfoWriter::WriteLongPCJump(uint32_t pc_delta) {
   // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
   // Otherwise write a variable length PC jump for the bits that do
   // not fit in the kSmallPCDeltaBits bits.
   if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
-  WriteExtraTag(kPCJumpExtraTag, kVariableLengthPCJumpTopTag);
+  WriteMode(RelocInfo::PC_JUMP);
   uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
   DCHECK(pc_jump > 0);
   // Write kChunkBits size chunks of the pc_jump.
@@ -350,55 +377,42 @@
 }
 
 
-void RelocInfoWriter::WriteTaggedPC(uint32_t pc_delta, int tag) {
-  // Write a byte of tagged pc-delta, possibly preceded by var. length pc-jump.
-  pc_delta = WriteVariableLengthPCJump(pc_delta);
+void RelocInfoWriter::WriteShortTaggedPC(uint32_t pc_delta, int tag) {
+  // Write a byte of tagged pc-delta, possibly preceded by an explicit pc-jump.
+  pc_delta = WriteLongPCJump(pc_delta);
   *--pos_ = pc_delta << kTagBits | tag;
 }
 
 
-void RelocInfoWriter::WriteTaggedData(intptr_t data_delta, int tag) {
-  *--pos_ = static_cast<byte>(data_delta << kLocatableTypeTagBits | tag);
+void RelocInfoWriter::WriteShortTaggedData(intptr_t data_delta, int tag) {
+  *--pos_ = static_cast<byte>(data_delta << kShortDataTypeTagBits | tag);
 }
 
 
-void RelocInfoWriter::WriteExtraTag(int extra_tag, int top_tag) {
-  *--pos_ = static_cast<int>(top_tag << (kTagBits + kExtraTagBits) |
-                             extra_tag << kTagBits |
-                             kDefaultTag);
+void RelocInfoWriter::WriteMode(RelocInfo::Mode rmode) {
+  STATIC_ASSERT(RelocInfo::NUMBER_OF_MODES <= (1 << kLongTagBits));
+  *--pos_ = static_cast<int>((rmode << kTagBits) | kDefaultTag);
 }
 
 
-void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
+void RelocInfoWriter::WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode) {
   // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
-  pc_delta = WriteVariableLengthPCJump(pc_delta);
-  WriteExtraTag(extra_tag, 0);
+  pc_delta = WriteLongPCJump(pc_delta);
+  WriteMode(rmode);
   *--pos_ = pc_delta;
 }
 
 
-void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
-  WriteExtraTag(kDataJumpExtraTag, top_tag);
+void RelocInfoWriter::WriteIntData(int number) {
   for (int i = 0; i < kIntSize; i++) {
-    *--pos_ = static_cast<byte>(data_delta);
+    *--pos_ = static_cast<byte>(number);
     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
-    data_delta = data_delta >> kBitsPerByte;
+    number = number >> kBitsPerByte;
   }
 }
 
 
-void RelocInfoWriter::WriteExtraTaggedPoolData(int data, int pool_type) {
-  WriteExtraTag(kPoolExtraTag, pool_type);
-  for (int i = 0; i < kIntSize; i++) {
-    *--pos_ = static_cast<byte>(data);
-    // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
-    data = data >> kBitsPerByte;
-  }
-}
-
-
-void RelocInfoWriter::WriteExtraTaggedData(intptr_t data_delta, int top_tag) {
-  WriteExtraTag(kDataJumpExtraTag, top_tag);
+void RelocInfoWriter::WriteData(intptr_t data_delta) {
   for (int i = 0; i < kIntptrSize; i++) {
     *--pos_ = static_cast<byte>(data_delta);
     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
@@ -407,73 +421,99 @@
 }
 
 
+void RelocInfoWriter::WritePosition(int pc_delta, int pos_delta,
+                                    RelocInfo::Mode rmode) {
+  int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag
+                                                    : kStatementPositionTag;
+  // Check if delta is small enough to fit in a tagged byte.
+  if (is_intn(pos_delta, kShortDataBits)) {
+    WriteShortTaggedPC(pc_delta, kLocatableTag);
+    WriteShortTaggedData(pos_delta, pos_type_tag);
+  } else {
+    // Otherwise, use costly encoding.
+    WriteModeAndPC(pc_delta, rmode);
+    WriteIntData(pos_delta);
+  }
+}
+
+
+void RelocInfoWriter::FlushPosition() {
+  if (!next_position_candidate_flushed_) {
+    WritePosition(next_position_candidate_pc_delta_,
+                  next_position_candidate_pos_delta_, RelocInfo::POSITION);
+    next_position_candidate_pos_delta_ = 0;
+    next_position_candidate_pc_delta_ = 0;
+    next_position_candidate_flushed_ = true;
+  }
+}
+
+
 void RelocInfoWriter::Write(const RelocInfo* rinfo) {
+  RelocInfo::Mode rmode = rinfo->rmode();
+  if (rmode != RelocInfo::POSITION) {
+    FlushPosition();
+  }
 #ifdef DEBUG
   byte* begin_pos = pos_;
 #endif
   DCHECK(rinfo->rmode() < RelocInfo::NUMBER_OF_MODES);
   DCHECK(rinfo->pc() - last_pc_ >= 0);
-  DCHECK(RelocInfo::LAST_STANDARD_NONCOMPACT_ENUM - RelocInfo::LAST_COMPACT_ENUM
-         <= kMaxStandardNonCompactModes);
   // Use unsigned delta-encoding for pc.
   uint32_t pc_delta = static_cast<uint32_t>(rinfo->pc() - last_pc_);
-  RelocInfo::Mode rmode = rinfo->rmode();
 
   // The two most common modes are given small tags, and usually fit in a byte.
   if (rmode == RelocInfo::EMBEDDED_OBJECT) {
-    WriteTaggedPC(pc_delta, kEmbeddedObjectTag);
+    WriteShortTaggedPC(pc_delta, kEmbeddedObjectTag);
   } else if (rmode == RelocInfo::CODE_TARGET) {
-    WriteTaggedPC(pc_delta, kCodeTargetTag);
+    WriteShortTaggedPC(pc_delta, kCodeTargetTag);
     DCHECK(begin_pos - pos_ <= RelocInfo::kMaxCallSize);
   } else if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
     // Use signed delta-encoding for id.
-    DCHECK(static_cast<int>(rinfo->data()) == rinfo->data());
+    DCHECK_EQ(static_cast<int>(rinfo->data()), rinfo->data());
     int id_delta = static_cast<int>(rinfo->data()) - last_id_;
     // Check if delta is small enough to fit in a tagged byte.
-    if (is_intn(id_delta, kSmallDataBits)) {
-      WriteTaggedPC(pc_delta, kLocatableTag);
-      WriteTaggedData(id_delta, kCodeWithIdTag);
+    if (is_intn(id_delta, kShortDataBits)) {
+      WriteShortTaggedPC(pc_delta, kLocatableTag);
+      WriteShortTaggedData(id_delta, kCodeWithIdTag);
     } else {
       // Otherwise, use costly encoding.
-      WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
-      WriteExtraTaggedIntData(id_delta, kCodeWithIdTag);
+      WriteModeAndPC(pc_delta, rmode);
+      WriteIntData(id_delta);
     }
     last_id_ = static_cast<int>(rinfo->data());
+  } else if (rmode == RelocInfo::DEOPT_REASON) {
+    DCHECK(rinfo->data() < (1 << kShortDataBits));
+    WriteShortTaggedPC(pc_delta, kLocatableTag);
+    WriteShortTaggedData(rinfo->data(), kDeoptReasonTag);
   } else if (RelocInfo::IsPosition(rmode)) {
     // Use signed delta-encoding for position.
-    DCHECK(static_cast<int>(rinfo->data()) == rinfo->data());
+    DCHECK_EQ(static_cast<int>(rinfo->data()), rinfo->data());
     int pos_delta = static_cast<int>(rinfo->data()) - last_position_;
-    int pos_type_tag = (rmode == RelocInfo::POSITION) ? kNonstatementPositionTag
-                                                      : kStatementPositionTag;
-    // Check if delta is small enough to fit in a tagged byte.
-    if (is_intn(pos_delta, kSmallDataBits)) {
-      WriteTaggedPC(pc_delta, kLocatableTag);
-      WriteTaggedData(pos_delta, pos_type_tag);
+    if (rmode == RelocInfo::STATEMENT_POSITION) {
+      WritePosition(pc_delta, pos_delta, rmode);
     } else {
-      // Otherwise, use costly encoding.
-      WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
-      WriteExtraTaggedIntData(pos_delta, pos_type_tag);
+      DCHECK_EQ(rmode, RelocInfo::POSITION);
+      if (pc_delta != 0 || last_mode_ != RelocInfo::POSITION) {
+        FlushPosition();
+        next_position_candidate_pc_delta_ = pc_delta;
+        next_position_candidate_pos_delta_ = pos_delta;
+      } else {
+        next_position_candidate_pos_delta_ += pos_delta;
+      }
+      next_position_candidate_flushed_ = false;
     }
     last_position_ = static_cast<int>(rinfo->data());
-  } else if (RelocInfo::IsComment(rmode)) {
-    // Comments are normally not generated, so we use the costly encoding.
-    WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
-    WriteExtraTaggedData(rinfo->data(), kCommentTag);
-    DCHECK(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
-  } else if (RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode)) {
-      WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
-      WriteExtraTaggedPoolData(static_cast<int>(rinfo->data()),
-                               RelocInfo::IsConstPool(rmode) ? kConstPoolTag
-                                                             : kVeneerPoolTag);
   } else {
-    DCHECK(rmode > RelocInfo::LAST_COMPACT_ENUM);
-    int saved_mode = rmode - RelocInfo::LAST_COMPACT_ENUM;
-    // For all other modes we simply use the mode as the extra tag.
-    // None of these modes need a data component.
-    DCHECK(saved_mode < kPCJumpExtraTag && saved_mode < kDataJumpExtraTag);
-    WriteExtraTaggedPC(pc_delta, saved_mode);
+    WriteModeAndPC(pc_delta, rmode);
+    if (RelocInfo::IsComment(rmode)) {
+      WriteData(rinfo->data());
+    } else if (RelocInfo::IsConstPool(rmode) ||
+               RelocInfo::IsVeneerPool(rmode)) {
+      WriteIntData(static_cast<int>(rinfo->data()));
+    }
   }
   last_pc_ = rinfo->pc();
+  last_mode_ = rmode;
 #ifdef DEBUG
   DCHECK(begin_pos - pos_ <= kMaxSize);
 #endif
@@ -485,17 +525,13 @@
 }
 
 
-inline int RelocIterator::GetExtraTag() {
-  return (*pos_ >> kTagBits) & ((1 << kExtraTagBits) - 1);
+inline RelocInfo::Mode RelocIterator::GetMode() {
+  return static_cast<RelocInfo::Mode>((*pos_ >> kTagBits) &
+                                      ((1 << kLongTagBits) - 1));
 }
 
 
-inline int RelocIterator::GetTopTag() {
-  return *pos_ >> (kTagBits + kExtraTagBits);
-}
-
-
-inline void RelocIterator::ReadTaggedPC() {
+inline void RelocIterator::ReadShortTaggedPC() {
   rinfo_.pc_ += *pos_ >> kTagBits;
 }
 
@@ -515,7 +551,7 @@
 }
 
 
-void RelocIterator::AdvanceReadPoolData() {
+void RelocIterator::AdvanceReadInt() {
   int x = 0;
   for (int i = 0; i < kIntSize; i++) {
     x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
@@ -543,7 +579,7 @@
 }
 
 
-void RelocIterator::AdvanceReadVariableLengthPCJump() {
+void RelocIterator::AdvanceReadLongPCJump() {
   // Read the 32-kSmallPCDeltaBits most significant bits of the
   // pc jump in kChunkBits bit chunks and shift them into place.
   // Stop when the last chunk is encountered.
@@ -559,27 +595,33 @@
 }
 
 
-inline int RelocIterator::GetLocatableTypeTag() {
-  return *pos_ & ((1 << kLocatableTypeTagBits) - 1);
+inline int RelocIterator::GetShortDataTypeTag() {
+  return *pos_ & ((1 << kShortDataTypeTagBits) - 1);
 }
 
 
-inline void RelocIterator::ReadTaggedId() {
+inline void RelocIterator::ReadShortTaggedId() {
   int8_t signed_b = *pos_;
   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
-  last_id_ += signed_b >> kLocatableTypeTagBits;
+  last_id_ += signed_b >> kShortDataTypeTagBits;
   rinfo_.data_ = last_id_;
 }
 
 
-inline void RelocIterator::ReadTaggedPosition() {
+inline void RelocIterator::ReadShortTaggedPosition() {
   int8_t signed_b = *pos_;
   // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
-  last_position_ += signed_b >> kLocatableTypeTagBits;
+  last_position_ += signed_b >> kShortDataTypeTagBits;
   rinfo_.data_ = last_position_;
 }
 
 
+inline void RelocIterator::ReadShortTaggedData() {
+  uint8_t unsigned_b = *pos_;
+  rinfo_.data_ = unsigned_b >> kTagBits;
+}
+
+
 static inline RelocInfo::Mode GetPositionModeFromTag(int tag) {
   DCHECK(tag == kNonstatementPositionTag ||
          tag == kStatementPositionTag);
@@ -599,78 +641,73 @@
   while (pos_ > end_) {
     int tag = AdvanceGetTag();
     if (tag == kEmbeddedObjectTag) {
-      ReadTaggedPC();
+      ReadShortTaggedPC();
       if (SetMode(RelocInfo::EMBEDDED_OBJECT)) return;
     } else if (tag == kCodeTargetTag) {
-      ReadTaggedPC();
+      ReadShortTaggedPC();
       if (SetMode(RelocInfo::CODE_TARGET)) return;
     } else if (tag == kLocatableTag) {
-      ReadTaggedPC();
+      ReadShortTaggedPC();
       Advance();
-      int locatable_tag = GetLocatableTypeTag();
-      if (locatable_tag == kCodeWithIdTag) {
+      int data_type_tag = GetShortDataTypeTag();
+      if (data_type_tag == kCodeWithIdTag) {
         if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
-          ReadTaggedId();
+          ReadShortTaggedId();
+          return;
+        }
+      } else if (data_type_tag == kDeoptReasonTag) {
+        if (SetMode(RelocInfo::DEOPT_REASON)) {
+          ReadShortTaggedData();
           return;
         }
       } else {
-        // Compact encoding is never used for comments,
-        // so it must be a position.
-        DCHECK(locatable_tag == kNonstatementPositionTag ||
-               locatable_tag == kStatementPositionTag);
+        DCHECK(data_type_tag == kNonstatementPositionTag ||
+               data_type_tag == kStatementPositionTag);
         if (mode_mask_ & RelocInfo::kPositionMask) {
-          ReadTaggedPosition();
-          if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
+          // Always update the position if we are interested in either
+          // statement positions or non-statement positions.
+          ReadShortTaggedPosition();
+          if (SetMode(GetPositionModeFromTag(data_type_tag))) return;
         }
       }
     } else {
       DCHECK(tag == kDefaultTag);
-      int extra_tag = GetExtraTag();
-      if (extra_tag == kPCJumpExtraTag) {
-        if (GetTopTag() == kVariableLengthPCJumpTopTag) {
-          AdvanceReadVariableLengthPCJump();
-        } else {
-          AdvanceReadPC();
-        }
-      } else if (extra_tag == kDataJumpExtraTag) {
-        int locatable_tag = GetTopTag();
-        if (locatable_tag == kCodeWithIdTag) {
-          if (SetMode(RelocInfo::CODE_TARGET_WITH_ID)) {
+      RelocInfo::Mode rmode = GetMode();
+      if (rmode == RelocInfo::PC_JUMP) {
+        AdvanceReadLongPCJump();
+      } else {
+        AdvanceReadPC();
+        if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
+          if (SetMode(rmode)) {
             AdvanceReadId();
             return;
           }
           Advance(kIntSize);
-        } else if (locatable_tag != kCommentTag) {
-          DCHECK(locatable_tag == kNonstatementPositionTag ||
-                 locatable_tag == kStatementPositionTag);
-          if (mode_mask_ & RelocInfo::kPositionMask) {
-            AdvanceReadPosition();
-            if (SetMode(GetPositionModeFromTag(locatable_tag))) return;
-          } else {
-            Advance(kIntSize);
-          }
-        } else {
-          DCHECK(locatable_tag == kCommentTag);
-          if (SetMode(RelocInfo::COMMENT)) {
+        } else if (RelocInfo::IsComment(rmode)) {
+          if (SetMode(rmode)) {
             AdvanceReadData();
             return;
           }
           Advance(kIntptrSize);
-        }
-      } else if (extra_tag == kPoolExtraTag) {
-        int pool_type = GetTopTag();
-        DCHECK(pool_type == kConstPoolTag || pool_type == kVeneerPoolTag);
-        RelocInfo::Mode rmode = (pool_type == kConstPoolTag) ?
-          RelocInfo::CONST_POOL : RelocInfo::VENEER_POOL;
-        if (SetMode(rmode)) {
-          AdvanceReadPoolData();
+        } else if (RelocInfo::IsPosition(rmode)) {
+          if (mode_mask_ & RelocInfo::kPositionMask) {
+            // Always update the position if we are interested in either
+            // statement positions or non-statement positions.
+            AdvanceReadPosition();
+            if (SetMode(rmode)) return;
+          } else {
+            Advance(kIntSize);
+          }
+        } else if (RelocInfo::IsConstPool(rmode) ||
+                   RelocInfo::IsVeneerPool(rmode)) {
+          if (SetMode(rmode)) {
+            AdvanceReadInt();
+            return;
+          }
+          Advance(kIntSize);
+        } else if (SetMode(static_cast<RelocInfo::Mode>(rmode))) {
           return;
         }
-        Advance(kIntSize);
-      } else {
-        AdvanceReadPC();
-        int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM;
-        if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return;
       }
     }
   }
@@ -687,7 +724,8 @@
 }
 
 
-RelocIterator::RelocIterator(Code* code, int mode_mask) {
+RelocIterator::RelocIterator(Code* code, int mode_mask)
+    : rinfo_(code->map()->GetIsolate()) {
   rinfo_.host_ = code;
   rinfo_.pc_ = code->instruction_start();
   rinfo_.data_ = 0;
@@ -712,7 +750,8 @@
 }
 
 
-RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask) {
+RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask)
+    : rinfo_(desc.origin->isolate()) {
   rinfo_.pc_ = desc.buffer;
   rinfo_.data_ = 0;
   // Relocation info is read backwards.
@@ -750,45 +789,52 @@
 #ifdef ENABLE_DISASSEMBLER
 const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
   switch (rmode) {
-    case RelocInfo::NONE32:
+    case NONE32:
       return "no reloc 32";
-    case RelocInfo::NONE64:
+    case NONE64:
       return "no reloc 64";
-    case RelocInfo::EMBEDDED_OBJECT:
+    case EMBEDDED_OBJECT:
       return "embedded object";
-    case RelocInfo::CONSTRUCT_CALL:
-      return "code target (js construct call)";
-    case RelocInfo::DEBUG_BREAK:
-      return "debug break";
-    case RelocInfo::CODE_TARGET:
+    case DEBUGGER_STATEMENT:
+      return "debugger statement";
+    case CODE_TARGET:
       return "code target";
-    case RelocInfo::CODE_TARGET_WITH_ID:
+    case CODE_TARGET_WITH_ID:
       return "code target with id";
-    case RelocInfo::CELL:
+    case CELL:
       return "property cell";
-    case RelocInfo::RUNTIME_ENTRY:
+    case RUNTIME_ENTRY:
       return "runtime entry";
-    case RelocInfo::JS_RETURN:
-      return "js return";
-    case RelocInfo::COMMENT:
+    case COMMENT:
       return "comment";
-    case RelocInfo::POSITION:
+    case POSITION:
       return "position";
-    case RelocInfo::STATEMENT_POSITION:
+    case STATEMENT_POSITION:
       return "statement position";
-    case RelocInfo::EXTERNAL_REFERENCE:
+    case EXTERNAL_REFERENCE:
       return "external reference";
-    case RelocInfo::INTERNAL_REFERENCE:
+    case INTERNAL_REFERENCE:
       return "internal reference";
-    case RelocInfo::CONST_POOL:
+    case INTERNAL_REFERENCE_ENCODED:
+      return "encoded internal reference";
+    case DEOPT_REASON:
+      return "deopt reason";
+    case CONST_POOL:
       return "constant pool";
-    case RelocInfo::VENEER_POOL:
+    case VENEER_POOL:
       return "veneer pool";
-    case RelocInfo::DEBUG_BREAK_SLOT:
-      return "debug break slot";
-    case RelocInfo::CODE_AGE_SEQUENCE:
-      return "code_age_sequence";
-    case RelocInfo::NUMBER_OF_MODES:
+    case DEBUG_BREAK_SLOT_AT_POSITION:
+      return "debug break slot at position";
+    case DEBUG_BREAK_SLOT_AT_RETURN:
+      return "debug break slot at return";
+    case DEBUG_BREAK_SLOT_AT_CALL:
+      return "debug break slot at call";
+    case CODE_AGE_SEQUENCE:
+      return "code age sequence";
+    case GENERATOR_CONTINUATION:
+      return "generator continuation";
+    case NUMBER_OF_MODES:
+    case PC_JUMP:
       UNREACHABLE();
       return "number_of_modes";
   }
@@ -800,12 +846,17 @@
   os << static_cast<const void*>(pc_) << "  " << RelocModeName(rmode_);
   if (IsComment(rmode_)) {
     os << "  (" << reinterpret_cast<char*>(data_) << ")";
+  } else if (rmode_ == DEOPT_REASON) {
+    os << "  (" << Deoptimizer::GetDeoptReason(
+                       static_cast<Deoptimizer::DeoptReason>(data_)) << ")";
   } else if (rmode_ == EMBEDDED_OBJECT) {
     os << "  (" << Brief(target_object()) << ")";
   } else if (rmode_ == EXTERNAL_REFERENCE) {
     ExternalReferenceEncoder ref_encoder(isolate);
-    os << " (" << ref_encoder.NameOfAddress(target_reference()) << ")  ("
-       << static_cast<const void*>(target_reference()) << ")";
+    os << " ("
+       << ref_encoder.NameOfAddress(isolate, target_external_reference())
+       << ")  (" << static_cast<const void*>(target_external_reference())
+       << ")";
   } else if (IsCodeTarget(rmode_)) {
     Code* code = Code::GetCodeFromTargetAddress(target_address());
     os << " (" << Code::Kind2String(code->kind()) << ")  ("
@@ -823,6 +874,8 @@
     if (id != Deoptimizer::kNotDeoptimizationEntry) {
       os << "  (deoptimization bailout " << id << ")";
     }
+  } else if (IsConstPool(rmode_)) {
+    os << " (size " << static_cast<int>(data_) << ")";
   }
 
   os << "\n";
@@ -839,8 +892,7 @@
     case CELL:
       Object::VerifyPointer(target_cell());
       break;
-    case DEBUG_BREAK:
-    case CONSTRUCT_CALL:
+    case DEBUGGER_STATEMENT:
     case CODE_TARGET_WITH_ID:
     case CODE_TARGET: {
       // convert inline target address to code object
@@ -853,20 +905,32 @@
       CHECK(code->address() == HeapObject::cast(found)->address());
       break;
     }
+    case INTERNAL_REFERENCE:
+    case INTERNAL_REFERENCE_ENCODED: {
+      Address target = target_internal_reference();
+      Address pc = target_internal_reference_address();
+      Code* code = Code::cast(isolate->FindCodeObject(pc));
+      CHECK(target >= code->instruction_start());
+      CHECK(target <= code->instruction_end());
+      break;
+    }
     case RUNTIME_ENTRY:
-    case JS_RETURN:
     case COMMENT:
     case POSITION:
     case STATEMENT_POSITION:
     case EXTERNAL_REFERENCE:
-    case INTERNAL_REFERENCE:
+    case DEOPT_REASON:
     case CONST_POOL:
     case VENEER_POOL:
-    case DEBUG_BREAK_SLOT:
+    case DEBUG_BREAK_SLOT_AT_POSITION:
+    case DEBUG_BREAK_SLOT_AT_RETURN:
+    case DEBUG_BREAK_SLOT_AT_CALL:
+    case GENERATOR_CONTINUATION:
     case NONE32:
     case NONE64:
       break;
     case NUMBER_OF_MODES:
+    case PC_JUMP:
       UNREACHABLE();
       break;
     case CODE_AGE_SEQUENCE:
@@ -877,14 +941,12 @@
 #endif  // VERIFY_HEAP
 
 
-// -----------------------------------------------------------------------------
 // Implementation of ExternalReference
 
 void ExternalReference::SetUp() {
   double_constants.min_int = kMinInt;
   double_constants.one_half = 0.5;
   double_constants.minus_one_half = -0.5;
-  double_constants.canonical_non_hole_nan = base::OS::nan_value();
   double_constants.the_hole_nan = bit_cast<double>(kHoleNanInt64);
   double_constants.negative_infinity = -V8_INFINITY;
   double_constants.uint32_bias =
@@ -962,14 +1024,13 @@
   : address_(isolate->builtins()->builtin_address(name)) {}
 
 
-ExternalReference::ExternalReference(Runtime::FunctionId id,
-                                     Isolate* isolate)
-  : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
+ExternalReference::ExternalReference(Runtime::FunctionId id, Isolate* isolate)
+    : address_(Redirect(isolate, Runtime::FunctionForId(id)->entry)) {}
 
 
 ExternalReference::ExternalReference(const Runtime::Function* f,
                                      Isolate* isolate)
-  : address_(Redirect(isolate, f->entry)) {}
+    : address_(Redirect(isolate, f->entry)) {}
 
 
 ExternalReference ExternalReference::isolate_address(Isolate* isolate) {
@@ -977,11 +1038,6 @@
 }
 
 
-ExternalReference::ExternalReference(const IC_Utility& ic_utility,
-                                     Isolate* isolate)
-  : address_(Redirect(isolate, ic_utility.address())) {}
-
-
 ExternalReference::ExternalReference(StatsCounter* counter)
   : address_(reinterpret_cast<Address>(counter->GetInternalPointer())) {}
 
@@ -1010,12 +1066,6 @@
 }
 
 
-ExternalReference ExternalReference::flush_icache_function(Isolate* isolate) {
-  return ExternalReference(
-      Redirect(isolate, FUNCTION_ADDR(CpuFeatures::FlushICache)));
-}
-
-
 ExternalReference ExternalReference::delete_handle_scope_extensions(
     Isolate* isolate) {
   return ExternalReference(Redirect(
@@ -1128,7 +1178,7 @@
 
 
 ExternalReference ExternalReference::store_buffer_top(Isolate* isolate) {
-  return ExternalReference(isolate->heap()->store_buffer()->TopAddress());
+  return ExternalReference(isolate->heap()->store_buffer_top_address());
 }
 
 
@@ -1150,31 +1200,15 @@
 }
 
 
-ExternalReference ExternalReference::old_pointer_space_allocation_top_address(
+ExternalReference ExternalReference::old_space_allocation_top_address(
     Isolate* isolate) {
-  return ExternalReference(
-      isolate->heap()->OldPointerSpaceAllocationTopAddress());
+  return ExternalReference(isolate->heap()->OldSpaceAllocationTopAddress());
 }
 
 
-ExternalReference ExternalReference::old_pointer_space_allocation_limit_address(
+ExternalReference ExternalReference::old_space_allocation_limit_address(
     Isolate* isolate) {
-  return ExternalReference(
-      isolate->heap()->OldPointerSpaceAllocationLimitAddress());
-}
-
-
-ExternalReference ExternalReference::old_data_space_allocation_top_address(
-    Isolate* isolate) {
-  return ExternalReference(
-      isolate->heap()->OldDataSpaceAllocationTopAddress());
-}
-
-
-ExternalReference ExternalReference::old_data_space_allocation_limit_address(
-    Isolate* isolate) {
-  return ExternalReference(
-      isolate->heap()->OldDataSpaceAllocationLimitAddress());
+  return ExternalReference(isolate->heap()->OldSpaceAllocationLimitAddress());
 }
 
 
@@ -1208,18 +1242,6 @@
 }
 
 
-ExternalReference ExternalReference::address_of_has_pending_message(
-    Isolate* isolate) {
-  return ExternalReference(isolate->has_pending_message_address());
-}
-
-
-ExternalReference ExternalReference::address_of_pending_message_script(
-    Isolate* isolate) {
-  return ExternalReference(isolate->pending_message_script_address());
-}
-
-
 ExternalReference ExternalReference::address_of_min_int() {
   return ExternalReference(reinterpret_cast<void*>(&double_constants.min_int));
 }
@@ -1242,12 +1264,6 @@
 }
 
 
-ExternalReference ExternalReference::address_of_canonical_non_hole_nan() {
-  return ExternalReference(
-      reinterpret_cast<void*>(&double_constants.canonical_non_hole_nan));
-}
-
-
 ExternalReference ExternalReference::address_of_the_hole_nan() {
   return ExternalReference(
       reinterpret_cast<void*>(&double_constants.the_hole_nan));
@@ -1297,6 +1313,8 @@
   function = FUNCTION_ADDR(RegExpMacroAssemblerARM64::CheckStackGuardState);
 #elif V8_TARGET_ARCH_ARM
   function = FUNCTION_ADDR(RegExpMacroAssemblerARM::CheckStackGuardState);
+#elif V8_TARGET_ARCH_PPC
+  function = FUNCTION_ADDR(RegExpMacroAssemblerPPC::CheckStackGuardState);
 #elif V8_TARGET_ARCH_MIPS
   function = FUNCTION_ADDR(RegExpMacroAssemblerMIPS::CheckStackGuardState);
 #elif V8_TARGET_ARCH_MIPS64
@@ -1399,25 +1417,38 @@
 }
 
 
-ExternalReference
-    ExternalReference::debug_restarter_frame_function_pointer_address(
-        Isolate* isolate) {
-  return ExternalReference(
-      isolate->debug()->restarter_frame_function_pointer_address());
+ExternalReference ExternalReference::virtual_handler_register(
+    Isolate* isolate) {
+  return ExternalReference(isolate->virtual_handler_register_address());
 }
 
 
-double power_helper(double x, double y) {
+ExternalReference ExternalReference::virtual_slot_register(Isolate* isolate) {
+  return ExternalReference(isolate->virtual_slot_register_address());
+}
+
+
+ExternalReference ExternalReference::runtime_function_table_address(
+    Isolate* isolate) {
+  return ExternalReference(
+      const_cast<Runtime::Function*>(Runtime::RuntimeFunctionTable(isolate)));
+}
+
+
+double power_helper(Isolate* isolate, double x, double y) {
   int y_int = static_cast<int>(y);
   if (y == y_int) {
     return power_double_int(x, y_int);  // Returns 1 if exponent is 0.
   }
   if (y == 0.5) {
+    lazily_initialize_fast_sqrt(isolate);
     return (std::isinf(x)) ? V8_INFINITY
-                           : fast_sqrt(x + 0.0);  // Convert -0 to +0.
+                           : fast_sqrt(x + 0.0, isolate);  // Convert -0 to +0.
   }
   if (y == -0.5) {
-    return (std::isinf(x)) ? 0 : 1.0 / fast_sqrt(x + 0.0);  // Convert -0 to +0.
+    lazily_initialize_fast_sqrt(isolate);
+    return (std::isinf(x)) ? 0 : 1.0 / fast_sqrt(x + 0.0,
+                                                 isolate);  // Convert -0 to +0.
   }
   return power_double_double(x, y);
 }
@@ -1443,15 +1474,18 @@
 
 
 double power_double_double(double x, double y) {
-#if defined(__MINGW64_VERSION_MAJOR) && \
-    (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)
-  // MinGW64 has a custom implementation for pow.  This handles certain
+#if (defined(__MINGW64_VERSION_MAJOR) &&                              \
+     (!defined(__MINGW64_VERSION_RC) || __MINGW64_VERSION_RC < 1)) || \
+    defined(V8_OS_AIX)
+  // MinGW64 and AIX have a custom implementation for pow.  This handles certain
   // special cases that are different.
-  if ((x == 0.0 || std::isinf(x)) && std::isfinite(y)) {
+  if ((x == 0.0 || std::isinf(x)) && y != 0.0 && std::isfinite(y)) {
     double f;
-    if (std::modf(y, &f) != 0.0) {
-      return ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
-    }
+    double result = ((x == 0.0) ^ (y > 0)) ? V8_INFINITY : 0;
+    /* retain sign if odd integer exponent */
+    return ((std::modf(y, &f) == 0.0) && (static_cast<int64_t>(y) & 1))
+               ? copysign(result, x)
+               : result;
   }
 
   if (x == 2.0) {
@@ -1465,7 +1499,7 @@
   // The checks for special cases can be dropped in ia32 because it has already
   // been done in generated code before bailing out here.
   if (std::isnan(y) || ((x == 1 || x == -1) && std::isinf(y))) {
-    return base::OS::nan_value();
+    return std::numeric_limits<double>::quiet_NaN();
   }
   return std::pow(x, y);
 }
@@ -1512,14 +1546,15 @@
 }
 
 
-ExternalReference ExternalReference::debug_break(Isolate* isolate) {
-  return ExternalReference(Redirect(isolate, FUNCTION_ADDR(Debug_Break)));
+ExternalReference ExternalReference::debug_step_in_enabled_address(
+    Isolate* isolate) {
+  return ExternalReference(isolate->debug()->step_in_enabled_address());
 }
 
 
-ExternalReference ExternalReference::debug_step_in_fp_address(
-    Isolate* isolate) {
-  return ExternalReference(isolate->debug()->step_in_fp_addr());
+ExternalReference ExternalReference::fixed_typed_array_base_data_offset() {
+  return ExternalReference(reinterpret_cast<void*>(
+      FixedTypedArrayBase::kDataOffset - kHeapObjectTag));
 }
 
 
@@ -1578,14 +1613,14 @@
     EnsureSpace ensure_space(assembler_);
     assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
                                 state_.current_statement_position);
+    state_.written_position = state_.current_statement_position;
     state_.written_statement_position = state_.current_statement_position;
     written = true;
   }
 
   // Write the position if it is different from what was written last time and
-  // also different from the written statement position.
-  if (state_.current_position != state_.written_position &&
-      state_.current_position != state_.written_statement_position) {
+  // also different from the statement position that was just written.
+  if (state_.current_position != state_.written_position) {
     EnsureSpace ensure_space(assembler_);
     assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
     state_.written_position = state_.current_position;
@@ -1596,4 +1631,249 @@
   return written;
 }
 
-} }  // namespace v8::internal
+
+ConstantPoolBuilder::ConstantPoolBuilder(int ptr_reach_bits,
+                                         int double_reach_bits) {
+  info_[ConstantPoolEntry::INTPTR].entries.reserve(64);
+  info_[ConstantPoolEntry::INTPTR].regular_reach_bits = ptr_reach_bits;
+  info_[ConstantPoolEntry::DOUBLE].regular_reach_bits = double_reach_bits;
+}
+
+
+ConstantPoolEntry::Access ConstantPoolBuilder::NextAccess(
+    ConstantPoolEntry::Type type) const {
+  const PerTypeEntryInfo& info = info_[type];
+
+  if (info.overflow()) return ConstantPoolEntry::OVERFLOWED;
+
+  int dbl_count = info_[ConstantPoolEntry::DOUBLE].regular_count;
+  int dbl_offset = dbl_count * kDoubleSize;
+  int ptr_count = info_[ConstantPoolEntry::INTPTR].regular_count;
+  int ptr_offset = ptr_count * kPointerSize + dbl_offset;
+
+  if (type == ConstantPoolEntry::DOUBLE) {
+    // Double overflow detection must take into account the reach for both types
+    int ptr_reach_bits = info_[ConstantPoolEntry::INTPTR].regular_reach_bits;
+    if (!is_uintn(dbl_offset, info.regular_reach_bits) ||
+        (ptr_count > 0 &&
+         !is_uintn(ptr_offset + kDoubleSize - kPointerSize, ptr_reach_bits))) {
+      return ConstantPoolEntry::OVERFLOWED;
+    }
+  } else {
+    DCHECK(type == ConstantPoolEntry::INTPTR);
+    if (!is_uintn(ptr_offset, info.regular_reach_bits)) {
+      return ConstantPoolEntry::OVERFLOWED;
+    }
+  }
+
+  return ConstantPoolEntry::REGULAR;
+}
+
+
+ConstantPoolEntry::Access ConstantPoolBuilder::AddEntry(
+    ConstantPoolEntry& entry, ConstantPoolEntry::Type type) {
+  DCHECK(!emitted_label_.is_bound());
+  PerTypeEntryInfo& info = info_[type];
+  const int entry_size = ConstantPoolEntry::size(type);
+  bool merged = false;
+
+  if (entry.sharing_ok()) {
+    // Try to merge entries
+    std::vector<ConstantPoolEntry>::iterator it = info.shared_entries.begin();
+    int end = static_cast<int>(info.shared_entries.size());
+    for (int i = 0; i < end; i++, it++) {
+      if ((entry_size == kPointerSize) ? entry.value() == it->value()
+                                       : entry.value64() == it->value64()) {
+        // Merge with found entry.
+        entry.set_merged_index(i);
+        merged = true;
+        break;
+      }
+    }
+  }
+
+  // By definition, merged entries have regular access.
+  DCHECK(!merged || entry.merged_index() < info.regular_count);
+  ConstantPoolEntry::Access access =
+      (merged ? ConstantPoolEntry::REGULAR : NextAccess(type));
+
+  // Enforce an upper bound on search time by limiting the search to
+  // unique sharable entries which fit in the regular section.
+  if (entry.sharing_ok() && !merged && access == ConstantPoolEntry::REGULAR) {
+    info.shared_entries.push_back(entry);
+  } else {
+    info.entries.push_back(entry);
+  }
+
+  // We're done if we found a match or have already triggered the
+  // overflow state.
+  if (merged || info.overflow()) return access;
+
+  if (access == ConstantPoolEntry::REGULAR) {
+    info.regular_count++;
+  } else {
+    info.overflow_start = static_cast<int>(info.entries.size()) - 1;
+  }
+
+  return access;
+}
+
+
+void ConstantPoolBuilder::EmitSharedEntries(Assembler* assm,
+                                            ConstantPoolEntry::Type type) {
+  PerTypeEntryInfo& info = info_[type];
+  std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
+  const int entry_size = ConstantPoolEntry::size(type);
+  int base = emitted_label_.pos();
+  DCHECK(base > 0);
+  int shared_end = static_cast<int>(shared_entries.size());
+  std::vector<ConstantPoolEntry>::iterator shared_it = shared_entries.begin();
+  for (int i = 0; i < shared_end; i++, shared_it++) {
+    int offset = assm->pc_offset() - base;
+    shared_it->set_offset(offset);  // Save offset for merged entries.
+    if (entry_size == kPointerSize) {
+      assm->dp(shared_it->value());
+    } else {
+      assm->dq(shared_it->value64());
+    }
+    DCHECK(is_uintn(offset, info.regular_reach_bits));
+
+    // Patch load sequence with correct offset.
+    assm->PatchConstantPoolAccessInstruction(shared_it->position(), offset,
+                                             ConstantPoolEntry::REGULAR, type);
+  }
+}
+
+
+void ConstantPoolBuilder::EmitGroup(Assembler* assm,
+                                    ConstantPoolEntry::Access access,
+                                    ConstantPoolEntry::Type type) {
+  PerTypeEntryInfo& info = info_[type];
+  const bool overflow = info.overflow();
+  std::vector<ConstantPoolEntry>& entries = info.entries;
+  std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
+  const int entry_size = ConstantPoolEntry::size(type);
+  int base = emitted_label_.pos();
+  DCHECK(base > 0);
+  int begin;
+  int end;
+
+  if (access == ConstantPoolEntry::REGULAR) {
+    // Emit any shared entries first
+    EmitSharedEntries(assm, type);
+  }
+
+  if (access == ConstantPoolEntry::REGULAR) {
+    begin = 0;
+    end = overflow ? info.overflow_start : static_cast<int>(entries.size());
+  } else {
+    DCHECK(access == ConstantPoolEntry::OVERFLOWED);
+    if (!overflow) return;
+    begin = info.overflow_start;
+    end = static_cast<int>(entries.size());
+  }
+
+  std::vector<ConstantPoolEntry>::iterator it = entries.begin();
+  if (begin > 0) std::advance(it, begin);
+  for (int i = begin; i < end; i++, it++) {
+    // Update constant pool if necessary and get the entry's offset.
+    int offset;
+    ConstantPoolEntry::Access entry_access;
+    if (!it->is_merged()) {
+      // Emit new entry
+      offset = assm->pc_offset() - base;
+      entry_access = access;
+      if (entry_size == kPointerSize) {
+        assm->dp(it->value());
+      } else {
+        assm->dq(it->value64());
+      }
+    } else {
+      // Retrieve offset from shared entry.
+      offset = shared_entries[it->merged_index()].offset();
+      entry_access = ConstantPoolEntry::REGULAR;
+    }
+
+    DCHECK(entry_access == ConstantPoolEntry::OVERFLOWED ||
+           is_uintn(offset, info.regular_reach_bits));
+
+    // Patch load sequence with correct offset.
+    assm->PatchConstantPoolAccessInstruction(it->position(), offset,
+                                             entry_access, type);
+  }
+}
+
+
+// Emit and return position of pool.  Zero implies no constant pool.
+int ConstantPoolBuilder::Emit(Assembler* assm) {
+  bool emitted = emitted_label_.is_bound();
+  bool empty = IsEmpty();
+
+  if (!emitted) {
+    // Mark start of constant pool.  Align if necessary.
+    if (!empty) assm->DataAlign(kDoubleSize);
+    assm->bind(&emitted_label_);
+    if (!empty) {
+      // Emit in groups based on access and type.
+      // Emit doubles first for alignment purposes.
+      EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::DOUBLE);
+      EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::INTPTR);
+      if (info_[ConstantPoolEntry::DOUBLE].overflow()) {
+        assm->DataAlign(kDoubleSize);
+        EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
+                  ConstantPoolEntry::DOUBLE);
+      }
+      if (info_[ConstantPoolEntry::INTPTR].overflow()) {
+        EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
+                  ConstantPoolEntry::INTPTR);
+      }
+    }
+  }
+
+  return !empty ? emitted_label_.pos() : 0;
+}
+
+
+// Platform specific but identical code for all the platforms.
+
+
+void Assembler::RecordDeoptReason(const int reason,
+                                  const SourcePosition position) {
+  if (FLAG_trace_deopt || isolate()->cpu_profiler()->is_profiling()) {
+    EnsureSpace ensure_space(this);
+    int raw_position = position.IsUnknown() ? 0 : position.raw();
+    RecordRelocInfo(RelocInfo::POSITION, raw_position);
+    RecordRelocInfo(RelocInfo::DEOPT_REASON, reason);
+  }
+}
+
+
+void Assembler::RecordComment(const char* msg) {
+  if (FLAG_code_comments) {
+    EnsureSpace ensure_space(this);
+    RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
+  }
+}
+
+
+void Assembler::RecordGeneratorContinuation() {
+  EnsureSpace ensure_space(this);
+  RecordRelocInfo(RelocInfo::GENERATOR_CONTINUATION);
+}
+
+
+void Assembler::RecordDebugBreakSlot(RelocInfo::Mode mode) {
+  EnsureSpace ensure_space(this);
+  DCHECK(RelocInfo::IsDebugBreakSlot(mode));
+  RecordRelocInfo(mode);
+}
+
+
+void Assembler::DataAlign(int m) {
+  DCHECK(m >= 2 && base::bits::IsPowerOfTwo32(m));
+  while ((pc_offset() & (m - 1)) != 0) {
+    db(0);
+  }
+}
+}  // namespace internal
+}  // namespace v8