summaryrefslogtreecommitdiff
path: root/deps/v8/src/arm
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2018-04-10 21:39:51 -0400
committerJames M Snell <jasnell@gmail.com>2018-04-16 16:02:46 -0700
commit9daebb48d6f0ca63e72197a69e46c8ab43bc5d02 (patch)
tree8605276308c8b4e3597516961266bae1af57557a /deps/v8/src/arm
parent7d2814e7903155e61f244ae70721da1531cbcaec (diff)
downloadnode-new-9daebb48d6f0ca63e72197a69e46c8ab43bc5d02.tar.gz
deps: update V8 to 6.6.346.23
PR-URL: https://github.com/nodejs/node/pull/19201 Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com> Reviewed-By: Myles Borins <myles.borins@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.h63
-rw-r--r--deps/v8/src/arm/assembler-arm.cc62
-rw-r--r--deps/v8/src/arm/assembler-arm.h98
-rw-r--r--deps/v8/src/arm/code-stubs-arm.cc16
-rw-r--r--deps/v8/src/arm/codegen-arm.cc10
-rw-r--r--deps/v8/src/arm/constants-arm.h4
-rw-r--r--deps/v8/src/arm/deoptimizer-arm.cc3
-rw-r--r--deps/v8/src/arm/disasm-arm.cc10
-rw-r--r--deps/v8/src/arm/frame-constants-arm.h6
-rw-r--r--deps/v8/src/arm/interface-descriptors-arm.cc6
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc165
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h30
-rw-r--r--deps/v8/src/arm/simulator-arm.cc23
-rw-r--r--deps/v8/src/arm/simulator-arm.h4
14 files changed, 319 insertions, 181 deletions
diff --git a/deps/v8/src/arm/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h
index f420f2e5cb..4d7d9895ce 100644
--- a/deps/v8/src/arm/assembler-arm-inl.h
+++ b/deps/v8/src/arm/assembler-arm-inl.h
@@ -46,7 +46,7 @@
namespace v8 {
namespace internal {
-bool CpuFeatures::SupportsCrankshaft() { return true; }
+bool CpuFeatures::SupportsOptimizer() { return true; }
bool CpuFeatures::SupportsWasmSimd128() { return IsSupported(NEON); }
@@ -109,7 +109,7 @@ void RelocInfo::set_target_object(HeapObject* target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
- Assembler::set_target_address_at(target->GetIsolate(), pc_, constant_pool_,
+ Assembler::set_target_address_at(pc_, constant_pool_,
reinterpret_cast<Address>(target),
icache_flush_mode);
if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != nullptr) {
@@ -143,27 +143,27 @@ Address RelocInfo::target_runtime_entry(Assembler* origin) {
return target_address();
}
-void RelocInfo::set_target_runtime_entry(Isolate* isolate, Address target,
+void RelocInfo::set_target_runtime_entry(Address target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
DCHECK(IsRuntimeEntry(rmode_));
if (target_address() != target)
- set_target_address(isolate, target, write_barrier_mode, icache_flush_mode);
+ set_target_address(target, write_barrier_mode, icache_flush_mode);
}
-void RelocInfo::WipeOut(Isolate* isolate) {
+void RelocInfo::WipeOut() {
DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) ||
IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) ||
IsInternalReference(rmode_));
if (IsInternalReference(rmode_)) {
Memory::Address_at(pc_) = nullptr;
} else {
- Assembler::set_target_address_at(isolate, pc_, constant_pool_, nullptr);
+ Assembler::set_target_address_at(pc_, constant_pool_, nullptr);
}
}
template <typename ObjectVisitor>
-void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
+void RelocInfo::Visit(ObjectVisitor* visitor) {
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
visitor->VisitEmbeddedPointer(host(), this);
@@ -189,7 +189,7 @@ Operand::Operand(const ExternalReference& f)
value_.immediate = reinterpret_cast<int32_t>(f.address());
}
-Operand::Operand(Smi* value) : rmode_(RelocInfo::NONE32) {
+Operand::Operand(Smi* value) : rmode_(RelocInfo::NONE) {
value_.immediate = reinterpret_cast<intptr_t>(value);
}
@@ -273,15 +273,13 @@ 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) {
+ Address constant_pool_entry, Code* code, Address target) {
Memory::Address_at(constant_pool_entry) = target;
}
-
void Assembler::deserialization_set_target_internal_reference_at(
- Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) {
+ Address pc, Address target, RelocInfo::Mode mode) {
Memory::Address_at(pc) = target;
}
@@ -329,17 +327,15 @@ Address Assembler::target_address_at(Address pc, Address constant_pool) {
}
}
-
-void Assembler::set_target_address_at(Isolate* isolate, Address pc,
- Address constant_pool, Address target,
+void Assembler::set_target_address_at(Address pc, Address constant_pool,
+ Address target,
ICacheFlushMode icache_flush_mode) {
- DCHECK_IMPLIES(isolate == nullptr, icache_flush_mode == SKIP_ICACHE_FLUSH);
if (is_constant_pool_load(pc)) {
// This is a constant pool lookup. Update the entry in the constant pool.
Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target;
// Intuitively, we would think it is necessary to always flush the
// instruction cache after patching a target address in the code as follows:
- // Assembler::FlushICache(isolate, pc, sizeof(target));
+ // Assembler::FlushICache(pc, sizeof(target));
// However, on ARM, no instruction is actually patched in the case
// of embedded constants of the form:
// ldr ip, [pp, #...]
@@ -357,7 +353,7 @@ void Assembler::set_target_address_at(Isolate* isolate, Address pc,
DCHECK(IsMovW(Memory::int32_at(pc)));
DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- Assembler::FlushICache(isolate, pc, 2 * kInstrSize);
+ Assembler::FlushICache(pc, 2 * kInstrSize);
}
} else {
// This is an mov / orr immediate load. Patch the immediate embedded in
@@ -377,13 +373,42 @@ void Assembler::set_target_address_at(Isolate* isolate, Address pc,
IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- Assembler::FlushICache(isolate, pc, 4 * kInstrSize);
+ Assembler::FlushICache(pc, 4 * kInstrSize);
}
}
}
EnsureSpace::EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
+template <typename T>
+bool UseScratchRegisterScope::CanAcquireVfp() const {
+ VfpRegList* available = assembler_->GetScratchVfpRegisterList();
+ DCHECK_NOT_NULL(available);
+ for (int index = 0; index < T::kNumRegisters; index++) {
+ T reg = T::from_code(index);
+ uint64_t mask = reg.ToVfpRegList();
+ if ((*available & mask) == mask) {
+ return true;
+ }
+ }
+ return false;
+}
+
+template <typename T>
+T UseScratchRegisterScope::AcquireVfp() {
+ VfpRegList* available = assembler_->GetScratchVfpRegisterList();
+ DCHECK_NOT_NULL(available);
+ for (int index = 0; index < T::kNumRegisters; index++) {
+ T reg = T::from_code(index);
+ uint64_t mask = reg.ToVfpRegList();
+ if ((*available & mask) == mask) {
+ *available &= ~mask;
+ return reg;
+ }
+ }
+ UNREACHABLE();
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc
index a615d67496..1011db4b80 100644
--- a/deps/v8/src/arm/assembler-arm.cc
+++ b/deps/v8/src/arm/assembler-arm.cc
@@ -347,22 +347,20 @@ uint32_t RelocInfo::embedded_size() const {
Assembler::target_address_at(pc_, constant_pool_));
}
-void RelocInfo::set_embedded_address(Isolate* isolate, Address address,
+void RelocInfo::set_embedded_address(Address address,
ICacheFlushMode flush_mode) {
- Assembler::set_target_address_at(isolate, pc_, constant_pool_, address,
- flush_mode);
+ Assembler::set_target_address_at(pc_, constant_pool_, address, flush_mode);
}
-void RelocInfo::set_embedded_size(Isolate* isolate, uint32_t size,
- ICacheFlushMode flush_mode) {
- Assembler::set_target_address_at(isolate, pc_, constant_pool_,
+void RelocInfo::set_embedded_size(uint32_t size, ICacheFlushMode flush_mode) {
+ Assembler::set_target_address_at(pc_, constant_pool_,
reinterpret_cast<Address>(size), flush_mode);
}
-void RelocInfo::set_js_to_wasm_address(Isolate* isolate, Address address,
+void RelocInfo::set_js_to_wasm_address(Address address,
ICacheFlushMode icache_flush_mode) {
DCHECK_EQ(rmode_, JS_TO_WASM_CALL);
- set_embedded_address(isolate, address, icache_flush_mode);
+ set_embedded_address(address, icache_flush_mode);
}
Address RelocInfo::js_to_wasm_address() const {
@@ -566,10 +564,16 @@ Assembler::Assembler(IsolateData isolate_data, void* buffer, int buffer_size)
// it's awkward to use CpuFeatures::VFP32DREGS with CpuFeatureScope. To make
// its use consistent with other features, we always enable it if we can.
EnableCpuFeature(VFP32DREGS);
+ // Make sure we pick two D registers which alias a Q register. This way, we
+ // can use a Q as a scratch if NEON is supported.
+ scratch_vfp_register_list_ = d14.ToVfpRegList() | d15.ToVfpRegList();
+ } else {
+ // When VFP32DREGS is not supported, d15 become allocatable. Therefore we
+ // cannot use it as a scratch.
+ scratch_vfp_register_list_ = d14.ToVfpRegList();
}
}
-
Assembler::~Assembler() {
DCHECK_EQ(const_pool_blocked_nesting_, 0);
DCHECK_EQ(code_target_sharing_blocked_nesting_, 0);
@@ -1214,6 +1218,7 @@ void Assembler::AddrMode1(Instr instr, Register rd, Register rn,
DCHECK(x.IsImmediate());
// Upon failure to encode, the opcode should not have changed.
DCHECK(opcode == (instr & kOpCodeMask));
+ UseScratchRegisterScope temps(this);
Condition cond = Instruction::ConditionField(instr);
if ((opcode == MOV) && !set_flags) {
// Generate a sequence of mov instructions or a load from the constant
@@ -1221,7 +1226,7 @@ void Assembler::AddrMode1(Instr instr, Register rd, Register rn,
DCHECK(!rn.is_valid());
Move32BitImmediate(rd, x, cond);
} else if ((opcode == ADD) && !set_flags && (rd == rn) &&
- (scratch_register_list_ == 0)) {
+ !temps.CanAcquire()) {
// Split the operation into a sequence of additions if we cannot use a
// scratch register. In this case, we cannot re-use rn and the assembler
// does not have any scratch registers to spare.
@@ -1244,7 +1249,6 @@ void Assembler::AddrMode1(Instr instr, Register rd, Register rn,
// The immediate operand cannot be encoded as a shifter operand, so load
// it first to a scratch register and change the original instruction to
// use it.
- UseScratchRegisterScope temps(this);
// Re-use the destination register if possible.
Register scratch =
(rd.is_valid() && rd != rn && rd != pc) ? rd : temps.Acquire();
@@ -1501,6 +1505,10 @@ void Assembler::and_(Register dst, Register src1, const Operand& src2,
AddrMode1(cond | AND | s, dst, src1, src2);
}
+void Assembler::and_(Register dst, Register src1, Register src2, SBit s,
+ Condition cond) {
+ and_(dst, src1, Operand(src2), s, cond);
+}
void Assembler::eor(Register dst, Register src1, const Operand& src2,
SBit s, Condition cond) {
@@ -2367,6 +2375,11 @@ void Assembler::isb(BarrierOption option) {
}
}
+void Assembler::csdb() {
+ // Details available in Arm Cache Speculation Side-channels white paper,
+ // version 1.1, page 4.
+ emit(0xE320F014);
+}
// Coprocessor instructions.
void Assembler::cdp(Coprocessor coproc,
@@ -5153,8 +5166,7 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
void Assembler::ConstantPoolAddEntry(int position, RelocInfo::Mode rmode,
intptr_t value) {
- DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::CONST_POOL &&
- rmode != RelocInfo::NONE64);
+ DCHECK(rmode != RelocInfo::COMMENT && rmode != RelocInfo::CONST_POOL);
bool sharing_ok = RelocInfo::IsNone(rmode) ||
(rmode >= RelocInfo::FIRST_SHAREABLE_RELOC_MODE);
DCHECK_LT(pending_32_bit_constants_.size(), kMaxNumPending32Constants);
@@ -5474,24 +5486,24 @@ void PatchingAssembler::Emit(Address addr) {
emit(reinterpret_cast<Instr>(addr));
}
-void PatchingAssembler::FlushICache(Isolate* isolate) {
- Assembler::FlushICache(isolate, buffer_, buffer_size_ - kGap);
-}
-
UseScratchRegisterScope::UseScratchRegisterScope(Assembler* assembler)
- : available_(assembler->GetScratchRegisterList()),
- old_available_(*available_) {}
+ : assembler_(assembler),
+ old_available_(*assembler->GetScratchRegisterList()),
+ old_available_vfp_(*assembler->GetScratchVfpRegisterList()) {}
UseScratchRegisterScope::~UseScratchRegisterScope() {
- *available_ = old_available_;
+ *assembler_->GetScratchRegisterList() = old_available_;
+ *assembler_->GetScratchVfpRegisterList() = old_available_vfp_;
}
Register UseScratchRegisterScope::Acquire() {
- DCHECK_NOT_NULL(available_);
- DCHECK_NE(*available_, 0);
- int index = static_cast<int>(base::bits::CountTrailingZeros32(*available_));
- *available_ &= ~(1UL << index);
- return Register::from_code(index);
+ RegList* available = assembler_->GetScratchRegisterList();
+ DCHECK_NOT_NULL(available);
+ DCHECK_NE(*available, 0);
+ int index = static_cast<int>(base::bits::CountTrailingZeros32(*available));
+ Register reg = Register::from_code(index);
+ *available &= ~reg.bit();
+ return reg;
}
} // namespace internal
diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h
index 8b95aad886..32baa0ae8d 100644
--- a/deps/v8/src/arm/assembler-arm.h
+++ b/deps/v8/src/arm/assembler-arm.h
@@ -56,8 +56,9 @@ namespace internal {
V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
V(r8) V(r9) V(r10) V(fp) V(ip) V(sp) V(lr) V(pc)
-#define ALLOCATABLE_GENERAL_REGISTERS(V) \
- V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) V(r8)
+#define ALLOCATABLE_GENERAL_REGISTERS(V) \
+ V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
+ V(r8) V(r9)
#define FLOAT_REGISTERS(V) \
V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \
@@ -184,6 +185,17 @@ enum SwVfpRegisterCode {
kSwVfpAfterLast
};
+// Representation of a list of non-overlapping VFP registers. This list
+// represents the data layout of VFP registers as a bitfield:
+// S registers cover 1 bit
+// D registers cover 2 bits
+// Q registers cover 4 bits
+//
+// This way, we make sure no registers in the list ever overlap. However, a list
+// may represent multiple different sets of registers,
+// e.g. [d0 s2 s3] <=> [s0 s1 d1].
+typedef uint64_t VfpRegList;
+
// Single word VFP register.
class SwVfpRegister : public RegisterBase<SwVfpRegister, kSwVfpAfterLast> {
public:
@@ -195,6 +207,11 @@ class SwVfpRegister : public RegisterBase<SwVfpRegister, kSwVfpAfterLast> {
*vm = reg_code >> 1;
}
void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
+ VfpRegList ToVfpRegList() const {
+ DCHECK(is_valid());
+ // Each bit in the list corresponds to a S register.
+ return uint64_t{0x1} << code();
+ }
private:
friend class RegisterBase;
@@ -217,10 +234,6 @@ enum DoubleRegisterCode {
// Double word VFP register.
class DwVfpRegister : public RegisterBase<DwVfpRegister, kDoubleAfterLast> {
public:
- // A few double registers are reserved: one as a scratch register and one to
- // hold 0.0, that does not fit in the immediate field of vmov instructions.
- // d14: 0.0
- // d15: scratch register.
static constexpr int kSizeInBytes = 8;
inline static int NumRegisters();
@@ -231,6 +244,11 @@ class DwVfpRegister : public RegisterBase<DwVfpRegister, kDoubleAfterLast> {
*vm = reg_code & 0x0F;
}
void split_code(int* vm, int* m) const { split_code(code(), vm, m); }
+ VfpRegList ToVfpRegList() const {
+ DCHECK(is_valid());
+ // A D register overlaps two S registers.
+ return uint64_t{0x3} << (code() * 2);
+ }
private:
friend class RegisterBase;
@@ -255,6 +273,11 @@ class LowDwVfpRegister
SwVfpRegister high() const {
return SwVfpRegister::from_code(code() * 2 + 1);
}
+ VfpRegList ToVfpRegList() const {
+ DCHECK(is_valid());
+ // A D register overlaps two S registers.
+ return uint64_t{0x3} << (code() * 2);
+ }
private:
friend class RegisterBase;
@@ -282,6 +305,11 @@ class QwNeonRegister : public RegisterBase<QwNeonRegister, kSimd128AfterLast> {
DwVfpRegister high() const {
return DwVfpRegister::from_code(code() * 2 + 1);
}
+ VfpRegList ToVfpRegList() const {
+ DCHECK(is_valid());
+ // A Q register overlaps four S registers.
+ return uint64_t{0xf} << (code() * 4);
+ }
private:
friend class RegisterBase;
@@ -334,12 +362,6 @@ SIMD128_REGISTERS(DECLARE_SIMD128_REGISTER)
constexpr LowDwVfpRegister kFirstCalleeSavedDoubleReg = d8;
constexpr LowDwVfpRegister kLastCalleeSavedDoubleReg = d15;
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;
constexpr CRegister no_creg = CRegister::no_reg();
@@ -376,7 +398,7 @@ class Operand BASE_EMBEDDED {
public:
// immediate
INLINE(explicit Operand(int32_t immediate,
- RelocInfo::Mode rmode = RelocInfo::NONE32));
+ RelocInfo::Mode rmode = RelocInfo::NONE));
INLINE(static Operand Zero());
INLINE(explicit Operand(const ExternalReference& f));
explicit Operand(Handle<HeapObject> handle);
@@ -651,7 +673,7 @@ class Assembler : public AssemblerBase {
// The isolate argument is unused (and may be nullptr) when skipping flushing.
INLINE(static Address target_address_at(Address pc, Address constant_pool));
INLINE(static void set_target_address_at(
- Isolate* isolate, Address pc, Address constant_pool, Address target,
+ Address pc, Address constant_pool, Address target,
ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
// Return the code target address at a call site from the return address
@@ -665,12 +687,11 @@ class Assembler : public AssemblerBase {
// This sets the branch destination (which is in the constant pool on ARM).
// This is for calls and branches within generated code.
inline static void deserialization_set_special_target_at(
- Isolate* isolate, Address constant_pool_entry, Code* code,
- Address target);
+ Address constant_pool_entry, Code* code, Address target);
// This sets the internal reference at the pc.
inline static void deserialization_set_target_internal_reference_at(
- Isolate* isolate, Address pc, Address target,
+ Address pc, Address target,
RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
// Here we are patching the address in the constant pool, not the actual call
@@ -685,6 +706,9 @@ class Assembler : public AssemblerBase {
// register.
static constexpr int kPcLoadDelta = 8;
RegList* GetScratchRegisterList() { return &scratch_register_list_; }
+ VfpRegList* GetScratchVfpRegisterList() {
+ return &scratch_vfp_register_list_;
+ }
// ---------------------------------------------------------------------------
// Code generation
@@ -717,6 +741,8 @@ class Assembler : public AssemblerBase {
void and_(Register dst, Register src1, const Operand& src2,
SBit s = LeaveCC, Condition cond = al);
+ void and_(Register dst, Register src1, Register src2, SBit s = LeaveCC,
+ Condition cond = al);
void eor(Register dst, Register src1, const Operand& src2,
SBit s = LeaveCC, Condition cond = al);
@@ -936,6 +962,9 @@ class Assembler : public AssemblerBase {
void dsb(BarrierOption option);
void isb(BarrierOption option);
+ // Conditional speculation barrier.
+ void csdb();
+
// Coprocessor instructions
void cdp(Coprocessor coproc, int opcode_1,
@@ -1655,6 +1684,7 @@ class Assembler : public AssemblerBase {
// Scratch registers available for use by the Assembler.
RegList scratch_register_list_;
+ VfpRegList scratch_vfp_register_list_;
private:
// Avoid overflows for displacements etc.
@@ -1732,6 +1762,7 @@ class Assembler : public AssemblerBase {
friend class BlockConstPoolScope;
friend class BlockCodeTargetSharingScope;
friend class EnsureSpace;
+ friend class UseScratchRegisterScope;
// The following functions help with avoiding allocations of embedded heap
// objects during the code assembly phase. {RequestHeapObject} records the
@@ -1747,8 +1778,6 @@ class Assembler : public AssemblerBase {
std::forward_list<HeapObjectRequest> heap_object_requests_;
};
-constexpr int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize;
-
class EnsureSpace BASE_EMBEDDED {
public:
INLINE(explicit EnsureSpace(Assembler* assembler));
@@ -1760,7 +1789,6 @@ class PatchingAssembler : public Assembler {
~PatchingAssembler();
void Emit(Address addr);
- void FlushICache(Isolate* isolate);
};
// This scope utility allows scratch registers to be managed safely. The
@@ -1779,12 +1807,38 @@ class UseScratchRegisterScope {
// Take a register from the list and return it.
Register Acquire();
+ SwVfpRegister AcquireS() { return AcquireVfp<SwVfpRegister>(); }
+ LowDwVfpRegister AcquireLowD() { return AcquireVfp<LowDwVfpRegister>(); }
+ DwVfpRegister AcquireD() {
+ DwVfpRegister reg = AcquireVfp<DwVfpRegister>();
+ DCHECK(assembler_->VfpRegisterIsAvailable(reg));
+ return reg;
+ }
+ QwNeonRegister AcquireQ() {
+ QwNeonRegister reg = AcquireVfp<QwNeonRegister>();
+ DCHECK(assembler_->VfpRegisterIsAvailable(reg));
+ return reg;
+ }
private:
- // Currently available scratch registers.
- RegList* available_;
+ friend class Assembler;
+ friend class TurboAssembler;
+
+ // Check if we have registers available to acquire.
+ // These methods are kept private intentionally to restrict their usage to the
+ // assemblers. Choosing to emit a difference instruction sequence depending on
+ // the availability of scratch registers is generally their job.
+ bool CanAcquire() const { return *assembler_->GetScratchRegisterList() != 0; }
+ template <typename T>
+ bool CanAcquireVfp() const;
+
+ template <typename T>
+ T AcquireVfp();
+
+ Assembler* assembler_;
// Available scratch registers at the start of this scope.
RegList old_available_;
+ VfpRegList old_available_vfp_;
};
} // namespace internal
diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc
index ee706c7656..2695bafc1b 100644
--- a/deps/v8/src/arm/code-stubs-arm.cc
+++ b/deps/v8/src/arm/code-stubs-arm.cc
@@ -46,7 +46,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
UseScratchRegisterScope temps(masm);
Register double_low = GetRegisterThatIsNotOneOf(result_reg);
Register double_high = GetRegisterThatIsNotOneOf(result_reg, double_low);
- LowDwVfpRegister double_scratch = kScratchDoubleReg;
+ LowDwVfpRegister double_scratch = temps.AcquireLowD();
// Save the old values from these temporary registers on the stack.
__ Push(double_high, double_low);
@@ -385,6 +385,12 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ cmp(cp, Operand(0));
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset), ne);
+ // Reset the masking register. This is done independent of the underlying
+ // feature flag {FLAG_branch_load_poisoning} to make the snapshot work with
+ // both configurations. It is safe to always do this, because the underlying
+ // register is caller-saved and can be arbitrarily clobbered.
+ __ ResetSpeculationPoisonRegister();
+
// Compute the handler entry address and jump to it.
ConstantPoolUnavailableScope constant_pool_unavailable(masm);
__ mov(r1, Operand(pending_handler_entrypoint_address));
@@ -572,8 +578,8 @@ void ProfileEntryHookStub::MaybeCallEntryHookDelayed(TurboAssembler* tasm,
Zone* zone) {
if (tasm->isolate()->function_entry_hook() != nullptr) {
tasm->MaybeCheckConstPool();
- PredictableCodeSizeScope predictable(tasm);
- predictable.ExpectSize(tasm->CallStubSize() + 2 * Assembler::kInstrSize);
+ PredictableCodeSizeScope predictable(
+ tasm, tasm->CallStubSize() + 2 * Assembler::kInstrSize);
tasm->push(lr);
tasm->CallStubDelayed(new (zone) ProfileEntryHookStub(nullptr));
tasm->pop(lr);
@@ -584,8 +590,8 @@ void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
if (masm->isolate()->function_entry_hook() != nullptr) {
ProfileEntryHookStub stub(masm->isolate());
masm->MaybeCheckConstPool();
- PredictableCodeSizeScope predictable(masm);
- predictable.ExpectSize(masm->CallStubSize() + 2 * Assembler::kInstrSize);
+ PredictableCodeSizeScope predictable(
+ masm, masm->CallStubSize() + 2 * Assembler::kInstrSize);
__ push(lr);
__ CallStub(&stub);
__ pop(lr);
diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc
index 9fb2eb4e8d..b3e880e048 100644
--- a/deps/v8/src/arm/codegen-arm.cc
+++ b/deps/v8/src/arm/codegen-arm.cc
@@ -166,9 +166,9 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
CodeDesc desc;
masm.GetCode(isolate, &desc);
- DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
+ DCHECK(!RelocInfo::RequiresRelocation(desc));
- Assembler::FlushICache(isolate, buffer, allocated);
+ Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif
@@ -257,7 +257,7 @@ MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
CodeDesc desc;
masm.GetCode(isolate, &desc);
- Assembler::FlushICache(isolate, buffer, allocated);
+ Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer);
#endif
@@ -282,9 +282,9 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
CodeDesc desc;
masm.GetCode(isolate, &desc);
- DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
+ DCHECK(!RelocInfo::RequiresRelocation(desc));
- Assembler::FlushICache(isolate, buffer, allocated);
+ Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif
diff --git a/deps/v8/src/arm/constants-arm.h b/deps/v8/src/arm/constants-arm.h
index 1c865afb09..4e52a91738 100644
--- a/deps/v8/src/arm/constants-arm.h
+++ b/deps/v8/src/arm/constants-arm.h
@@ -641,8 +641,8 @@ class Instruction {
&& (Bit(20) == 0)
&& ((Bit(7) == 0)); }
- // Test for a nop instruction, which falls under type 1.
- inline bool IsNopType1() const { return Bits(24, 0) == 0x0120F000; }
+ // Test for nop-like instructions which fall under type 1.
+ inline bool IsNopLikeType1() const { return Bits(24, 8) == 0x120F0; }
// Test for a stop instruction.
inline bool IsStop() const {
diff --git a/deps/v8/src/arm/deoptimizer-arm.cc b/deps/v8/src/arm/deoptimizer-arm.cc
index 9a21ef862c..a4a540512d 100644
--- a/deps/v8/src/arm/deoptimizer-arm.cc
+++ b/deps/v8/src/arm/deoptimizer-arm.cc
@@ -30,9 +30,6 @@ void Deoptimizer::TableEntryGenerator::Generate() {
const int kFloatRegsSize = kFloatSize * SwVfpRegister::kNumRegisters;
// Save all allocatable VFP registers before messing with them.
- DCHECK_EQ(kDoubleRegZero.code(), 13);
- DCHECK_EQ(kScratchDoubleReg.code(), 14);
-
{
// We use a run-time check for VFP32DREGS.
CpuFeatureScope scope(masm(), VFP32DREGS,
diff --git a/deps/v8/src/arm/disasm-arm.cc b/deps/v8/src/arm/disasm-arm.cc
index 9951136561..9459a7e60d 100644
--- a/deps/v8/src/arm/disasm-arm.cc
+++ b/deps/v8/src/arm/disasm-arm.cc
@@ -937,8 +937,14 @@ void Decoder::DecodeType01(Instruction* instr) {
} else {
Unknown(instr); // not used by V8
}
- } else if ((type == 1) && instr->IsNopType1()) {
- Format(instr, "nop'cond");
+ } else if ((type == 1) && instr->IsNopLikeType1()) {
+ if (instr->BitField(7, 0) == 0) {
+ Format(instr, "nop'cond");
+ } else if (instr->BitField(7, 0) == 20) {
+ Format(instr, "csdb");
+ } else {
+ Unknown(instr); // Not used in V8.
+ }
} else {
switch (instr->OpcodeField()) {
case AND: {
diff --git a/deps/v8/src/arm/frame-constants-arm.h b/deps/v8/src/arm/frame-constants-arm.h
index 9307cc22de..1230a26956 100644
--- a/deps/v8/src/arm/frame-constants-arm.h
+++ b/deps/v8/src/arm/frame-constants-arm.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef V8_ARM_FRAMES_ARM_H_
-#define V8_ARM_FRAMES_ARM_H_
+#ifndef V8_ARM_FRAME_CONSTANTS_ARM_H_
+#define V8_ARM_FRAME_CONSTANTS_ARM_H_
namespace v8 {
namespace internal {
@@ -45,4 +45,4 @@ class JavaScriptFrameConstants : public AllStatic {
} // namespace internal
} // namespace v8
-#endif // V8_ARM_FRAMES_ARM_H_
+#endif // V8_ARM_FRAME_CONSTANTS_ARM_H_
diff --git a/deps/v8/src/arm/interface-descriptors-arm.cc b/deps/v8/src/arm/interface-descriptors-arm.cc
index 6b7498fde5..20ecef6c1c 100644
--- a/deps/v8/src/arm/interface-descriptors-arm.cc
+++ b/deps/v8/src/arm/interface-descriptors-arm.cc
@@ -70,12 +70,6 @@ const Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
const Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
-void FastNewClosureDescriptor::InitializePlatformSpecific(
- CallInterfaceDescriptorData* data) {
- Register registers[] = {r1, r2, r3};
- data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
// static
const Register TypeConversionDescriptor::ArgumentRegister() { return r0; }
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index 30190d3f34..3a96b640a2 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -18,6 +18,7 @@
#include "src/double.h"
#include "src/external-reference-table.h"
#include "src/frames-inl.h"
+#include "src/instruction-stream.h"
#include "src/objects-inl.h"
#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
@@ -241,22 +242,6 @@ void TurboAssembler::Ret(int drop, Condition cond) {
Ret(cond);
}
-
-void MacroAssembler::Swap(Register reg1,
- Register reg2,
- Register scratch,
- Condition cond) {
- if (scratch == no_reg) {
- eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
- eor(reg2, reg2, Operand(reg1), LeaveCC, cond);
- eor(reg1, reg1, Operand(reg2), LeaveCC, cond);
- } else {
- mov(scratch, reg1, LeaveCC, cond);
- mov(reg1, reg2, LeaveCC, cond);
- mov(reg2, scratch, LeaveCC, cond);
- }
-}
-
void TurboAssembler::Call(Label* target) { bl(target); }
void TurboAssembler::Push(Handle<HeapObject> handle) {
@@ -305,27 +290,34 @@ void TurboAssembler::Move(QwNeonRegister dst, QwNeonRegister src) {
}
}
-void TurboAssembler::Swap(DwVfpRegister srcdst0, DwVfpRegister srcdst1) {
- if (srcdst0 == srcdst1) return; // Swapping aliased registers emits nothing.
+void TurboAssembler::Swap(Register srcdst0, Register srcdst1) {
+ DCHECK(srcdst0 != srcdst1);
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
+ mov(scratch, srcdst0);
+ mov(srcdst0, srcdst1);
+ mov(srcdst1, scratch);
+}
+void TurboAssembler::Swap(DwVfpRegister srcdst0, DwVfpRegister srcdst1) {
+ DCHECK(srcdst0 != srcdst1);
DCHECK(VfpRegisterIsAvailable(srcdst0));
DCHECK(VfpRegisterIsAvailable(srcdst1));
if (CpuFeatures::IsSupported(NEON)) {
vswp(srcdst0, srcdst1);
} else {
- DCHECK_NE(srcdst0, kScratchDoubleReg);
- DCHECK_NE(srcdst1, kScratchDoubleReg);
- vmov(kScratchDoubleReg, srcdst0);
+ UseScratchRegisterScope temps(this);
+ DwVfpRegister scratch = temps.AcquireD();
+ vmov(scratch, srcdst0);
vmov(srcdst0, srcdst1);
- vmov(srcdst1, kScratchDoubleReg);
+ vmov(srcdst1, scratch);
}
}
void TurboAssembler::Swap(QwNeonRegister srcdst0, QwNeonRegister srcdst1) {
- if (srcdst0 != srcdst1) {
- vswp(srcdst0, srcdst1);
- }
+ DCHECK(srcdst0 != srcdst1);
+ vswp(srcdst0, srcdst1);
}
void MacroAssembler::Mls(Register dst, Register src1, Register src2,
@@ -817,11 +809,14 @@ void TurboAssembler::VmovExtended(int dst_code, int src_code) {
int dst_offset = dst_code & 1;
int src_offset = src_code & 1;
if (CpuFeatures::IsSupported(NEON)) {
+ UseScratchRegisterScope temps(this);
+ DwVfpRegister scratch = temps.AcquireD();
// 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;
+ vdup(Neon32, scratch, src_d_reg, src_offset);
+ // Here we are extending the lifetime of scratch.
+ src_d_reg = scratch;
src_offset = dst_offset ^ 1;
}
if (dst_offset) {
@@ -842,27 +837,30 @@ void TurboAssembler::VmovExtended(int dst_code, int src_code) {
// 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();
+ UseScratchRegisterScope temps(this);
+ LowDwVfpRegister d_scratch = temps.AcquireLowD();
+ LowDwVfpRegister d_scratch2 = temps.AcquireLowD();
+ int s_scratch_code = d_scratch.low().code();
+ int s_scratch_code2 = d_scratch2.low().code();
if (src_code < SwVfpRegister::kNumRegisters) {
// src is an s-register, dst is not.
- vmov(kScratchDoubleReg, dst_d_reg);
- vmov(SwVfpRegister::from_code(scratchSCode + dst_offset),
+ vmov(d_scratch, dst_d_reg);
+ vmov(SwVfpRegister::from_code(s_scratch_code + dst_offset),
SwVfpRegister::from_code(src_code));
- vmov(dst_d_reg, kScratchDoubleReg);
+ vmov(dst_d_reg, d_scratch);
} else if (dst_code < SwVfpRegister::kNumRegisters) {
// dst is an s-register, src is not.
- vmov(kScratchDoubleReg, src_d_reg);
+ vmov(d_scratch, src_d_reg);
vmov(SwVfpRegister::from_code(dst_code),
- SwVfpRegister::from_code(scratchSCode + src_offset));
+ SwVfpRegister::from_code(s_scratch_code + src_offset));
} else {
// 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());
+ vmov(d_scratch, src_d_reg);
+ vmov(d_scratch2, dst_d_reg);
+ vmov(SwVfpRegister::from_code(s_scratch_code + dst_offset),
+ SwVfpRegister::from_code(s_scratch_code2 + src_offset));
+ vmov(dst_d_reg, d_scratch2);
}
}
@@ -870,11 +868,13 @@ void TurboAssembler::VmovExtended(int dst_code, const MemOperand& src) {
if (dst_code < SwVfpRegister::kNumRegisters) {
vldr(SwVfpRegister::from_code(dst_code), src);
} else {
+ UseScratchRegisterScope temps(this);
+ LowDwVfpRegister scratch = temps.AcquireLowD();
// 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));
+ int dst_s_code = scratch.low().code() + (dst_code & 1);
+ vmov(scratch, DwVfpRegister::from_code(dst_code / 2));
vldr(SwVfpRegister::from_code(dst_s_code), src);
- vmov(DwVfpRegister::from_code(dst_code / 2), kScratchDoubleReg);
+ vmov(DwVfpRegister::from_code(dst_code / 2), scratch);
}
}
@@ -883,8 +883,10 @@ void TurboAssembler::VmovExtended(const MemOperand& dst, int src_code) {
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));
+ UseScratchRegisterScope temps(this);
+ LowDwVfpRegister scratch = temps.AcquireLowD();
+ int src_s_code = scratch.low().code() + (src_code & 1);
+ vmov(scratch, DwVfpRegister::from_code(src_code / 2));
vstr(SwVfpRegister::from_code(src_s_code), dst);
}
}
@@ -938,9 +940,11 @@ void TurboAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src,
void TurboAssembler::LslPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
- Register scratch, Register shift) {
+ Register shift) {
DCHECK(!AreAliased(dst_high, src_low));
DCHECK(!AreAliased(dst_high, shift));
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
Label less_than_32;
Label done;
@@ -984,9 +988,11 @@ void TurboAssembler::LslPair(Register dst_low, Register dst_high,
void TurboAssembler::LsrPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
- Register scratch, Register shift) {
+ Register shift) {
DCHECK(!AreAliased(dst_low, src_high));
DCHECK(!AreAliased(dst_low, shift));
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
Label less_than_32;
Label done;
@@ -1031,9 +1037,11 @@ void TurboAssembler::LsrPair(Register dst_low, Register dst_high,
void TurboAssembler::AsrPair(Register dst_low, Register dst_high,
Register src_low, Register src_high,
- Register scratch, Register shift) {
+ Register shift) {
DCHECK(!AreAliased(dst_low, src_high));
DCHECK(!AreAliased(dst_low, shift));
+ UseScratchRegisterScope temps(this);
+ Register scratch = temps.Acquire();
Label less_than_32;
Label done;
@@ -1362,13 +1370,30 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
const ParameterCount& expected,
const ParameterCount& actual) {
- Label skip_hook;
+ Label skip_hook, call_hook;
+
+ ExternalReference debug_is_active =
+ ExternalReference::debug_is_active_address(isolate());
+ mov(r4, Operand(debug_is_active));
+ ldrsb(r4, MemOperand(r4));
+ cmp(r4, Operand(0));
+ b(eq, &skip_hook);
+
ExternalReference debug_hook_avtive =
ExternalReference::debug_hook_on_function_call_address(isolate());
mov(r4, Operand(debug_hook_avtive));
ldrsb(r4, MemOperand(r4));
cmp(r4, Operand(0));
+ b(ne, &call_hook);
+
+ ldr(r4, FieldMemOperand(fun, JSFunction::kSharedFunctionInfoOffset));
+ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kDebugInfoOffset));
+ JumpIfSmi(r4, &skip_hook);
+ ldr(r4, FieldMemOperand(r4, DebugInfo::kFlagsOffset));
+ tst(r4, Operand(Smi::FromInt(DebugInfo::kBreakAtEntry)));
b(eq, &skip_hook);
+
+ bind(&call_hook);
{
FrameScope frame(this,
has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
@@ -1426,7 +1451,7 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.
- Register code = r4;
+ Register code = kJavaScriptCallCodeStartRegister;
ldr(code, FieldMemOperand(function, JSFunction::kCodeOffset));
add(code, code, Operand(Code::kHeaderSize - kHeapObjectTag));
if (flag == CALL_FUNCTION) {
@@ -1480,14 +1505,6 @@ void MacroAssembler::InvokeFunction(Register function,
InvokeFunctionCode(r1, no_reg, expected, actual, flag);
}
-void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
- const ParameterCount& expected,
- const ParameterCount& actual,
- InvokeFlag flag) {
- Move(r1, function);
- InvokeFunction(r1, expected, actual, flag);
-}
-
void MacroAssembler::MaybeDropFrames() {
// Check whether we need to drop frames to restart a function on the stack.
ExternalReference restart_fp =
@@ -1615,13 +1632,22 @@ void MacroAssembler::TryDoubleToInt32Exact(Register result,
void TurboAssembler::TryInlineTruncateDoubleToI(Register result,
DwVfpRegister double_input,
Label* done) {
- LowDwVfpRegister double_scratch = kScratchDoubleReg;
- vcvt_s32_f64(double_scratch.low(), double_input);
- vmov(result, double_scratch.low());
-
UseScratchRegisterScope temps(this);
- Register scratch = temps.Acquire();
+ SwVfpRegister single_scratch = SwVfpRegister::no_reg();
+ if (temps.CanAcquireVfp<SwVfpRegister>()) {
+ single_scratch = temps.AcquireS();
+ } else {
+ // Re-use the input as a scratch register. However, we can only do this if
+ // the input register is d0-d15 as there are no s32+ registers.
+ DCHECK_LT(double_input.code(), LowDwVfpRegister::kNumRegisters);
+ LowDwVfpRegister double_scratch =
+ LowDwVfpRegister::from_code(double_input.code());
+ single_scratch = double_scratch.low();
+ }
+ vcvt_s32_f64(single_scratch, double_input);
+ vmov(result, single_scratch);
+ Register scratch = temps.Acquire();
// If result is not saturated (0x7FFFFFFF or 0x80000000), we are done.
sub(scratch, result, Operand(1));
cmp(scratch, Operand(0x7FFFFFFE));
@@ -1704,6 +1730,12 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin,
Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
}
+void MacroAssembler::JumpToInstructionStream(const InstructionStream* stream) {
+ int32_t bytes_address = reinterpret_cast<int32_t>(stream->bytes());
+ mov(kOffHeapTrampolineRegister, Operand(bytes_address, RelocInfo::NONE));
+ Jump(kOffHeapTrampolineRegister);
+}
+
void MacroAssembler::IncrementCounter(StatsCounter* counter, int value,
Register scratch1, Register scratch2) {
DCHECK_GT(value, 0);
@@ -2275,6 +2307,15 @@ bool AreAliased(Register reg1,
}
#endif
+void TurboAssembler::ComputeCodeStartAddress(Register dst) {
+ // We can use the register pc - 8 for the address of the current instruction.
+ sub(dst, pc, Operand(pc_offset() + TurboAssembler::kPcLoadDelta));
+}
+
+void TurboAssembler::ResetSpeculationPoisonRegister() {
+ mov(kSpeculationPoisonRegister, Operand(-1));
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index cf731cbedb..50ce6dc005 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -20,12 +20,15 @@ constexpr Register kReturnRegister2 = r2;
constexpr Register kJSFunctionRegister = r1;
constexpr Register kContextRegister = r7;
constexpr Register kAllocateSizeRegister = r1;
+constexpr Register kSpeculationPoisonRegister = r9;
constexpr Register kInterpreterAccumulatorRegister = r0;
constexpr Register kInterpreterBytecodeOffsetRegister = r5;
constexpr Register kInterpreterBytecodeArrayRegister = r6;
constexpr Register kInterpreterDispatchTableRegister = r8;
constexpr Register kJavaScriptCallArgCountRegister = r0;
+constexpr Register kJavaScriptCallCodeStartRegister = r2;
constexpr Register kJavaScriptCallNewTargetRegister = r3;
+constexpr Register kOffHeapTrampolineRegister = r4;
constexpr Register kRuntimeCallFunctionRegister = r1;
constexpr Register kRuntimeCallArgCountRegister = r0;
@@ -305,15 +308,15 @@ class TurboAssembler : public Assembler {
inline bool AllowThisStubCall(CodeStub* stub);
void LslPair(Register dst_low, Register dst_high, Register src_low,
- Register src_high, Register scratch, Register shift);
+ Register src_high, Register shift);
void LslPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, uint32_t shift);
void LsrPair(Register dst_low, Register dst_high, Register src_low,
- Register src_high, Register scratch, Register shift);
+ Register src_high, Register shift);
void LsrPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, uint32_t shift);
void AsrPair(Register dst_low, Register dst_high, Register src_low,
- Register src_high, Register scratch, Register shift);
+ Register src_high, Register shift);
void AsrPair(Register dst_low, Register dst_high, Register src_low,
Register src_high, uint32_t shift);
@@ -481,7 +484,8 @@ class TurboAssembler : public Assembler {
void VmovExtended(int dst_code, const MemOperand& src);
void VmovExtended(const MemOperand& dst, int src_code);
- // Register swap.
+ // Register swap. Note that the register operands should be distinct.
+ void Swap(Register srcdst0, Register srcdst1);
void Swap(DwVfpRegister srcdst0, DwVfpRegister srcdst1);
void Swap(QwNeonRegister srcdst0, QwNeonRegister srcdst1);
@@ -530,6 +534,12 @@ class TurboAssembler : public Assembler {
#endif
}
+ // Compute the start of the generated instruction stream from the current PC.
+ // This is an alternative to embedding the {CodeObject} handle as a reference.
+ void ComputeCodeStartAddress(Register dst);
+
+ void ResetSpeculationPoisonRegister();
+
private:
bool has_frame_ = false;
Isolate* const isolate_;
@@ -579,11 +589,6 @@ class MacroAssembler : public TurboAssembler {
MacroAssembler(Isolate* isolate, void* buffer, int size,
CodeObjectRequired create_code_object);
- // Swap two registers. If the scratch register is omitted then a slightly
- // less efficient form using xor instead of mov is emitted.
- void Swap(Register reg1, Register reg2, Register scratch = no_reg,
- Condition cond = al);
-
void Mls(Register dst, Register src1, Register src2, Register srcA,
Condition cond = al);
void And(Register dst, Register src1, const Operand& src2,
@@ -694,10 +699,6 @@ class MacroAssembler : public TurboAssembler {
void InvokeFunction(Register function, const ParameterCount& expected,
const ParameterCount& actual, InvokeFlag flag);
- void InvokeFunction(Handle<JSFunction> function,
- const ParameterCount& expected,
- const ParameterCount& actual, InvokeFlag flag);
-
// Frame restart support
void MaybeDropFrames();
@@ -797,6 +798,9 @@ class MacroAssembler : public TurboAssembler {
void JumpToExternalReference(const ExternalReference& builtin,
bool builtin_exit_frame = false);
+ // Generates a trampoline to jump to the off-heap instruction stream.
+ void JumpToInstructionStream(const InstructionStream* stream);
+
// ---------------------------------------------------------------------------
// StatsCounter support
diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc
index 52fe902237..6a735fcef6 100644
--- a/deps/v8/src/arm/simulator-arm.cc
+++ b/deps/v8/src/arm/simulator-arm.cc
@@ -547,8 +547,7 @@ void ArmDebugger::Debug() {
#undef XSTR
}
-
-static bool ICacheMatch(void* one, void* two) {
+bool Simulator::ICacheMatch(void* one, void* two) {
DCHECK_EQ(reinterpret_cast<intptr_t>(one) & CachePage::kPageMask, 0);
DCHECK_EQ(reinterpret_cast<intptr_t>(two) & CachePage::kPageMask, 0);
return one == two;
@@ -645,11 +644,6 @@ void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
- i_cache_ = isolate_->simulator_i_cache();
- if (i_cache_ == nullptr) {
- i_cache_ = new base::CustomMatcherHashMap(&ICacheMatch);
- isolate_->set_simulator_i_cache(i_cache_);
- }
// Set up simulator support first. Some of this information is needed to
// setup the architecture state.
size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
@@ -2314,8 +2308,15 @@ void Simulator::DecodeType01(Instruction* instr) {
PrintF("%08x\n", instr->InstructionBits());
UNIMPLEMENTED();
}
- } else if ((type == 1) && instr->IsNopType1()) {
- // NOP.
+ } else if ((type == 1) && instr->IsNopLikeType1()) {
+ if (instr->BitField(7, 0) == 0) {
+ // NOP.
+ } else if (instr->BitField(7, 0) == 20) {
+ // CSDB.
+ } else {
+ PrintF("%08x\n", instr->InstructionBits());
+ UNIMPLEMENTED();
+ }
} else {
int rd = instr->RdValue();
int rn = instr->RnValue();
@@ -5640,7 +5641,7 @@ void Simulator::DecodeSpecialCondition(Instruction* instr) {
// Executes the current instruction.
void Simulator::InstructionDecode(Instruction* instr) {
if (v8::internal::FLAG_check_icache) {
- CheckICache(isolate_->simulator_i_cache(), instr);
+ CheckICache(i_cache(), instr);
}
pc_modified_ = false;
if (::v8::internal::FLAG_trace_sim) {
@@ -5822,7 +5823,7 @@ intptr_t Simulator::CallImpl(byte* entry, int argument_count,
return get_register(r0);
}
-int32_t Simulator::CallFPImpl(byte* entry, double d0, double d1) {
+intptr_t Simulator::CallFPImpl(byte* entry, double d0, double d1) {
if (use_eabi_hardfloat()) {
set_d_register_from_double(0, d0);
set_d_register_from_double(1, d1);
diff --git a/deps/v8/src/arm/simulator-arm.h b/deps/v8/src/arm/simulator-arm.h
index 1cb11ffd96..46a84ff4b4 100644
--- a/deps/v8/src/arm/simulator-arm.h
+++ b/deps/v8/src/arm/simulator-arm.h
@@ -183,6 +183,7 @@ class Simulator : public SimulatorBase {
static void SetRedirectInstruction(Instruction* instruction);
// ICache checking.
+ static bool ICacheMatch(void* one, void* two);
static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start,
size_t size);
@@ -381,9 +382,6 @@ class Simulator : public SimulatorBase {
// Debugger input.
char* last_debugger_input_;
- // Icache simulation
- base::CustomMatcherHashMap* i_cache_;
-
// Registered breakpoints.
Instruction* break_pc_;
Instr break_instr_;