summaryrefslogtreecommitdiff
path: root/deps/v8/src/diagnostics
diff options
context:
space:
mode:
authorMatheus Marchini <mmarchini@netflix.com>2020-03-05 10:49:19 -0800
committerMatheus Marchini <mmarchini@netflix.com>2020-03-18 16:23:22 -0700
commit2883c855e0105b51e5c8020d21458af109ffe3d4 (patch)
tree26777aad0a398e9f7755c8b65ac76827fe352a81 /deps/v8/src/diagnostics
parent5f0af2af2a67216e00fe07ccda11e889d14abfcd (diff)
downloadnode-new-2883c855e0105b51e5c8020d21458af109ffe3d4.tar.gz
deps: update V8 to 8.1.307.20
PR-URL: https://github.com/nodejs/node/pull/32116 Reviewed-By: Michaƫl Zasso <targos@protonmail.com> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Diffstat (limited to 'deps/v8/src/diagnostics')
-rw-r--r--deps/v8/src/diagnostics/arm/disasm-arm.cc90
-rw-r--r--deps/v8/src/diagnostics/arm64/disasm-arm64.cc2
-rw-r--r--deps/v8/src/diagnostics/disassembler.cc16
-rw-r--r--deps/v8/src/diagnostics/eh-frame.cc37
-rw-r--r--deps/v8/src/diagnostics/eh-frame.h11
-rw-r--r--deps/v8/src/diagnostics/gdb-jit.cc12
-rw-r--r--deps/v8/src/diagnostics/ia32/disasm-ia32.cc28
-rw-r--r--deps/v8/src/diagnostics/objects-debug.cc328
-rw-r--r--deps/v8/src/diagnostics/objects-printer.cc379
-rw-r--r--deps/v8/src/diagnostics/perf-jit.cc83
-rw-r--r--deps/v8/src/diagnostics/perf-jit.h54
-rw-r--r--deps/v8/src/diagnostics/ppc/eh-frame-ppc.cc57
-rw-r--r--deps/v8/src/diagnostics/s390/disasm-s390.cc7
-rw-r--r--deps/v8/src/diagnostics/s390/eh-frame-s390.cc65
-rw-r--r--deps/v8/src/diagnostics/unwinder.cc192
-rw-r--r--deps/v8/src/diagnostics/unwinding-info-win64.cc194
-rw-r--r--deps/v8/src/diagnostics/unwinding-info-win64.h29
-rw-r--r--deps/v8/src/diagnostics/x64/disasm-x64.cc213
18 files changed, 1021 insertions, 776 deletions
diff --git a/deps/v8/src/diagnostics/arm/disasm-arm.cc b/deps/v8/src/diagnostics/arm/disasm-arm.cc
index 891ab0662e..e17936d8d2 100644
--- a/deps/v8/src/diagnostics/arm/disasm-arm.cc
+++ b/deps/v8/src/diagnostics/arm/disasm-arm.cc
@@ -1861,6 +1861,11 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"vorr q%d, q%d, q%d", Vd, Vn, Vm);
}
+ } else if (instr->Bits(21, 20) == 1 && instr->Bit(6) == 1 &&
+ instr->Bit(4) == 1) {
+ // vbic Qd, Qn, Qm
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+ "vbic q%d, q%d, q%d", Vd, Vn, Vm);
} else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
instr->Bit(4) == 1) {
// vand Qd, Qm, Qn.
@@ -1991,8 +1996,27 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
break;
}
case 5:
- if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
- (instr->Bit(4) == 1)) {
+ if (instr->Bit(23) == 1 && instr->Bits(21, 19) == 0 &&
+ instr->Bit(7) == 0 && instr->Bit(4) == 1) {
+ // One register and a modified immediate value, see ARM DDI 0406C.d
+ // A7.4.6.
+ byte cmode = instr->Bits(11, 8);
+ switch (cmode) {
+ case 0: {
+ int vd = instr->VFPDRegValue(kSimd128Precision);
+ int a = instr->Bit(24);
+ int bcd = instr->Bits(18, 16);
+ int efgh = instr->Bits(3, 0);
+ int imm64 = a << 7 | bcd << 4 | efgh;
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+ "vmov.i32 q%d, %d", vd, imm64);
+ break;
+ }
+ default:
+ Unknown(instr);
+ }
+ } else if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
+ (instr->Bit(4) == 1)) {
// vmovl signed
if ((instr->VdValue() & 1) != 0) Unknown(instr);
int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
@@ -2009,19 +2033,23 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "vext.8 q%d, q%d, q%d, #%d",
Vd, Vn, Vm, imm4);
- } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
+ } else if (instr->Bits(11, 8) == 5 && instr->Bit(4) == 1) {
// vshl.i<size> Qd, Qm, shift
- int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
- int shift = instr->Bits(21, 16) - size;
+ int imm7 = instr->Bits(21, 16);
+ if (instr->Bit(7) != 0) imm7 += 64;
+ int size = base::bits::RoundDownToPowerOfTwo32(imm7);
+ int shift = imm7 - size;
int Vd = instr->VFPDRegValue(kSimd128Precision);
int Vm = instr->VFPMRegValue(kSimd128Precision);
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "vshl.i%d q%d, q%d, #%d",
size, Vd, Vm, shift);
- } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
+ } else if (instr->Bits(11, 8) == 0 && instr->Bit(4) == 1) {
// vshr.s<size> Qd, Qm, shift
- int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
- int shift = 2 * size - instr->Bits(21, 16);
+ int imm7 = instr->Bits(21, 16);
+ if (instr->Bit(7) != 0) imm7 += 64;
+ int size = base::bits::RoundDownToPowerOfTwo32(imm7);
+ int shift = 2 * size - imm7;
int Vd = instr->VFPDRegValue(kSimd128Precision);
int Vm = instr->VFPMRegValue(kSimd128Precision);
out_buffer_pos_ +=
@@ -2070,6 +2098,16 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"veor q%d, q%d, q%d", Vd, Vn, Vm);
}
+ } else if (instr->Bit(4) == 0) {
+ if (instr->Bit(6) == 1) {
+ // vrhadd.u<size> Qd, Qm, Qn.
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_,
+ "vrhadd.u%d q%d, q%d, q%d", size, Vd, Vn, Vm);
+ } else {
+ // vrhadd.u<size> Dd, Dm, Dn.
+ Unknown(instr);
+ }
} else {
Unknown(instr);
}
@@ -2216,13 +2254,15 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
PrintDRegister(Vm);
} else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 8) == 0x2 &&
instr->Bits(7, 6) != 0) {
- // vqmovn.<type><size> Dd, Qm.
+ // vqmov{u}n.<type><size> Dd, Qm.
int Vd = instr->VFPDRegValue(kDoublePrecision);
int Vm = instr->VFPMRegValue(kSimd128Precision);
- char type = instr->Bit(6) != 0 ? 'u' : 's';
+ int op = instr->Bits(7, 6);
+ const char* name = op == 0b01 ? "vqmovun" : "vqmovn";
+ char type = op == 0b11 ? 'u' : 's';
int size = 2 * kBitsPerByte * (1 << instr->Bits(19, 18));
out_buffer_pos_ +=
- SNPrintF(out_buffer_ + out_buffer_pos_, "vqmovn.%c%i d%d, q%d",
+ SNPrintF(out_buffer_ + out_buffer_pos_, "%s.%c%i d%d, q%d", name,
type, size, Vd, Vm);
} else {
int Vd, Vm;
@@ -2322,11 +2362,13 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
Unknown(instr);
}
}
- } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1 &&
+ } else if (instr->Bits(11, 8) == 0 && instr->Bit(4) == 1 &&
instr->Bit(6) == 1) {
// vshr.u<size> Qd, Qm, shift
- int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
- int shift = 2 * size - instr->Bits(21, 16);
+ int imm7 = instr->Bits(21, 16);
+ if (instr->Bit(7) != 0) imm7 += 64;
+ int size = base::bits::RoundDownToPowerOfTwo32(imm7);
+ int shift = 2 * size - imm7;
int Vd = instr->VFPDRegValue(kSimd128Precision);
int Vm = instr->VFPMRegValue(kSimd128Precision);
out_buffer_pos_ +=
@@ -2353,6 +2395,26 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "vs%ci.%d d%d, d%d, #%d",
direction, size, Vd, Vm, shift);
+ } else if (instr->Bits(11, 8) == 0x8 && instr->Bit(6) == 0 &&
+ instr->Bit(4) == 0) {
+ // vmlal.u<size> <Qd>, <Dn>, <Dm>
+ int Vd = instr->VFPDRegValue(kSimd128Precision);
+ int Vn = instr->VFPNRegValue(kDoublePrecision);
+ int Vm = instr->VFPMRegValue(kDoublePrecision);
+ int size = 8 << instr->Bits(21, 20);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "vmlal.u%d q%d, d%d, d%d",
+ size, Vd, Vn, Vm);
+ } else if (instr->Bits(11, 8) == 0xC && instr->Bit(6) == 0 &&
+ instr->Bit(4) == 0) {
+ // vmull.u<size> <Qd>, <Dn>, <Dm>
+ int Vd = instr->VFPDRegValue(kSimd128Precision);
+ int Vn = instr->VFPNRegValue(kDoublePrecision);
+ int Vm = instr->VFPMRegValue(kDoublePrecision);
+ int size = 8 << instr->Bits(21, 20);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "vmull.u%d q%d, d%d, d%d",
+ size, Vd, Vn, Vm);
} else {
Unknown(instr);
}
diff --git a/deps/v8/src/diagnostics/arm64/disasm-arm64.cc b/deps/v8/src/diagnostics/arm64/disasm-arm64.cc
index db14689ad1..5a87f73529 100644
--- a/deps/v8/src/diagnostics/arm64/disasm-arm64.cc
+++ b/deps/v8/src/diagnostics/arm64/disasm-arm64.cc
@@ -3563,7 +3563,7 @@ void DisassemblingDecoder::ProcessOutput(Instruction* /*instr*/) {
}
void DisassemblingDecoder::AppendRegisterNameToOutput(const CPURegister& reg) {
- DCHECK(reg.IsValid());
+ DCHECK(reg.is_valid());
char reg_char;
if (reg.IsRegister()) {
diff --git a/deps/v8/src/diagnostics/disassembler.cc b/deps/v8/src/diagnostics/disassembler.cc
index 8307ef3ff4..785c535e0a 100644
--- a/deps/v8/src/diagnostics/disassembler.cc
+++ b/deps/v8/src/diagnostics/disassembler.cc
@@ -8,6 +8,7 @@
#include <unordered_map>
#include <vector>
+#include "src/base/memory.h"
#include "src/codegen/assembler-inl.h"
#include "src/codegen/code-comments.h"
#include "src/codegen/code-reference.h"
@@ -291,23 +292,26 @@ static int DecodeIt(Isolate* isolate, ExternalReferenceEncoder* ref_encoder,
// First decode instruction so that we know its length.
byte* prev_pc = pc;
if (constants > 0) {
- SNPrintF(decode_buffer, "%08x constant",
- *reinterpret_cast<int32_t*>(pc));
+ SNPrintF(
+ decode_buffer, "%08x constant",
+ base::ReadUnalignedValue<int32_t>(reinterpret_cast<Address>(pc)));
constants--;
pc += 4;
} else {
int num_const = d.ConstantPoolSizeAt(pc);
if (num_const >= 0) {
- SNPrintF(decode_buffer,
- "%08x constant pool begin (num_const = %d)",
- *reinterpret_cast<int32_t*>(pc), num_const);
+ SNPrintF(
+ decode_buffer, "%08x constant pool begin (num_const = %d)",
+ base::ReadUnalignedValue<int32_t>(reinterpret_cast<Address>(pc)),
+ num_const);
constants = num_const;
pc += 4;
} else if (it != nullptr && !it->done() &&
it->rinfo()->pc() == reinterpret_cast<Address>(pc) &&
it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
// raw pointer embedded in code stream, e.g., jump table
- byte* ptr = *reinterpret_cast<byte**>(pc);
+ byte* ptr =
+ base::ReadUnalignedValue<byte*>(reinterpret_cast<Address>(pc));
SNPrintF(decode_buffer, "%08" V8PRIxPTR " jump table entry %4zu",
reinterpret_cast<intptr_t>(ptr),
static_cast<size_t>(ptr - begin));
diff --git a/deps/v8/src/diagnostics/eh-frame.cc b/deps/v8/src/diagnostics/eh-frame.cc
index 45d693a476..35cb529f09 100644
--- a/deps/v8/src/diagnostics/eh-frame.cc
+++ b/deps/v8/src/diagnostics/eh-frame.cc
@@ -9,8 +9,9 @@
#include "src/codegen/code-desc.h"
-#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM) && \
- !defined(V8_TARGET_ARCH_ARM64)
+#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM) && \
+ !defined(V8_TARGET_ARCH_ARM64) && !defined(V8_TARGET_ARCH_S390X) && \
+ !defined(V8_TARGET_ARCH_PPC64)
// Placeholders for unsupported architectures.
@@ -303,36 +304,48 @@ void EhFrameWriter::SetBaseAddressRegisterAndOffset(Register base_register,
base_register_ = base_register;
}
-void EhFrameWriter::RecordRegisterSavedToStack(int register_code, int offset) {
+void EhFrameWriter::RecordRegisterSavedToStack(int dwarf_register_code,
+ int offset) {
DCHECK_EQ(writer_state_, InternalState::kInitialized);
DCHECK_EQ(offset % EhFrameConstants::kDataAlignmentFactor, 0);
int factored_offset = offset / EhFrameConstants::kDataAlignmentFactor;
if (factored_offset >= 0) {
- DCHECK_LE(register_code, EhFrameConstants::kSavedRegisterMask);
+ DCHECK_LE(dwarf_register_code, EhFrameConstants::kSavedRegisterMask);
WriteByte((EhFrameConstants::kSavedRegisterTag
<< EhFrameConstants::kSavedRegisterMaskSize) |
- (register_code & EhFrameConstants::kSavedRegisterMask));
+ (dwarf_register_code & EhFrameConstants::kSavedRegisterMask));
WriteULeb128(factored_offset);
} else {
WriteOpcode(EhFrameConstants::DwarfOpcodes::kOffsetExtendedSf);
- WriteULeb128(register_code);
+ WriteULeb128(dwarf_register_code);
WriteSLeb128(factored_offset);
}
}
void EhFrameWriter::RecordRegisterNotModified(Register name) {
+ RecordRegisterNotModified(RegisterToDwarfCode(name));
+}
+
+void EhFrameWriter::RecordRegisterNotModified(int dwarf_register_code) {
DCHECK_EQ(writer_state_, InternalState::kInitialized);
WriteOpcode(EhFrameConstants::DwarfOpcodes::kSameValue);
- WriteULeb128(RegisterToDwarfCode(name));
+ WriteULeb128(dwarf_register_code);
}
void EhFrameWriter::RecordRegisterFollowsInitialRule(Register name) {
+ RecordRegisterFollowsInitialRule(RegisterToDwarfCode(name));
+}
+
+void EhFrameWriter::RecordRegisterFollowsInitialRule(int dwarf_register_code) {
DCHECK_EQ(writer_state_, InternalState::kInitialized);
- int code = RegisterToDwarfCode(name);
- DCHECK_LE(code, EhFrameConstants::kFollowInitialRuleMask);
- WriteByte((EhFrameConstants::kFollowInitialRuleTag
- << EhFrameConstants::kFollowInitialRuleMaskSize) |
- (code & EhFrameConstants::kFollowInitialRuleMask));
+ if (dwarf_register_code <= EhFrameConstants::kFollowInitialRuleMask) {
+ WriteByte((EhFrameConstants::kFollowInitialRuleTag
+ << EhFrameConstants::kFollowInitialRuleMaskSize) |
+ (dwarf_register_code & EhFrameConstants::kFollowInitialRuleMask));
+ } else {
+ WriteOpcode(EhFrameConstants::DwarfOpcodes::kRestoreExtended);
+ WriteULeb128(dwarf_register_code);
+ }
}
void EhFrameWriter::Finish(int code_size) {
diff --git a/deps/v8/src/diagnostics/eh-frame.h b/deps/v8/src/diagnostics/eh-frame.h
index a9d76a2743..17ef8c0ad5 100644
--- a/deps/v8/src/diagnostics/eh-frame.h
+++ b/deps/v8/src/diagnostics/eh-frame.h
@@ -24,6 +24,7 @@ class V8_EXPORT_PRIVATE EhFrameConstants final
kAdvanceLoc1 = 0x02,
kAdvanceLoc2 = 0x03,
kAdvanceLoc4 = 0x04,
+ kRestoreExtended = 0x06,
kSameValue = 0x08,
kDefCfa = 0x0c,
kDefCfaRegister = 0x0d,
@@ -102,11 +103,17 @@ class V8_EXPORT_PRIVATE EhFrameWriter {
RecordRegisterSavedToStack(RegisterToDwarfCode(name), offset);
}
+ // Directly accepts a DWARF register code, needed for
+ // handling pseudo-registers on some platforms.
+ void RecordRegisterSavedToStack(int dwarf_register_code, int offset);
+
// The register has not been modified from the previous frame.
void RecordRegisterNotModified(Register name);
+ void RecordRegisterNotModified(int dwarf_register_code);
// The register follows the rule defined in the CIE.
void RecordRegisterFollowsInitialRule(Register name);
+ void RecordRegisterFollowsInitialRule(int dwarf_register_code);
void Finish(int code_size);
@@ -169,10 +176,6 @@ class V8_EXPORT_PRIVATE EhFrameWriter {
// Write nops until the size reaches a multiple of 8 bytes.
void WritePaddingToAlignedSize(int unpadded_size);
- // Internal version that directly accepts a DWARF register code, needed for
- // handling pseudo-registers on some platforms.
- void RecordRegisterSavedToStack(int register_code, int offset);
-
int GetProcedureAddressOffset() const {
return fde_offset() + EhFrameConstants::kProcedureAddressOffsetInFde;
}
diff --git a/deps/v8/src/diagnostics/gdb-jit.cc b/deps/v8/src/diagnostics/gdb-jit.cc
index e1290bae4e..5f36437302 100644
--- a/deps/v8/src/diagnostics/gdb-jit.cc
+++ b/deps/v8/src/diagnostics/gdb-jit.cc
@@ -16,7 +16,6 @@
#include "src/handles/global-handles.h"
#include "src/init/bootstrapper.h"
#include "src/objects/objects.h"
-#include "src/snapshot/natives.h"
#include "src/utils/ostreams.h"
#include "src/utils/vector.h"
#include "src/zone/zone-chunk-list.h"
@@ -220,7 +219,7 @@ class MachOSection : public DebugSectionBase<MachOSectionHeader> {
: name_(name), segment_(segment), align_(align), flags_(flags) {
if (align_ != 0) {
DCHECK(base::bits::IsPowerOfTwo(align));
- align_ = WhichPowerOf2(align_);
+ align_ = base::bits::WhichPowerOfTwo(align_);
}
}
@@ -1105,25 +1104,22 @@ class DebugInfoSection : public DebugSection {
Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
uintptr_t block_start = w->position();
w->Write<uint8_t>(DW_OP_fbreg);
- w->WriteSLEB128(JavaScriptFrameConstants::kLastParameterOffset +
+ w->WriteSLEB128(StandardFrameConstants::kFixedFrameSizeAboveFp +
kSystemPointerSize * (params - param - 1));
block_size.set(static_cast<uint32_t>(w->position() - block_start));
}
// See contexts.h for more information.
- DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, 4);
+ DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, 3);
DCHECK_EQ(Context::SCOPE_INFO_INDEX, 0);
DCHECK_EQ(Context::PREVIOUS_INDEX, 1);
DCHECK_EQ(Context::EXTENSION_INDEX, 2);
- DCHECK_EQ(Context::NATIVE_CONTEXT_INDEX, 3);
w->WriteULEB128(current_abbreviation++);
w->WriteString(".scope_info");
w->WriteULEB128(current_abbreviation++);
w->WriteString(".previous");
w->WriteULEB128(current_abbreviation++);
w->WriteString(".extension");
- w->WriteULEB128(current_abbreviation++);
- w->WriteString(".native_context");
for (int context_slot = 0; context_slot < context_slots; ++context_slot) {
w->WriteULEB128(current_abbreviation++);
@@ -1139,7 +1135,7 @@ class DebugInfoSection : public DebugSection {
Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
uintptr_t block_start = w->position();
w->Write<uint8_t>(DW_OP_fbreg);
- w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset);
+ w->WriteSLEB128(StandardFrameConstants::kFunctionOffset);
block_size.set(static_cast<uint32_t>(w->position() - block_start));
}
diff --git a/deps/v8/src/diagnostics/ia32/disasm-ia32.cc b/deps/v8/src/diagnostics/ia32/disasm-ia32.cc
index ead0a5a709..0cb36d1228 100644
--- a/deps/v8/src/diagnostics/ia32/disasm-ia32.cc
+++ b/deps/v8/src/diagnostics/ia32/disasm-ia32.cc
@@ -692,6 +692,10 @@ int DisassemblerIA32::AVXInstruction(byte* data) {
int mod, regop, rm, vvvv = vex_vreg();
get_modrm(*current, &mod, &regop, &rm);
switch (opcode) {
+ case 0x18:
+ AppendToBuffer("vbroadcastss %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ break;
case 0x99:
AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
@@ -846,6 +850,10 @@ int DisassemblerIA32::AVXInstruction(byte* data) {
int mod, regop, rm, vvvv = vex_vreg();
get_modrm(*current, &mod, &regop, &rm);
switch (opcode) {
+ case 0x12:
+ AppendToBuffer("vmovddup %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ break;
case 0x51:
AppendToBuffer("vsqrtsd %s,%s,", NameOfXMMRegister(regop),
NameOfXMMRegister(vvvv));
@@ -2259,13 +2267,6 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
} else if (*data == 0x90) {
data++;
AppendToBuffer("nop"); // 2 byte nop.
- } else if (*data == 0xF3) {
- data++;
- int mod, regop, rm;
- get_modrm(*data, &mod, &regop, &rm);
- AppendToBuffer("psllq %s,%s", NameOfXMMRegister(regop),
- NameOfXMMRegister(rm));
- data++;
} else if (*data == 0x71) {
data++;
int mod, regop, rm;
@@ -2291,13 +2292,6 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
AppendToBuffer("ps%sq %s,%d", sf_str[regop / 2],
NameOfXMMRegister(rm), static_cast<int>(imm8));
data += 2;
- } else if (*data == 0xD3) {
- data++;
- int mod, regop, rm;
- get_modrm(*data, &mod, &regop, &rm);
- AppendToBuffer("psrlq %s,%s", NameOfXMMRegister(regop),
- NameOfXMMRegister(rm));
- data++;
} else if (*data == 0x7F) {
AppendToBuffer("movdqa ");
data++;
@@ -2444,6 +2438,12 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
get_modrm(*data, &mod, &regop, &rm);
AppendToBuffer("movsd %s,", NameOfXMMRegister(regop));
data += PrintRightXMMOperand(data);
+ } else if (b2 == 0x12) {
+ data += 3;
+ int mod, regop, rm;
+ get_modrm(*data, &mod, &regop, &rm);
+ AppendToBuffer("movddup %s,", NameOfXMMRegister(regop));
+ data += PrintRightXMMOperand(data);
} else if (b2 == 0x5A) {
data += 3;
int mod, regop, rm;
diff --git a/deps/v8/src/diagnostics/objects-debug.cc b/deps/v8/src/diagnostics/objects-debug.cc
index 9c4b176dc6..d087a6d21d 100644
--- a/deps/v8/src/diagnostics/objects-debug.cc
+++ b/deps/v8/src/diagnostics/objects-debug.cc
@@ -10,6 +10,7 @@
#include "src/diagnostics/disassembler.h"
#include "src/heap/combined-heap.h"
#include "src/heap/heap-write-barrier-inl.h"
+#include "src/heap/read-only-heap.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/init/bootstrapper.h"
#include "src/logging/counters.h"
@@ -38,6 +39,7 @@
#include "src/objects/js-collection-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-date-time-format-inl.h"
+#include "src/objects/js-display-names-inl.h"
#endif // V8_INTL_SUPPORT
#include "src/objects/js-generator-inl.h"
#ifdef V8_INTL_SUPPORT
@@ -60,6 +62,7 @@
#include "src/objects/module-inl.h"
#include "src/objects/oddball-inl.h"
#include "src/objects/promise-inl.h"
+#include "src/objects/property-descriptor-object-inl.h"
#include "src/objects/stack-frame-info-inl.h"
#include "src/objects/struct-inl.h"
#include "src/objects/template-objects-inl.h"
@@ -156,28 +159,10 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
String::cast(*this).StringVerify(isolate);
}
break;
- case SYMBOL_TYPE:
- Symbol::cast(*this).SymbolVerify(isolate);
- break;
- case MAP_TYPE:
- Map::cast(*this).MapVerify(isolate);
- break;
- case HEAP_NUMBER_TYPE:
- CHECK(IsHeapNumber());
- break;
- case BIGINT_TYPE:
- BigInt::cast(*this).BigIntVerify(isolate);
- break;
- case CALL_HANDLER_INFO_TYPE:
- CallHandlerInfo::cast(*this).CallHandlerInfoVerify(isolate);
- break;
case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
ObjectBoilerplateDescription::cast(*this)
.ObjectBoilerplateDescriptionVerify(isolate);
break;
- case EMBEDDER_DATA_ARRAY_TYPE:
- EmbedderDataArray::cast(*this).EmbedderDataArrayVerify(isolate);
- break;
// FixedArray types
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
case HASH_TABLE_TYPE:
@@ -212,46 +197,16 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case WEAK_FIXED_ARRAY_TYPE:
WeakFixedArray::cast(*this).WeakFixedArrayVerify(isolate);
break;
- case WEAK_ARRAY_LIST_TYPE:
- WeakArrayList::cast(*this).WeakArrayListVerify(isolate);
- break;
- case FIXED_DOUBLE_ARRAY_TYPE:
- FixedDoubleArray::cast(*this).FixedDoubleArrayVerify(isolate);
- break;
case FEEDBACK_METADATA_TYPE:
FeedbackMetadata::cast(*this).FeedbackMetadataVerify(isolate);
break;
- case BYTE_ARRAY_TYPE:
- ByteArray::cast(*this).ByteArrayVerify(isolate);
- break;
- case BYTECODE_ARRAY_TYPE:
- BytecodeArray::cast(*this).BytecodeArrayVerify(isolate);
- break;
- case DESCRIPTOR_ARRAY_TYPE:
- DescriptorArray::cast(*this).DescriptorArrayVerify(isolate);
- break;
case TRANSITION_ARRAY_TYPE:
TransitionArray::cast(*this).TransitionArrayVerify(isolate);
break;
- case PROPERTY_ARRAY_TYPE:
- PropertyArray::cast(*this).PropertyArrayVerify(isolate);
- break;
- case FREE_SPACE_TYPE:
- FreeSpace::cast(*this).FreeSpaceVerify(isolate);
- break;
- case FEEDBACK_CELL_TYPE:
- FeedbackCell::cast(*this).FeedbackCellVerify(isolate);
- break;
- case FEEDBACK_VECTOR_TYPE:
- FeedbackVector::cast(*this).FeedbackVectorVerify(isolate);
- break;
case CODE_TYPE:
Code::cast(*this).CodeVerify(isolate);
break;
- case ODDBALL_TYPE:
- Oddball::cast(*this).OddballVerify(isolate);
- break;
case JS_OBJECT_TYPE:
case JS_ERROR_TYPE:
case JS_API_OBJECT_TYPE:
@@ -259,72 +214,12 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
JSObject::cast(*this).JSObjectVerify(isolate);
break;
- case WASM_MODULE_OBJECT_TYPE:
- WasmModuleObject::cast(*this).WasmModuleObjectVerify(isolate);
- break;
- case WASM_TABLE_OBJECT_TYPE:
- WasmTableObject::cast(*this).WasmTableObjectVerify(isolate);
- break;
- case WASM_MEMORY_OBJECT_TYPE:
- WasmMemoryObject::cast(*this).WasmMemoryObjectVerify(isolate);
- break;
- case WASM_GLOBAL_OBJECT_TYPE:
- WasmGlobalObject::cast(*this).WasmGlobalObjectVerify(isolate);
- break;
- case WASM_EXCEPTION_OBJECT_TYPE:
- WasmExceptionObject::cast(*this).WasmExceptionObjectVerify(isolate);
- break;
case WASM_INSTANCE_OBJECT_TYPE:
WasmInstanceObject::cast(*this).WasmInstanceObjectVerify(isolate);
break;
- case JS_ARGUMENTS_OBJECT_TYPE:
- JSArgumentsObject::cast(*this).JSArgumentsObjectVerify(isolate);
- break;
case JS_GENERATOR_OBJECT_TYPE:
JSGeneratorObject::cast(*this).JSGeneratorObjectVerify(isolate);
break;
- case JS_ASYNC_FUNCTION_OBJECT_TYPE:
- JSAsyncFunctionObject::cast(*this).JSAsyncFunctionObjectVerify(isolate);
- break;
- case JS_ASYNC_GENERATOR_OBJECT_TYPE:
- JSAsyncGeneratorObject::cast(*this).JSAsyncGeneratorObjectVerify(isolate);
- break;
- case JS_PRIMITIVE_WRAPPER_TYPE:
- JSPrimitiveWrapper::cast(*this).JSPrimitiveWrapperVerify(isolate);
- break;
- case JS_DATE_TYPE:
- JSDate::cast(*this).JSDateVerify(isolate);
- break;
- case JS_BOUND_FUNCTION_TYPE:
- JSBoundFunction::cast(*this).JSBoundFunctionVerify(isolate);
- break;
- case JS_FUNCTION_TYPE:
- JSFunction::cast(*this).JSFunctionVerify(isolate);
- break;
- case JS_GLOBAL_PROXY_TYPE:
- JSGlobalProxy::cast(*this).JSGlobalProxyVerify(isolate);
- break;
- case JS_GLOBAL_OBJECT_TYPE:
- JSGlobalObject::cast(*this).JSGlobalObjectVerify(isolate);
- break;
- case CELL_TYPE:
- Cell::cast(*this).CellVerify(isolate);
- break;
- case PROPERTY_CELL_TYPE:
- PropertyCell::cast(*this).PropertyCellVerify(isolate);
- break;
- case JS_ARRAY_TYPE:
- JSArray::cast(*this).JSArrayVerify(isolate);
- break;
- case JS_MODULE_NAMESPACE_TYPE:
- JSModuleNamespace::cast(*this).JSModuleNamespaceVerify(isolate);
- break;
- case JS_SET_TYPE:
- JSSet::cast(*this).JSSetVerify(isolate);
- break;
- case JS_MAP_TYPE:
- JSMap::cast(*this).JSMapVerify(isolate);
- break;
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
JSSetIterator::cast(*this).JSSetIteratorVerify(isolate);
@@ -334,136 +229,20 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case JS_MAP_VALUE_ITERATOR_TYPE:
JSMapIterator::cast(*this).JSMapIteratorVerify(isolate);
break;
- case JS_ARRAY_ITERATOR_TYPE:
- JSArrayIterator::cast(*this).JSArrayIteratorVerify(isolate);
- break;
- case JS_STRING_ITERATOR_TYPE:
- JSStringIterator::cast(*this).JSStringIteratorVerify(isolate);
- break;
- case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
- JSAsyncFromSyncIterator::cast(*this).JSAsyncFromSyncIteratorVerify(
- isolate);
- break;
- case WEAK_CELL_TYPE:
- WeakCell::cast(*this).WeakCellVerify(isolate);
- break;
- case JS_WEAK_REF_TYPE:
- JSWeakRef::cast(*this).JSWeakRefVerify(isolate);
- break;
- case JS_FINALIZATION_GROUP_TYPE:
- JSFinalizationGroup::cast(*this).JSFinalizationGroupVerify(isolate);
- break;
- case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
- JSFinalizationGroupCleanupIterator::cast(*this)
- .JSFinalizationGroupCleanupIteratorVerify(isolate);
- break;
- case JS_WEAK_MAP_TYPE:
- JSWeakMap::cast(*this).JSWeakMapVerify(isolate);
- break;
- case JS_WEAK_SET_TYPE:
- JSWeakSet::cast(*this).JSWeakSetVerify(isolate);
- break;
- case JS_PROMISE_TYPE:
- JSPromise::cast(*this).JSPromiseVerify(isolate);
- break;
- case JS_REG_EXP_TYPE:
- JSRegExp::cast(*this).JSRegExpVerify(isolate);
- break;
- case JS_REG_EXP_STRING_ITERATOR_TYPE:
- JSRegExpStringIterator::cast(*this).JSRegExpStringIteratorVerify(isolate);
- break;
case FILLER_TYPE:
break;
- case JS_PROXY_TYPE:
- JSProxy::cast(*this).JSProxyVerify(isolate);
- break;
- case FOREIGN_TYPE:
- Foreign::cast(*this).ForeignVerify(isolate);
- break;
- case PREPARSE_DATA_TYPE:
- PreparseData::cast(*this).PreparseDataVerify(isolate);
- break;
- case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE:
- UncompiledDataWithoutPreparseData::cast(*this)
- .UncompiledDataWithoutPreparseDataVerify(isolate);
- break;
- case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE:
- UncompiledDataWithPreparseData::cast(*this)
- .UncompiledDataWithPreparseDataVerify(isolate);
- break;
- case SHARED_FUNCTION_INFO_TYPE:
- SharedFunctionInfo::cast(*this).SharedFunctionInfoVerify(isolate);
- break;
- case JS_MESSAGE_OBJECT_TYPE:
- JSMessageObject::cast(*this).JSMessageObjectVerify(isolate);
- break;
- case JS_ARRAY_BUFFER_TYPE:
- JSArrayBuffer::cast(*this).JSArrayBufferVerify(isolate);
- break;
- case JS_TYPED_ARRAY_TYPE:
- JSTypedArray::cast(*this).JSTypedArrayVerify(isolate);
- break;
- case JS_DATA_VIEW_TYPE:
- JSDataView::cast(*this).JSDataViewVerify(isolate);
- break;
- case SMALL_ORDERED_HASH_SET_TYPE:
- SmallOrderedHashSet::cast(*this).SmallOrderedHashSetVerify(isolate);
- break;
- case SMALL_ORDERED_HASH_MAP_TYPE:
- SmallOrderedHashMap::cast(*this).SmallOrderedHashMapVerify(isolate);
- break;
- case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
- SmallOrderedNameDictionary::cast(*this).SmallOrderedNameDictionaryVerify(
- isolate);
- break;
- case SOURCE_TEXT_MODULE_TYPE:
- SourceTextModule::cast(*this).SourceTextModuleVerify(isolate);
- break;
- case SYNTHETIC_MODULE_TYPE:
- SyntheticModule::cast(*this).SyntheticModuleVerify(isolate);
- break;
case CODE_DATA_CONTAINER_TYPE:
CodeDataContainer::cast(*this).CodeDataContainerVerify(isolate);
break;
-#ifdef V8_INTL_SUPPORT
- case JS_V8_BREAK_ITERATOR_TYPE:
- JSV8BreakIterator::cast(*this).JSV8BreakIteratorVerify(isolate);
- break;
- case JS_COLLATOR_TYPE:
- JSCollator::cast(*this).JSCollatorVerify(isolate);
- break;
- case JS_DATE_TIME_FORMAT_TYPE:
- JSDateTimeFormat::cast(*this).JSDateTimeFormatVerify(isolate);
- break;
- case JS_LIST_FORMAT_TYPE:
- JSListFormat::cast(*this).JSListFormatVerify(isolate);
- break;
- case JS_LOCALE_TYPE:
- JSLocale::cast(*this).JSLocaleVerify(isolate);
- break;
- case JS_NUMBER_FORMAT_TYPE:
- JSNumberFormat::cast(*this).JSNumberFormatVerify(isolate);
- break;
- case JS_PLURAL_RULES_TYPE:
- JSPluralRules::cast(*this).JSPluralRulesVerify(isolate);
- break;
- case JS_RELATIVE_TIME_FORMAT_TYPE:
- JSRelativeTimeFormat::cast(*this).JSRelativeTimeFormatVerify(isolate);
- break;
- case JS_SEGMENT_ITERATOR_TYPE:
- JSSegmentIterator::cast(*this).JSSegmentIteratorVerify(isolate);
- break;
- case JS_SEGMENTER_TYPE:
- JSSegmenter::cast(*this).JSSegmenterVerify(isolate);
- break;
-#endif // V8_INTL_SUPPORT
-#define MAKE_STRUCT_CASE(TYPE, Name, name) \
+#define MAKE_TORQUE_CASE(Name, TYPE) \
case TYPE: \
Name::cast(*this).Name##Verify(isolate); \
break;
- STRUCT_LIST(MAKE_STRUCT_CASE)
-#undef MAKE_STRUCT_CASE
+ // Every class that has its fields defined in a .tq file and corresponds
+ // to exactly one InstanceType value is included in the following list.
+ TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
+#undef MAKE_TORQUE_CASE
case ALLOCATION_SITE_TYPE:
AllocationSite::cast(*this).AllocationSiteVerify(isolate);
@@ -489,8 +268,9 @@ void Symbol::SymbolVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::SymbolVerify(*this, isolate);
CHECK(HasHashCode());
CHECK_GT(Hash(), 0);
- CHECK(name().IsUndefined(isolate) || name().IsString());
+ CHECK(description().IsUndefined(isolate) || description().IsString());
CHECK_IMPLIES(IsPrivateName(), IsPrivate());
+ CHECK_IMPLIES(IsPrivateBrand(), IsPrivateName());
}
USE_TORQUE_VERIFIER(ByteArray)
@@ -506,23 +286,19 @@ void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {
VerifyHeapPointer(isolate, constant_pool());
CHECK(source_position_table().IsUndefined() ||
source_position_table().IsException() ||
- source_position_table().IsByteArray() ||
- source_position_table().IsSourcePositionTableWithFrameCache());
+ source_position_table().IsByteArray());
CHECK(handler_table().IsByteArray());
}
USE_TORQUE_VERIFIER(FreeSpace)
-void FeedbackVector::FeedbackVectorVerify(Isolate* isolate) {
- TorqueGeneratedClassVerifiers::FeedbackVectorVerify(*this, isolate);
- MaybeObject code = optimized_code_weak_or_smi();
- MaybeObject::VerifyMaybeObjectPointer(isolate, code);
- CHECK(code->IsSmi() || code->IsWeakOrCleared());
-}
+USE_TORQUE_VERIFIER(HeapNumber)
+
+USE_TORQUE_VERIFIER(FeedbackVector)
USE_TORQUE_VERIFIER(JSReceiver)
-bool JSObject::ElementsAreSafeToExamine(Isolate* isolate) const {
+bool JSObject::ElementsAreSafeToExamine(const Isolate* isolate) const {
// If a GC was caused while constructing this object, the elements
// pointer may point to a one pointer filler map.
return elements(isolate) !=
@@ -652,8 +428,37 @@ void Map::MapVerify(Isolate* isolate) {
CHECK(instance_size() == kVariableSizeSentinel ||
(kTaggedSize <= instance_size() &&
static_cast<size_t>(instance_size()) < heap->Capacity()));
- CHECK(GetBackPointer().IsUndefined(isolate) ||
- !Map::cast(GetBackPointer()).is_stable());
+ if (IsContextMap()) {
+ CHECK(native_context().IsNativeContext());
+ } else {
+ if (GetBackPointer().IsUndefined(isolate)) {
+ // Root maps must not have descriptors in the descriptor array that do not
+ // belong to the map.
+ CHECK_EQ(NumberOfOwnDescriptors(),
+ instance_descriptors().number_of_descriptors());
+ } else {
+ // If there is a parent map it must be non-stable.
+ Map parent = Map::cast(GetBackPointer());
+ CHECK(!parent.is_stable());
+ DescriptorArray descriptors = instance_descriptors();
+ if (descriptors == parent.instance_descriptors()) {
+ if (NumberOfOwnDescriptors() == parent.NumberOfOwnDescriptors() + 1) {
+ // Descriptors sharing through property transitions takes over
+ // ownership from the parent map.
+ CHECK(!parent.owns_descriptors());
+ } else {
+ CHECK_EQ(NumberOfOwnDescriptors(), parent.NumberOfOwnDescriptors());
+ // Descriptors sharing through special transitions properly takes over
+ // ownership from the parent map unless it uses the canonical empty
+ // descriptor array.
+ if (descriptors != ReadOnlyRoots(isolate).empty_descriptor_array()) {
+ CHECK_IMPLIES(owns_descriptors(), !parent.owns_descriptors());
+ CHECK_IMPLIES(parent.owns_descriptors(), !owns_descriptors());
+ }
+ }
+ }
+ }
+ }
SLOW_DCHECK(instance_descriptors().IsSortedNoDuplicates());
DisallowHeapAllocation no_gc;
SLOW_DCHECK(
@@ -662,6 +467,9 @@ void Map::MapVerify(Isolate* isolate) {
.IsConsistentWithBackPointers());
SLOW_DCHECK(!FLAG_unbox_double_fields ||
layout_descriptor().IsConsistentWithMap(*this));
+ // Only JSFunction maps have has_prototype_slot() bit set and constructible
+ // JSFunction objects must have prototype slot.
+ CHECK_IMPLIES(has_prototype_slot(), instance_type() == JS_FUNCTION_TYPE);
if (!may_have_interesting_symbols()) {
CHECK(!has_named_interceptor());
CHECK(!is_dictionary_map());
@@ -680,7 +488,7 @@ void Map::MapVerify(Isolate* isolate) {
IsAnyHoleyNonextensibleElementsKind(elements_kind()));
CHECK_IMPLIES(is_deprecated(), !is_stable());
if (is_prototype_map()) {
- DCHECK(prototype_info() == Smi::kZero ||
+ DCHECK(prototype_info() == Smi::zero() ||
prototype_info().IsPrototypeInfo());
}
}
@@ -716,13 +524,7 @@ void WeakFixedArray::WeakFixedArrayVerify(Isolate* isolate) {
}
}
-void WeakArrayList::WeakArrayListVerify(Isolate* isolate) {
- VerifySmiField(kCapacityOffset);
- VerifySmiField(kLengthOffset);
- for (int i = 0; i < length(); i++) {
- MaybeObject::VerifyMaybeObjectPointer(isolate, Get(i));
- }
-}
+USE_TORQUE_VERIFIER(WeakArrayList)
void PropertyArray::PropertyArrayVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::PropertyArrayVerify(*this, isolate);
@@ -783,13 +585,6 @@ void FeedbackMetadata::FeedbackMetadataVerify(Isolate* isolate) {
void DescriptorArray::DescriptorArrayVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::DescriptorArrayVerify(*this, isolate);
- for (int i = 0; i < number_of_all_descriptors(); i++) {
- MaybeObjectSlot slot(GetDescriptorSlot(i));
- MaybeObject::VerifyMaybeObjectPointer(isolate, *(slot + kEntryKeyIndex));
- MaybeObject::VerifyMaybeObjectPointer(isolate,
- *(slot + kEntryDetailsIndex));
- MaybeObject::VerifyMaybeObjectPointer(isolate, *(slot + kEntryValueIndex));
- }
if (number_of_all_descriptors() == 0) {
CHECK_EQ(ReadOnlyRoots(isolate).empty_descriptor_array(), *this);
CHECK_EQ(0, number_of_all_descriptors());
@@ -1148,7 +943,13 @@ void Code::CodeVerify(Isolate* isolate) {
CHECK_LE(handler_table_offset(), constant_pool_offset());
CHECK_LE(constant_pool_offset(), code_comments_offset());
CHECK_LE(code_comments_offset(), InstructionSize());
- CHECK(IsAligned(raw_instruction_start(), kCodeAlignment));
+ CHECK_IMPLIES(!ReadOnlyHeap::Contains(*this),
+ IsAligned(raw_instruction_start(), kCodeAlignment));
+ // TODO(delphick): Refactor Factory::CodeBuilder::BuildInternal, so that the
+ // following CHECK works builtin trampolines. It currently fails because
+ // CodeVerify is called halfway through constructing the trampoline and so not
+ // everything is set up.
+ // CHECK_EQ(ReadOnlyHeap::Contains(*this), !IsExecutable());
relocation_info().ObjectVerify(isolate);
CHECK(Code::SizeFor(body_size()) <= kMaxRegularHeapObjectSize ||
isolate->heap()->InSpace(*this, CODE_LO_SPACE));
@@ -1247,9 +1048,9 @@ void WeakCell::WeakCellVerify(Isolate* isolate) {
CHECK_EQ(WeakCell::cast(next()).prev(), *this);
}
- CHECK_IMPLIES(key().IsUndefined(isolate),
+ CHECK_IMPLIES(unregister_token().IsUndefined(isolate),
key_list_prev().IsUndefined(isolate));
- CHECK_IMPLIES(key().IsUndefined(isolate),
+ CHECK_IMPLIES(unregister_token().IsUndefined(isolate),
key_list_next().IsUndefined(isolate));
CHECK(key_list_prev().IsWeakCell() || key_list_prev().IsUndefined(isolate));
@@ -1449,6 +1250,7 @@ void JSRegExp::JSRegExpVerify(Isolate* isolate) {
CHECK(arr.get(JSRegExp::kIrregexpCaptureCountIndex).IsSmi());
CHECK(arr.get(JSRegExp::kIrregexpMaxRegisterCountIndex).IsSmi());
CHECK(arr.get(JSRegExp::kIrregexpTicksUntilTierUpIndex).IsSmi());
+ CHECK(arr.get(JSRegExp::kIrregexpBacktrackLimit).IsSmi());
break;
}
default:
@@ -1509,8 +1311,8 @@ void AsyncGeneratorRequest::AsyncGeneratorRequestVerify(Isolate* isolate) {
next().ObjectVerify(isolate);
}
-void BigInt::BigIntVerify(Isolate* isolate) {
- CHECK(IsBigInt());
+void BigIntBase::BigIntBaseVerify(Isolate* isolate) {
+ TorqueGeneratedClassVerifiers::BigIntBaseVerify(*this, isolate);
CHECK_GE(length(), 0);
CHECK_IMPLIES(is_zero(), !sign()); // There is no -0n.
}
@@ -1706,7 +1508,7 @@ void AllocationSite::AllocationSiteVerify(Isolate* isolate) {
CHECK(dependent_code().IsDependentCode());
CHECK(transition_info_or_boilerplate().IsSmi() ||
transition_info_or_boilerplate().IsJSObject());
- CHECK(nested_site().IsAllocationSite() || nested_site() == Smi::kZero);
+ CHECK(nested_site().IsAllocationSite() || nested_site() == Smi::zero());
}
USE_TORQUE_VERIFIER(AllocationMemento)
@@ -1762,6 +1564,8 @@ USE_TORQUE_VERIFIER(JSCollator)
USE_TORQUE_VERIFIER(JSDateTimeFormat)
+USE_TORQUE_VERIFIER(JSDisplayNames)
+
USE_TORQUE_VERIFIER(JSListFormat)
USE_TORQUE_VERIFIER(JSLocale)
diff --git a/deps/v8/src/diagnostics/objects-printer.cc b/deps/v8/src/diagnostics/objects-printer.cc
index 20afb9e520..9dae2881b9 100644
--- a/deps/v8/src/diagnostics/objects-printer.cc
+++ b/deps/v8/src/diagnostics/objects-printer.cc
@@ -35,6 +35,7 @@
#include "src/objects/js-collection-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-date-time-format-inl.h"
+#include "src/objects/js-display-names-inl.h"
#endif // V8_INTL_SUPPORT
#include "src/objects/js-generator-inl.h"
#ifdef V8_INTL_SUPPORT
@@ -57,6 +58,7 @@
#include "src/objects/module-inl.h"
#include "src/objects/oddball-inl.h"
#include "src/objects/promise-inl.h"
+#include "src/objects/property-descriptor-object-inl.h"
#include "src/objects/stack-frame-info-inl.h"
#include "src/objects/struct-inl.h"
#include "src/objects/template-objects-inl.h"
@@ -120,26 +122,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
}
switch (instance_type) {
- case SYMBOL_TYPE:
- Symbol::cast(*this).SymbolPrint(os);
- break;
- case MAP_TYPE:
- Map::cast(*this).MapPrint(os);
- break;
- case HEAP_NUMBER_TYPE:
- HeapNumber::cast(*this).HeapNumberPrint(os);
- os << "\n";
- break;
- case BIGINT_TYPE:
- BigInt::cast(*this).BigIntPrint(os);
- os << "\n";
- break;
- case EMBEDDER_DATA_ARRAY_TYPE:
- EmbedderDataArray::cast(*this).EmbedderDataArrayPrint(os);
- break;
- case FIXED_DOUBLE_ARRAY_TYPE:
- FixedDoubleArray::cast(*this).FixedDoubleArrayPrint(os);
- break;
case FIXED_ARRAY_TYPE:
FixedArray::cast(*this).FixedArrayPrint(os);
break;
@@ -180,33 +162,12 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
ObjectBoilerplateDescription::cast(*this)
.ObjectBoilerplateDescriptionPrint(os);
break;
- case PROPERTY_ARRAY_TYPE:
- PropertyArray::cast(*this).PropertyArrayPrint(os);
- break;
- case BYTE_ARRAY_TYPE:
- ByteArray::cast(*this).ByteArrayPrint(os);
- break;
- case BYTECODE_ARRAY_TYPE:
- BytecodeArray::cast(*this).BytecodeArrayPrint(os);
- break;
- case DESCRIPTOR_ARRAY_TYPE:
- DescriptorArray::cast(*this).DescriptorArrayPrint(os);
- break;
case TRANSITION_ARRAY_TYPE:
TransitionArray::cast(*this).TransitionArrayPrint(os);
break;
- case FEEDBACK_CELL_TYPE:
- FeedbackCell::cast(*this).FeedbackCellPrint(os);
- break;
case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
ClosureFeedbackCellArray::cast(*this).ClosureFeedbackCellArrayPrint(os);
break;
- case FEEDBACK_VECTOR_TYPE:
- FeedbackVector::cast(*this).FeedbackVectorPrint(os);
- break;
- case FREE_SPACE_TYPE:
- FreeSpace::cast(*this).FreeSpacePrint(os);
- break;
case FILLER_TYPE:
os << "filler";
@@ -215,80 +176,21 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case JS_API_OBJECT_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
- case JS_ARGUMENTS_OBJECT_TYPE:
case JS_ERROR_TYPE:
- // TODO(titzer): debug printing for more wasm objects
- case WASM_EXCEPTION_OBJECT_TYPE:
JSObject::cast(*this).JSObjectPrint(os);
break;
- case WASM_MODULE_OBJECT_TYPE:
- WasmModuleObject::cast(*this).WasmModuleObjectPrint(os);
- break;
- case WASM_MEMORY_OBJECT_TYPE:
- WasmMemoryObject::cast(*this).WasmMemoryObjectPrint(os);
- break;
- case WASM_TABLE_OBJECT_TYPE:
- WasmTableObject::cast(*this).WasmTableObjectPrint(os);
- break;
- case WASM_GLOBAL_OBJECT_TYPE:
- WasmGlobalObject::cast(*this).WasmGlobalObjectPrint(os);
- break;
case WASM_INSTANCE_OBJECT_TYPE:
WasmInstanceObject::cast(*this).WasmInstanceObjectPrint(os);
break;
- case JS_ASYNC_FUNCTION_OBJECT_TYPE:
- case JS_ASYNC_GENERATOR_OBJECT_TYPE:
case JS_GENERATOR_OBJECT_TYPE:
JSGeneratorObject::cast(*this).JSGeneratorObjectPrint(os);
break;
- case JS_PROMISE_TYPE:
- JSPromise::cast(*this).JSPromisePrint(os);
- break;
- case JS_ARRAY_TYPE:
- JSArray::cast(*this).JSArrayPrint(os);
- break;
- case JS_REG_EXP_TYPE:
- JSRegExp::cast(*this).JSRegExpPrint(os);
- break;
- case JS_REG_EXP_STRING_ITERATOR_TYPE:
- JSRegExpStringIterator::cast(*this).JSRegExpStringIteratorPrint(os);
- break;
- case ODDBALL_TYPE:
- Oddball::cast(*this).to_string().Print(os);
- break;
- case JS_BOUND_FUNCTION_TYPE:
- JSBoundFunction::cast(*this).JSBoundFunctionPrint(os);
- break;
- case JS_FUNCTION_TYPE:
- JSFunction::cast(*this).JSFunctionPrint(os);
- break;
- case JS_GLOBAL_PROXY_TYPE:
- JSGlobalProxy::cast(*this).JSGlobalProxyPrint(os);
- break;
- case JS_GLOBAL_OBJECT_TYPE:
- JSGlobalObject::cast(*this).JSGlobalObjectPrint(os);
- break;
- case JS_PRIMITIVE_WRAPPER_TYPE:
- JSPrimitiveWrapper::cast(*this).JSPrimitiveWrapperPrint(os);
- break;
- case JS_DATE_TYPE:
- JSDate::cast(*this).JSDatePrint(os);
- break;
case CODE_TYPE:
Code::cast(*this).CodePrint(os);
break;
case CODE_DATA_CONTAINER_TYPE:
CodeDataContainer::cast(*this).CodeDataContainerPrint(os);
break;
- case JS_PROXY_TYPE:
- JSProxy::cast(*this).JSProxyPrint(os);
- break;
- case JS_SET_TYPE:
- JSSet::cast(*this).JSSetPrint(os);
- break;
- case JS_MAP_TYPE:
- JSMap::cast(*this).JSMapPrint(os);
- break;
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
JSSetIterator::cast(*this).JSSetIteratorPrint(os);
@@ -298,107 +200,14 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case JS_MAP_VALUE_ITERATOR_TYPE:
JSMapIterator::cast(*this).JSMapIteratorPrint(os);
break;
- case WEAK_CELL_TYPE:
- WeakCell::cast(*this).WeakCellPrint(os);
- break;
- case JS_WEAK_REF_TYPE:
- JSWeakRef::cast(*this).JSWeakRefPrint(os);
- break;
- case JS_FINALIZATION_GROUP_TYPE:
- JSFinalizationGroup::cast(*this).JSFinalizationGroupPrint(os);
- break;
- case JS_FINALIZATION_GROUP_CLEANUP_ITERATOR_TYPE:
- JSFinalizationGroupCleanupIterator::cast(*this)
- .JSFinalizationGroupCleanupIteratorPrint(os);
- break;
- case JS_WEAK_MAP_TYPE:
- JSWeakMap::cast(*this).JSWeakMapPrint(os);
- break;
- case JS_WEAK_SET_TYPE:
- JSWeakSet::cast(*this).JSWeakSetPrint(os);
- break;
- case JS_MODULE_NAMESPACE_TYPE:
- JSModuleNamespace::cast(*this).JSModuleNamespacePrint(os);
- break;
- case FOREIGN_TYPE:
- Foreign::cast(*this).ForeignPrint(os);
- break;
- case CALL_HANDLER_INFO_TYPE:
- CallHandlerInfo::cast(*this).CallHandlerInfoPrint(os);
- break;
- case PREPARSE_DATA_TYPE:
- PreparseData::cast(*this).PreparseDataPrint(os);
- break;
- case UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE:
- UncompiledDataWithoutPreparseData::cast(*this)
- .UncompiledDataWithoutPreparseDataPrint(os);
- break;
- case UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE:
- UncompiledDataWithPreparseData::cast(*this)
- .UncompiledDataWithPreparseDataPrint(os);
- break;
- case SHARED_FUNCTION_INFO_TYPE:
- SharedFunctionInfo::cast(*this).SharedFunctionInfoPrint(os);
- break;
- case JS_MESSAGE_OBJECT_TYPE:
- JSMessageObject::cast(*this).JSMessageObjectPrint(os);
- break;
- case CELL_TYPE:
- Cell::cast(*this).CellPrint(os);
- break;
- case PROPERTY_CELL_TYPE:
- PropertyCell::cast(*this).PropertyCellPrint(os);
- break;
- case JS_ARRAY_BUFFER_TYPE:
- JSArrayBuffer::cast(*this).JSArrayBufferPrint(os);
- break;
- case JS_ARRAY_ITERATOR_TYPE:
- JSArrayIterator::cast(*this).JSArrayIteratorPrint(os);
- break;
- case JS_TYPED_ARRAY_TYPE:
- JSTypedArray::cast(*this).JSTypedArrayPrint(os);
- break;
- case JS_DATA_VIEW_TYPE:
- JSDataView::cast(*this).JSDataViewPrint(os);
- break;
-#ifdef V8_INTL_SUPPORT
- case JS_V8_BREAK_ITERATOR_TYPE:
- JSV8BreakIterator::cast(*this).JSV8BreakIteratorPrint(os);
- break;
- case JS_COLLATOR_TYPE:
- JSCollator::cast(*this).JSCollatorPrint(os);
- break;
- case JS_DATE_TIME_FORMAT_TYPE:
- JSDateTimeFormat::cast(*this).JSDateTimeFormatPrint(os);
- break;
- case JS_LIST_FORMAT_TYPE:
- JSListFormat::cast(*this).JSListFormatPrint(os);
- break;
- case JS_LOCALE_TYPE:
- JSLocale::cast(*this).JSLocalePrint(os);
- break;
- case JS_NUMBER_FORMAT_TYPE:
- JSNumberFormat::cast(*this).JSNumberFormatPrint(os);
- break;
- case JS_PLURAL_RULES_TYPE:
- JSPluralRules::cast(*this).JSPluralRulesPrint(os);
- break;
- case JS_RELATIVE_TIME_FORMAT_TYPE:
- JSRelativeTimeFormat::cast(*this).JSRelativeTimeFormatPrint(os);
- break;
- case JS_SEGMENT_ITERATOR_TYPE:
- JSSegmentIterator::cast(*this).JSSegmentIteratorPrint(os);
- break;
- case JS_SEGMENTER_TYPE:
- JSSegmenter::cast(*this).JSSegmenterPrint(os);
- break;
-#endif // V8_INTL_SUPPORT
-#define MAKE_STRUCT_CASE(TYPE, Name, name) \
- case TYPE: \
- Name::cast(*this).Name##Print(os); \
+#define MAKE_TORQUE_CASE(Name, TYPE) \
+ case TYPE: \
+ Name::cast(*this).Name##Print(os); \
break;
- STRUCT_LIST(MAKE_STRUCT_CASE)
-#undef MAKE_STRUCT_CASE
+ // Every class that has its fields defined in a .tq file and corresponds
+ // to exactly one InstanceType value is included in the following list.
+ TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
+#undef MAKE_TORQUE_CASE
case ALLOCATION_SITE_TYPE:
AllocationSite::cast(*this).AllocationSitePrint(os);
@@ -412,21 +221,12 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case SCOPE_INFO_TYPE:
ScopeInfo::cast(*this).ScopeInfoPrint(os);
break;
- case SOURCE_TEXT_MODULE_TYPE:
- SourceTextModule::cast(*this).SourceTextModulePrint(os);
- break;
- case SYNTHETIC_MODULE_TYPE:
- SyntheticModule::cast(*this).SyntheticModulePrint(os);
- break;
case FEEDBACK_METADATA_TYPE:
FeedbackMetadata::cast(*this).FeedbackMetadataPrint(os);
break;
case WEAK_FIXED_ARRAY_TYPE:
WeakFixedArray::cast(*this).WeakFixedArrayPrint(os);
break;
- case WEAK_ARRAY_LIST_TYPE:
- WeakArrayList::cast(*this).WeakArrayListPrint(os);
- break;
case INTERNALIZED_STRING_TYPE:
case EXTERNAL_INTERNALIZED_STRING_TYPE:
case ONE_BYTE_INTERNALIZED_STRING_TYPE:
@@ -445,11 +245,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case THIN_ONE_BYTE_STRING_TYPE:
case UNCACHED_EXTERNAL_STRING_TYPE:
case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE:
- case SMALL_ORDERED_HASH_MAP_TYPE:
- case SMALL_ORDERED_HASH_SET_TYPE:
- case SMALL_ORDERED_NAME_DICTIONARY_TYPE:
- case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
- case JS_STRING_ITERATOR_TYPE:
// TODO(all): Handle these types too.
os << "UNKNOWN TYPE " << map().instance_type();
UNREACHABLE();
@@ -477,8 +272,7 @@ bool JSObject::PrintProperties(std::ostream& os) { // NOLINT
if (HasFastProperties()) {
DescriptorArray descs = map().instance_descriptors();
int nof_inobject_properties = map().GetInObjectProperties();
- for (InternalIndex i :
- InternalIndex::Range(map().NumberOfOwnDescriptors())) {
+ for (InternalIndex i : map().IterateOwnDescriptors()) {
os << "\n ";
descs.GetKey(i).NamePrint(os);
os << ": ";
@@ -570,9 +364,15 @@ void DoPrintElements(std::ostream& os, Object object, int length) { // NOLINT
template <typename ElementType>
void PrintTypedArrayElements(std::ostream& os, const ElementType* data_ptr,
- size_t length) {
+ size_t length, bool is_on_heap) {
if (length == 0) return;
size_t previous_index = 0;
+ if (i::FLAG_mock_arraybuffer_allocator && !is_on_heap) {
+ // Don't try to print data that's not actually allocated.
+ os << "\n 0-" << length << ": <mocked array buffer bytes>";
+ return;
+ }
+
ElementType previous_value = data_ptr[0];
ElementType value = 0;
for (size_t i = 1; i <= length; i++) {
@@ -586,7 +386,7 @@ void PrintTypedArrayElements(std::ostream& os, const ElementType* data_ptr,
if (previous_index != i - 1) {
ss << '-' << (i - 1);
}
- os << std::setw(12) << ss.str() << ": " << previous_value;
+ os << std::setw(12) << ss.str() << ": " << +previous_value;
previous_index = i;
previous_value = value;
}
@@ -696,9 +496,10 @@ void JSObject::PrintElements(std::ostream& os) { // NOLINT
#define PRINT_ELEMENTS(Type, type, TYPE, elementType) \
case TYPE##_ELEMENTS: { \
size_t length = JSTypedArray::cast(*this).length(); \
+ bool is_on_heap = JSTypedArray::cast(*this).is_on_heap(); \
const elementType* data_ptr = \
static_cast<const elementType*>(JSTypedArray::cast(*this).DataPtr()); \
- PrintTypedArrayElements<elementType>(os, data_ptr, length); \
+ PrintTypedArrayElements<elementType>(os, data_ptr, length, is_on_heap); \
break; \
}
TYPED_ARRAYS(PRINT_ELEMENTS)
@@ -852,6 +653,7 @@ void JSPromise::JSPromisePrint(std::ostream& os) { // NOLINT
os << "\n - result: " << Brief(result());
}
os << "\n - has_handler: " << has_handler();
+ os << "\n - handled_hint: " << handled_hint();
JSObjectPrintBody(os, *this);
}
@@ -876,8 +678,8 @@ void JSRegExpStringIterator::JSRegExpStringIteratorPrint(
void Symbol::SymbolPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "Symbol");
os << "\n - hash: " << Hash();
- os << "\n - name: " << Brief(name());
- if (name().IsUndefined()) {
+ os << "\n - description: " << Brief(description());
+ if (description().IsUndefined()) {
os << " (" << PrivateSymbolToName() << ")";
}
os << "\n - private: " << is_private();
@@ -926,9 +728,9 @@ void PrintHashTableWithHeader(std::ostream& os, T table, const char* type) {
os << "\n - capacity: " << table.Capacity();
os << "\n - elements: {";
- for (int i = 0; i < table.Capacity(); i++) {
+ for (InternalIndex i : table.IterateEntries()) {
os << '\n'
- << std::setw(12) << i << ": " << Brief(table.KeyAt(i)) << " -> "
+ << std::setw(12) << i.as_int() << ": " << Brief(table.KeyAt(i)) << " -> "
<< Brief(table.ValueAt(i));
}
os << "\n }\n";
@@ -984,7 +786,6 @@ void PrintContextWithHeader(std::ostream& os, Context context,
os << "\n - length: " << context.length();
os << "\n - scope_info: " << Brief(context.scope_info());
os << "\n - previous: " << Brief(context.unchecked_previous());
- os << "\n - extension: " << Brief(context.extension());
os << "\n - native_context: " << Brief(context.native_context());
PrintFixedArrayElements(os, context);
os << "\n";
@@ -1197,6 +998,39 @@ void FeedbackNexus::Print(std::ostream& os) { // NOLINT
}
}
+void Oddball::OddballPrint(std::ostream& os) { // NOLINT
+ to_string().Print(os);
+}
+
+void JSAsyncFunctionObject::JSAsyncFunctionObjectPrint(
+ std::ostream& os) { // NOLINT
+ JSGeneratorObjectPrint(os);
+}
+
+void JSAsyncGeneratorObject::JSAsyncGeneratorObjectPrint(
+ std::ostream& os) { // NOLINT
+ JSGeneratorObjectPrint(os);
+}
+
+void JSArgumentsObject::JSArgumentsObjectPrint(std::ostream& os) { // NOLINT
+ JSObjectPrint(os);
+}
+
+void JSStringIterator::JSStringIteratorPrint(std::ostream& os) { // NOLINT
+ JSObjectPrintHeader(os, *this, "JSStringIterator");
+ os << "\n - string: " << Brief(string());
+ os << "\n - index: " << index();
+ JSObjectPrintBody(os, *this);
+}
+
+void JSAsyncFromSyncIterator::JSAsyncFromSyncIteratorPrint(
+ std::ostream& os) { // NOLINT
+ JSObjectPrintHeader(os, *this, "JSAsyncFromSyncIterator");
+ os << "\n - sync_iterator: " << Brief(sync_iterator());
+ os << "\n - next: " << Brief(next());
+ JSObjectPrintBody(os, *this);
+}
+
void JSPrimitiveWrapper::JSPrimitiveWrapperPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSPrimitiveWrapper");
os << "\n - value: " << Brief(value());
@@ -1321,7 +1155,7 @@ void WeakCell::WeakCellPrint(std::ostream& os) {
os << "\n - holdings: " << Brief(holdings());
os << "\n - prev: " << Brief(prev());
os << "\n - next: " << Brief(next());
- os << "\n - key: " << Brief(key());
+ os << "\n - unregister_token: " << Brief(unregister_token());
os << "\n - key_list_prev: " << Brief(key_list_prev());
os << "\n - key_list_next: " << Brief(key_list_next());
}
@@ -1503,6 +1337,22 @@ void SharedFunctionInfo::PrintSourceCode(std::ostream& os) {
}
}
+void SmallOrderedHashSet::SmallOrderedHashSetPrint(std::ostream& os) {
+ PrintHeader(os, "SmallOrderedHashSet");
+ // TODO(tebbi): Print all fields.
+}
+
+void SmallOrderedHashMap::SmallOrderedHashMapPrint(std::ostream& os) {
+ PrintHeader(os, "SmallOrderedHashMap");
+ // TODO(tebbi): Print all fields.
+}
+
+void SmallOrderedNameDictionary::SmallOrderedNameDictionaryPrint(
+ std::ostream& os) {
+ PrintHeader(os, "SmallOrderedNameDictionary");
+ // TODO(tebbi): Print all fields.
+}
+
void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "SharedFunctionInfo");
os << "\n - name: ";
@@ -1529,9 +1379,8 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) { // NOLINT
os << "\n - data: " << Brief(function_data());
os << "\n - code (from data): " << Brief(GetCode());
PrintSourceCode(os);
- // Script files are often large, hard to read.
- // os << "\n - script =";
- // script()->Print(os);
+ // Script files are often large, thus only print their {Brief} representation.
+ os << "\n - script: " << Brief(script());
os << "\n - function token position: " << function_token_position();
os << "\n - start position: " << StartPosition();
os << "\n - end position: " << EndPosition();
@@ -1824,7 +1673,6 @@ void AsmWasmData::AsmWasmDataPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "AsmWasmData");
os << "\n - native module: " << Brief(managed_native_module());
os << "\n - export_wrappers: " << Brief(export_wrappers());
- os << "\n - offset table: " << Brief(asm_js_offset_table());
os << "\n - uses bitset: " << uses_bitset().value();
os << "\n";
}
@@ -1913,9 +1761,6 @@ void WasmModuleObject::WasmModuleObjectPrint(std::ostream& os) { // NOLINT
os << "\n - native module: " << native_module();
os << "\n - export wrappers: " << Brief(export_wrappers());
os << "\n - script: " << Brief(script());
- if (has_asm_js_offset_table()) {
- os << "\n - asm_js_offset_table: " << Brief(asm_js_offset_table());
- }
os << "\n";
}
@@ -2179,6 +2024,7 @@ void JSCollator::JSCollatorPrint(std::ostream& os) { // NOLINT
void JSDateTimeFormat::JSDateTimeFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSDateTimeFormat");
+ os << "\n - locale: " << Brief(locale());
os << "\n - icu locale: " << Brief(icu_locale());
os << "\n - icu simple date format: " << Brief(icu_simple_date_format());
os << "\n - icu date interval format: " << Brief(icu_date_interval_format());
@@ -2187,6 +2033,14 @@ void JSDateTimeFormat::JSDateTimeFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintBody(os, *this);
}
+void JSDisplayNames::JSDisplayNamesPrint(std::ostream& os) { // NOLINT
+ JSObjectPrintHeader(os, *this, "JSDisplayNames");
+ os << "\n - internal: " << Brief(internal());
+ os << "\n - style: " << StyleAsString();
+ os << "\n - fallback: " << FallbackAsString();
+ JSObjectPrintBody(os, *this);
+}
+
void JSListFormat::JSListFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSListFormat");
os << "\n - locale: " << Brief(locale());
@@ -2205,6 +2059,7 @@ void JSLocale::JSLocalePrint(std::ostream& os) { // NOLINT
void JSNumberFormat::JSNumberFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSNumberFormat");
os << "\n - locale: " << Brief(locale());
+ os << "\n - numberingSystem: " << Brief(numberingSystem());
os << "\n - icu_number_formatter: " << Brief(icu_number_formatter());
os << "\n - bound_format: " << Brief(bound_format());
JSObjectPrintBody(os, *this);
@@ -2223,6 +2078,7 @@ void JSRelativeTimeFormat::JSRelativeTimeFormatPrint(
std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, *this, "JSRelativeTimeFormat");
os << "\n - locale: " << Brief(locale());
+ os << "\n - numberingSystem: " << Brief(numberingSystem());
os << "\n - style: " << StyleAsString();
os << "\n - numeric: " << NumericAsString();
os << "\n - icu formatter: " << Brief(icu_formatter());
@@ -2282,14 +2138,13 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT
os << "\n - language mode: " << language_mode();
if (is_declaration_scope()) os << "\n - declaration scope";
if (HasReceiver()) {
- os << "\n - receiver: " << ReceiverVariableField::decode(flags);
+ os << "\n - receiver: " << ReceiverVariableBits::decode(flags);
}
if (HasClassBrand()) os << "\n - has class brand";
if (HasSavedClassVariableIndex()) os << "\n - has saved class variable index";
if (HasNewTarget()) os << "\n - needs new target";
if (HasFunctionName()) {
- os << "\n - function name(" << FunctionVariableField::decode(flags)
- << "): ";
+ os << "\n - function name(" << FunctionVariableBits::decode(flags) << "): ";
FunctionName().ShortPrint(os);
}
if (IsAsmModule()) os << "\n - asm module";
@@ -2298,12 +2153,18 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT
if (HasOuterScopeInfo()) {
os << "\n - outer scope info: " << Brief(OuterScopeInfo());
}
+ if (HasLocalsBlackList()) {
+ os << "\n - locals blacklist: " << Brief(LocalsBlackList());
+ }
if (HasFunctionName()) {
os << "\n - function name: " << Brief(FunctionName());
}
if (HasInferredFunctionName()) {
os << "\n - inferred function name: " << Brief(InferredFunctionName());
}
+ if (HasContextExtensionSlot()) {
+ os << "\n - has context extension slot";
+ }
if (HasPositionInfo()) {
os << "\n - start position: " << StartPosition();
@@ -2460,9 +2321,31 @@ void TaggedImpl<kRefType, StorageType>::Print(std::ostream& os) {
}
}
+void HeapNumber::HeapNumberPrint(std::ostream& os) {
+ HeapNumberShortPrint(os);
+ os << "\n";
+}
+
#endif // OBJECT_PRINT
-void HeapNumber::HeapNumberPrint(std::ostream& os) { os << value(); }
+void HeapNumber::HeapNumberShortPrint(std::ostream& os) {
+ static constexpr uint64_t kUint64AllBitsSet =
+ static_cast<uint64_t>(int64_t{-1});
+ // Min/max integer values representable by 52 bits of mantissa and 1 sign bit.
+ static constexpr int64_t kMinSafeInteger =
+ static_cast<int64_t>(kUint64AllBitsSet << 53);
+ static constexpr int64_t kMaxSafeInteger = -(kMinSafeInteger + 1);
+
+ double val = value();
+ if (val == DoubleToInteger(val) &&
+ val >= static_cast<double>(kMinSafeInteger) &&
+ val <= static_cast<double>(kMaxSafeInteger)) {
+ int64_t i = static_cast<int64_t>(val);
+ os << i << ".0";
+ } else {
+ os << val;
+ }
+}
// TODO(cbruni): remove once the new maptracer is in place.
void Name::NameShortPrint() {
@@ -2471,10 +2354,10 @@ void Name::NameShortPrint() {
} else {
DCHECK(this->IsSymbol());
Symbol s = Symbol::cast(*this);
- if (s.name().IsUndefined()) {
+ if (s.description().IsUndefined()) {
PrintF("#<%s>", s.PrivateSymbolToName());
} else {
- PrintF("<%s>", String::cast(s.name()).ToCString().get());
+ PrintF("<%s>", String::cast(s.description()).ToCString().get());
}
}
}
@@ -2486,10 +2369,11 @@ int Name::NameShortPrint(Vector<char> str) {
} else {
DCHECK(this->IsSymbol());
Symbol s = Symbol::cast(*this);
- if (s.name().IsUndefined()) {
+ if (s.description().IsUndefined()) {
return SNPrintF(str, "#<%s>", s.PrivateSymbolToName());
} else {
- return SNPrintF(str, "<%s>", String::cast(s.name()).ToCString().get());
+ return SNPrintF(str, "<%s>",
+ String::cast(s.description()).ToCString().get());
}
}
}
@@ -2540,7 +2424,9 @@ void Map::MapPrint(std::ostream& os) { // NOLINT
}
if (is_access_check_needed()) os << "\n - access_check_needed";
if (!is_extensible()) os << "\n - non-extensible";
- if (is_prototype_map()) {
+ if (IsContextMap()) {
+ os << "\n - native context: " << Brief(native_context());
+ } else if (is_prototype_map()) {
os << "\n - prototype_map";
os << "\n - prototype info: " << Brief(prototype_info());
} else {
@@ -2577,7 +2463,9 @@ void Map::MapPrint(std::ostream& os) { // NOLINT
}
}
os << "\n - prototype: " << Brief(prototype());
- os << "\n - constructor: " << Brief(GetConstructor());
+ if (!IsContextMap()) {
+ os << "\n - constructor: " << Brief(GetConstructor());
+ }
os << "\n - dependent code: " << Brief(dependent_code());
os << "\n - construction counter: " << construction_counter();
os << "\n";
@@ -2808,10 +2696,11 @@ V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) {
if (!isolate->heap()->InSpaceSlow(address, i::CODE_SPACE) &&
!isolate->heap()->InSpaceSlow(address, i::LO_SPACE) &&
- !i::InstructionStream::PcIsOffHeap(isolate, address)) {
+ !i::InstructionStream::PcIsOffHeap(isolate, address) &&
+ !i::ReadOnlyHeap::Contains(address)) {
i::PrintF(
- "%p is not within the current isolate's large object, code or embedded "
- "spaces\n",
+ "%p is not within the current isolate's large object, code, read_only "
+ "or embedded spaces\n",
object);
return;
}
diff --git a/deps/v8/src/diagnostics/perf-jit.cc b/deps/v8/src/diagnostics/perf-jit.cc
index d84c2e4f53..9b42d68037 100644
--- a/deps/v8/src/diagnostics/perf-jit.cc
+++ b/deps/v8/src/diagnostics/perf-jit.cc
@@ -27,29 +27,26 @@
#include "src/diagnostics/perf-jit.h"
+// Only compile the {PerfJitLogger} on Linux.
+#if V8_OS_LINUX
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
#include <memory>
#include "src/codegen/assembler.h"
#include "src/codegen/source-position-table.h"
#include "src/diagnostics/eh-frame.h"
#include "src/objects/objects-inl.h"
+#include "src/objects/shared-function-info.h"
#include "src/snapshot/embedded/embedded-data.h"
#include "src/utils/ostreams.h"
#include "src/wasm/wasm-code-manager.h"
-#if V8_OS_LINUX
-#include <fcntl.h>
-#include <sys/mman.h>
-// jumbo: conflicts with v8::internal::InstanceType::MAP_TYPE
-#undef MAP_TYPE // NOLINT
-#include <unistd.h>
-#endif // V8_OS_LINUX
-
namespace v8 {
namespace internal {
-#if V8_OS_LINUX
-
struct PerfJitHeader {
uint32_t magic_;
uint32_t version_;
@@ -132,6 +129,11 @@ void PerfJitLogger::OpenJitDumpFile() {
int fd = open(perf_dump_name.begin(), O_CREAT | O_TRUNC | O_RDWR, 0666);
if (fd == -1) return;
+ // If --perf-prof-delete-file is given, unlink the file right after opening
+ // it. This keeps the file handle to the file valid. This only works on Linux,
+ // which is the only platform supported for --perf-prof anyway.
+ if (FLAG_perf_prof_delete_file) CHECK_EQ(0, unlink(perf_dump_name.begin()));
+
marker_address_ = OpenMarkerFile(fd);
if (marker_address_ == nullptr) return;
@@ -197,12 +199,13 @@ uint64_t PerfJitLogger::GetTimestamp() {
return (ts.tv_sec * kNsecPerSec) + ts.tv_nsec;
}
-void PerfJitLogger::LogRecordedBuffer(AbstractCode abstract_code,
- SharedFunctionInfo shared,
- const char* name, int length) {
+void PerfJitLogger::LogRecordedBuffer(
+ Handle<AbstractCode> abstract_code,
+ MaybeHandle<SharedFunctionInfo> maybe_shared, const char* name,
+ int length) {
if (FLAG_perf_basic_prof_only_functions &&
- (abstract_code.kind() != AbstractCode::INTERPRETED_FUNCTION &&
- abstract_code.kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
+ (abstract_code->kind() != AbstractCode::INTERPRETED_FUNCTION &&
+ abstract_code->kind() != AbstractCode::OPTIMIZED_FUNCTION)) {
return;
}
@@ -211,28 +214,29 @@ void PerfJitLogger::LogRecordedBuffer(AbstractCode abstract_code,
if (perf_output_handle_ == nullptr) return;
// We only support non-interpreted functions.
- if (!abstract_code.IsCode()) return;
- Code code = abstract_code.GetCode();
- DCHECK(code.raw_instruction_start() == code.address() + Code::kHeaderSize);
+ if (!abstract_code->IsCode()) return;
+ Handle<Code> code = Handle<Code>::cast(abstract_code);
+ DCHECK(code->raw_instruction_start() == code->address() + Code::kHeaderSize);
// Debug info has to be emitted first.
- if (FLAG_perf_prof && !shared.is_null()) {
+ Handle<SharedFunctionInfo> shared;
+ if (FLAG_perf_prof && !maybe_shared.ToHandle(&shared)) {
// TODO(herhut): This currently breaks for js2wasm/wasm2js functions.
- if (code.kind() != Code::JS_TO_WASM_FUNCTION &&
- code.kind() != Code::WASM_TO_JS_FUNCTION) {
+ if (code->kind() != Code::JS_TO_WASM_FUNCTION &&
+ code->kind() != Code::WASM_TO_JS_FUNCTION) {
LogWriteDebugInfo(code, shared);
}
}
const char* code_name = name;
- uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code.InstructionStart());
+ uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code->InstructionStart());
// Code generated by Turbofan will have the safepoint table directly after
// instructions. There is no need to record the safepoint table itself.
- uint32_t code_size = code.ExecutableInstructionSize();
+ uint32_t code_size = code->ExecutableInstructionSize();
// Unwinding info comes right after debug info.
- if (FLAG_perf_prof_unwinding_info) LogWriteUnwindingInfo(code);
+ if (FLAG_perf_prof_unwinding_info) LogWriteUnwindingInfo(*code);
WriteJitCodeLoadEntry(code_pointer, code_size, code_name, length);
}
@@ -328,24 +332,24 @@ SourcePositionInfo GetSourcePositionInfo(Handle<Code> code,
} // namespace
-void PerfJitLogger::LogWriteDebugInfo(Code code, SharedFunctionInfo shared) {
+void PerfJitLogger::LogWriteDebugInfo(Handle<Code> code,
+ Handle<SharedFunctionInfo> shared) {
// Compute the entry count and get the name of the script.
uint32_t entry_count = 0;
- for (SourcePositionTableIterator iterator(code.SourcePositionTable());
+ for (SourcePositionTableIterator iterator(code->SourcePositionTable());
!iterator.done(); iterator.Advance()) {
entry_count++;
}
if (entry_count == 0) return;
// The WasmToJS wrapper stubs have source position entries.
- if (!shared.HasSourceCode()) return;
- Isolate* isolate = shared.GetIsolate();
- Handle<Script> script(Script::cast(shared.script()), isolate);
+ if (!shared->HasSourceCode()) return;
+ Handle<Script> script(Script::cast(shared->script()), isolate_);
PerfJitCodeDebugInfo debug_info;
debug_info.event_ = PerfJitCodeLoad::kDebugInfo;
debug_info.time_stamp_ = GetTimestamp();
- debug_info.address_ = code.InstructionStart();
+ debug_info.address_ = code->InstructionStart();
debug_info.entry_count_ = entry_count;
uint32_t size = sizeof(debug_info);
@@ -353,12 +357,10 @@ void PerfJitLogger::LogWriteDebugInfo(Code code, SharedFunctionInfo shared) {
size += entry_count * sizeof(PerfJitDebugEntry);
// Add the size of the name after each entry.
- Handle<Code> code_handle(code, isolate);
- Handle<SharedFunctionInfo> function_handle(shared, isolate);
- for (SourcePositionTableIterator iterator(code.SourcePositionTable());
+ for (SourcePositionTableIterator iterator(code->SourcePositionTable());
!iterator.done(); iterator.Advance()) {
- SourcePositionInfo info(GetSourcePositionInfo(code_handle, function_handle,
- iterator.source_position()));
+ SourcePositionInfo info(
+ GetSourcePositionInfo(code, shared, iterator.source_position()));
size += GetScriptNameLength(info) + 1;
}
@@ -366,12 +368,12 @@ void PerfJitLogger::LogWriteDebugInfo(Code code, SharedFunctionInfo shared) {
debug_info.size_ = size + padding;
LogWriteBytes(reinterpret_cast<const char*>(&debug_info), sizeof(debug_info));
- Address code_start = code.InstructionStart();
+ Address code_start = code->InstructionStart();
- for (SourcePositionTableIterator iterator(code.SourcePositionTable());
+ for (SourcePositionTableIterator iterator(code->SourcePositionTable());
!iterator.done(); iterator.Advance()) {
- SourcePositionInfo info(GetSourcePositionInfo(code_handle, function_handle,
- iterator.source_position()));
+ SourcePositionInfo info(
+ GetSourcePositionInfo(code, shared, iterator.source_position()));
PerfJitDebugEntry entry;
// The entry point of the function will be placed straight after the ELF
// header when processed by "perf inject". Adjust the position addresses
@@ -523,6 +525,7 @@ void PerfJitLogger::LogWriteHeader() {
LogWriteBytes(reinterpret_cast<const char*>(&header), sizeof(header));
}
-#endif // V8_OS_LINUX
} // namespace internal
} // namespace v8
+
+#endif // V8_OS_LINUX
diff --git a/deps/v8/src/diagnostics/perf-jit.h b/deps/v8/src/diagnostics/perf-jit.h
index 36ab844110..2192063508 100644
--- a/deps/v8/src/diagnostics/perf-jit.h
+++ b/deps/v8/src/diagnostics/perf-jit.h
@@ -28,22 +28,25 @@
#ifndef V8_DIAGNOSTICS_PERF_JIT_H_
#define V8_DIAGNOSTICS_PERF_JIT_H_
+#include "include/v8config.h"
+
+// {PerfJitLogger} is only implemented on Linux.
+#if V8_OS_LINUX
+
#include "src/logging/log.h"
namespace v8 {
namespace internal {
-#if V8_OS_LINUX
-
-// Linux perf tool logging support
+// Linux perf tool logging support.
class PerfJitLogger : public CodeEventLogger {
public:
explicit PerfJitLogger(Isolate* isolate);
~PerfJitLogger() override;
void CodeMoveEvent(AbstractCode from, AbstractCode to) override;
- void CodeDisableOptEvent(AbstractCode code,
- SharedFunctionInfo shared) override {}
+ void CodeDisableOptEvent(Handle<AbstractCode> code,
+ Handle<SharedFunctionInfo> shared) override {}
private:
void OpenJitDumpFile();
@@ -52,7 +55,8 @@ class PerfJitLogger : public CodeEventLogger {
void CloseMarkerFile(void* marker_address);
uint64_t GetTimestamp();
- void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
+ void LogRecordedBuffer(Handle<AbstractCode> code,
+ MaybeHandle<SharedFunctionInfo> maybe_shared,
const char* name, int length) override;
void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
int length) override;
@@ -70,7 +74,7 @@ class PerfJitLogger : public CodeEventLogger {
void LogWriteBytes(const char* bytes, int size);
void LogWriteHeader();
- void LogWriteDebugInfo(Code code, SharedFunctionInfo shared);
+ void LogWriteDebugInfo(Handle<Code> code, Handle<SharedFunctionInfo> shared);
void LogWriteDebugInfo(const wasm::WasmCode* code);
void LogWriteUnwindingInfo(Code code);
@@ -79,6 +83,8 @@ class PerfJitLogger : public CodeEventLogger {
static const uint32_t kElfMachARM = 40;
static const uint32_t kElfMachMIPS = 10;
static const uint32_t kElfMachARM64 = 183;
+ static const uint32_t kElfMachS390x = 22;
+ static const uint32_t kElfMachPPC64 = 21;
uint32_t GetElfMach() {
#if V8_TARGET_ARCH_IA32
@@ -91,6 +97,10 @@ class PerfJitLogger : public CodeEventLogger {
return kElfMachMIPS;
#elif V8_TARGET_ARCH_ARM64
return kElfMachARM64;
+#elif V8_TARGET_ARCH_S390X
+ return kElfMachS390x;
+#elif V8_TARGET_ARCH_PPC64
+ return kElfMachPPC64;
#else
UNIMPLEMENTED();
return 0;
@@ -114,35 +124,9 @@ class PerfJitLogger : public CodeEventLogger {
static uint64_t code_index_;
};
-#else
-
-// PerfJitLogger is only implemented on Linux
-class PerfJitLogger : public CodeEventLogger {
- public:
- explicit PerfJitLogger(Isolate* isolate) : CodeEventLogger(isolate) {}
-
- void CodeMoveEvent(AbstractCode from, AbstractCode to) override {
- UNIMPLEMENTED();
- }
-
- void CodeDisableOptEvent(AbstractCode code,
- SharedFunctionInfo shared) override {
- UNIMPLEMENTED();
- }
-
- void LogRecordedBuffer(AbstractCode code, SharedFunctionInfo shared,
- const char* name, int length) override {
- UNIMPLEMENTED();
- }
-
- void LogRecordedBuffer(const wasm::WasmCode* code, const char* name,
- int length) override {
- UNIMPLEMENTED();
- }
-};
-
-#endif // V8_OS_LINUX
} // namespace internal
} // namespace v8
+#endif // V8_OS_LINUX
+
#endif // V8_DIAGNOSTICS_PERF_JIT_H_
diff --git a/deps/v8/src/diagnostics/ppc/eh-frame-ppc.cc b/deps/v8/src/diagnostics/ppc/eh-frame-ppc.cc
new file mode 100644
index 0000000000..148d01116d
--- /dev/null
+++ b/deps/v8/src/diagnostics/ppc/eh-frame-ppc.cc
@@ -0,0 +1,57 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/codegen/ppc/constants-ppc.h"
+#include "src/diagnostics/eh-frame.h"
+
+namespace v8 {
+namespace internal {
+
+const int EhFrameConstants::kCodeAlignmentFactor = 4;
+// all PPC are 4 bytes instruction
+const int EhFrameConstants::kDataAlignmentFactor = -8; // 64-bit always -8
+
+void EhFrameWriter::WriteReturnAddressRegisterCode() {
+ WriteULeb128(kLrDwarfCode);
+}
+
+void EhFrameWriter::WriteInitialStateInCie() {
+ SetBaseAddressRegisterAndOffset(fp, 0);
+ RecordRegisterNotModified(kLrDwarfCode);
+}
+
+// static
+int EhFrameWriter::RegisterToDwarfCode(Register name) {
+ switch (name.code()) {
+ case kRegCode_fp:
+ return kFpDwarfCode;
+ case kRegCode_sp:
+ return kSpDwarfCode;
+ case kRegCode_r0:
+ return kR0DwarfCode;
+ default:
+ UNIMPLEMENTED();
+ return -1;
+ }
+}
+
+#ifdef ENABLE_DISASSEMBLER
+
+// static
+const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) {
+ switch (code) {
+ case kFpDwarfCode:
+ return "fp";
+ case kSpDwarfCode:
+ return "sp";
+ default:
+ UNIMPLEMENTED();
+ return nullptr;
+ }
+}
+
+#endif
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/src/diagnostics/s390/disasm-s390.cc b/deps/v8/src/diagnostics/s390/disasm-s390.cc
index 9b10e236ce..5bb771fc37 100644
--- a/deps/v8/src/diagnostics/s390/disasm-s390.cc
+++ b/deps/v8/src/diagnostics/s390/disasm-s390.cc
@@ -827,6 +827,13 @@ bool Decoder::DecodeGeneric(Instruction* instr) {
S390_VRR_E_OPCODE_LIST(DECODE_VRR_E_INSTRUCTIONS)
#undef DECODE_VRR_E_INSTRUCTIONS
+#define DECODE_VRR_F_INSTRUCTIONS(name, opcode_name, opcode_value) \
+ case opcode_name: \
+ Format(instr, #name "\t'f1,'r1,'r2"); \
+ break;
+ S390_VRR_F_OPCODE_LIST(DECODE_VRR_F_INSTRUCTIONS)
+#undef DECODE_VRR_F_INSTRUCTIONS
+
#define DECODE_VRX_INSTRUCTIONS(name, opcode_name, opcode_value) \
case opcode_name: \
Format(instr, #name "\t'f1,'d1('r2d,'r3),'m4"); \
diff --git a/deps/v8/src/diagnostics/s390/eh-frame-s390.cc b/deps/v8/src/diagnostics/s390/eh-frame-s390.cc
new file mode 100644
index 0000000000..4f5994c8da
--- /dev/null
+++ b/deps/v8/src/diagnostics/s390/eh-frame-s390.cc
@@ -0,0 +1,65 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/codegen/s390/assembler-s390-inl.h"
+#include "src/diagnostics/eh-frame.h"
+
+namespace v8 {
+namespace internal {
+
+static const int kR0DwarfCode = 0;
+static const int kFpDwarfCode = 11; // frame-pointer
+static const int kR14DwarfCode = 14; // return-address(lr)
+static const int kSpDwarfCode = 15; // stack-pointer
+
+const int EhFrameConstants::kCodeAlignmentFactor = 2; // 1 or 2 in s390
+const int EhFrameConstants::kDataAlignmentFactor = -8;
+
+void EhFrameWriter::WriteReturnAddressRegisterCode() {
+ WriteULeb128(kR14DwarfCode);
+}
+
+void EhFrameWriter::WriteInitialStateInCie() {
+ SetBaseAddressRegisterAndOffset(fp, 0);
+ RecordRegisterNotModified(r14);
+}
+
+// static
+int EhFrameWriter::RegisterToDwarfCode(Register name) {
+ switch (name.code()) {
+ case kRegCode_fp:
+ return kFpDwarfCode;
+ case kRegCode_r14:
+ return kR14DwarfCode;
+ case kRegCode_sp:
+ return kSpDwarfCode;
+ case kRegCode_r0:
+ return kR0DwarfCode;
+ default:
+ UNIMPLEMENTED();
+ return -1;
+ }
+}
+
+#ifdef ENABLE_DISASSEMBLER
+
+// static
+const char* EhFrameDisassembler::DwarfRegisterCodeToString(int code) {
+ switch (code) {
+ case kFpDwarfCode:
+ return "fp";
+ case kR14DwarfCode:
+ return "lr";
+ case kSpDwarfCode:
+ return "sp";
+ default:
+ UNIMPLEMENTED();
+ return nullptr;
+ }
+}
+
+#endif
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/src/diagnostics/unwinder.cc b/deps/v8/src/diagnostics/unwinder.cc
index 84097c288f..64adf17b82 100644
--- a/deps/v8/src/diagnostics/unwinder.cc
+++ b/deps/v8/src/diagnostics/unwinder.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <algorithm>
+
#include "include/v8.h"
#include "src/common/globals.h"
#include "src/execution/frame-constants.h"
@@ -10,17 +12,62 @@ namespace v8 {
namespace {
-bool PCIsInCodeRange(const v8::MemoryRange& code_range, void* pc) {
+const i::byte* CalculateEnd(const void* start, size_t length_in_bytes) {
// Given that the length of the memory range is in bytes and it is not
// necessarily aligned, we need to do the pointer arithmetic in byte* here.
- const i::byte* pc_as_byte = reinterpret_cast<i::byte*>(pc);
- const i::byte* start = reinterpret_cast<const i::byte*>(code_range.start);
- const i::byte* end = start + code_range.length_in_bytes;
- return pc_as_byte >= start && pc_as_byte < end;
+ const i::byte* start_as_byte = reinterpret_cast<const i::byte*>(start);
+ return start_as_byte + length_in_bytes;
+}
+
+bool PCIsInCodeRange(const v8::MemoryRange& code_range, void* pc) {
+ return pc >= code_range.start &&
+ pc < CalculateEnd(code_range.start, code_range.length_in_bytes);
+}
+
+// This relies on the fact that the code pages are ordered, and that they don't
+// overlap.
+bool PCIsInCodePages(size_t code_pages_length, const MemoryRange* code_pages,
+ void* pc) {
+ DCHECK(std::is_sorted(code_pages, code_pages + code_pages_length,
+ [](const MemoryRange& a, const MemoryRange& b) {
+ return a.start < b.start;
+ }));
+
+ MemoryRange fake_range{pc, 1};
+ auto it =
+ std::upper_bound(code_pages, code_pages + code_pages_length, fake_range,
+ [](const MemoryRange& a, const MemoryRange& b) {
+ return a.start < b.start;
+ });
+ DCHECK_IMPLIES(it != code_pages + code_pages_length, pc < it->start);
+ if (it == code_pages) return false;
+ --it;
+ return it->start <= pc && pc < CalculateEnd(it->start, it->length_in_bytes);
+}
+
+bool IsInJSEntryRange(const UnwindState& unwind_state, void* pc) {
+ return PCIsInCodeRange(unwind_state.js_entry_stub.code, pc) ||
+ PCIsInCodeRange(unwind_state.js_construct_entry_stub.code, pc) ||
+ PCIsInCodeRange(unwind_state.js_run_microtasks_entry_stub.code, pc);
}
-bool IsInUnsafeJSEntryRange(const v8::JSEntryStub& js_entry_stub, void* pc) {
- return PCIsInCodeRange(js_entry_stub.code, pc);
+bool IsInUnsafeJSEntryRange(const UnwindState& unwind_state, void* pc) {
+ return IsInJSEntryRange(unwind_state, pc);
+
+ // TODO(petermarshall): We can be more precise by checking whether we are
+ // in JSEntry but after frame setup and before frame teardown, in which case
+ // we are safe to unwind the stack. For now, we bail out if the PC is anywhere
+ // within JSEntry.
+}
+
+bool IsInJSEntryRange(const JSEntryStubs& entry_stubs, void* pc) {
+ return PCIsInCodeRange(entry_stubs.js_entry_stub.code, pc) ||
+ PCIsInCodeRange(entry_stubs.js_construct_entry_stub.code, pc) ||
+ PCIsInCodeRange(entry_stubs.js_run_microtasks_entry_stub.code, pc);
+}
+
+bool IsInUnsafeJSEntryRange(const JSEntryStubs& entry_stubs, void* pc) {
+ return IsInJSEntryRange(entry_stubs, pc);
// TODO(petermarshall): We can be more precise by checking whether we are
// in JSEntry but after frame setup and before frame teardown, in which case
@@ -32,21 +79,74 @@ i::Address Load(i::Address address) {
return *reinterpret_cast<i::Address*>(address);
}
-void* GetReturnAddressFromFP(void* fp) {
+void* GetReturnAddressFromFP(void* fp, void* pc,
+ const v8::UnwindState& unwind_state) {
+ int caller_pc_offset = i::CommonFrameConstants::kCallerPCOffset;
+#ifdef V8_TARGET_ARCH_ARM64
+ if (IsInJSEntryRange(unwind_state, pc)) {
+ caller_pc_offset = i::EntryFrameConstants::kDirectCallerPCOffset;
+ }
+#endif
+ return reinterpret_cast<void*>(
+ Load(reinterpret_cast<i::Address>(fp) + caller_pc_offset));
+}
+
+void* GetReturnAddressFromFP(void* fp, void* pc,
+ const JSEntryStubs& entry_stubs) {
+ int caller_pc_offset = i::CommonFrameConstants::kCallerPCOffset;
+#ifdef V8_TARGET_ARCH_ARM64
+ if (IsInJSEntryRange(entry_stubs, pc)) {
+ caller_pc_offset = i::EntryFrameConstants::kDirectCallerPCOffset;
+ }
+#endif
+ return reinterpret_cast<void*>(
+ Load(reinterpret_cast<i::Address>(fp) + caller_pc_offset));
+}
+
+void* GetCallerFPFromFP(void* fp, void* pc,
+ const v8::UnwindState& unwind_state) {
+ int caller_fp_offset = i::CommonFrameConstants::kCallerFPOffset;
+#ifdef V8_TARGET_ARCH_ARM64
+ if (IsInJSEntryRange(unwind_state, pc)) {
+ caller_fp_offset = i::EntryFrameConstants::kDirectCallerFPOffset;
+ }
+#endif
return reinterpret_cast<void*>(
- Load(reinterpret_cast<i::Address>(fp) +
- i::CommonFrameConstants::kCallerPCOffset));
+ Load(reinterpret_cast<i::Address>(fp) + caller_fp_offset));
}
-void* GetCallerFPFromFP(void* fp) {
+void* GetCallerFPFromFP(void* fp, void* pc, const JSEntryStubs& entry_stubs) {
+ int caller_fp_offset = i::CommonFrameConstants::kCallerFPOffset;
+#ifdef V8_TARGET_ARCH_ARM64
+ if (IsInJSEntryRange(entry_stubs, pc)) {
+ caller_fp_offset = i::EntryFrameConstants::kDirectCallerFPOffset;
+ }
+#endif
return reinterpret_cast<void*>(
- Load(reinterpret_cast<i::Address>(fp) +
- i::CommonFrameConstants::kCallerFPOffset));
+ Load(reinterpret_cast<i::Address>(fp) + caller_fp_offset));
+}
+
+void* GetCallerSPFromFP(void* fp, void* pc,
+ const v8::UnwindState& unwind_state) {
+ int caller_sp_offset = i::CommonFrameConstants::kCallerSPOffset;
+#ifdef V8_TARGET_ARCH_ARM64
+ if (IsInJSEntryRange(unwind_state, pc)) {
+ caller_sp_offset = i::EntryFrameConstants::kDirectCallerSPOffset;
+ }
+#endif
+ return reinterpret_cast<void*>(reinterpret_cast<i::Address>(fp) +
+ caller_sp_offset);
}
-void* GetCallerSPFromFP(void* fp) {
+void* GetCallerSPFromFP(void* fp, void* pc, const JSEntryStubs& entry_stubs) {
+ int caller_sp_offset = i::CommonFrameConstants::kCallerSPOffset;
+#ifdef V8_TARGET_ARCH_ARM64
+ if (IsInJSEntryRange(entry_stubs, pc)) {
+ caller_sp_offset = i::EntryFrameConstants::kDirectCallerSPOffset;
+ }
+#endif
return reinterpret_cast<void*>(reinterpret_cast<i::Address>(fp) +
- i::CommonFrameConstants::kCallerSPOffset);
+ caller_sp_offset);
}
bool AddressIsInStack(const void* address, const void* stack_base,
@@ -62,21 +162,21 @@ bool Unwinder::TryUnwindV8Frames(const UnwindState& unwind_state,
const void* stack_top = register_state->sp;
void* pc = register_state->pc;
- if (PCIsInV8(unwind_state, pc) &&
- !IsInUnsafeJSEntryRange(unwind_state.js_entry_stub, pc)) {
+ if (PCIsInV8(unwind_state, pc) && !IsInUnsafeJSEntryRange(unwind_state, pc)) {
void* current_fp = register_state->fp;
if (!AddressIsInStack(current_fp, stack_base, stack_top)) return false;
// Peek at the return address that the caller pushed. If it's in V8, then we
// assume the caller frame is a JS frame and continue to unwind.
- void* next_pc = GetReturnAddressFromFP(current_fp);
+ void* next_pc = GetReturnAddressFromFP(current_fp, pc, unwind_state);
while (PCIsInV8(unwind_state, next_pc)) {
- current_fp = GetCallerFPFromFP(current_fp);
+ current_fp = GetCallerFPFromFP(current_fp, pc, unwind_state);
if (!AddressIsInStack(current_fp, stack_base, stack_top)) return false;
- next_pc = GetReturnAddressFromFP(current_fp);
+ pc = next_pc;
+ next_pc = GetReturnAddressFromFP(current_fp, pc, unwind_state);
}
- void* final_sp = GetCallerSPFromFP(current_fp);
+ void* final_sp = GetCallerSPFromFP(current_fp, pc, unwind_state);
if (!AddressIsInStack(final_sp, stack_base, stack_top)) return false;
register_state->sp = final_sp;
@@ -84,7 +184,50 @@ bool Unwinder::TryUnwindV8Frames(const UnwindState& unwind_state,
// this is just the rbp value that JSEntryStub pushed. On platforms like
// Win64 this is not used as a dedicated FP register, and could contain
// anything.
- void* final_fp = GetCallerFPFromFP(current_fp);
+ void* final_fp = GetCallerFPFromFP(current_fp, pc, unwind_state);
+ register_state->fp = final_fp;
+
+ register_state->pc = next_pc;
+
+ // Link register no longer valid after unwinding.
+ register_state->lr = nullptr;
+ return true;
+ }
+ return false;
+}
+
+bool Unwinder::TryUnwindV8Frames(const JSEntryStubs& entry_stubs,
+ size_t code_pages_length,
+ const MemoryRange* code_pages,
+ RegisterState* register_state,
+ const void* stack_base) {
+ const void* stack_top = register_state->sp;
+
+ void* pc = register_state->pc;
+ if (PCIsInV8(code_pages_length, code_pages, pc) &&
+ !IsInUnsafeJSEntryRange(entry_stubs, pc)) {
+ void* current_fp = register_state->fp;
+ if (!AddressIsInStack(current_fp, stack_base, stack_top)) return false;
+
+ // Peek at the return address that the caller pushed. If it's in V8, then we
+ // assume the caller frame is a JS frame and continue to unwind.
+ void* next_pc = GetReturnAddressFromFP(current_fp, pc, entry_stubs);
+ while (PCIsInV8(code_pages_length, code_pages, next_pc)) {
+ current_fp = GetCallerFPFromFP(current_fp, pc, entry_stubs);
+ if (!AddressIsInStack(current_fp, stack_base, stack_top)) return false;
+ pc = next_pc;
+ next_pc = GetReturnAddressFromFP(current_fp, pc, entry_stubs);
+ }
+
+ void* final_sp = GetCallerSPFromFP(current_fp, pc, entry_stubs);
+ if (!AddressIsInStack(final_sp, stack_base, stack_top)) return false;
+ register_state->sp = final_sp;
+
+ // We don't check that the final FP value is within the stack bounds because
+ // this is just the rbp value that JSEntryStub pushed. On platforms like
+ // Win64 this is not used as a dedicated FP register, and could contain
+ // anything.
+ void* final_fp = GetCallerFPFromFP(current_fp, pc, entry_stubs);
register_state->fp = final_fp;
register_state->pc = next_pc;
@@ -101,4 +244,9 @@ bool Unwinder::PCIsInV8(const UnwindState& unwind_state, void* pc) {
PCIsInCodeRange(unwind_state.embedded_code_range, pc));
}
+bool Unwinder::PCIsInV8(size_t code_pages_length, const MemoryRange* code_pages,
+ void* pc) {
+ return pc && PCIsInCodePages(code_pages_length, code_pages, pc);
+}
+
} // namespace v8
diff --git a/deps/v8/src/diagnostics/unwinding-info-win64.cc b/deps/v8/src/diagnostics/unwinding-info-win64.cc
index 5a2fc73631..19b03af522 100644
--- a/deps/v8/src/diagnostics/unwinding-info-win64.cc
+++ b/deps/v8/src/diagnostics/unwinding-info-win64.cc
@@ -16,37 +16,6 @@
#error "Unsupported OS"
#endif // V8_OS_WIN_X64
-// Forward declaration to keep this independent of Win8
-NTSYSAPI
-DWORD
-NTAPI
-RtlAddGrowableFunctionTable(
- _Out_ PVOID* DynamicTable,
- _In_reads_(MaximumEntryCount) PRUNTIME_FUNCTION FunctionTable,
- _In_ DWORD EntryCount,
- _In_ DWORD MaximumEntryCount,
- _In_ ULONG_PTR RangeBase,
- _In_ ULONG_PTR RangeEnd
- );
-
-
-NTSYSAPI
-void
-NTAPI
-RtlGrowFunctionTable(
- _Inout_ PVOID DynamicTable,
- _In_ DWORD NewEntryCount
- );
-
-
-NTSYSAPI
-void
-NTAPI
-RtlDeleteGrowableFunctionTable(
- _In_ PVOID DynamicTable
- );
-
-
namespace v8 {
namespace internal {
namespace win64_unwindinfo {
@@ -213,15 +182,17 @@ void InitUnwindingRecord(Record* record, size_t code_size_in_bytes) {
// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
enum UnwindOp8Bit {
OpNop = 0xE3,
+ OpAllocS = 0x00,
OpSaveFpLr = 0x40,
OpSaveFpLrX = 0x80,
OpSetFp = 0xE1,
+ OpAddFp = 0xE2,
OpEnd = 0xE4,
};
typedef uint32_t UNWIND_CODE;
-constexpr UNWIND_CODE Combine8BitUnwindCodes(uint8_t code0,
+constexpr UNWIND_CODE Combine8BitUnwindCodes(uint8_t code0 = OpNop,
uint8_t code1 = OpNop,
uint8_t code2 = OpNop,
uint8_t code3 = OpNop) {
@@ -242,39 +213,97 @@ struct UNWIND_INFO {
uint32_t CodeWords : 5;
};
-static constexpr int kNumberOfUnwindCodes = 1;
+static constexpr int kDefaultNumberOfUnwindCodeWords = 1;
static constexpr int kMaxExceptionThunkSize = 16;
static constexpr int kFunctionLengthShiftSize = 2;
static constexpr int kFunctionLengthMask = (1 << kFunctionLengthShiftSize) - 1;
-static constexpr int kFramePointerAdjustmentShiftSize = 3;
-static constexpr int kFramePointerAdjustmentShiftMask =
- (1 << kFramePointerAdjustmentShiftSize) - 1;
+static constexpr int kAllocStackShiftSize = 4;
+static constexpr int kAllocStackShiftMask = (1 << kAllocStackShiftSize) - 1;
+// Generate an unwind code for "stp fp, lr, [sp, #pre_index_offset]!".
+uint8_t MakeOpSaveFpLrX(int pre_index_offset) {
+ // See unwind code save_fplr_x in
+ // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
+ DCHECK_LE(pre_index_offset, -8);
+ DCHECK_GE(pre_index_offset, -512);
+ constexpr int kShiftSize = 3;
+ constexpr int kShiftMask = (1 << kShiftSize) - 1;
+ DCHECK_EQ(pre_index_offset & kShiftMask, 0);
+ USE(kShiftMask);
+ // Solve for Z where -(Z+1)*8 = pre_index_offset.
+ int encoded_value = (-pre_index_offset >> kShiftSize) - 1;
+ return OpSaveFpLrX | encoded_value;
+}
+
+// Generate an unwind code for "sub sp, sp, #stack_space".
+uint8_t MakeOpAllocS(int stack_space) {
+ // See unwind code alloc_s in
+ // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
+ DCHECK_GE(stack_space, 0);
+ DCHECK_LT(stack_space, 512);
+ DCHECK_EQ(stack_space & kAllocStackShiftMask, 0);
+ return OpAllocS | (stack_space >> kAllocStackShiftSize);
+}
+
+// Generate the second byte of the unwind code for "add fp, sp, #offset".
+uint8_t MakeOpAddFpArgument(int offset) {
+ // See unwind code add_fp in
+ // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
+ DCHECK_GE(offset, 0);
+ constexpr int kShiftSize = 3;
+ constexpr int kShiftMask = (1 << kShiftSize) - 1;
+ DCHECK_EQ(offset & kShiftMask, 0);
+ USE(kShiftMask);
+ int encoded_value = offset >> kShiftSize;
+ // Encoded value must fit in 8 bits.
+ DCHECK_LE(encoded_value, 0xff);
+ return encoded_value;
+}
+
+template <int kNumberOfUnwindCodeWords = kDefaultNumberOfUnwindCodeWords>
struct V8UnwindData {
UNWIND_INFO unwind_info;
- UNWIND_CODE unwind_codes[kNumberOfUnwindCodes];
+ UNWIND_CODE unwind_codes[kNumberOfUnwindCodeWords];
V8UnwindData() {
memset(&unwind_info, 0, sizeof(UNWIND_INFO));
unwind_info.X = 1; // has exception handler after unwind-codes.
- unwind_info.CodeWords = 1;
-
- // stp fp, lr, [sp, #offset]!
- unwind_codes[0] = Combine8BitUnwindCodes(OpSetFp, OpSaveFpLrX, OpEnd);
+ unwind_info.CodeWords = kNumberOfUnwindCodeWords;
+
+ // Generate unwind codes for the following prolog:
+ //
+ // stp fp, lr, [sp, #-kCallerSPOffset]!
+ // mov fp, sp
+ //
+ // This is a very rough approximation of the actual function prologs used in
+ // V8. In particular, we often push other data before the (fp, lr) pair,
+ // meaning the stack pointer computed for the caller frame is wrong. That
+ // error is acceptable when the unwinding info for the caller frame also
+ // depends on fp rather than sp, as is the case for V8 builtins and runtime-
+ // generated code.
+ STATIC_ASSERT(kNumberOfUnwindCodeWords >= 1);
+ unwind_codes[0] = Combine8BitUnwindCodes(
+ OpSetFp, MakeOpSaveFpLrX(-CommonFrameConstants::kCallerSPOffset),
+ OpEnd);
+
+ // Fill the rest with nops.
+ for (int i = 1; i < kNumberOfUnwindCodeWords; ++i) {
+ unwind_codes[i] = Combine8BitUnwindCodes();
+ }
}
};
struct CodeRangeUnwindingRecord {
void* dynamic_table;
uint32_t runtime_function_count;
- V8UnwindData unwind_info;
+ V8UnwindData<> unwind_info;
uint32_t exception_handler;
// For Windows ARM64 unwinding, register 2 unwind_info for each code range,
// unwind_info for all full size ranges (1MB - 4 bytes) and unwind_info1 for
// the remaining non full size range. There is at most 1 range which is less
// than full size.
- V8UnwindData unwind_info1;
+ V8UnwindData<> unwind_info1;
uint32_t exception_handler1;
uint8_t exception_thunk[kMaxExceptionThunkSize];
@@ -286,33 +315,66 @@ struct CodeRangeUnwindingRecord {
#pragma pack(pop)
-std::vector<uint8_t> GetUnwindInfoForBuiltinFunction(uint32_t func_len,
- int32_t fp_adjustment) {
+FrameOffsets::FrameOffsets()
+ : fp_to_saved_caller_fp(CommonFrameConstants::kCallerFPOffset),
+ fp_to_caller_sp(CommonFrameConstants::kCallerSPOffset) {}
+bool FrameOffsets::IsDefault() const {
+ FrameOffsets other;
+ return fp_to_saved_caller_fp == other.fp_to_saved_caller_fp &&
+ fp_to_caller_sp == other.fp_to_caller_sp;
+}
+
+std::vector<uint8_t> GetUnwindInfoForBuiltinFunction(
+ uint32_t func_len, FrameOffsets fp_adjustment) {
DCHECK_LE(func_len, kMaxFunctionLength);
DCHECK_EQ((func_len & kFunctionLengthMask), 0);
USE(kFunctionLengthMask);
- // Unwind code save_fplr requires the offset to be within range [0, 504].
- // This range is defined in below doc for unwind code save_fplr.
- // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
- DCHECK_GE(fp_adjustment, 0);
- DCHECK_LE(fp_adjustment, 504);
- DCHECK_EQ((fp_adjustment & kFramePointerAdjustmentShiftMask), 0);
- USE(kFramePointerAdjustmentShiftMask);
+ // The largest size of unwind data required for all options below.
+ constexpr int kMaxNumberOfUnwindCodeWords = 2;
- V8UnwindData xdata;
+ V8UnwindData<kMaxNumberOfUnwindCodeWords> xdata;
// FunctionLength is ensured to be aligned at instruction size and Windows
// ARM64 doesn't encoding its 2 LSB.
xdata.unwind_info.FunctionLength = func_len >> kFunctionLengthShiftSize;
- xdata.unwind_info.CodeWords = 1;
- xdata.unwind_codes[0] = Combine8BitUnwindCodes(
- OpSetFp,
- (OpSaveFpLr | (fp_adjustment >> kFramePointerAdjustmentShiftSize)),
- OpEnd);
+
+ if (fp_adjustment.IsDefault()) {
+ // One code word is plenty.
+ STATIC_ASSERT(kDefaultNumberOfUnwindCodeWords <
+ kMaxNumberOfUnwindCodeWords);
+ xdata.unwind_info.CodeWords = kDefaultNumberOfUnwindCodeWords;
+ } else {
+ // We want to convey the following facts:
+ // 1. The caller's fp is found at [fp + fp_to_saved_caller_fp].
+ // 2. The caller's pc is found at [fp + fp_to_saved_caller_fp + 8].
+ // 3. The caller's sp is equal to fp + fp_to_caller_sp.
+ //
+ // An imaginary prolog that would establish those relationships might look
+ // like the following, with appropriate values for the various constants:
+ //
+ // stp fp, lr, [sp, #pre_index_amount]!
+ // sub sp, sp, #stack_space
+ // add fp, sp, offset_from_stack_top
+ //
+ // Why do we need offset_from_stack_top? The unwinding encoding for
+ // allocating stack space has 16-byte granularity, and the frame pointer has
+ // only 8-byte alignment.
+ int pre_index_amount =
+ fp_adjustment.fp_to_saved_caller_fp - fp_adjustment.fp_to_caller_sp;
+ int stack_space = fp_adjustment.fp_to_saved_caller_fp;
+ int offset_from_stack_top = stack_space & kAllocStackShiftMask;
+ stack_space += offset_from_stack_top;
+
+ xdata.unwind_codes[0] = Combine8BitUnwindCodes(
+ OpAddFp, MakeOpAddFpArgument(offset_from_stack_top),
+ MakeOpAllocS(stack_space), MakeOpSaveFpLrX(pre_index_amount));
+ xdata.unwind_codes[1] = Combine8BitUnwindCodes(OpEnd);
+ }
return std::vector<uint8_t>(
reinterpret_cast<uint8_t*>(&xdata),
- reinterpret_cast<uint8_t*>(&xdata) + sizeof(xdata));
+ reinterpret_cast<uint8_t*>(
+ &xdata.unwind_codes[xdata.unwind_info.CodeWords]));
}
template <typename Record>
@@ -542,17 +604,13 @@ void XdataEncoder::onSaveFpLr() {
current_frame_code_offset_ = assembler_.pc_offset() - 4;
fp_offsets_.push_back(current_frame_code_offset_);
fp_adjustments_.push_back(current_frame_adjustment_);
- if (current_frame_adjustment_ != 0) {
- current_frame_adjustment_ = 0;
- }
+ current_frame_adjustment_ = FrameOffsets();
}
-void XdataEncoder::onFramePointerAdjustment(int bytes) {
- // According to below doc, offset for save_fplr is aligned to pointer size.
- // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
- DCHECK_EQ((bytes & kPointerAlignmentMask), 0);
-
- current_frame_adjustment_ = bytes;
+void XdataEncoder::onFramePointerAdjustment(int fp_to_saved_caller_fp,
+ int fp_to_caller_sp) {
+ current_frame_adjustment_.fp_to_saved_caller_fp = fp_to_saved_caller_fp;
+ current_frame_adjustment_.fp_to_caller_sp = fp_to_caller_sp;
}
#endif // V8_OS_WIN_X64
diff --git a/deps/v8/src/diagnostics/unwinding-info-win64.h b/deps/v8/src/diagnostics/unwinding-info-win64.h
index 8f8c9469eb..102df15590 100644
--- a/deps/v8/src/diagnostics/unwinding-info-win64.h
+++ b/deps/v8/src/diagnostics/unwinding-info-win64.h
@@ -114,6 +114,13 @@ class XdataEncoder {
*/
static const int kMaxFunctionLength = ((1 << 18) - 1) << 2;
+struct FrameOffsets {
+ FrameOffsets();
+ bool IsDefault() const;
+ int fp_to_saved_caller_fp;
+ int fp_to_caller_sp;
+};
+
/**
* Returns a vector of bytes that contains the Win ARM64 unwind data used for
* all V8 builtin functions.
@@ -123,18 +130,20 @@ static const int kMaxFunctionLength = ((1 << 18) - 1) << 2;
* this is necessary to encode unwind data for Windows stack
* unwinder to find correct caller's fp.
*/
-std::vector<uint8_t> GetUnwindInfoForBuiltinFunction(uint32_t func_len,
- int32_t fp_adjustment);
+std::vector<uint8_t> GetUnwindInfoForBuiltinFunction(
+ uint32_t func_len, FrameOffsets fp_adjustment);
class BuiltinUnwindInfo {
public:
BuiltinUnwindInfo() : is_leaf_function_(true) {}
explicit BuiltinUnwindInfo(const std::vector<int>& fp_offsets,
- const std::vector<int>& fp_adjustments)
+ const std::vector<FrameOffsets>& fp_adjustments)
: is_leaf_function_(false),
fp_offsets_(fp_offsets),
fp_adjustments_(fp_adjustments) {}
- const std::vector<int>& fp_adjustments() const { return fp_adjustments_; }
+ const std::vector<FrameOffsets>& fp_adjustments() const {
+ return fp_adjustments_;
+ }
bool is_leaf_function() const { return is_leaf_function_; }
const std::vector<int>& fp_offsets() const { return fp_offsets_; }
@@ -142,18 +151,16 @@ class BuiltinUnwindInfo {
private:
bool is_leaf_function_;
std::vector<int> fp_offsets_;
- std::vector<int> fp_adjustments_;
+ std::vector<FrameOffsets> fp_adjustments_;
};
class XdataEncoder {
public:
explicit XdataEncoder(const Assembler& assembler)
- : assembler_(assembler),
- current_frame_code_offset_(-1),
- current_frame_adjustment_(0) {}
+ : assembler_(assembler), current_frame_code_offset_(-1) {}
void onSaveFpLr();
- void onFramePointerAdjustment(int bytes);
+ void onFramePointerAdjustment(int fp_to_saved_caller_fp, int fp_to_caller_sp);
BuiltinUnwindInfo unwinding_info() const {
return BuiltinUnwindInfo(fp_offsets_, fp_adjustments_);
@@ -163,8 +170,8 @@ class XdataEncoder {
const Assembler& assembler_;
std::vector<int> fp_offsets_;
int current_frame_code_offset_;
- int current_frame_adjustment_;
- std::vector<int> fp_adjustments_;
+ FrameOffsets current_frame_adjustment_;
+ std::vector<FrameOffsets> fp_adjustments_;
};
#endif
diff --git a/deps/v8/src/diagnostics/x64/disasm-x64.cc b/deps/v8/src/diagnostics/x64/disasm-x64.cc
index 2195556af7..a1331784a3 100644
--- a/deps/v8/src/diagnostics/x64/disasm-x64.cc
+++ b/deps/v8/src/diagnostics/x64/disasm-x64.cc
@@ -11,6 +11,7 @@
#include "src/base/compiler-specific.h"
#include "src/base/lazy-instance.h"
+#include "src/base/memory.h"
#include "src/base/v8-fallthrough.h"
#include "src/codegen/x64/register-x64.h"
#include "src/codegen/x64/sse-instr.h"
@@ -245,19 +246,24 @@ uint8_t Imm8_U(const uint8_t* data) {
return *reinterpret_cast<const uint8_t*>(data);
}
int16_t Imm16(const uint8_t* data) {
- return *reinterpret_cast<const int16_t*>(data);
+ return v8::base::ReadUnalignedValue<int16_t>(
+ reinterpret_cast<v8::internal::Address>(data));
}
uint16_t Imm16_U(const uint8_t* data) {
- return *reinterpret_cast<const uint16_t*>(data);
+ return v8::base::ReadUnalignedValue<uint16_t>(
+ reinterpret_cast<v8::internal::Address>(data));
}
int32_t Imm32(const uint8_t* data) {
- return *reinterpret_cast<const int32_t*>(data);
+ return v8::base::ReadUnalignedValue<int32_t>(
+ reinterpret_cast<v8::internal::Address>(data));
}
uint32_t Imm32_U(const uint8_t* data) {
- return *reinterpret_cast<const uint32_t*>(data);
+ return v8::base::ReadUnalignedValue<uint32_t>(
+ reinterpret_cast<v8::internal::Address>(data));
}
int64_t Imm64(const uint8_t* data) {
- return *reinterpret_cast<const int64_t*>(data);
+ return v8::base::ReadUnalignedValue<int64_t>(
+ reinterpret_cast<v8::internal::Address>(data));
}
} // namespace
@@ -673,7 +679,7 @@ int DisassemblerX64::F6F7Instruction(byte* data) {
byte modrm = *(data + 1);
int mod, regop, rm;
get_modrm(modrm, &mod, &regop, &rm);
- if (mod == 3 && regop != 0) {
+ if (regop != 0) {
const char* mnem = nullptr;
switch (regop) {
case 2:
@@ -697,8 +703,18 @@ int DisassemblerX64::F6F7Instruction(byte* data) {
default:
UnimplementedInstruction();
}
- AppendToBuffer("%s%c %s", mnem, operand_size_code(), NameOfCPURegister(rm));
- return 2;
+ if (mod == 3) {
+ AppendToBuffer("%s%c %s", mnem, operand_size_code(),
+ NameOfCPURegister(rm));
+ return 2;
+ } else if (mod == 1) {
+ AppendToBuffer("%s%c ", mnem, operand_size_code());
+ int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
+ return 1 + count;
+ } else {
+ UnimplementedInstruction();
+ return 2;
+ }
} else if (regop == 0) {
AppendToBuffer("test%c ", operand_size_code());
int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
@@ -819,6 +835,10 @@ int DisassemblerX64::AVXInstruction(byte* data) {
int mod, regop, rm, vvvv = vex_vreg();
get_modrm(*current, &mod, &regop, &rm);
switch (opcode) {
+ case 0x18:
+ AppendToBuffer("vbroadcastss %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ break;
case 0x99:
AppendToBuffer("vfmadd132s%c %s,%s,", float_size_code(),
NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
@@ -829,6 +849,11 @@ int DisassemblerX64::AVXInstruction(byte* data) {
NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
current += PrintRightXMMOperand(current);
break;
+ case 0xB8:
+ AppendToBuffer("vfmadd231p%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
case 0xB9:
AppendToBuffer("vfmadd231s%c %s,%s,", float_size_code(),
NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
@@ -849,6 +874,11 @@ int DisassemblerX64::AVXInstruction(byte* data) {
NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
current += PrintRightXMMOperand(current);
break;
+ case 0xBC:
+ AppendToBuffer("vfnmadd231p%c %s,%s,", float_size_code(),
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
case 0x9D:
AppendToBuffer("vfnmadd132s%c %s,%s,", float_size_code(),
NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
@@ -896,7 +926,19 @@ int DisassemblerX64::AVXInstruction(byte* data) {
SSSE3_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
SSE4_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
+ SSE4_2_INSTRUCTION_LIST(DECLARE_SSE_AVX_DIS_CASE)
#undef DECLARE_SSE_AVX_DIS_CASE
+
+#define DECLARE_SSE_PMOV_AVX_DIS_CASE(instruction, notUsed1, notUsed2, \
+ notUsed3, opcode) \
+ case 0x##opcode: { \
+ AppendToBuffer("v" #instruction " %s,", NameOfXMMRegister(regop)); \
+ current += PrintRightXMMOperand(current); \
+ break; \
+ }
+ SSE4_PMOV_INSTRUCTION_LIST(DECLARE_SSE_PMOV_AVX_DIS_CASE)
+#undef DECLARE_SSE_PMOV_AVX_DIS_CASE
+
default:
UnimplementedInstruction();
}
@@ -916,6 +958,18 @@ int DisassemblerX64::AVXInstruction(byte* data) {
current += PrintRightXMMOperand(current);
AppendToBuffer(",0x%x", *current++);
break;
+ case 0x0E:
+ AppendToBuffer("vpblendw %s,%s,", NameOfXMMRegister(regop),
+ NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",0x%x", *current++);
+ break;
+ case 0x0F:
+ AppendToBuffer("vpalignr %s,%s,", NameOfXMMRegister(regop),
+ NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",0x%x", *current++);
+ break;
case 0x14:
AppendToBuffer("vpextrb ");
current += PrintRightByteOperand(current);
@@ -927,7 +981,12 @@ int DisassemblerX64::AVXInstruction(byte* data) {
AppendToBuffer(",%s,0x%x,", NameOfXMMRegister(regop), *current++);
break;
case 0x16:
- AppendToBuffer("vpextrd ");
+ AppendToBuffer("vpextr%c ", rex_w() ? 'q' : 'd');
+ current += PrintRightOperand(current);
+ AppendToBuffer(",%s,0x%x,", NameOfXMMRegister(regop), *current++);
+ break;
+ case 0x17:
+ AppendToBuffer("vextractps ");
current += PrintRightOperand(current);
AppendToBuffer(",%s,0x%x,", NameOfXMMRegister(regop), *current++);
break;
@@ -937,12 +996,25 @@ int DisassemblerX64::AVXInstruction(byte* data) {
current += PrintRightByteOperand(current);
AppendToBuffer(",0x%x", *current++);
break;
- case 0x22:
- AppendToBuffer("vpinsrd %s,%s,", NameOfXMMRegister(regop),
+ case 0x21:
+ AppendToBuffer("vinsertps %s,%s,", NameOfXMMRegister(regop),
NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",0x%x", *current++);
+ break;
+ case 0x22:
+ AppendToBuffer("vpinsr%c %s,%s,", rex_w() ? 'q' : 'd',
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
current += PrintRightOperand(current);
AppendToBuffer(",0x%x", *current++);
break;
+ case 0x4B: {
+ AppendToBuffer("vblendvpd %s,%s,", NameOfXMMRegister(regop),
+ NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",%s", NameOfXMMRegister((*current++) >> 4));
+ break;
+ }
default:
UnimplementedInstruction();
}
@@ -1015,6 +1087,15 @@ int DisassemblerX64::AVXInstruction(byte* data) {
NameOfXMMRegister(vvvv));
current += PrintRightXMMOperand(current);
break;
+ case 0x6F:
+ AppendToBuffer("vmovdqu %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ break;
+ case 0x7F:
+ AppendToBuffer("vmovdqu ");
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",%s", NameOfXMMRegister(regop));
+ break;
default:
UnimplementedInstruction();
}
@@ -1037,6 +1118,10 @@ int DisassemblerX64::AVXInstruction(byte* data) {
}
AppendToBuffer(",%s", NameOfXMMRegister(regop));
break;
+ case 0x12:
+ AppendToBuffer("vmovddup %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ break;
case 0x2A:
AppendToBuffer("%s %s,%s,", vex_w() ? "vcvtqsi2sd" : "vcvtlsi2sd",
NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
@@ -1096,6 +1181,11 @@ int DisassemblerX64::AVXInstruction(byte* data) {
AppendToBuffer("vlddqu %s,", NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
break;
+ case 0x70:
+ AppendToBuffer("vpshuflw %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",0x%x", *current++);
+ break;
case 0x7C:
AppendToBuffer("vhaddps %s,%s,", NameOfXMMRegister(regop),
NameOfXMMRegister(vvvv));
@@ -1225,6 +1315,11 @@ int DisassemblerX64::AVXInstruction(byte* data) {
current += PrintRightXMMOperand(current);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
break;
+ case 0x16:
+ AppendToBuffer("vmovlhps %s,%s,", NameOfXMMRegister(regop),
+ NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ break;
case 0x28:
AppendToBuffer("vmovaps %s,", NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
@@ -1242,21 +1337,45 @@ int DisassemblerX64::AVXInstruction(byte* data) {
AppendToBuffer("vmovmskps %s,", NameOfCPURegister(regop));
current += PrintRightXMMOperand(current);
break;
- case 0x54:
- AppendToBuffer("vandps %s,%s,", NameOfXMMRegister(regop),
- NameOfXMMRegister(vvvv));
+ case 0x51:
+ case 0x52:
+ case 0x53: {
+ const char* const pseudo_op[] = {"vsqrtps", "vrsqrtps", "vrcpps"};
+
+ AppendToBuffer("%s %s,", pseudo_op[opcode - 0x51],
+ NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
break;
- case 0x55:
- AppendToBuffer("vandnps %s,%s,", NameOfXMMRegister(regop),
- NameOfXMMRegister(vvvv));
+ }
+ case 0x5A:
+ case 0x5B: {
+ const char* const pseudo_op[] = {"vcvtps2pd", "vcvtdq2ps"};
+
+ AppendToBuffer("%s %s,", pseudo_op[opcode - 0x5A],
+ NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
break;
+ }
+ case 0x54:
+ case 0x55:
+ case 0x56:
case 0x57:
- AppendToBuffer("vxorps %s,%s,", NameOfXMMRegister(regop),
- NameOfXMMRegister(vvvv));
+ case 0x58:
+ case 0x59:
+ case 0x5C:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F: {
+ const char* const pseudo_op[] = {
+ "vandps", "vandnps", "vorps", "vxorps", "vaddps", "vmulps",
+ "", "", "vsubps", "vminps", "vdivps", "vmaxps",
+ };
+
+ AppendToBuffer("%s %s,%s,", pseudo_op[opcode - 0x54],
+ NameOfXMMRegister(regop), NameOfXMMRegister(vvvv));
current += PrintRightXMMOperand(current);
break;
+ }
case 0xC2: {
AppendToBuffer("vcmpps %s,%s,", NameOfXMMRegister(regop),
NameOfXMMRegister(vvvv));
@@ -1267,6 +1386,13 @@ int DisassemblerX64::AVXInstruction(byte* data) {
current += 1;
break;
}
+ case 0xC6: {
+ AppendToBuffer("vshufps %s,%s,", NameOfXMMRegister(regop),
+ NameOfXMMRegister(vvvv));
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",0x%x", *current++);
+ break;
+ }
default:
UnimplementedInstruction();
}
@@ -1675,6 +1801,12 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
current = data + 3;
get_modrm(*current, &mod, &regop, &rm);
switch (third_byte) {
+ case 0x15: {
+ AppendToBuffer("blendvpd %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",<xmm0>");
+ break;
+ }
#define SSE34_DIS_CASE(instruction, notUsed1, notUsed2, notUsed3, opcode) \
case 0x##opcode: { \
AppendToBuffer(#instruction " %s,", NameOfXMMRegister(regop)); \
@@ -1684,6 +1816,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
SSSE3_INSTRUCTION_LIST(SSE34_DIS_CASE)
SSE4_INSTRUCTION_LIST(SSE34_DIS_CASE)
+ SSE4_PMOV_INSTRUCTION_LIST(SSE34_DIS_CASE)
SSE4_2_INSTRUCTION_LIST(SSE34_DIS_CASE)
#undef SSE34_DIS_CASE
default:
@@ -1714,14 +1847,14 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
} else if (third_byte == 0x0E) {
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("pblendw %s,", NameOfXMMRegister(regop));
- current += PrintRightXMMOperand(data);
- AppendToBuffer(",0x%x", (*current) & 3);
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",0x%x", *current);
current += 1;
} else if (third_byte == 0x0F) {
- get_modrm(*data, &mod, &regop, &rm);
+ get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("palignr %s,", NameOfXMMRegister(regop));
- current += PrintRightXMMOperand(data);
- AppendToBuffer(",0x%x", (*current) & 3);
+ current += PrintRightXMMOperand(current);
+ AppendToBuffer(",0x%x", (*current));
current += 1;
} else if (third_byte == 0x14) {
get_modrm(*current, &mod, &regop, &rm);
@@ -1754,7 +1887,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
// insertps xmm, xmm/m32, imm8
AppendToBuffer("insertps %s,", NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
- AppendToBuffer(",0x%x", (*current) & 3);
+ AppendToBuffer(",0x%x", (*current));
current += 1;
} else if (third_byte == 0x22) {
get_modrm(*current, &mod, &regop, &rm);
@@ -1767,6 +1900,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
} else {
UnimplementedInstruction();
}
+ } else if (opcode == 0xC1) {
+ current += PrintOperands("xadd", OPER_REG_OP_ORDER, current);
} else {
get_modrm(*current, &mod, &regop, &rm);
if (opcode == 0x1F) {
@@ -1907,6 +2042,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
mnemonic = "pcmpeqw";
} else if (opcode == 0x76) {
mnemonic = "pcmpeqd";
+ } else if (opcode == 0xC2) {
+ mnemonic = "cmppd";
} else if (opcode == 0xD1) {
mnemonic = "psrlw";
} else if (opcode == 0xD2) {
@@ -1933,10 +2070,14 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
mnemonic = "paddusw";
} else if (opcode == 0xDE) {
mnemonic = "pmaxub";
+ } else if (opcode == 0xE0) {
+ mnemonic = "pavgb";
} else if (opcode == 0xE1) {
mnemonic = "psraw";
} else if (opcode == 0xE2) {
mnemonic = "psrad";
+ } else if (opcode == 0xE3) {
+ mnemonic = "pavgw";
} else if (opcode == 0xE8) {
mnemonic = "psubsb";
} else if (opcode == 0xE9) {
@@ -1975,8 +2116,6 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
mnemonic = "paddw";
} else if (opcode == 0xFE) {
mnemonic = "paddd";
- } else if (opcode == 0xC2) {
- mnemonic = "cmppd";
} else {
UnimplementedInstruction();
}
@@ -2176,6 +2315,12 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
AppendToBuffer("%s,", NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
}
+ } else if (opcode == 0x16) {
+ // movlhps xmm1, xmm2
+ int mod, regop, rm;
+ get_modrm(*current, &mod, &regop, &rm);
+ AppendToBuffer("movlhps %s,", NameOfXMMRegister(regop));
+ current += PrintRightXMMOperand(current);
} else if (opcode == 0x1F) {
// NOP
int mod, regop, rm;
@@ -2233,6 +2378,11 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
+ } else if (opcode == 0xC0) {
+ byte_size_operand_ = true;
+ current += PrintOperands("xadd", OPER_REG_OP_ORDER, current);
+ } else if (opcode == 0xC1) {
+ current += PrintOperands("xadd", OPER_REG_OP_ORDER, current);
} else if (opcode == 0xC2) {
// cmpps xmm, xmm/m128, imm8
int mod, regop, rm;
@@ -2261,13 +2411,6 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("movmskps %s,", NameOfCPURegister(regop));
current += PrintRightXMMOperand(current);
- } else if (opcode == 0x70) {
- int mod, regop, rm;
- get_modrm(*current, &mod, &regop, &rm);
- AppendToBuffer("pshufw %s, ", NameOfXMMRegister(regop));
- current += PrintRightXMMOperand(current);
- AppendToBuffer(", %d", (*current) & 3);
- current += 1;
} else if ((opcode & 0xF0) == 0x80) {
// Jcc: Conditional jump (branch).
current = data + JumpConditional(data);
@@ -2345,6 +2488,8 @@ const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
return (group_1_prefix_ == 0xF2) ? "mulsd" : "mulss";
case 0x5A: // F2/F3 prefix.
return (group_1_prefix_ == 0xF2) ? "cvtsd2ss" : "cvtss2sd";
+ case 0x5B: // F2/F3 prefix.
+ return "cvttps2dq";
case 0x5D: // F2/F3 prefix.
return (group_1_prefix_ == 0xF2) ? "minsd" : "minss";
case 0x5C: // F2/F3 prefix.