diff options
author | Myles Borins <mylesborins@google.com> | 2017-08-01 11:36:44 -0500 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2017-08-01 15:23:15 -0500 |
commit | 0a66b223e149a841669bfad5598e4254589730cb (patch) | |
tree | 5ec050f7f78aafbf5b1e0e50d639fb843141e162 /deps/v8/src/arm | |
parent | 1782b3836ba58ef0da6b687f2bb970c0bd8199ad (diff) | |
download | node-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.h | 118 | ||||
-rw-r--r-- | deps/v8/src/arm/assembler-arm.cc | 471 | ||||
-rw-r--r-- | deps/v8/src/arm/assembler-arm.h | 50 | ||||
-rw-r--r-- | deps/v8/src/arm/code-stubs-arm.cc | 80 | ||||
-rw-r--r-- | deps/v8/src/arm/constants-arm.h | 19 | ||||
-rw-r--r-- | deps/v8/src/arm/deoptimizer-arm.cc | 57 | ||||
-rw-r--r-- | deps/v8/src/arm/disasm-arm.cc | 99 | ||||
-rw-r--r-- | deps/v8/src/arm/frames-arm.cc | 8 | ||||
-rw-r--r-- | deps/v8/src/arm/frames-arm.h | 16 | ||||
-rw-r--r-- | deps/v8/src/arm/interface-descriptors-arm.cc | 18 | ||||
-rw-r--r-- | deps/v8/src/arm/macro-assembler-arm.cc | 278 | ||||
-rw-r--r-- | deps/v8/src/arm/macro-assembler-arm.h | 25 | ||||
-rw-r--r-- | deps/v8/src/arm/simulator-arm.cc | 185 | ||||
-rw-r--r-- | deps/v8/src/arm/simulator-arm.h | 17 |
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 |