summaryrefslogtreecommitdiff
path: root/deps/v8/src/arm
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2017-08-01 11:36:44 -0500
committerMyles Borins <mylesborins@google.com>2017-08-01 15:23:15 -0500
commit0a66b223e149a841669bfad5598e4254589730cb (patch)
tree5ec050f7f78aafbf5b1e0e50d639fb843141e162 /deps/v8/src/arm
parent1782b3836ba58ef0da6b687f2bb970c0bd8199ad (diff)
downloadnode-new-0a66b223e149a841669bfad5598e4254589730cb.tar.gz
deps: update V8 to 6.0.286.52
PR-URL: https://github.com/nodejs/node/pull/14004 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/src/arm')
-rw-r--r--deps/v8/src/arm/assembler-arm-inl.h118
-rw-r--r--deps/v8/src/arm/assembler-arm.cc471
-rw-r--r--deps/v8/src/arm/assembler-arm.h50
-rw-r--r--deps/v8/src/arm/code-stubs-arm.cc80
-rw-r--r--deps/v8/src/arm/constants-arm.h19
-rw-r--r--deps/v8/src/arm/deoptimizer-arm.cc57
-rw-r--r--deps/v8/src/arm/disasm-arm.cc99
-rw-r--r--deps/v8/src/arm/frames-arm.cc8
-rw-r--r--deps/v8/src/arm/frames-arm.h16
-rw-r--r--deps/v8/src/arm/interface-descriptors-arm.cc18
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc278
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h25
-rw-r--r--deps/v8/src/arm/simulator-arm.cc185
-rw-r--r--deps/v8/src/arm/simulator-arm.h17
14 files changed, 664 insertions, 777 deletions
diff --git a/deps/v8/src/arm/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h
index 50b5ea2053..b5a59bb476 100644
--- a/deps/v8/src/arm/assembler-arm-inl.h
+++ b/deps/v8/src/arm/assembler-arm-inl.h
@@ -75,11 +75,7 @@ Address RelocInfo::target_address_address() {
DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
|| rmode_ == EMBEDDED_OBJECT
|| rmode_ == EXTERNAL_REFERENCE);
- if (FLAG_enable_embedded_constant_pool ||
- Assembler::IsMovW(Memory::int32_at(pc_))) {
- // We return the PC for embedded constant pool since this function is used
- // by the serializer and expects the address to reside within the code
- // object.
+ if (Assembler::IsMovW(Memory::int32_at(pc_))) {
return reinterpret_cast<Address>(pc_);
} else {
DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
@@ -238,22 +234,22 @@ template <typename ObjectVisitor>
void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
- visitor->VisitEmbeddedPointer(this);
+ visitor->VisitEmbeddedPointer(host(), this);
} else if (RelocInfo::IsCodeTarget(mode)) {
- visitor->VisitCodeTarget(this);
+ visitor->VisitCodeTarget(host(), this);
} else if (mode == RelocInfo::CELL) {
- visitor->VisitCell(this);
+ visitor->VisitCellPointer(host(), this);
} else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
- visitor->VisitExternalReference(this);
+ visitor->VisitExternalReference(host(), this);
} else if (mode == RelocInfo::INTERNAL_REFERENCE) {
- visitor->VisitInternalReference(this);
+ visitor->VisitInternalReference(host(), this);
} else if (RelocInfo::IsCodeAgeSequence(mode)) {
- visitor->VisitCodeAgeSequence(this);
+ visitor->VisitCodeAgeSequence(host(), this);
} else if (RelocInfo::IsDebugBreakSlot(mode) &&
IsPatchedDebugBreakSlotSequence()) {
- visitor->VisitDebugTarget(this);
+ visitor->VisitDebugTarget(host(), this);
} else if (RelocInfo::IsRuntimeEntry(mode)) {
- visitor->VisitRuntimeEntry(this);
+ visitor->VisitRuntimeEntry(host(), this);
}
}
@@ -344,32 +340,14 @@ Address Assembler::target_address_from_return_address(Address pc) {
// @ return address
// In cases that need frequent patching, the address is in the
// constant pool. It could be a small constant pool load:
- // ldr ip, [pc / pp, #...] @ call address
- // blx ip
- // @ return address
- // Or an extended constant pool load (ARMv7):
- // movw ip, #...
- // movt ip, #...
- // ldr ip, [pc, ip] @ call address
- // blx ip
- // @ return address
- // Or an extended constant pool load (ARMv6):
- // mov ip, #...
- // orr ip, ip, #...
- // orr ip, ip, #...
- // orr ip, ip, #...
- // ldr ip, [pc, ip] @ call address
+ // ldr ip, [pc, #...] @ call address
// blx ip
// @ return address
Address candidate = pc - 2 * Assembler::kInstrSize;
Instr candidate_instr(Memory::int32_at(candidate));
- if (IsLdrPcImmediateOffset(candidate_instr) |
- IsLdrPpImmediateOffset(candidate_instr)) {
+ if (IsLdrPcImmediateOffset(candidate_instr)) {
return candidate;
} else {
- if (IsLdrPpRegOffset(candidate_instr)) {
- candidate -= Assembler::kInstrSize;
- }
if (CpuFeatures::IsSupported(ARMv7)) {
candidate -= 1 * Assembler::kInstrSize;
DCHECK(IsMovW(Memory::int32_at(candidate)) &&
@@ -388,33 +366,22 @@ Address Assembler::target_address_from_return_address(Address pc) {
Address Assembler::return_address_from_call_start(Address pc) {
- if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) |
- IsLdrPpImmediateOffset(Memory::int32_at(pc))) {
+ if (IsLdrPcImmediateOffset(Memory::int32_at(pc))) {
// Load from constant pool, small section.
return pc + kInstrSize * 2;
} else {
if (CpuFeatures::IsSupported(ARMv7)) {
DCHECK(IsMovW(Memory::int32_at(pc)));
DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
- if (IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))) {
- // Load from constant pool, extended section.
- return pc + kInstrSize * 4;
- } else {
- // A movw / movt load immediate.
- return pc + kInstrSize * 3;
- }
+ // A movw / movt load immediate.
+ return pc + kInstrSize * 3;
} else {
DCHECK(IsMovImmed(Memory::int32_at(pc)));
DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize)));
DCHECK(IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)));
DCHECK(IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
- if (IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize))) {
- // Load from constant pool, extended section.
- return pc + kInstrSize * 6;
- } else {
- // A mov / orr load immediate.
- return pc + kInstrSize * 5;
- }
+ // A mov / orr load immediate.
+ return pc + kInstrSize * 5;
}
}
}
@@ -422,11 +389,7 @@ Address Assembler::return_address_from_call_start(Address pc) {
void Assembler::deserialization_set_special_target_at(
Isolate* isolate, Address constant_pool_entry, Code* code, Address target) {
- if (FLAG_enable_embedded_constant_pool) {
- set_target_address_at(isolate, constant_pool_entry, code, target);
- } else {
- Memory::Address_at(constant_pool_entry) = target;
- }
+ Memory::Address_at(constant_pool_entry) = target;
}
@@ -438,55 +401,18 @@ void Assembler::deserialization_set_target_internal_reference_at(
bool Assembler::is_constant_pool_load(Address pc) {
if (CpuFeatures::IsSupported(ARMv7)) {
- return !Assembler::IsMovW(Memory::int32_at(pc)) ||
- (FLAG_enable_embedded_constant_pool &&
- Assembler::IsLdrPpRegOffset(
- Memory::int32_at(pc + 2 * Assembler::kInstrSize)));
+ return !Assembler::IsMovW(Memory::int32_at(pc));
} else {
- return !Assembler::IsMovImmed(Memory::int32_at(pc)) ||
- (FLAG_enable_embedded_constant_pool &&
- Assembler::IsLdrPpRegOffset(
- Memory::int32_at(pc + 4 * Assembler::kInstrSize)));
+ return !Assembler::IsMovImmed(Memory::int32_at(pc));
}
}
Address Assembler::constant_pool_entry_address(Address pc,
Address constant_pool) {
- if (FLAG_enable_embedded_constant_pool) {
- DCHECK(constant_pool != NULL);
- int cp_offset;
- if (!CpuFeatures::IsSupported(ARMv7) && IsMovImmed(Memory::int32_at(pc))) {
- DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
- IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
- IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)) &&
- IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize)));
- // This is an extended constant pool lookup (ARMv6).
- Instr mov_instr = instr_at(pc);
- Instr orr_instr_1 = instr_at(pc + kInstrSize);
- Instr orr_instr_2 = instr_at(pc + 2 * kInstrSize);
- Instr orr_instr_3 = instr_at(pc + 3 * kInstrSize);
- cp_offset = DecodeShiftImm(mov_instr) | DecodeShiftImm(orr_instr_1) |
- DecodeShiftImm(orr_instr_2) | DecodeShiftImm(orr_instr_3);
- } else if (IsMovW(Memory::int32_at(pc))) {
- DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) &&
- IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize)));
- // This is an extended constant pool lookup (ARMv7).
- Instruction* movw_instr = Instruction::At(pc);
- Instruction* movt_instr = Instruction::At(pc + kInstrSize);
- cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) |
- movw_instr->ImmedMovwMovtValue();
- } else {
- // This is a small constant pool lookup.
- DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc)));
- cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc));
- }
- return constant_pool + cp_offset;
- } else {
- DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc)));
- Instr instr = Memory::int32_at(pc);
- return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
- }
+ DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc)));
+ Instr instr = Memory::int32_at(pc);
+ return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
}
diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc
index 2a7f68c07c..6932e97379 100644
--- a/deps/v8/src/arm/assembler-arm.cc
+++ b/deps/v8/src/arm/assembler-arm.cc
@@ -327,10 +327,9 @@ const int RelocInfo::kApplyMask = 0;
bool RelocInfo::IsCodedSpecially() {
// The deserializer needs to know whether a pointer is specially coded.  Being
- // specially coded on ARM means that it is a movw/movt instruction, or is an
- // embedded constant pool entry.  These only occur if
- // FLAG_enable_embedded_constant_pool is true.
- return FLAG_enable_embedded_constant_pool;
+ // specially coded on ARM means that it is a movw/movt instruction. We don't
+ // generate those for relocatable pointers.
+ return false;
}
@@ -503,18 +502,9 @@ const Instr kPopRegPattern =
// ldr rd, [pc, #offset]
const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
-// ldr rd, [pp, #offset]
-const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
-// ldr rd, [pp, rn]
-const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
// vldr dd, [pc, #offset]
const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
-// vldr dd, [pp, #offset]
-const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
-const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
// blxcc rm
const Instr kBlxRegMask =
15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
@@ -554,8 +544,7 @@ Assembler::Assembler(IsolateData isolate_data, void* buffer, int buffer_size)
: AssemblerBase(isolate_data, buffer, buffer_size),
recorded_ast_id_(TypeFeedbackId::None()),
pending_32_bit_constants_(),
- pending_64_bit_constants_(),
- constant_pool_builder_(kLdrMaxReachBits, kVldrMaxReachBits) {
+ pending_64_bit_constants_() {
pending_32_bit_constants_.reserve(kMinNumPendingConstants);
pending_64_bit_constants_.reserve(kMinNumPendingConstants);
reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_);
@@ -583,13 +572,9 @@ Assembler::~Assembler() {
void Assembler::GetCode(CodeDesc* desc) {
// Emit constant pool if necessary.
int constant_pool_offset = 0;
- if (FLAG_enable_embedded_constant_pool) {
- constant_pool_offset = EmitEmbeddedConstantPool();
- } else {
- CheckConstPool(true, false);
- DCHECK(pending_32_bit_constants_.empty());
- DCHECK(pending_64_bit_constants_.empty());
- }
+ CheckConstPool(true, false);
+ DCHECK(pending_32_bit_constants_.empty());
+ DCHECK(pending_64_bit_constants_.empty());
// Set up code descriptor.
desc->buffer = buffer_;
desc->buffer_size = buffer_size_;
@@ -740,24 +725,6 @@ Register Assembler::GetRm(Instr instr) {
}
-Instr Assembler::GetConsantPoolLoadPattern() {
- if (FLAG_enable_embedded_constant_pool) {
- return kLdrPpImmedPattern;
- } else {
- return kLdrPCImmedPattern;
- }
-}
-
-
-Instr Assembler::GetConsantPoolLoadMask() {
- if (FLAG_enable_embedded_constant_pool) {
- return kLdrPpImmedMask;
- } else {
- return kLdrPCImmedMask;
- }
-}
-
-
bool Assembler::IsPush(Instr instr) {
return ((instr & ~kRdMask) == kPushRegPattern);
}
@@ -795,23 +762,6 @@ bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
}
-bool Assembler::IsLdrPpImmediateOffset(Instr instr) {
- // Check the instruction is indeed a
- // ldr<cond> <Rd>, [pp +/- offset_12].
- return (instr & kLdrPpImmedMask) == kLdrPpImmedPattern;
-}
-
-
-bool Assembler::IsLdrPpRegOffset(Instr instr) {
- // Check the instruction is indeed a
- // ldr<cond> <Rd>, [pp, +/- <Rm>].
- return (instr & kLdrPpRegMask) == kLdrPpRegPattern;
-}
-
-
-Instr Assembler::GetLdrPpRegOffsetPattern() { return kLdrPpRegPattern; }
-
-
bool Assembler::IsVldrDPcImmediateOffset(Instr instr) {
// Check the instruction is indeed a
// vldr<cond> <Dd>, [pc +/- offset_10].
@@ -819,13 +769,6 @@ bool Assembler::IsVldrDPcImmediateOffset(Instr instr) {
}
-bool Assembler::IsVldrDPpImmediateOffset(Instr instr) {
- // Check the instruction is indeed a
- // vldr<cond> <Dd>, [pp +/- offset_10].
- return (instr & kVldrDPpMask) == kVldrDPpPattern;
-}
-
-
bool Assembler::IsBlxReg(Instr instr) {
// Check the instruction is indeed a
// blxcc <Rm>
@@ -1169,10 +1112,7 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const {
static bool use_mov_immediate_load(const Operand& x,
const Assembler* assembler) {
DCHECK(assembler != nullptr);
- if (FLAG_enable_embedded_constant_pool &&
- !assembler->is_constant_pool_available()) {
- return true;
- } else if (x.must_output_reloc_info(assembler)) {
+ if (x.must_output_reloc_info(assembler)) {
// Prefer constant pool if data is likely to be patched.
return false;
} else {
@@ -1196,14 +1136,10 @@ int Operand::instructions_required(const Assembler* assembler,
if (use_mov_immediate_load(*this, assembler)) {
// A movw / movt or mov / orr immediate load.
instructions = CpuFeatures::IsSupported(ARMv7) ? 2 : 4;
- } else if (assembler->ConstantPoolAccessIsInOverflow()) {
- // An overflowed constant pool load.
- instructions = CpuFeatures::IsSupported(ARMv7) ? 3 : 5;
} else {
// A small constant pool load.
instructions = 1;
}
-
if ((instr & ~kCondMask) != 13 * B21) { // mov, S not set
// For a mov or mvn instruction which doesn't set the condition
// code, the constant pool or immediate load is enough, otherwise we need
@@ -1228,51 +1164,25 @@ void Assembler::move_32_bit_immediate(Register rd,
}
if (use_mov_immediate_load(x, this)) {
+ // use_mov_immediate_load should return false when we need to output
+ // relocation info, since we prefer the constant pool for values that
+ // can be patched.
+ DCHECK(!x.must_output_reloc_info(this));
Register target = rd.code() == pc.code() ? ip : rd;
if (CpuFeatures::IsSupported(ARMv7)) {
CpuFeatureScope scope(this, ARMv7);
- if (!FLAG_enable_embedded_constant_pool &&
- x.must_output_reloc_info(this)) {
- // Make sure the movw/movt doesn't get separated.
- BlockConstPoolFor(2);
- }
movw(target, imm32 & 0xffff, cond);
movt(target, imm32 >> 16, cond);
- } else {
- DCHECK(FLAG_enable_embedded_constant_pool);
- mov(target, Operand(imm32 & kImm8Mask), LeaveCC, cond);
- orr(target, target, Operand(imm32 & (kImm8Mask << 8)), LeaveCC, cond);
- orr(target, target, Operand(imm32 & (kImm8Mask << 16)), LeaveCC, cond);
- orr(target, target, Operand(imm32 & (kImm8Mask << 24)), LeaveCC, cond);
}
if (target.code() != rd.code()) {
mov(rd, target, LeaveCC, cond);
}
} else {
- DCHECK(!FLAG_enable_embedded_constant_pool || is_constant_pool_available());
ConstantPoolEntry::Access access =
ConstantPoolAddEntry(pc_offset(), x.rmode_, x.imm32_);
- if (access == ConstantPoolEntry::OVERFLOWED) {
- DCHECK(FLAG_enable_embedded_constant_pool);
- Register target = rd.code() == pc.code() ? ip : rd;
- // Emit instructions to load constant pool offset.
- if (CpuFeatures::IsSupported(ARMv7)) {
- CpuFeatureScope scope(this, ARMv7);
- movw(target, 0, cond);
- movt(target, 0, cond);
- } else {
- mov(target, Operand(0), LeaveCC, cond);
- orr(target, target, Operand(0), LeaveCC, cond);
- orr(target, target, Operand(0), LeaveCC, cond);
- orr(target, target, Operand(0), LeaveCC, cond);
- }
- // Load from constant pool at offset.
- ldr(rd, MemOperand(pp, target), cond);
- } else {
- DCHECK(access == ConstantPoolEntry::REGULAR);
- ldr(rd, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0),
- cond);
- }
+ DCHECK(access == ConstantPoolEntry::REGULAR);
+ USE(access);
+ ldr(rd, MemOperand(pc, 0), cond);
}
}
@@ -2787,12 +2697,6 @@ void Assembler::vmov(const DwVfpRegister dst,
DCHECK(VfpRegisterIsAvailable(dst));
DCHECK(!scratch.is(ip));
uint32_t enc;
- // If the embedded constant pool is disabled, we can use the normal, inline
- // constant pool. If the embedded constant pool is enabled (via
- // FLAG_enable_embedded_constant_pool), we can only use it where the pool
- // pointer (pp) is valid.
- bool can_use_pool =
- !FLAG_enable_embedded_constant_pool || is_constant_pool_available();
if (CpuFeatures::IsSupported(VFPv3) && FitsVmovFPImmediate(imm, &enc)) {
CpuFeatureScope scope(this, VFPv3);
// The double can be encoded in the instruction.
@@ -2804,8 +2708,7 @@ void Assembler::vmov(const DwVfpRegister dst,
int vd, d;
dst.split_code(&vd, &d);
emit(al | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc);
- } else if (CpuFeatures::IsSupported(ARMv7) && FLAG_enable_vldr_imm &&
- can_use_pool) {
+ } else if (CpuFeatures::IsSupported(ARMv7) && FLAG_enable_vldr_imm) {
CpuFeatureScope scope(this, ARMv7);
// TODO(jfb) Temporarily turned off until we have constant blinding or
// some equivalent mitigation: an attacker can otherwise control
@@ -2823,17 +2726,9 @@ void Assembler::vmov(const DwVfpRegister dst,
// that's tricky because vldr has a limited reach. Furthermore
// it breaks load locality.
ConstantPoolEntry::Access access = ConstantPoolAddEntry(pc_offset(), imm);
- if (access == ConstantPoolEntry::OVERFLOWED) {
- DCHECK(FLAG_enable_embedded_constant_pool);
- // Emit instructions to load constant pool offset.
- movw(ip, 0);
- movt(ip, 0);
- // Load from constant pool at offset.
- vldr(dst, MemOperand(pp, ip));
- } else {
- DCHECK(access == ConstantPoolEntry::REGULAR);
- vldr(dst, MemOperand(FLAG_enable_embedded_constant_pool ? pp : pc, 0));
- }
+ DCHECK(access == ConstantPoolEntry::REGULAR);
+ USE(access);
+ vldr(dst, MemOperand(pc, 0));
} else {
// Synthesise the double from ARM immediates.
uint32_t lo, hi;
@@ -4015,19 +3910,47 @@ void Assembler::vdup(NeonSize size, QwNeonRegister dst, Register src) {
0xB * B8 | d * B7 | E * B5 | B4);
}
-void Assembler::vdup(QwNeonRegister dst, SwVfpRegister src) {
- DCHECK(IsEnabled(NEON));
- // Instruction details available in ARM DDI 0406C.b, A8-884.
- int index = src.code() & 1;
- int d_reg = src.code() / 2;
- int imm4 = 4 | index << 3; // esize = 32, index in bit 3.
+enum NeonRegType { NEON_D, NEON_Q };
+
+void NeonSplitCode(NeonRegType type, int code, int* vm, int* m, int* encoding) {
+ if (type == NEON_D) {
+ DwVfpRegister::split_code(code, vm, m);
+ } else {
+ DCHECK_EQ(type, NEON_Q);
+ QwNeonRegister::split_code(code, vm, m);
+ *encoding |= B6;
+ }
+}
+
+static Instr EncodeNeonDupOp(NeonSize size, NeonRegType reg_type, int dst_code,
+ DwVfpRegister src, int index) {
+ DCHECK_NE(Neon64, size);
+ int sz = static_cast<int>(size);
+ DCHECK_LE(0, index);
+ DCHECK_GT(kSimd128Size / (1 << sz), index);
+ int imm4 = (1 << sz) | ((index << (sz + 1)) & 0xF);
+ int qbit = 0;
int vd, d;
- dst.split_code(&vd, &d);
+ NeonSplitCode(reg_type, dst_code, &vd, &d, &qbit);
int vm, m;
- DwVfpRegister::from_code(d_reg).split_code(&vm, &m);
+ src.split_code(&vm, &m);
- emit(0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 | 0x18 * B7 |
- B6 | m * B5 | vm);
+ return 0x1E7U * B23 | d * B22 | 0x3 * B20 | imm4 * B16 | vd * B12 |
+ 0x18 * B7 | qbit | m * B5 | vm;
+}
+
+void Assembler::vdup(NeonSize size, DwVfpRegister dst, DwVfpRegister src,
+ int index) {
+ DCHECK(IsEnabled(NEON));
+ // Instruction details available in ARM DDI 0406C.b, A8-884.
+ emit(EncodeNeonDupOp(size, NEON_D, dst.code(), src, index));
+}
+
+void Assembler::vdup(NeonSize size, QwNeonRegister dst, DwVfpRegister src,
+ int index) {
+ // Instruction details available in ARM DDI 0406C.b, A8-884.
+ DCHECK(IsEnabled(NEON));
+ emit(EncodeNeonDupOp(size, NEON_Q, dst.code(), src, index));
}
// Encode NEON vcvt.src_type.dst_type instruction.
@@ -4082,18 +4005,6 @@ void Assembler::vcvt_u32_f32(QwNeonRegister dst, QwNeonRegister src) {
emit(EncodeNeonVCVT(U32, dst, F32, src));
}
-enum NeonRegType { NEON_D, NEON_Q };
-
-void NeonSplitCode(NeonRegType type, int code, int* vm, int* m, int* encoding) {
- if (type == NEON_D) {
- DwVfpRegister::split_code(code, vm, m);
- } else {
- DCHECK_EQ(type, NEON_Q);
- QwNeonRegister::split_code(code, vm, m);
- *encoding |= B6;
- }
-}
-
enum UnaryOp { VMVN, VSWP, VABS, VABSF, VNEG, VNEGF };
static Instr EncodeNeonUnaryOp(UnaryOp op, NeonRegType reg_type, NeonSize size,
@@ -4508,30 +4419,55 @@ void Assembler::vmax(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src1,
emit(EncodeNeonBinOp(VMAX, dt, dst, src1, src2));
}
-enum NeonShiftOp { VSHL, VSHR };
+enum NeonShiftOp { VSHL, VSHR, VSLI, VSRI };
-static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonDataType dt,
- QwNeonRegister dst, QwNeonRegister src,
+static Instr EncodeNeonShiftOp(NeonShiftOp op, NeonSize size, bool is_unsigned,
+ NeonRegType reg_type, int dst_code, int src_code,
int shift) {
- int vd, d;
- dst.split_code(&vd, &d);
- int vm, m;
- src.split_code(&vm, &m);
- int size_in_bits = kBitsPerByte << NeonSz(dt);
- int op_encoding = 0;
int imm6 = 0;
- if (op == VSHL) {
- DCHECK(shift >= 0 && size_in_bits > shift);
- imm6 = size_in_bits + shift;
- op_encoding = 0x5 * B8;
- } else {
- DCHECK_EQ(VSHR, op);
- DCHECK(shift > 0 && size_in_bits >= shift);
- imm6 = 2 * size_in_bits - shift;
- op_encoding = NeonU(dt) * B24;
+ int size_in_bits = kBitsPerByte << static_cast<int>(size);
+ int op_encoding = 0;
+ switch (op) {
+ case VSHL: {
+ DCHECK(shift >= 0 && size_in_bits > shift);
+ imm6 = size_in_bits + shift;
+ op_encoding = 0x5 * B8;
+ break;
+ }
+ case VSHR: {
+ DCHECK(shift > 0 && size_in_bits >= shift);
+ imm6 = 2 * size_in_bits - shift;
+ if (is_unsigned) op_encoding |= B24;
+ break;
+ }
+ case VSLI: {
+ DCHECK(shift >= 0 && size_in_bits > shift);
+ imm6 = size_in_bits + shift;
+ int L = imm6 >> 6;
+ imm6 &= 0x3F;
+ op_encoding = B24 | 0x5 * B8 | L * B7;
+ break;
+ }
+ case VSRI: {
+ DCHECK(shift > 0 && size_in_bits >= shift);
+ imm6 = 2 * size_in_bits - shift;
+ int L = imm6 >> 6;
+ imm6 &= 0x3F;
+ op_encoding = B24 | 0x4 * B8 | L * B7;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
}
- return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | B6 | m * B5 | B4 |
- vm | op_encoding;
+
+ int vd, d;
+ NeonSplitCode(reg_type, dst_code, &vd, &d, &op_encoding);
+ int vm, m;
+ NeonSplitCode(reg_type, src_code, &vm, &m, &op_encoding);
+
+ return 0x1E5U * B23 | d * B22 | imm6 * B16 | vd * B12 | m * B5 | B4 | vm |
+ op_encoding;
}
void Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
@@ -4539,7 +4475,8 @@ void Assembler::vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
DCHECK(IsEnabled(NEON));
// Qd = vshl(Qm, bits) SIMD shift left immediate.
// Instruction details available in ARM DDI 0406C.b, A8-1046.
- emit(EncodeNeonShiftOp(VSHL, dt, dst, src, shift));
+ emit(EncodeNeonShiftOp(VSHL, NeonDataTypeToSize(dt), false, NEON_Q,
+ dst.code(), src.code(), shift));
}
void Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
@@ -4547,7 +4484,26 @@ void Assembler::vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src,
DCHECK(IsEnabled(NEON));
// Qd = vshl(Qm, bits) SIMD shift right immediate.
// Instruction details available in ARM DDI 0406C.b, A8-1052.
- emit(EncodeNeonShiftOp(VSHR, dt, dst, src, shift));
+ emit(EncodeNeonShiftOp(VSHR, NeonDataTypeToSize(dt), NeonU(dt), NEON_Q,
+ dst.code(), src.code(), shift));
+}
+
+void Assembler::vsli(NeonSize size, DwVfpRegister dst, DwVfpRegister src,
+ int shift) {
+ DCHECK(IsEnabled(NEON));
+ // Dd = vsli(Dm, bits) SIMD shift left and insert.
+ // Instruction details available in ARM DDI 0406C.b, A8-1056.
+ emit(EncodeNeonShiftOp(VSLI, size, false, NEON_D, dst.code(), src.code(),
+ shift));
+}
+
+void Assembler::vsri(NeonSize size, DwVfpRegister dst, DwVfpRegister src,
+ int shift) {
+ DCHECK(IsEnabled(NEON));
+ // Dd = vsri(Dm, bits) SIMD shift right and insert.
+ // Instruction details available in ARM DDI 0406C.b, A8-1062.
+ emit(EncodeNeonShiftOp(VSRI, size, false, NEON_D, dst.code(), src.code(),
+ shift));
}
static Instr EncodeNeonEstimateOp(bool is_rsqrt, QwNeonRegister dst,
@@ -4591,13 +4547,16 @@ void Assembler::vrsqrts(QwNeonRegister dst, QwNeonRegister src1,
emit(EncodeNeonBinOp(VRSQRTS, dst, src1, src2));
}
-enum NeonPairwiseOp { VPMIN, VPMAX };
+enum NeonPairwiseOp { VPADD, VPMIN, VPMAX };
static Instr EncodeNeonPairwiseOp(NeonPairwiseOp op, NeonDataType dt,
DwVfpRegister dst, DwVfpRegister src1,
DwVfpRegister src2) {
int op_encoding = 0;
switch (op) {
+ case VPADD:
+ op_encoding = 0xB * B8 | B4;
+ break;
case VPMIN:
op_encoding = 0xA * B8 | B4;
break;
@@ -4620,6 +4579,30 @@ static Instr EncodeNeonPairwiseOp(NeonPairwiseOp op, NeonDataType dt,
n * B7 | m * B5 | vm | op_encoding;
}
+void Assembler::vpadd(DwVfpRegister dst, DwVfpRegister src1,
+ DwVfpRegister src2) {
+ DCHECK(IsEnabled(NEON));
+ // Dd = vpadd(Dn, Dm) SIMD integer pairwise ADD.
+ // Instruction details available in ARM DDI 0406C.b, A8-982.
+ int vd, d;
+ dst.split_code(&vd, &d);
+ int vn, n;
+ src1.split_code(&vn, &n);
+ int vm, m;
+ src2.split_code(&vm, &m);
+
+ emit(0x1E6U * B23 | d * B22 | vn * B16 | vd * B12 | 0xD * B8 | n * B7 |
+ m * B5 | vm);
+}
+
+void Assembler::vpadd(NeonSize size, DwVfpRegister dst, DwVfpRegister src1,
+ DwVfpRegister src2) {
+ DCHECK(IsEnabled(NEON));
+ // Dd = vpadd(Dn, Dm) SIMD integer pairwise ADD.
+ // Instruction details available in ARM DDI 0406C.b, A8-980.
+ emit(EncodeNeonPairwiseOp(VPADD, NeonSizeToDataType(size), dst, src1, src2));
+}
+
void Assembler::vpmin(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1,
DwVfpRegister src2) {
DCHECK(IsEnabled(NEON));
@@ -4747,10 +4730,14 @@ static Instr EncodeNeonSizedOp(NeonSizedOp op, NeonRegType reg_type,
}
void Assembler::vzip(NeonSize size, DwVfpRegister src1, DwVfpRegister src2) {
- DCHECK(IsEnabled(NEON));
- // vzip.<size>(Dn, Dm) SIMD zip (interleave).
- // Instruction details available in ARM DDI 0406C.b, A8-1102.
- emit(EncodeNeonSizedOp(VZIP, NEON_D, size, src1.code(), src2.code()));
+ if (size == Neon32) { // vzip.32 Dd, Dm is a pseudo-op for vtrn.32 Dd, Dm.
+ vtrn(size, src1, src2);
+ } else {
+ DCHECK(IsEnabled(NEON));
+ // vzip.<size>(Dn, Dm) SIMD zip (interleave).
+ // Instruction details available in ARM DDI 0406C.b, A8-1102.
+ emit(EncodeNeonSizedOp(VZIP, NEON_D, size, src1.code(), src2.code()));
+ }
}
void Assembler::vzip(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
@@ -4761,10 +4748,14 @@ void Assembler::vzip(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
}
void Assembler::vuzp(NeonSize size, DwVfpRegister src1, DwVfpRegister src2) {
- DCHECK(IsEnabled(NEON));
- // vuzp.<size>(Dn, Dm) SIMD un-zip (de-interleave).
- // Instruction details available in ARM DDI 0406C.b, A8-1100.
- emit(EncodeNeonSizedOp(VUZP, NEON_D, size, src1.code(), src2.code()));
+ if (size == Neon32) { // vuzp.32 Dd, Dm is a pseudo-op for vtrn.32 Dd, Dm.
+ vtrn(size, src1, src2);
+ } else {
+ DCHECK(IsEnabled(NEON));
+ // vuzp.<size>(Dn, Dm) SIMD un-zip (de-interleave).
+ // Instruction details available in ARM DDI 0406C.b, A8-1100.
+ emit(EncodeNeonSizedOp(VUZP, NEON_D, size, src1.code(), src2.code()));
+ }
}
void Assembler::vuzp(NeonSize size, QwNeonRegister src1, QwNeonRegister src2) {
@@ -4951,7 +4942,14 @@ void Assembler::GrowBuffer() {
} else {
desc.buffer_size = buffer_size_ + 1*MB;
}
- CHECK_GT(desc.buffer_size, 0); // no overflow
+
+ // Some internal data structures overflow for very large buffers,
+ // they must ensure that kMaximalBufferSize is not too large.
+ if (desc.buffer_size > kMaximalBufferSize ||
+ static_cast<size_t>(desc.buffer_size) >
+ isolate_data().max_old_generation_size_) {
+ V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
+ }
// Set up new buffer.
desc.buffer = NewArray<byte>(desc.buffer_size);
@@ -5046,52 +5044,37 @@ ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
rmode != RelocInfo::NONE64);
bool sharing_ok = RelocInfo::IsNone(rmode) ||
!(serializer_enabled() || rmode < RelocInfo::CELL);
- if (FLAG_enable_embedded_constant_pool) {
- return constant_pool_builder_.AddEntry(position, value, sharing_ok);
- } else {
- DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants);
- if (pending_32_bit_constants_.empty()) {
- first_const_pool_32_use_ = position;
- }
- ConstantPoolEntry entry(position, value, sharing_ok);
- pending_32_bit_constants_.push_back(entry);
-
- // Make sure the constant pool is not emitted in place of the next
- // instruction for which we just recorded relocation info.
- BlockConstPoolFor(1);
- return ConstantPoolEntry::REGULAR;
+ DCHECK(pending_32_bit_constants_.size() < kMaxNumPending32Constants);
+ if (pending_32_bit_constants_.empty()) {
+ first_const_pool_32_use_ = position;
}
+ ConstantPoolEntry entry(position, value, sharing_ok);
+ pending_32_bit_constants_.push_back(entry);
+
+ // Make sure the constant pool is not emitted in place of the next
+ // instruction for which we just recorded relocation info.
+ BlockConstPoolFor(1);
+ return ConstantPoolEntry::REGULAR;
}
ConstantPoolEntry::Access Assembler::ConstantPoolAddEntry(int position,
double value) {
- if (FLAG_enable_embedded_constant_pool) {
- return constant_pool_builder_.AddEntry(position, value);
- } else {
- DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants);
- if (pending_64_bit_constants_.empty()) {
- first_const_pool_64_use_ = position;
- }
- ConstantPoolEntry entry(position, value);
- pending_64_bit_constants_.push_back(entry);
-
- // Make sure the constant pool is not emitted in place of the next
- // instruction for which we just recorded relocation info.
- BlockConstPoolFor(1);
- return ConstantPoolEntry::REGULAR;
+ DCHECK(pending_64_bit_constants_.size() < kMaxNumPending64Constants);
+ if (pending_64_bit_constants_.empty()) {
+ first_const_pool_64_use_ = position;
}
+ ConstantPoolEntry entry(position, value);
+ pending_64_bit_constants_.push_back(entry);
+
+ // Make sure the constant pool is not emitted in place of the next
+ // instruction for which we just recorded relocation info.
+ BlockConstPoolFor(1);
+ return ConstantPoolEntry::REGULAR;
}
void Assembler::BlockConstPoolFor(int instructions) {
- if (FLAG_enable_embedded_constant_pool) {
- // Should be a no-op if using an embedded constant pool.
- DCHECK(pending_32_bit_constants_.empty());
- DCHECK(pending_64_bit_constants_.empty());
- return;
- }
-
int pc_limit = pc_offset() + instructions * kInstrSize;
if (no_const_pool_before_ < pc_limit) {
// Max pool start (if we need a jump and an alignment).
@@ -5114,13 +5097,6 @@ void Assembler::BlockConstPoolFor(int instructions) {
void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
- if (FLAG_enable_embedded_constant_pool) {
- // Should be a no-op if using an embedded constant pool.
- DCHECK(pending_32_bit_constants_.empty());
- DCHECK(pending_64_bit_constants_.empty());
- return;
- }
-
// Some short sequence of instruction mustn't be broken up by constant pool
// emission, such sequences are protected by calls to BlockConstPoolFor and
// BlockConstPoolScope.
@@ -5333,61 +5309,6 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) {
next_buffer_check_ = pc_offset() + kCheckPoolInterval;
}
-
-void Assembler::PatchConstantPoolAccessInstruction(
- int pc_offset, int offset, ConstantPoolEntry::Access access,
- ConstantPoolEntry::Type type) {
- DCHECK(FLAG_enable_embedded_constant_pool);
- Address pc = buffer_ + pc_offset;
-
- // Patch vldr/ldr instruction with correct offset.
- Instr instr = instr_at(pc);
- if (access == ConstantPoolEntry::OVERFLOWED) {
- if (CpuFeatures::IsSupported(ARMv7)) {
- CpuFeatureScope scope(this, ARMv7);
- // Instructions to patch must be 'movw rd, [#0]' and 'movt rd, [#0].
- Instr next_instr = instr_at(pc + kInstrSize);
- DCHECK((IsMovW(instr) && Instruction::ImmedMovwMovtValue(instr) == 0));
- DCHECK((IsMovT(next_instr) &&
- Instruction::ImmedMovwMovtValue(next_instr) == 0));
- instr_at_put(pc, PatchMovwImmediate(instr, offset & 0xffff));
- instr_at_put(pc + kInstrSize,
- PatchMovwImmediate(next_instr, offset >> 16));
- } else {
- // Instructions to patch must be 'mov rd, [#0]' and 'orr rd, rd, [#0].
- Instr instr_2 = instr_at(pc + kInstrSize);
- Instr instr_3 = instr_at(pc + 2 * kInstrSize);
- Instr instr_4 = instr_at(pc + 3 * kInstrSize);
- DCHECK((IsMovImmed(instr) && Instruction::Immed8Value(instr) == 0));
- DCHECK((IsOrrImmed(instr_2) && Instruction::Immed8Value(instr_2) == 0) &&
- GetRn(instr_2).is(GetRd(instr_2)));
- DCHECK((IsOrrImmed(instr_3) && Instruction::Immed8Value(instr_3) == 0) &&
- GetRn(instr_3).is(GetRd(instr_3)));
- DCHECK((IsOrrImmed(instr_4) && Instruction::Immed8Value(instr_4) == 0) &&
- GetRn(instr_4).is(GetRd(instr_4)));
- instr_at_put(pc, PatchShiftImm(instr, (offset & kImm8Mask)));
- instr_at_put(pc + kInstrSize,
- PatchShiftImm(instr_2, (offset & (kImm8Mask << 8))));
- instr_at_put(pc + 2 * kInstrSize,
- PatchShiftImm(instr_3, (offset & (kImm8Mask << 16))));
- instr_at_put(pc + 3 * kInstrSize,
- PatchShiftImm(instr_4, (offset & (kImm8Mask << 24))));
- }
- } else if (type == ConstantPoolEntry::DOUBLE) {
- // Instruction to patch must be 'vldr rd, [pp, #0]'.
- DCHECK((IsVldrDPpImmediateOffset(instr) &&
- GetVldrDRegisterImmediateOffset(instr) == 0));
- DCHECK(is_uint10(offset));
- instr_at_put(pc, SetVldrDRegisterImmediateOffset(instr, offset));
- } else {
- // Instruction to patch must be 'ldr rd, [pp, #0]'.
- DCHECK((IsLdrPpImmediateOffset(instr) &&
- GetLdrRegisterImmediateOffset(instr) == 0));
- DCHECK(is_uint12(offset));
- instr_at_put(pc, SetLdrRegisterImmediateOffset(instr, offset));
- }
-}
-
PatchingAssembler::PatchingAssembler(IsolateData isolate_data, byte* address,
int instructions)
: Assembler(isolate_data, address, instructions * kInstrSize + kGap) {
diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h
index 076274d8bc..a628493723 100644
--- a/deps/v8/src/arm/assembler-arm.h
+++ b/deps/v8/src/arm/assembler-arm.h
@@ -75,13 +75,13 @@ namespace internal {
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
+ V(d8) V(d9) V(d10) V(d11) V(d12) \
V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
#define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V) \
V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
+ V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) \
// clang-format on
// CPU Registers.
@@ -142,7 +142,6 @@ struct Register {
};
// r7: context register
-// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
// r9: lithium scratch
#define DECLARE_REGISTER(R) constexpr Register R = {Register::kCode_##R};
GENERAL_REGISTERS(DECLARE_REGISTER)
@@ -424,12 +423,13 @@ constexpr QwNeonRegister q15 = { 15 };
// Aliases for double registers.
constexpr LowDwVfpRegister kFirstCalleeSavedDoubleReg = d8;
constexpr LowDwVfpRegister kLastCalleeSavedDoubleReg = d15;
-// kDoubleRegZero and kScratchDoubleReg must pair to form kScratchQuadReg. SIMD
-// code depends on kDoubleRegZero before kScratchDoubleReg.
-constexpr LowDwVfpRegister kDoubleRegZero = d14;
-constexpr LowDwVfpRegister kScratchDoubleReg = d15;
-// After using kScratchQuadReg, kDoubleRegZero must be reset to 0.
+constexpr LowDwVfpRegister kDoubleRegZero = d13;
+constexpr LowDwVfpRegister kScratchDoubleReg = d14;
+// This scratch q-register aliases d14 (kScratchDoubleReg) and d15, but is only
+// used if NEON is supported, which implies VFP32DREGS. When there are only 16
+// d-registers, d15 is still allocatable.
constexpr QwNeonRegister kScratchQuadReg = q7;
+constexpr LowDwVfpRegister kScratchDoubleReg2 = d15;
// Coprocessor register
struct CRegister {
@@ -1332,7 +1332,8 @@ class Assembler : public AssemblerBase {
void vmov(QwNeonRegister dst, QwNeonRegister src);
void vdup(NeonSize size, QwNeonRegister dst, Register src);
- void vdup(QwNeonRegister dst, SwVfpRegister src);
+ void vdup(NeonSize size, QwNeonRegister dst, DwVfpRegister src, int index);
+ void vdup(NeonSize size, DwVfpRegister dst, DwVfpRegister src, int index);
void vcvt_f32_s32(QwNeonRegister dst, QwNeonRegister src);
void vcvt_f32_u32(QwNeonRegister dst, QwNeonRegister src);
@@ -1372,12 +1373,17 @@ class Assembler : public AssemblerBase {
void vmax(QwNeonRegister dst, QwNeonRegister src1, QwNeonRegister src2);
void vmax(NeonDataType dt, QwNeonRegister dst,
QwNeonRegister src1, QwNeonRegister src2);
+ void vpadd(DwVfpRegister dst, DwVfpRegister src1, DwVfpRegister src2);
+ void vpadd(NeonSize size, DwVfpRegister dst, DwVfpRegister src1,
+ DwVfpRegister src2);
void vpmin(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1,
DwVfpRegister src2);
void vpmax(NeonDataType dt, DwVfpRegister dst, DwVfpRegister src1,
DwVfpRegister src2);
void vshl(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, int shift);
void vshr(NeonDataType dt, QwNeonRegister dst, QwNeonRegister src, int shift);
+ void vsli(NeonSize size, DwVfpRegister dst, DwVfpRegister src, int shift);
+ void vsri(NeonSize size, DwVfpRegister dst, DwVfpRegister src, int shift);
// vrecpe and vrsqrte only support floating point lanes.
void vrecpe(QwNeonRegister dst, QwNeonRegister src);
void vrsqrte(QwNeonRegister dst, QwNeonRegister src);
@@ -1558,12 +1564,6 @@ class Assembler : public AssemblerBase {
static int GetBranchOffset(Instr instr);
static bool IsLdrRegisterImmediate(Instr instr);
static bool IsVldrDRegisterImmediate(Instr instr);
- static Instr GetConsantPoolLoadPattern();
- static Instr GetConsantPoolLoadMask();
- static bool IsLdrPpRegOffset(Instr instr);
- static Instr GetLdrPpRegOffsetPattern();
- static bool IsLdrPpImmediateOffset(Instr instr);
- static bool IsVldrDPpImmediateOffset(Instr instr);
static int GetLdrRegisterImmediateOffset(Instr instr);
static int GetVldrDRegisterImmediateOffset(Instr instr);
static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
@@ -1628,19 +1628,12 @@ class Assembler : public AssemblerBase {
}
}
- int EmitEmbeddedConstantPool() {
- DCHECK(FLAG_enable_embedded_constant_pool);
- return constant_pool_builder_.Emit(this);
- }
-
- bool ConstantPoolAccessIsInOverflow() const {
- return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
- ConstantPoolEntry::OVERFLOWED;
- }
-
void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
ConstantPoolEntry::Access access,
- ConstantPoolEntry::Type type);
+ ConstantPoolEntry::Type type) {
+ // No embedded constant pool support.
+ UNREACHABLE();
+ }
protected:
// Relocation for a type-recording IC has the AST id added to it. This
@@ -1734,6 +1727,9 @@ class Assembler : public AssemblerBase {
std::vector<ConstantPoolEntry> pending_64_bit_constants_;
private:
+ // Avoid overflows for displacements etc.
+ static const int kMaximalBufferSize = 512 * MB;
+
int next_buffer_check_; // pc offset of next buffer check
// Constant pool generation
@@ -1763,8 +1759,6 @@ class Assembler : public AssemblerBase {
int first_const_pool_32_use_;
int first_const_pool_64_use_;
- ConstantPoolBuilder constant_pool_builder_;
-
// The bound position, before this we cannot do instruction elimination.
int last_bound_pos_;
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc
index 12b35ba5e7..fc59f4007e 100644
--- a/deps/v8/src/arm/code-stubs-arm.cc
+++ b/deps/v8/src/arm/code-stubs-arm.cc
@@ -983,9 +983,6 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ mov(r2, Operand(pending_handler_offset_address));
__ ldr(r2, MemOperand(r2));
__ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start
- if (FLAG_enable_embedded_constant_pool) {
- __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r1);
- }
__ add(pc, r1, r2);
}
@@ -1029,9 +1026,6 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
// r3: argc
// r4: argv
StackFrame::Type marker = type();
- if (FLAG_enable_embedded_constant_pool) {
- __ mov(r8, Operand::Zero());
- }
__ mov(r7, Operand(StackFrame::TypeToMarker(marker)));
__ mov(r6, Operand(StackFrame::TypeToMarker(marker)));
__ mov(r5,
@@ -1039,7 +1033,6 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ ldr(r5, MemOperand(r5));
__ mov(ip, Operand(-1)); // Push a bad frame pointer to fail if it is used.
__ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() |
- (FLAG_enable_embedded_constant_pool ? r8.bit() : 0) |
ip.bit());
// Set up frame pointer for the frame to be pushed.
@@ -1152,75 +1145,6 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ ldm(ia_w, sp, kCalleeSaved | pc.bit());
}
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
- // This case is handled prior to the RegExpExecStub call.
- __ Abort(kUnexpectedRegExpExecCall);
-#else // V8_INTERPRETED_REGEXP
- // Isolates: note we add an additional parameter here (isolate pointer).
- const int kRegExpExecuteArguments = 9;
- const int kParameterRegisters = 4;
- __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
-
- // Stack pointer now points to cell where return address is to be written.
- // Arguments are before that on the stack or in registers.
-
- // Argument 9 (sp[20]): Pass current isolate address.
- __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
- __ str(r5, MemOperand(sp, 5 * kPointerSize));
-
- // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript.
- __ mov(r5, Operand(1));
- __ str(r5, MemOperand(sp, 4 * kPointerSize));
-
- // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area.
- ExternalReference address_of_regexp_stack_memory_address =
- ExternalReference::address_of_regexp_stack_memory_address(isolate());
- ExternalReference address_of_regexp_stack_memory_size =
- ExternalReference::address_of_regexp_stack_memory_size(isolate());
- __ mov(r5, Operand(address_of_regexp_stack_memory_address));
- __ ldr(r5, MemOperand(r5, 0));
- __ mov(r6, Operand(address_of_regexp_stack_memory_size));
- __ ldr(r6, MemOperand(r6, 0));
- __ add(r5, r5, Operand(r6));
- __ str(r5, MemOperand(sp, 3 * kPointerSize));
-
- // Argument 6: Set the number of capture registers to zero to force global
- // regexps to behave as non-global. This does not affect non-global regexps.
- __ mov(r5, Operand::Zero());
- __ str(r5, MemOperand(sp, 2 * kPointerSize));
-
- // Argument 5 (sp[4]): static offsets vector buffer.
- __ mov(
- r5,
- Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
- __ str(r5, MemOperand(sp, 1 * kPointerSize));
-
- // Argument 4: End of string data
- // Argument 3: Start of string data
- CHECK(r3.is(RegExpExecDescriptor::StringEndRegister()));
- CHECK(r2.is(RegExpExecDescriptor::StringStartRegister()));
-
- // Argument 2 (r1): Previous index.
- CHECK(r1.is(RegExpExecDescriptor::LastIndexRegister()));
-
- // Argument 1 (r0): Subject string.
- CHECK(r0.is(RegExpExecDescriptor::StringRegister()));
-
- // Locate the code entry and call it.
- Register code_reg = RegExpExecDescriptor::CodeRegister();
- __ add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
-
- DirectCEntryStub stub(isolate());
- stub.GenerateCall(masm, code_reg);
-
- __ LeaveExitFrame(false, no_reg, true);
-
- __ SmiTag(r0);
- __ Ret();
-#endif // V8_INTERPRETED_REGEXP
-}
-
static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
// r0 : number of arguments to the construct function
// r1 : the function to call
@@ -2875,9 +2799,7 @@ void CallApiCallbackStub::Generate(MacroAssembler* masm) {
__ push(call_data);
Register scratch = call_data;
- if (!call_data_undefined()) {
- __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
- }
+ __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
// return value
__ push(scratch);
// return value default
diff --git a/deps/v8/src/arm/constants-arm.h b/deps/v8/src/arm/constants-arm.h
index 0b86f3e149..21794a5a5c 100644
--- a/deps/v8/src/arm/constants-arm.h
+++ b/deps/v8/src/arm/constants-arm.h
@@ -324,6 +324,8 @@ enum LFlag {
Short = 0 << 22 // Short load/store coprocessor.
};
+// Neon sizes.
+enum NeonSize { Neon8 = 0x0, Neon16 = 0x1, Neon32 = 0x2, Neon64 = 0x3 };
// NEON data type
enum NeonDataType {
@@ -339,6 +341,16 @@ enum NeonDataType {
inline int NeonU(NeonDataType dt) { return static_cast<int>(dt) >> 2; }
inline int NeonSz(NeonDataType dt) { return static_cast<int>(dt) & 0x3; }
+// Convert sizes to data types (U bit is clear).
+inline NeonDataType NeonSizeToDataType(NeonSize size) {
+ DCHECK_NE(Neon64, size);
+ return static_cast<NeonDataType>(size);
+}
+
+inline NeonSize NeonDataTypeToSize(NeonDataType dt) {
+ return static_cast<NeonSize>(NeonSz(dt));
+}
+
enum NeonListType {
nlt_1 = 0x7,
nlt_2 = 0xA,
@@ -346,13 +358,6 @@ enum NeonListType {
nlt_4 = 0x2
};
-enum NeonSize {
- Neon8 = 0x0,
- Neon16 = 0x1,
- Neon32 = 0x2,
- Neon64 = 0x3
-};
-
// -----------------------------------------------------------------------------
// Supervisor Call (svc) specific support.
diff --git a/deps/v8/src/arm/deoptimizer-arm.cc b/deps/v8/src/arm/deoptimizer-arm.cc
index 37687f0d55..b33b977879 100644
--- a/deps/v8/src/arm/deoptimizer-arm.cc
+++ b/deps/v8/src/arm/deoptimizer-arm.cc
@@ -34,30 +34,28 @@ void Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) {
// code patching below, and is not needed any more.
code->InvalidateRelocation();
- if (FLAG_zap_code_space) {
- // Fail hard and early if we enter this code object again.
- byte* pointer = code->FindCodeAgeSequence();
- if (pointer != NULL) {
- pointer += kNoCodeAgeSequenceLength;
- } else {
- pointer = code->instruction_start();
- }
+ // Fail hard and early if we enter this code object again.
+ byte* pointer = code->FindCodeAgeSequence();
+ if (pointer != NULL) {
+ pointer += kNoCodeAgeSequenceLength;
+ } else {
+ pointer = code->instruction_start();
+ }
- {
- PatchingAssembler patcher(Assembler::IsolateData(isolate), pointer, 1);
- patcher.bkpt(0);
- patcher.FlushICache(isolate);
- }
+ {
+ PatchingAssembler patcher(Assembler::IsolateData(isolate), pointer, 1);
+ patcher.bkpt(0);
+ patcher.FlushICache(isolate);
+ }
- DeoptimizationInputData* data =
- DeoptimizationInputData::cast(code->deoptimization_data());
- int osr_offset = data->OsrPcOffset()->value();
- if (osr_offset > 0) {
- PatchingAssembler patcher(Assembler::IsolateData(isolate),
- code->instruction_start() + osr_offset, 1);
- patcher.bkpt(0);
- patcher.FlushICache(isolate);
- }
+ DeoptimizationInputData* data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+ int osr_offset = data->OsrPcOffset()->value();
+ if (osr_offset > 0) {
+ PatchingAssembler patcher(Assembler::IsolateData(isolate),
+ code_start_address + osr_offset, 1);
+ patcher.bkpt(0);
+ patcher.FlushICache(isolate);
}
DeoptimizationInputData* deopt_data =
@@ -124,8 +122,8 @@ void Deoptimizer::TableEntryGenerator::Generate() {
const int kFloatRegsSize = kFloatSize * SwVfpRegister::kMaxNumRegisters;
// Save all allocatable VFP registers before messing with them.
- DCHECK(kDoubleRegZero.code() == 14);
- DCHECK(kScratchDoubleReg.code() == 15);
+ DCHECK(kDoubleRegZero.code() == 13);
+ DCHECK(kScratchDoubleReg.code() == 14);
{
// We use a run-time check for VFP32DREGS.
@@ -141,11 +139,8 @@ void Deoptimizer::TableEntryGenerator::Generate() {
__ sub(sp, sp, Operand(16 * kDoubleSize), LeaveCC, eq);
__ vstm(db_w, sp, d0, d15);
- // Push registers s0-s15, and possibly s16-s31, on the stack.
- // If s16-s31 are not pushed, decrease the stack pointer instead.
- __ vstm(db_w, sp, s16, s31, ne);
- __ sub(sp, sp, Operand(16 * kFloatSize), LeaveCC, eq);
- __ vstm(db_w, sp, s0, s15);
+ // Push registers s0-s31 on the stack.
+ __ vstm(db_w, sp, s0, s31);
}
// Push all 16 registers (needed to populate FrameDescription::registers_).
@@ -391,8 +386,8 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) {
- DCHECK(FLAG_enable_embedded_constant_pool);
- SetFrameSlot(offset, value);
+ // No embedded constant pool support.
+ UNREACHABLE();
}
diff --git a/deps/v8/src/arm/disasm-arm.cc b/deps/v8/src/arm/disasm-arm.cc
index c9e7b1844b..0b8fee10f4 100644
--- a/deps/v8/src/arm/disasm-arm.cc
+++ b/deps/v8/src/arm/disasm-arm.cc
@@ -667,6 +667,28 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
case 'v': {
return FormatVFPinstruction(instr, format);
}
+ case 'A': {
+ // Print pc-relative address.
+ int offset = instr->Offset12Value();
+ byte* pc = reinterpret_cast<byte*>(instr) + Instruction::kPCReadOffset;
+ byte* addr;
+ switch (instr->PUField()) {
+ case db_x: {
+ addr = pc - offset;
+ break;
+ }
+ case ib_x: {
+ addr = pc + offset;
+ break;
+ }
+ default: {
+ UNREACHABLE();
+ return -1;
+ }
+ }
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%p", addr);
+ return 1;
+ }
case 'S':
case 'D': {
return FormatVFPRegister(instr, format);
@@ -1033,11 +1055,19 @@ void Decoder::DecodeType2(Instruction* instr) {
break;
}
case db_x: {
- Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
+ if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
+ Format(instr, "'memop'cond'b 'rd, [pc, #-'off12]'w (addr 'A)");
+ } else {
+ Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
+ }
break;
}
case ib_x: {
- Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
+ if (instr->HasL() && (instr->RnValue() == kPCRegister)) {
+ Format(instr, "'memop'cond'b 'rd, [pc, #+'off12]'w (addr 'A)");
+ } else {
+ Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
+ }
break;
}
default: {
@@ -1950,6 +1980,13 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
op, size, Vd, Vn, Vm);
break;
}
+ case 0xb: {
+ // vpadd.i<size> Dd, Dm, Dn.
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "vpadd.i%d d%d, d%d, d%d",
+ size, Vd, Vn, Vm);
+ break;
+ }
case 0xd: {
if (instr->Bit(4) == 0) {
const char* op = (instr->Bits(21, 20) == 0) ? "vadd" : "vsub";
@@ -2130,10 +2167,16 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
break;
}
case 0xd: {
- if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) {
- // vmul.f32 Qd, Qn, Qm
+ if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
+ instr->Bit(4) == 1) {
+ // vmul.f32 Qd, Qm, Qn
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"vmul.f32 q%d, q%d, q%d", Vd, Vn, Vm);
+ } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 0 &&
+ instr->Bit(4) == 0) {
+ // vpadd.f32 Dd, Dm, Dn.
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
+ "vpadd.f32 d%d, d%d, d%d", Vd, Vn, Vm);
} else {
Unknown(instr);
}
@@ -2168,11 +2211,30 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
"vmovl.u%d q%d, d%d", imm3 * 8, Vd, Vm);
} else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
if (instr->Bits(11, 7) == 0x18) {
- int Vd = instr->VFPDRegValue(kSimd128Precision);
int Vm = instr->VFPMRegValue(kDoublePrecision);
- int index = instr->Bit(19);
- out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
- "vdup q%d, d%d[%d]", Vd, Vm, index);
+ int imm4 = instr->Bits(19, 16);
+ int size = 0, index = 0;
+ if ((imm4 & 0x1) != 0) {
+ size = 8;
+ index = imm4 >> 1;
+ } else if ((imm4 & 0x2) != 0) {
+ size = 16;
+ index = imm4 >> 2;
+ } else {
+ size = 32;
+ index = imm4 >> 3;
+ }
+ if (instr->Bit(6) == 0) {
+ int Vd = instr->VFPDRegValue(kDoublePrecision);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i d%d, d%d[%d]",
+ size, Vd, Vm, index);
+ } else {
+ int Vd = instr->VFPDRegValue(kSimd128Precision);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "vdup.%i q%d, d%d[%d]",
+ size, Vd, Vm, index);
+ }
} else if (instr->Bits(11, 10) == 0x2) {
int Vd = instr->VFPDRegValue(kDoublePrecision);
int Vn = instr->VFPNRegValue(kDoublePrecision);
@@ -2303,6 +2365,27 @@ void Decoder::DecodeSpecialCondition(Instruction* instr) {
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "vshr.u%d q%d, q%d, #%d",
size, Vd, Vm, shift);
+ } else if (instr->Bit(10) == 1 && instr->Bit(6) == 0 &&
+ instr->Bit(4) == 1) {
+ // vsli.<size> Dd, Dm, shift
+ // vsri.<size> Dd, Dm, shift
+ int imm7 = instr->Bits(21, 16);
+ if (instr->Bit(7) != 0) imm7 += 64;
+ int size = base::bits::RoundDownToPowerOfTwo32(imm7);
+ int shift;
+ char direction;
+ if (instr->Bit(8) == 1) {
+ shift = imm7 - size;
+ direction = 'l'; // vsli
+ } else {
+ shift = 2 * size - imm7;
+ direction = 'r'; // vsri
+ }
+ int Vd = instr->VFPDRegValue(kDoublePrecision);
+ int Vm = instr->VFPMRegValue(kDoublePrecision);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "vs%ci.%d d%d, d%d, #%d",
+ direction, size, Vd, Vm, shift);
} else {
Unknown(instr);
}
diff --git a/deps/v8/src/arm/frames-arm.cc b/deps/v8/src/arm/frames-arm.cc
index b1139bacc4..8529bb541c 100644
--- a/deps/v8/src/arm/frames-arm.cc
+++ b/deps/v8/src/arm/frames-arm.cc
@@ -20,16 +20,16 @@ namespace internal {
Register JavaScriptFrame::fp_register() { return v8::internal::fp; }
Register JavaScriptFrame::context_register() { return cp; }
Register JavaScriptFrame::constant_pool_pointer_register() {
- DCHECK(FLAG_enable_embedded_constant_pool);
- return pp;
+ UNREACHABLE();
+ return no_reg;
}
Register StubFailureTrampolineFrame::fp_register() { return v8::internal::fp; }
Register StubFailureTrampolineFrame::context_register() { return cp; }
Register StubFailureTrampolineFrame::constant_pool_pointer_register() {
- DCHECK(FLAG_enable_embedded_constant_pool);
- return pp;
+ UNREACHABLE();
+ return no_reg;
}
diff --git a/deps/v8/src/arm/frames-arm.h b/deps/v8/src/arm/frames-arm.h
index 37927758c3..170c0b1825 100644
--- a/deps/v8/src/arm/frames-arm.h
+++ b/deps/v8/src/arm/frames-arm.h
@@ -66,23 +66,11 @@ const int kNumDoubleCalleeSaved = 8;
// TODO(regis): Only 8 registers may actually be sufficient. Revisit.
const int kNumSafepointRegisters = 16;
-// The embedded constant pool pointer (r8/pp) is not included in the safepoint
-// since it is not tagged. This register is preserved in the stack frame where
-// its value will be updated if GC code movement occurs. Including it in the
-// safepoint (where it will not be relocated) would cause a stale value to be
-// restored.
-const RegList kConstantPointerRegMask =
- FLAG_enable_embedded_constant_pool ? (1 << 8) : 0;
-const int kNumConstantPoolPointerReg =
- FLAG_enable_embedded_constant_pool ? 1 : 0;
-
// Define the list of registers actually saved at safepoints.
// Note that the number of saved registers may be smaller than the reserved
// space, i.e. kNumSafepointSavedRegisters <= kNumSafepointRegisters.
-const RegList kSafepointSavedRegisters =
- kJSCallerSaved | (kCalleeSaved & ~kConstantPointerRegMask);
-const int kNumSafepointSavedRegisters =
- kNumJSCallerSaved + kNumCalleeSaved - kNumConstantPoolPointerReg;
+const RegList kSafepointSavedRegisters = kJSCallerSaved | kCalleeSaved;
+const int kNumSafepointSavedRegisters = kNumJSCallerSaved + kNumCalleeSaved;
// ----------------------------------------------------
diff --git a/deps/v8/src/arm/interface-descriptors-arm.cc b/deps/v8/src/arm/interface-descriptors-arm.cc
index 7e56698f00..f2fb703b9f 100644
--- a/deps/v8/src/arm/interface-descriptors-arm.cc
+++ b/deps/v8/src/arm/interface-descriptors-arm.cc
@@ -58,11 +58,6 @@ const Register MathPowIntegerDescriptor::exponent() {
return MathPowTaggedDescriptor::exponent();
}
-const Register RegExpExecDescriptor::StringRegister() { return r0; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return r1; }
-const Register RegExpExecDescriptor::StringStartRegister() { return r2; }
-const Register RegExpExecDescriptor::StringEndRegister() { return r3; }
-const Register RegExpExecDescriptor::CodeRegister() { return r4; }
const Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
@@ -162,9 +157,20 @@ void CallTrampolineDescriptor::InitializePlatformSpecific(
void CallForwardVarargsDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
+ // r0 : number of arguments
+ // r2 : start index (to support rest parameters)
+ // r1 : the target to call
+ Register registers[] = {r1, r0, r2};
+ data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+void ConstructForwardVarargsDescriptor::InitializePlatformSpecific(
+ CallInterfaceDescriptorData* data) {
+ // r0 : number of arguments
+ // r3 : the new target
// r2 : start index (to support rest parameters)
// r1 : the target to call
- Register registers[] = {r1, r2};
+ Register registers[] = {r1, r3, r0, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index f451ba5d3f..7256086b1d 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -497,7 +497,7 @@ void MacroAssembler::RecordWriteField(
add(dst, object, Operand(offset - kHeapObjectTag));
if (emit_debug_code()) {
Label ok;
- tst(dst, Operand((1 << kPointerSizeLog2) - 1));
+ tst(dst, Operand(kPointerSize - 1));
b(eq, &ok);
stop("Unaligned cell in write barrier");
bind(&ok);
@@ -561,7 +561,7 @@ void MacroAssembler::RecordWriteForMap(Register object,
add(dst, object, Operand(HeapObject::kMapOffset - kHeapObjectTag));
if (emit_debug_code()) {
Label ok;
- tst(dst, Operand((1 << kPointerSizeLog2) - 1));
+ tst(dst, Operand(kPointerSize - 1));
b(eq, &ok);
stop("Unaligned cell in write barrier");
bind(&ok);
@@ -770,59 +770,36 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
void MacroAssembler::PushCommonFrame(Register marker_reg) {
if (marker_reg.is_valid()) {
- if (FLAG_enable_embedded_constant_pool) {
- if (marker_reg.code() > pp.code()) {
- stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());
- add(fp, sp, Operand(kPointerSize));
- Push(marker_reg);
- } else {
- stm(db_w, sp, marker_reg.bit() | pp.bit() | fp.bit() | lr.bit());
- add(fp, sp, Operand(2 * kPointerSize));
- }
+ if (marker_reg.code() > fp.code()) {
+ stm(db_w, sp, fp.bit() | lr.bit());
+ mov(fp, Operand(sp));
+ Push(marker_reg);
} else {
- if (marker_reg.code() > fp.code()) {
- stm(db_w, sp, fp.bit() | lr.bit());
- mov(fp, Operand(sp));
- Push(marker_reg);
- } else {
- stm(db_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
- add(fp, sp, Operand(kPointerSize));
- }
+ stm(db_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
+ add(fp, sp, Operand(kPointerSize));
}
} else {
- stm(db_w, sp, (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) |
- fp.bit() | lr.bit());
- add(fp, sp, Operand(FLAG_enable_embedded_constant_pool ? kPointerSize : 0));
+ stm(db_w, sp, fp.bit() | lr.bit());
+ mov(fp, sp);
}
}
void MacroAssembler::PopCommonFrame(Register marker_reg) {
if (marker_reg.is_valid()) {
- if (FLAG_enable_embedded_constant_pool) {
- if (marker_reg.code() > pp.code()) {
- pop(marker_reg);
- ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit());
- } else {
- ldm(ia_w, sp, marker_reg.bit() | pp.bit() | fp.bit() | lr.bit());
- }
+ if (marker_reg.code() > fp.code()) {
+ pop(marker_reg);
+ ldm(ia_w, sp, fp.bit() | lr.bit());
} else {
- if (marker_reg.code() > fp.code()) {
- pop(marker_reg);
- ldm(ia_w, sp, fp.bit() | lr.bit());
- } else {
- ldm(ia_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
- }
+ ldm(ia_w, sp, marker_reg.bit() | fp.bit() | lr.bit());
}
} else {
- ldm(ia_w, sp, (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) |
- fp.bit() | lr.bit());
+ ldm(ia_w, sp, fp.bit() | lr.bit());
}
}
void MacroAssembler::PushStandardFrame(Register function_reg) {
DCHECK(!function_reg.is_valid() || function_reg.code() < cp.code());
stm(db_w, sp, (function_reg.is_valid() ? function_reg.bit() : 0) | cp.bit() |
- (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) |
fp.bit() | lr.bit());
int offset = -StandardFrameConstants::kContextOffset;
offset += function_reg.is_valid() ? kPointerSize : 0;
@@ -833,11 +810,7 @@ void MacroAssembler::PushStandardFrame(Register function_reg) {
// Push and pop all registers that can hold pointers.
void MacroAssembler::PushSafepointRegisters() {
// Safepoints expect a block of contiguous register values starting with r0.
- // except when FLAG_enable_embedded_constant_pool, which omits pp.
- DCHECK(kSafepointSavedRegisters ==
- (FLAG_enable_embedded_constant_pool
- ? ((1 << (kNumSafepointSavedRegisters + 1)) - 1) & ~pp.bit()
- : (1 << kNumSafepointSavedRegisters) - 1));
+ DCHECK(kSafepointSavedRegisters == (1 << kNumSafepointSavedRegisters) - 1);
// Safepoints expect a block of kNumSafepointRegisters values on the
// stack, so adjust the stack for unsaved registers.
const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters;
@@ -867,10 +840,6 @@ void MacroAssembler::LoadFromSafepointRegisterSlot(Register dst, Register src) {
int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
// The registers are pushed starting with the highest encoding,
// which means that lowest encodings are closest to the stack pointer.
- if (FLAG_enable_embedded_constant_pool && reg_code > pp.code()) {
- // RegList omits pp.
- reg_code -= 1;
- }
DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters);
return reg_code;
}
@@ -1110,47 +1079,90 @@ void MacroAssembler::VmovExtended(int dst_code, Register src) {
}
}
-void MacroAssembler::VmovExtended(int dst_code, int src_code,
- Register scratch) {
+void MacroAssembler::VmovExtended(int dst_code, int src_code) {
+ if (src_code == dst_code) return;
+
if (src_code < SwVfpRegister::kMaxNumRegisters &&
dst_code < SwVfpRegister::kMaxNumRegisters) {
// src and dst are both s-registers.
vmov(SwVfpRegister::from_code(dst_code),
SwVfpRegister::from_code(src_code));
- } else if (src_code < SwVfpRegister::kMaxNumRegisters) {
- // src is an s-register.
- vmov(scratch, SwVfpRegister::from_code(src_code));
- VmovExtended(dst_code, scratch);
+ return;
+ }
+ DwVfpRegister dst_d_reg = DwVfpRegister::from_code(dst_code / 2);
+ DwVfpRegister src_d_reg = DwVfpRegister::from_code(src_code / 2);
+ int dst_offset = dst_code & 1;
+ int src_offset = src_code & 1;
+ if (CpuFeatures::IsSupported(NEON)) {
+ // On Neon we can shift and insert from d-registers.
+ if (src_offset == dst_offset) {
+ // Offsets are the same, use vdup to copy the source to the opposite lane.
+ vdup(Neon32, kScratchDoubleReg, src_d_reg, src_offset);
+ src_d_reg = kScratchDoubleReg;
+ src_offset = dst_offset ^ 1;
+ }
+ if (dst_offset) {
+ if (dst_d_reg.is(src_d_reg)) {
+ vdup(Neon32, dst_d_reg, src_d_reg, 0);
+ } else {
+ vsli(Neon64, dst_d_reg, src_d_reg, 32);
+ }
+ } else {
+ if (dst_d_reg.is(src_d_reg)) {
+ vdup(Neon32, dst_d_reg, src_d_reg, 1);
+ } else {
+ vsri(Neon64, dst_d_reg, src_d_reg, 32);
+ }
+ }
+ return;
+ }
+
+ // Without Neon, use the scratch registers to move src and/or dst into
+ // s-registers.
+ int scratchSCode = kScratchDoubleReg.low().code();
+ int scratchSCode2 = kScratchDoubleReg2.low().code();
+ if (src_code < SwVfpRegister::kMaxNumRegisters) {
+ // src is an s-register, dst is not.
+ vmov(kScratchDoubleReg, dst_d_reg);
+ vmov(SwVfpRegister::from_code(scratchSCode + dst_offset),
+ SwVfpRegister::from_code(src_code));
+ vmov(dst_d_reg, kScratchDoubleReg);
} else if (dst_code < SwVfpRegister::kMaxNumRegisters) {
- // dst is an s-register.
- VmovExtended(scratch, src_code);
- vmov(SwVfpRegister::from_code(dst_code), scratch);
+ // dst is an s-register, src is not.
+ vmov(kScratchDoubleReg, src_d_reg);
+ vmov(SwVfpRegister::from_code(dst_code),
+ SwVfpRegister::from_code(scratchSCode + src_offset));
} else {
- // Neither src or dst are s-registers.
- DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, src_code);
- DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, dst_code);
- VmovExtended(scratch, src_code);
- VmovExtended(dst_code, scratch);
+ // Neither src or dst are s-registers. Both scratch double registers are
+ // available when there are 32 VFP registers.
+ vmov(kScratchDoubleReg, src_d_reg);
+ vmov(kScratchDoubleReg2, dst_d_reg);
+ vmov(SwVfpRegister::from_code(scratchSCode + dst_offset),
+ SwVfpRegister::from_code(scratchSCode2 + src_offset));
+ vmov(dst_d_reg, kScratchQuadReg.high());
}
}
-void MacroAssembler::VmovExtended(int dst_code, const MemOperand& src,
- Register scratch) {
- if (dst_code >= SwVfpRegister::kMaxNumRegisters) {
- ldr(scratch, src);
- VmovExtended(dst_code, scratch);
- } else {
+void MacroAssembler::VmovExtended(int dst_code, const MemOperand& src) {
+ if (dst_code < SwVfpRegister::kMaxNumRegisters) {
vldr(SwVfpRegister::from_code(dst_code), src);
+ } else {
+ // TODO(bbudge) If Neon supported, use load single lane form of vld1.
+ int dst_s_code = kScratchDoubleReg.low().code() + (dst_code & 1);
+ vmov(kScratchDoubleReg, DwVfpRegister::from_code(dst_code / 2));
+ vldr(SwVfpRegister::from_code(dst_s_code), src);
+ vmov(DwVfpRegister::from_code(dst_code / 2), kScratchDoubleReg);
}
}
-void MacroAssembler::VmovExtended(const MemOperand& dst, int src_code,
- Register scratch) {
- if (src_code >= SwVfpRegister::kMaxNumRegisters) {
- VmovExtended(scratch, src_code);
- str(scratch, dst);
- } else {
+void MacroAssembler::VmovExtended(const MemOperand& dst, int src_code) {
+ if (src_code < SwVfpRegister::kMaxNumRegisters) {
vstr(SwVfpRegister::from_code(src_code), dst);
+ } else {
+ // TODO(bbudge) If Neon supported, use store single lane form of vst1.
+ int src_s_code = kScratchDoubleReg.low().code() + (src_code & 1);
+ vmov(kScratchDoubleReg, DwVfpRegister::from_code(src_code / 2));
+ vstr(SwVfpRegister::from_code(src_s_code), dst);
}
}
@@ -1176,9 +1188,9 @@ void MacroAssembler::ExtractLane(Register dst, DwVfpRegister src,
}
void MacroAssembler::ExtractLane(SwVfpRegister dst, QwNeonRegister src,
- Register scratch, int lane) {
+ int lane) {
int s_code = src.code() * 4 + lane;
- VmovExtended(dst.code(), s_code, scratch);
+ VmovExtended(dst.code(), s_code);
}
void MacroAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
@@ -1195,69 +1207,10 @@ void MacroAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
}
void MacroAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
- SwVfpRegister src_lane, Register scratch,
- int lane) {
+ SwVfpRegister src_lane, int lane) {
Move(dst, src);
int s_code = dst.code() * 4 + lane;
- VmovExtended(s_code, src_lane.code(), scratch);
-}
-
-void MacroAssembler::Swizzle(QwNeonRegister dst, QwNeonRegister src,
- Register scratch, NeonSize size, uint32_t lanes) {
- // TODO(bbudge) Handle Int16x8, Int8x16 vectors.
- DCHECK_EQ(Neon32, size);
- DCHECK_IMPLIES(size == Neon32, lanes < 0xFFFFu);
- if (size == Neon32) {
- switch (lanes) {
- // TODO(bbudge) Handle more special cases.
- case 0x3210: // Identity.
- Move(dst, src);
- return;
- case 0x1032: // Swap top and bottom.
- vext(dst, src, src, 8);
- return;
- case 0x2103: // Rotation.
- vext(dst, src, src, 12);
- return;
- case 0x0321: // Rotation.
- vext(dst, src, src, 4);
- return;
- case 0x0000: // Equivalent to vdup.
- case 0x1111:
- case 0x2222:
- case 0x3333: {
- int lane_code = src.code() * 4 + (lanes & 0xF);
- if (lane_code >= SwVfpRegister::kMaxNumRegisters) {
- // TODO(bbudge) use vdup (vdup.32 dst, D<src>[lane]) once implemented.
- int temp_code = kScratchDoubleReg.code() * 2;
- VmovExtended(temp_code, lane_code, scratch);
- lane_code = temp_code;
- }
- vdup(dst, SwVfpRegister::from_code(lane_code));
- return;
- }
- case 0x2301: // Swap lanes 0, 1 and lanes 2, 3.
- vrev64(Neon32, dst, src);
- return;
- default: // Handle all other cases with vmovs.
- int src_code = src.code() * 4;
- int dst_code = dst.code() * 4;
- bool in_place = src.is(dst);
- if (in_place) {
- vmov(kScratchQuadReg, src);
- src_code = kScratchQuadReg.code() * 4;
- }
- for (int i = 0; i < 4; i++) {
- int lane = (lanes >> (i * 4) & 0xF);
- VmovExtended(dst_code + i, src_code + lane, scratch);
- }
- if (in_place) {
- // Restore zero reg.
- veor(kDoubleRegZero, kDoubleRegZero, kDoubleRegZero);
- }
- return;
- }
- }
+ VmovExtended(s_code, src_lane.code());
}
void MacroAssembler::LslPair(Register dst_low, Register dst_high,
@@ -1399,29 +1352,9 @@ void MacroAssembler::AsrPair(Register dst_low, Register dst_high,
}
}
-void MacroAssembler::LoadConstantPoolPointerRegisterFromCodeTargetAddress(
- Register code_target_address) {
- DCHECK(FLAG_enable_embedded_constant_pool);
- ldr(pp, MemOperand(code_target_address,
- Code::kConstantPoolOffset - Code::kHeaderSize));
- add(pp, pp, code_target_address);
-}
-
-
-void MacroAssembler::LoadConstantPoolPointerRegister() {
- DCHECK(FLAG_enable_embedded_constant_pool);
- int entry_offset = pc_offset() + Instruction::kPCReadOffset;
- sub(ip, pc, Operand(entry_offset));
- LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip);
-}
-
void MacroAssembler::StubPrologue(StackFrame::Type type) {
mov(ip, Operand(StackFrame::TypeToMarker(type)));
PushCommonFrame(ip);
- if (FLAG_enable_embedded_constant_pool) {
- LoadConstantPoolPointerRegister();
- set_constant_pool_available(true);
- }
}
void MacroAssembler::Prologue(bool code_pre_aging) {
@@ -1440,10 +1373,6 @@ void MacroAssembler::Prologue(bool code_pre_aging) {
nop(ip.code());
}
}
- if (FLAG_enable_embedded_constant_pool) {
- LoadConstantPoolPointerRegister();
- set_constant_pool_available(true);
- }
}
void MacroAssembler::EmitLoadFeedbackVector(Register vector) {
@@ -1458,9 +1387,6 @@ void MacroAssembler::EnterFrame(StackFrame::Type type,
// r0-r3: preserved
mov(ip, Operand(StackFrame::TypeToMarker(type)));
PushCommonFrame(ip);
- if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) {
- LoadConstantPoolPointerRegister();
- }
if (type == StackFrame::INTERNAL) {
mov(ip, Operand(CodeObject()));
push(ip);
@@ -1474,18 +1400,10 @@ int MacroAssembler::LeaveFrame(StackFrame::Type type) {
// r2: preserved
// Drop the execution stack down to the frame pointer and restore
- // the caller frame pointer, return address and constant pool pointer
- // (if FLAG_enable_embedded_constant_pool).
- int frame_ends;
- if (FLAG_enable_embedded_constant_pool) {
- add(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset));
- frame_ends = pc_offset();
- ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit());
- } else {
- mov(sp, fp);
- frame_ends = pc_offset();
- ldm(ia_w, sp, fp.bit() | lr.bit());
- }
+ // the caller frame pointer and return address.
+ mov(sp, fp);
+ int frame_ends = pc_offset();
+ ldm(ia_w, sp, fp.bit() | lr.bit());
return frame_ends;
}
@@ -1519,9 +1437,6 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
mov(ip, Operand::Zero());
str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset));
}
- if (FLAG_enable_embedded_constant_pool) {
- str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
- }
mov(ip, Operand(CodeObject()));
str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset));
@@ -1537,8 +1452,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space,
// Note that d0 will be accessible at
// fp - ExitFrameConstants::kFrameSize -
// DwVfpRegister::kMaxNumRegisters * kDoubleSize,
- // since the sp slot, code slot and constant pool slot (if
- // FLAG_enable_embedded_constant_pool) were pushed after the fp.
+ // since the sp slot and code slot were pushed after the fp.
}
// Reserve place for the return address and stack space and align the frame
@@ -1603,9 +1517,6 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
#endif
// Tear down the exit frame, pop the arguments, and return.
- if (FLAG_enable_embedded_constant_pool) {
- ldr(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset));
- }
mov(sp, Operand(fp));
ldm(ia_w, sp, fp.bit() | lr.bit());
if (argument_count.is_valid()) {
@@ -3404,6 +3315,7 @@ void MacroAssembler::CallCFunction(Register function,
void MacroAssembler::CallCFunctionHelper(Register function,
int num_reg_arguments,
int num_double_arguments) {
+ DCHECK_LE(num_reg_arguments + num_double_arguments, kMaxCParameters);
DCHECK(has_frame());
// Make sure that the stack is aligned before calling a C function unless
// running in the simulator. The simulator has its own alignment check which
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index a69b918ed8..506364686f 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -41,7 +41,6 @@ inline MemOperand FieldMemOperand(Register object, int offset) {
// Give alias names to registers
const Register cp = {Register::kCode_r7}; // JavaScript context pointer.
-const Register pp = {Register::kCode_r8}; // Constant pool pointer.
const Register kRootRegister = {Register::kCode_r10}; // Roots array pointer.
// Flags used for AllocateHeapNumber
@@ -474,12 +473,10 @@ class MacroAssembler: public Assembler {
}
}
- // Push a fixed frame, consisting of lr, fp, constant pool (if
- // FLAG_enable_embedded_constant_pool)
+ // Push a fixed frame, consisting of lr, fp
void PushCommonFrame(Register marker_reg = no_reg);
- // Push a standard frame, consisting of lr, fp, constant pool (if
- // FLAG_enable_embedded_constant_pool), context and JS function
+ // Push a standard frame, consisting of lr, fp, context and JS function
void PushStandardFrame(Register function_reg);
void PopCommonFrame(Register marker_reg = no_reg);
@@ -562,20 +559,17 @@ class MacroAssembler: public Assembler {
void VmovExtended(Register dst, int src_code);
void VmovExtended(int dst_code, Register src);
// Move between s-registers and imaginary s-registers.
- void VmovExtended(int dst_code, int src_code, Register scratch);
- void VmovExtended(int dst_code, const MemOperand& src, Register scratch);
- void VmovExtended(const MemOperand& dst, int src_code, Register scratch);
+ void VmovExtended(int dst_code, int src_code);
+ void VmovExtended(int dst_code, const MemOperand& src);
+ void VmovExtended(const MemOperand& dst, int src_code);
void ExtractLane(Register dst, QwNeonRegister src, NeonDataType dt, int lane);
void ExtractLane(Register dst, DwVfpRegister src, NeonDataType dt, int lane);
- void ExtractLane(SwVfpRegister dst, QwNeonRegister src, Register scratch,
- int lane);
+ void ExtractLane(SwVfpRegister dst, QwNeonRegister src, int lane);
void ReplaceLane(QwNeonRegister dst, QwNeonRegister src, Register src_lane,
NeonDataType dt, int lane);
void ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
- SwVfpRegister src_lane, Register scratch, int lane);
- void Swizzle(QwNeonRegister dst, QwNeonRegister src, Register scratch,
- NeonSize size, uint32_t lanes);
+ SwVfpRegister src_lane, int lane);
void LslPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, Register scratch, Register shift);
@@ -1337,11 +1331,6 @@ class MacroAssembler: public Assembler {
Register scratch_reg,
Label* no_memento_found);
- // Loads the constant pool pointer (pp) register.
- void LoadConstantPoolPointerRegisterFromCodeTargetAddress(
- Register code_target_address);
- void LoadConstantPoolPointerRegister();
-
private:
void CallCFunctionHelper(Register function,
int num_reg_arguments,
diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc
index c1e6fc1f4d..1f7e146692 100644
--- a/deps/v8/src/arm/simulator-arm.cc
+++ b/deps/v8/src/arm/simulator-arm.cc
@@ -803,6 +803,8 @@ void Simulator::TearDown(base::CustomMatcherHashMap* i_cache,
void* Simulator::RedirectExternalReference(Isolate* isolate,
void* external_function,
ExternalReference::Type type) {
+ base::LockGuard<base::Mutex> lock_guard(
+ isolate->simulator_redirection_mutex());
Redirection* redirection = Redirection::Get(isolate, external_function, type);
return redirection->address_of_swi_instruction();
}
@@ -1706,12 +1708,11 @@ void Simulator::HandleVList(Instruction* instr) {
// 64-bit value. With the code below we assume that all runtime calls return
// 64 bits of result. If they don't, the r1 result register contains a bogus
// value, which is fine because it is caller-saved.
-typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
- int32_t arg1,
- int32_t arg2,
- int32_t arg3,
- int32_t arg4,
- int32_t arg5);
+typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3,
+ int32_t arg4, int32_t arg5,
+ int32_t arg6, int32_t arg7,
+ int32_t arg8);
typedef ObjectTriple (*SimulatorRuntimeTripleCall)(int32_t arg0, int32_t arg1,
int32_t arg2, int32_t arg3,
@@ -1752,6 +1753,11 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
int32_t arg4 = stack_pointer[0];
int32_t arg5 = stack_pointer[1];
+ int32_t arg6 = stack_pointer[2];
+ int32_t arg7 = stack_pointer[3];
+ int32_t arg8 = stack_pointer[4];
+ STATIC_ASSERT(kMaxCParameters == 9);
+
bool fp_call =
(redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
(redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
@@ -1939,16 +1945,17 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
PrintF(
"Call to host function at %p "
- "args %08x, %08x, %08x, %08x, %08x, %08x",
+ "args %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x",
static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
- arg4, arg5);
+ arg4, arg5, arg6, arg7, arg8);
if (!stack_aligned) {
PrintF(" with unaligned stack %08x\n", get_register(sp));
}
PrintF("\n");
}
CHECK(stack_aligned);
- int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
+ int64_t result =
+ target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
int32_t lo_res = static_cast<int32_t>(result);
int32_t hi_res = static_cast<int32_t>(result >> 32);
if (::v8::internal::FLAG_trace_sim) {
@@ -4216,6 +4223,34 @@ void ArithmeticShiftRight(Simulator* simulator, int Vd, int Vm, int shift) {
}
template <typename T, int SIZE>
+void ShiftLeftAndInsert(Simulator* simulator, int Vd, int Vm, int shift) {
+ static const int kElems = SIZE / sizeof(T);
+ T src[kElems];
+ T dst[kElems];
+ simulator->get_neon_register<T, SIZE>(Vm, src);
+ simulator->get_neon_register<T, SIZE>(Vd, dst);
+ uint64_t mask = (1llu << shift) - 1llu;
+ for (int i = 0; i < kElems; i++) {
+ dst[i] = (src[i] << shift) | (dst[i] & mask);
+ }
+ simulator->set_neon_register<T, SIZE>(Vd, dst);
+}
+
+template <typename T, int SIZE>
+void ShiftRightAndInsert(Simulator* simulator, int Vd, int Vm, int shift) {
+ static const int kElems = SIZE / sizeof(T);
+ T src[kElems];
+ T dst[kElems];
+ simulator->get_neon_register<T, SIZE>(Vm, src);
+ simulator->get_neon_register<T, SIZE>(Vd, dst);
+ uint64_t mask = ~((1llu << (kBitsPerByte * SIZE - shift)) - 1llu);
+ for (int i = 0; i < kElems; i++) {
+ dst[i] = (src[i] >> shift) | (dst[i] & mask);
+ }
+ simulator->set_neon_register<T, SIZE>(Vd, dst);
+}
+
+template <typename T, int SIZE>
void CompareEqual(Simulator* simulator, int Vd, int Vm, int Vn) {
static const int kElems = SIZE / sizeof(T);
T src1[kElems], src2[kElems];
@@ -4273,6 +4308,20 @@ void PairwiseMinMax(Simulator* simulator, int Vd, int Vm, int Vn, bool min) {
simulator->set_neon_register<T, kDoubleSize>(Vd, dst);
}
+template <typename T>
+void PairwiseAdd(Simulator* simulator, int Vd, int Vm, int Vn) {
+ static const int kElems = kDoubleSize / sizeof(T);
+ static const int kPairs = kElems / 2;
+ T dst[kElems], src1[kElems], src2[kElems];
+ simulator->get_neon_register<T, kDoubleSize>(Vn, src1);
+ simulator->get_neon_register<T, kDoubleSize>(Vm, src2);
+ for (int i = 0; i < kPairs; i++) {
+ dst[i] = src1[i * 2] + src1[i * 2 + 1];
+ dst[i + kPairs] = src2[i * 2] + src2[i * 2 + 1];
+ }
+ simulator->set_neon_register<T, kDoubleSize>(Vd, dst);
+}
+
void Simulator::DecodeSpecialCondition(Instruction* instr) {
switch (instr->SpecialValue()) {
case 4: {
@@ -4484,6 +4533,25 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
}
break;
}
+ case 0xb: {
+ // vpadd.i<size> Dd, Dm, Dn.
+ NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
+ switch (size) {
+ case Neon8:
+ PairwiseAdd<int8_t>(this, Vd, Vm, Vn);
+ break;
+ case Neon16:
+ PairwiseAdd<int16_t>(this, Vd, Vm, Vn);
+ break;
+ case Neon32:
+ PairwiseAdd<int32_t>(this, Vd, Vm, Vn);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ }
case 0xd: {
if (instr->Bit(4) == 0) {
float src1[4], src2[4];
@@ -4832,7 +4900,8 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
break;
}
case 0xd: {
- if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) {
+ if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
+ instr->Bit(4) == 1) {
// vmul.f32 Qd, Qn, Qm
float src1[4], src2[4];
get_neon_register(Vn, src1);
@@ -4841,6 +4910,10 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
src1[i] = src1[i] * src2[i];
}
set_neon_register(Vd, src1);
+ } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 0 &&
+ instr->Bit(4) == 0) {
+ // vpadd.f32 Dd, Dn, Dm
+ PairwiseAdd<float>(this, Vd, Vm, Vn);
} else {
UNIMPLEMENTED();
}
@@ -4950,14 +5023,40 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
set_neon_register(vd, mval);
}
} else if (instr->Bits(11, 7) == 0x18) {
- // vdup.32 Qd, Sm.
- int vd = instr->VFPDRegValue(kSimd128Precision);
+ // vdup.<size> Dd, Dm[index].
+ // vdup.<size> Qd, Dm[index].
int vm = instr->VFPMRegValue(kDoublePrecision);
- int index = instr->Bit(19);
- uint32_t s_data = get_s_register(vm * 2 + index);
- uint32_t q_data[4];
- for (int i = 0; i < 4; i++) q_data[i] = s_data;
- set_neon_register(vd, q_data);
+ int imm4 = instr->Bits(19, 16);
+ int size = 0, index = 0, mask = 0;
+ if ((imm4 & 0x1) != 0) {
+ size = 8;
+ index = imm4 >> 1;
+ mask = 0xffu;
+ } else if ((imm4 & 0x2) != 0) {
+ size = 16;
+ index = imm4 >> 2;
+ mask = 0xffffu;
+ } else {
+ size = 32;
+ index = imm4 >> 3;
+ mask = 0xffffffffu;
+ }
+ uint64_t d_data;
+ get_d_register(vm, &d_data);
+ uint32_t scalar = (d_data >> (size * index)) & mask;
+ uint32_t duped = scalar;
+ for (int i = 1; i < 32 / size; i++) {
+ scalar <<= size;
+ duped |= scalar;
+ }
+ uint32_t result[4] = {duped, duped, duped, duped};
+ if (instr->Bit(6) == 0) {
+ int vd = instr->VFPDRegValue(kDoublePrecision);
+ set_d_register(vd, result);
+ } else {
+ int vd = instr->VFPDRegValue(kSimd128Precision);
+ set_neon_register(vd, result);
+ }
} else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
// vmvn Qd, Qm.
int vd = instr->VFPDRegValue(kSimd128Precision);
@@ -5334,6 +5433,58 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
UNREACHABLE();
break;
}
+ } else if (instr->Bits(11, 8) == 0x5 && instr->Bit(6) == 0 &&
+ instr->Bit(4) == 1) {
+ // vsli.<size> Dd, Dm, shift
+ 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(kDoublePrecision);
+ int Vm = instr->VFPMRegValue(kDoublePrecision);
+ switch (size) {
+ case 8:
+ ShiftLeftAndInsert<uint8_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ case 16:
+ ShiftLeftAndInsert<uint16_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ case 32:
+ ShiftLeftAndInsert<uint32_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ case 64:
+ ShiftLeftAndInsert<uint64_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ } else if (instr->Bits(11, 8) == 0x4 && instr->Bit(6) == 0 &&
+ instr->Bit(4) == 1) {
+ // vsri.<size> Dd, Dm, shift
+ 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(kDoublePrecision);
+ int Vm = instr->VFPMRegValue(kDoublePrecision);
+ switch (size) {
+ case 8:
+ ShiftRightAndInsert<uint8_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ case 16:
+ ShiftRightAndInsert<uint16_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ case 32:
+ ShiftRightAndInsert<uint32_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ case 64:
+ ShiftRightAndInsert<uint64_t, kDoubleSize>(this, Vd, Vm, shift);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
} else {
UNIMPLEMENTED();
}
diff --git a/deps/v8/src/arm/simulator-arm.h b/deps/v8/src/arm/simulator-arm.h
index f5ebf219cb..35fc2f930e 100644
--- a/deps/v8/src/arm/simulator-arm.h
+++ b/deps/v8/src/arm/simulator-arm.h
@@ -27,18 +27,14 @@ namespace internal {
#define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
(entry(p0, p1, p2, p3, p4))
-typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*,
- void*, int*, int, Address, int, Isolate*);
-
+typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*, int*,
+ int, Address, int, Isolate*);
// Call the generated regexp code directly. The code at the entry address
// should act as a function matching the type arm_regexp_matcher.
-// The fifth argument is a dummy that reserves the space used for
-// the return address added by the ExitFrame in native calls.
#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
p7, p8) \
- (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6, \
- p7, p8))
+ (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, p8))
// The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on arm uses the C stack, we
@@ -365,7 +361,7 @@ class Simulator {
static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
void* page);
- // Runtime call support.
+ // Runtime call support. Uses the isolate in a thread-safe way.
static void* RedirectExternalReference(
Isolate* isolate, void* external_function,
v8::internal::ExternalReference::Type type);
@@ -549,9 +545,8 @@ class Simulator {
#define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
p7, p8) \
- Simulator::current(isolate) \
- ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
-
+ Simulator::current(isolate)->Call(entry, 9, p0, p1, p2, p3, p4, p5, p6, p7, \
+ p8)
// The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code. The JS-based limit normally points near the end of