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/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index 168a196..f120a62 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -36,12 +36,17 @@
#include "src/ia32/assembler-ia32.h"
+#include <cstring>
+
+#if V8_TARGET_ARCH_IA32
+
+#if V8_LIBC_MSVCRT
+#include <intrin.h> // _xgetbv()
+#endif
#if V8_OS_MACOSX
#include <sys/sysctl.h>
#endif
-#if V8_TARGET_ARCH_IA32
-
#include "src/base/bits.h"
#include "src/base/cpu.h"
#include "src/disassembler.h"
@@ -56,22 +61,44 @@
namespace {
-bool EnableAVX() {
+#if !V8_LIBC_MSVCRT
+
+V8_INLINE uint64_t _xgetbv(unsigned int xcr) {
+ unsigned eax, edx;
+ // Check xgetbv; this uses a .byte sequence instead of the instruction
+ // directly because older assemblers do not include support for xgetbv and
+ // there is no easy way to conditionally compile based on the assembler
+ // used.
+ __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr));
+ return static_cast<uint64_t>(eax) | (static_cast<uint64_t>(edx) << 32);
+}
+
+#define _XCR_XFEATURE_ENABLED_MASK 0
+
+#endif // !V8_LIBC_MSVCRT
+
+
+bool OSHasAVXSupport() {
#if V8_OS_MACOSX
- // Mac OS X 10.9 has a bug where AVX transitions were indeed being caused by
- // ISRs, so we detect Mac OS X 10.9 here and disable AVX in that case.
+ // Mac OS X up to 10.9 has a bug where AVX transitions were indeed being
+ // caused by ISRs, so we detect that here and disable AVX in that case.
char buffer[128];
size_t buffer_size = arraysize(buffer);
- int ctl_name[] = { CTL_KERN , KERN_OSRELEASE };
+ int ctl_name[] = {CTL_KERN, KERN_OSRELEASE};
if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
}
// The buffer now contains a string of the form XX.YY.ZZ, where
- // XX is the major kernel version component. 13.x.x (Mavericks) is
- // affected by this bug, so disable AVX there.
- if (memcmp(buffer, "13.", 3) == 0) return false;
+ // XX is the major kernel version component.
+ char* period_pos = strchr(buffer, '.');
+ DCHECK_NOT_NULL(period_pos);
+ *period_pos = '\0';
+ long kernel_version_major = strtol(buffer, nullptr, 10); // NOLINT
+ if (kernel_version_major <= 13) return false;
#endif // V8_OS_MACOSX
- return FLAG_enable_avx;
+ // Check whether OS claims to support AVX.
+ uint64_t feature_mask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+ return (feature_mask & 0x6) == 0x6;
}
} // namespace
@@ -87,16 +114,36 @@
if (cpu.has_sse41() && FLAG_enable_sse4_1) supported_ |= 1u << SSE4_1;
if (cpu.has_sse3() && FLAG_enable_sse3) supported_ |= 1u << SSE3;
- if (cpu.has_avx() && EnableAVX()) supported_ |= 1u << AVX;
- if (cpu.has_fma3() && FLAG_enable_fma3) supported_ |= 1u << FMA3;
+ if (cpu.has_avx() && FLAG_enable_avx && cpu.has_osxsave() &&
+ OSHasAVXSupport()) {
+ supported_ |= 1u << AVX;
+ }
+ if (cpu.has_fma3() && FLAG_enable_fma3 && cpu.has_osxsave() &&
+ OSHasAVXSupport()) {
+ supported_ |= 1u << FMA3;
+ }
+ if (cpu.has_bmi1() && FLAG_enable_bmi1) supported_ |= 1u << BMI1;
+ if (cpu.has_bmi2() && FLAG_enable_bmi2) supported_ |= 1u << BMI2;
+ if (cpu.has_lzcnt() && FLAG_enable_lzcnt) supported_ |= 1u << LZCNT;
+ if (cpu.has_popcnt() && FLAG_enable_popcnt) supported_ |= 1u << POPCNT;
+ if (strcmp(FLAG_mcpu, "auto") == 0) {
+ if (cpu.is_atom()) supported_ |= 1u << ATOM;
+ } else if (strcmp(FLAG_mcpu, "atom") == 0) {
+ supported_ |= 1u << ATOM;
+ }
}
void CpuFeatures::PrintTarget() { }
void CpuFeatures::PrintFeatures() {
- printf("SSE3=%d SSE4_1=%d AVX=%d FMA3=%d\n", CpuFeatures::IsSupported(SSE3),
- CpuFeatures::IsSupported(SSE4_1), CpuFeatures::IsSupported(AVX),
- CpuFeatures::IsSupported(FMA3));
+ printf(
+ "SSE3=%d SSE4_1=%d AVX=%d FMA3=%d BMI1=%d BMI2=%d LZCNT=%d POPCNT=%d "
+ "ATOM=%d\n",
+ CpuFeatures::IsSupported(SSE3), CpuFeatures::IsSupported(SSE4_1),
+ CpuFeatures::IsSupported(AVX), CpuFeatures::IsSupported(FMA3),
+ CpuFeatures::IsSupported(BMI1), CpuFeatures::IsSupported(BMI2),
+ CpuFeatures::IsSupported(LZCNT), CpuFeatures::IsSupported(POPCNT),
+ CpuFeatures::IsSupported(ATOM));
}
@@ -121,9 +168,9 @@
const int RelocInfo::kApplyMask =
- RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
- 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE |
- 1 << RelocInfo::DEBUG_BREAK_SLOT | 1 << RelocInfo::CODE_AGE_SEQUENCE;
+ RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
+ 1 << RelocInfo::INTERNAL_REFERENCE | 1 << RelocInfo::CODE_AGE_SEQUENCE |
+ RelocInfo::kDebugBreakSlotMask;
bool RelocInfo::IsCodedSpecially() {
@@ -140,48 +187,6 @@
}
-void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
- // Patch the code at the current address with the supplied instructions.
- for (int i = 0; i < instruction_count; i++) {
- *(pc_ + i) = *(instructions + i);
- }
-
- // Indicate that code has changed.
- CpuFeatures::FlushICache(pc_, instruction_count);
-}
-
-
-// Patch the code at the current PC with a call to the target address.
-// Additional guard int3 instructions can be added if required.
-void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
- // Call instruction takes up 5 bytes and int3 takes up one byte.
- static const int kCallCodeSize = 5;
- int code_size = kCallCodeSize + guard_bytes;
-
- // Create a code patcher.
- CodePatcher patcher(pc_, code_size);
-
- // Add a label for checking the size of the code used for returning.
-#ifdef DEBUG
- Label check_codesize;
- patcher.masm()->bind(&check_codesize);
-#endif
-
- // Patch the code.
- patcher.masm()->call(target, RelocInfo::NONE32);
-
- // Check that the size of the code generated is as expected.
- DCHECK_EQ(kCallCodeSize,
- patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
-
- // Add the requested number of int3 instructions after the call.
- DCHECK_GE(guard_bytes, 0);
- for (int i = 0; i < guard_bytes; i++) {
- patcher.masm()->int3();
- }
-}
-
-
// -----------------------------------------------------------------------------
// Implementation of Operand
@@ -294,6 +299,7 @@
void Assembler::GetCode(CodeDesc* desc) {
// Finalize code (at this point overflow() may be true, but the gap ensures
// that we are still not overlapping instructions and relocation info).
+ reloc_info_writer.Finish();
DCHECK(pc_ <= reloc_info_writer.pos()); // No overlap.
// Set up code descriptor.
desc->buffer = buffer_;
@@ -301,6 +307,7 @@
desc->instr_size = pc_offset();
desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos();
desc->origin = this;
+ desc->constant_pool_size = 0;
}
@@ -1270,6 +1277,14 @@
}
+void Assembler::bsf(Register dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0x0F);
+ EMIT(0xBC);
+ emit_operand(dst, src);
+}
+
+
void Assembler::hlt() {
EnsureSpace ensure_space(this);
EMIT(0xF4);
@@ -1301,6 +1316,13 @@
}
+void Assembler::ud2() {
+ EnsureSpace ensure_space(this);
+ EMIT(0x0F);
+ EMIT(0x0B);
+}
+
+
// Labels refer to positions in the (to be) generated code.
// There are bound, linked, and unused labels.
//
@@ -1339,7 +1361,10 @@
while (L->is_linked()) {
Displacement disp = disp_at(L);
int fixup_pos = L->pos();
- if (disp.type() == Displacement::CODE_RELATIVE) {
+ if (disp.type() == Displacement::CODE_ABSOLUTE) {
+ long_at_put(fixup_pos, reinterpret_cast<int>(buffer_ + pos));
+ internal_reference_positions_.push_back(fixup_pos);
+ } else if (disp.type() == Displacement::CODE_RELATIVE) {
// Relative to Code* heap object pointer.
long_at_put(fixup_pos, pos + Code::kHeaderSize - kHeapObjectTag);
} else {
@@ -1540,12 +1565,12 @@
}
-void Assembler::j(Condition cc, Handle<Code> code) {
+void Assembler::j(Condition cc, Handle<Code> code, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
// 0000 1111 1000 tttn #32-bit disp
EMIT(0x0F);
EMIT(0x80 | cc);
- emit(code, RelocInfo::CODE_TARGET);
+ emit(code, rmode);
}
@@ -2139,6 +2164,19 @@
}
+void Assembler::roundss(XMMRegister dst, XMMRegister src, RoundingMode mode) {
+ DCHECK(IsEnabled(SSE4_1));
+ EnsureSpace ensure_space(this);
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x3A);
+ EMIT(0x0A);
+ emit_sse_operand(dst, src);
+ // Mask precision exeption.
+ EMIT(static_cast<byte>(mode) | 0x8);
+}
+
+
void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) {
DCHECK(IsEnabled(SSE4_1));
EnsureSpace ensure_space(this);
@@ -2178,6 +2216,42 @@
}
+void Assembler::punpckldq(XMMRegister dst, XMMRegister src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x62);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::punpckhdq(XMMRegister dst, XMMRegister src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x6A);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::maxsd(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0xF2);
+ EMIT(0x0F);
+ EMIT(0x5F);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::minsd(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0xF2);
+ EMIT(0x0F);
+ EMIT(0x5D);
+ emit_sse_operand(dst, src);
+}
+
+
void Assembler::cmpltsd(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
EMIT(0xF2);
@@ -2242,26 +2316,6 @@
}
-void Assembler::movntdqa(XMMRegister dst, const Operand& src) {
- DCHECK(IsEnabled(SSE4_1));
- EnsureSpace ensure_space(this);
- EMIT(0x66);
- EMIT(0x0F);
- EMIT(0x38);
- EMIT(0x2A);
- emit_sse_operand(dst, src);
-}
-
-
-void Assembler::movntdq(const Operand& dst, XMMRegister src) {
- EnsureSpace ensure_space(this);
- EMIT(0x66);
- EMIT(0x0F);
- EMIT(0xE7);
- emit_sse_operand(src, dst);
-}
-
-
void Assembler::prefetch(const Operand& src, int level) {
DCHECK(is_uint2(level));
EnsureSpace ensure_space(this);
@@ -2506,6 +2560,15 @@
}
+void Assembler::sqrtss(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0xF3);
+ EMIT(0x0F);
+ EMIT(0x51);
+ emit_sse_operand(dst, src);
+}
+
+
void Assembler::ucomiss(XMMRegister dst, const Operand& src) {
EnsureSpace ensure_space(this);
EMIT(0x0f);
@@ -2514,6 +2577,24 @@
}
+void Assembler::maxss(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0xF3);
+ EMIT(0x0F);
+ EMIT(0x5F);
+ emit_sse_operand(dst, src);
+}
+
+
+void Assembler::minss(XMMRegister dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ EMIT(0xF3);
+ EMIT(0x0F);
+ EMIT(0x5D);
+ emit_sse_operand(dst, src);
+}
+
+
// AVX instructions
void Assembler::vfmasd(byte op, XMMRegister dst, XMMRegister src1,
const Operand& src2) {
@@ -2545,6 +2626,97 @@
}
+void Assembler::vss(byte op, XMMRegister dst, XMMRegister src1,
+ const Operand& src2) {
+ DCHECK(IsEnabled(AVX));
+ EnsureSpace ensure_space(this);
+ emit_vex_prefix(src1, kLIG, kF3, k0F, kWIG);
+ EMIT(op);
+ emit_sse_operand(dst, src2);
+}
+
+
+void Assembler::vps(byte op, XMMRegister dst, XMMRegister src1,
+ const Operand& src2) {
+ DCHECK(IsEnabled(AVX));
+ EnsureSpace ensure_space(this);
+ emit_vex_prefix(src1, kL128, kNone, k0F, kWIG);
+ EMIT(op);
+ emit_sse_operand(dst, src2);
+}
+
+
+void Assembler::vpd(byte op, XMMRegister dst, XMMRegister src1,
+ const Operand& src2) {
+ DCHECK(IsEnabled(AVX));
+ EnsureSpace ensure_space(this);
+ emit_vex_prefix(src1, kL128, k66, k0F, kWIG);
+ EMIT(op);
+ emit_sse_operand(dst, src2);
+}
+
+
+void Assembler::bmi1(byte op, Register reg, Register vreg, const Operand& rm) {
+ DCHECK(IsEnabled(BMI1));
+ EnsureSpace ensure_space(this);
+ emit_vex_prefix(vreg, kLZ, kNone, k0F38, kW0);
+ EMIT(op);
+ emit_operand(reg, rm);
+}
+
+
+void Assembler::tzcnt(Register dst, const Operand& src) {
+ DCHECK(IsEnabled(BMI1));
+ EnsureSpace ensure_space(this);
+ EMIT(0xF3);
+ EMIT(0x0F);
+ EMIT(0xBC);
+ emit_operand(dst, src);
+}
+
+
+void Assembler::lzcnt(Register dst, const Operand& src) {
+ DCHECK(IsEnabled(LZCNT));
+ EnsureSpace ensure_space(this);
+ EMIT(0xF3);
+ EMIT(0x0F);
+ EMIT(0xBD);
+ emit_operand(dst, src);
+}
+
+
+void Assembler::popcnt(Register dst, const Operand& src) {
+ DCHECK(IsEnabled(POPCNT));
+ EnsureSpace ensure_space(this);
+ EMIT(0xF3);
+ EMIT(0x0F);
+ EMIT(0xB8);
+ emit_operand(dst, src);
+}
+
+
+void Assembler::bmi2(SIMDPrefix pp, byte op, Register reg, Register vreg,
+ const Operand& rm) {
+ DCHECK(IsEnabled(BMI2));
+ EnsureSpace ensure_space(this);
+ emit_vex_prefix(vreg, kLZ, pp, k0F38, kW0);
+ EMIT(op);
+ emit_operand(reg, rm);
+}
+
+
+void Assembler::rorx(Register dst, const Operand& src, byte imm8) {
+ DCHECK(IsEnabled(BMI2));
+ DCHECK(is_uint8(imm8));
+ Register vreg = {0}; // VEX.vvvv unused
+ EnsureSpace ensure_space(this);
+ emit_vex_prefix(vreg, kLZ, kF2, k0F3A, kW0);
+ EMIT(0xF0);
+ emit_operand(dst, src);
+ EMIT(imm8);
+}
+
+
void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
Register ireg = { reg.code() };
emit_operand(ireg, adr);
@@ -2570,7 +2742,8 @@
LeadingOpcode mm, VexW w) {
if (mm != k0F || w != kW0) {
EMIT(0xc4);
- EMIT(0xc0 | mm);
+ // Change RXB from "110" to "111" to align with gdb disassembler.
+ EMIT(0xe0 | mm);
EMIT(w | ((~vreg.code() & 0xf) << 3) | l | pp);
} else {
EMIT(0xc5);
@@ -2579,25 +2752,10 @@
}
-void Assembler::RecordJSReturn() {
- positions_recorder()->WriteRecordedPositions();
- EnsureSpace ensure_space(this);
- RecordRelocInfo(RelocInfo::JS_RETURN);
-}
-
-
-void Assembler::RecordDebugBreakSlot() {
- positions_recorder()->WriteRecordedPositions();
- EnsureSpace ensure_space(this);
- RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
-}
-
-
-void Assembler::RecordComment(const char* msg, bool force) {
- if (FLAG_code_comments || force) {
- EnsureSpace ensure_space(this);
- RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
- }
+void Assembler::emit_vex_prefix(Register vreg, VectorLength l, SIMDPrefix pp,
+ LeadingOpcode mm, VexW w) {
+ XMMRegister ivreg = {vreg.code()};
+ emit_vex_prefix(ivreg, l, pp, mm, w);
}
@@ -2618,6 +2776,7 @@
// Set up new buffer.
desc.buffer = NewArray<byte>(desc.buffer_size);
+ desc.origin = this;
desc.instr_size = pc_offset();
desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos());
@@ -2642,15 +2801,10 @@
reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
reloc_info_writer.last_pc() + pc_delta);
- // Relocate runtime entries.
- for (RelocIterator it(desc); !it.done(); it.next()) {
- RelocInfo::Mode rmode = it.rinfo()->rmode();
- if (rmode == RelocInfo::INTERNAL_REFERENCE) {
- int32_t* p = reinterpret_cast<int32_t*>(it.rinfo()->pc());
- if (*p != 0) { // 0 means uninitialized.
- *p += pc_delta;
- }
- }
+ // Relocate internal references.
+ for (auto pos : internal_reference_positions_) {
+ int32_t* p = reinterpret_cast<int32_t*>(buffer_ + pos);
+ *p += pc_delta;
}
DCHECK(!buffer_overflow());
@@ -2700,7 +2854,21 @@
if (length >= sizeof(int32_t) && !RelocInfo::IsNone(adr.rmode_)) {
pc_ -= sizeof(int32_t); // pc_ must be *at* disp32
RecordRelocInfo(adr.rmode_);
- pc_ += sizeof(int32_t);
+ if (adr.rmode_ == RelocInfo::INTERNAL_REFERENCE) { // Fixup for labels
+ emit_label(*reinterpret_cast<Label**>(pc_));
+ } else {
+ pc_ += sizeof(int32_t);
+ }
+ }
+}
+
+
+void Assembler::emit_label(Label* label) {
+ if (label->is_bound()) {
+ internal_reference_positions_.push_back(pc_offset());
+ emit(reinterpret_cast<uint32_t>(buffer_ + label->pos()));
+ } else {
+ emit_disp(label, Displacement::CODE_ABSOLUTE);
}
}
@@ -2725,6 +2893,19 @@
}
+void Assembler::dq(uint64_t data) {
+ EnsureSpace ensure_space(this);
+ emit_q(data);
+}
+
+
+void Assembler::dd(Label* label) {
+ EnsureSpace ensure_space(this);
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
+ emit_label(label);
+}
+
+
void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
DCHECK(!RelocInfo::IsNone(rmode));
// Don't record external references unless the heap will be serialized.
@@ -2732,25 +2913,11 @@
!serializer_enabled() && !emit_debug_code()) {
return;
}
- RelocInfo rinfo(pc_, rmode, data, NULL);
+ RelocInfo rinfo(isolate(), pc_, rmode, data, NULL);
reloc_info_writer.Write(&rinfo);
}
-Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) {
- // No out-of-line constant pool support.
- DCHECK(!FLAG_enable_ool_constant_pool);
- return isolate->factory()->empty_constant_pool_array();
-}
-
-
-void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) {
- // No out-of-line constant pool support.
- DCHECK(!FLAG_enable_ool_constant_pool);
- return;
-}
-
-
#ifdef GENERATED_CODE_COVERAGE
static FILE* coverage_log = NULL;
@@ -2776,6 +2943,7 @@
#endif
-} } // namespace v8::internal
+} // namespace internal
+} // namespace v8
#endif // V8_TARGET_ARCH_IA32