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