diff options
Diffstat (limited to 'src/qml/jit')
-rw-r--r-- | src/qml/jit/qv4assembler.cpp | 56 | ||||
-rw-r--r-- | src/qml/jit/qv4assembler_p.h | 346 | ||||
-rw-r--r-- | src/qml/jit/qv4binop.cpp | 2 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 94 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 18 |
5 files changed, 340 insertions, 176 deletions
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index 71dabcd590..d062f3bbb2 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -249,13 +249,16 @@ void Assembler<TargetConfiguration>::generateCJumpOnCompare(RelationalCondition } template <typename TargetConfiguration> -typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>::loadAddress(RegisterID tmp, IR::Expr *e) +typename Assembler<TargetConfiguration>::Pointer +Assembler<TargetConfiguration>::loadAddressForWriting(RegisterID tmp, IR::Expr *e, WriteBarrier::Type *barrier) { + if (barrier) + *barrier = WriteBarrier::NoBarrier; IR::Temp *t = e->asTemp(); if (t) return loadTempAddress(t); else - return loadArgLocalAddress(tmp, e->asArgLocal()); + return loadArgLocalAddressForWriting(tmp, e->asArgLocal(), barrier); } template <typename TargetConfiguration> @@ -268,34 +271,42 @@ typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>: } template <typename TargetConfiguration> -typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>::loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al) +typename Assembler<TargetConfiguration>::Pointer +Assembler<TargetConfiguration>::loadArgLocalAddressForWriting(RegisterID baseReg, IR::ArgLocal *al, WriteBarrier::Type *barrier) { + if (barrier) + *barrier = _function->argLocalRequiresWriteBarrier(al) ? WriteBarrier::Barrier : WriteBarrier::NoBarrier; + int32_t offset = 0; int scope = al->scope; loadPtr(Address(EngineRegister, targetStructureOffset(offsetof(EngineBase, current))), baseReg); - const qint32 outerOffset = targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, outer)); + const qint32 outerOffset = targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, outer)); + const qint32 localsOffset = targetStructureOffset(Heap::CallContextData::baseOffset + offsetof(Heap::CallContextData, function)) + + 8 // locals is always 8 bytes away from function, regardless of pointer size. + + offsetof(ValueArray<0>, values); - if (scope) { + while (scope) { loadPtr(Address(baseReg, outerOffset), baseReg); --scope; - while (scope) { - loadPtr(Address(baseReg, outerOffset), baseReg); - --scope; - } } switch (al->kind) { case IR::ArgLocal::Formal: case IR::ArgLocal::ScopedFormal: { - const qint32 callDataOffset = targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, callData)); - loadPtr(Address(baseReg, callDataOffset), baseReg); - offset = sizeof(CallData) + (al->index - 1) * sizeof(Value); + if (barrier && *barrier == WriteBarrier::Barrier) { + // if we need a barrier, the baseReg has to point to the ExecutionContext + // callData comes directly after locals, calculate the offset using that + offset = localsOffset + _function->localsCountForScope(al) * sizeof(Value); + offset += sizeof(CallData) + (al->index - 1) * sizeof(Value); + } else { + const qint32 callDataOffset = targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, callData)); + loadPtr(Address(baseReg, callDataOffset), baseReg); + offset = sizeof(CallData) + (al->index - 1) * sizeof(Value); + } } break; case IR::ArgLocal::Local: case IR::ArgLocal::ScopedLocal: { - const qint32 localsOffset = targetStructureOffset(Heap::CallContext::baseOffset + offsetof(Heap::CallContextData, locals)); - loadPtr(Address(baseReg, localsOffset), baseReg); - offset = al->index * sizeof(Value); + offset = localsOffset + al->index * sizeof(Value); } break; default: Q_UNREACHABLE(); @@ -307,7 +318,7 @@ template <typename TargetConfiguration> typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>::loadStringAddress(RegisterID reg, const QString &string) { loadPtr(Address(Assembler::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), Assembler::ScratchRegister); - loadPtr(Address(Assembler::ScratchRegister, targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, compilationUnit))), Assembler::ScratchRegister); + loadPtr(Address(Assembler::ScratchRegister, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, compilationUnit))), Assembler::ScratchRegister); loadPtr(Address(Assembler::ScratchRegister, offsetof(CompiledData::CompilationUnitBase, runtimeStrings)), reg); const int id = _jsGenerator->registerString(string); return Pointer(reg, id * RegisterSize); @@ -323,7 +334,7 @@ template <typename TargetConfiguration> typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(const TargetPrimitive &v, RegisterID baseReg) { loadPtr(Address(Assembler::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), baseReg); - loadPtr(Address(baseReg, targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, constantTable))), baseReg); + loadPtr(Address(baseReg, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, constantTable))), baseReg); const int index = _jsGenerator->registerConstant(v.rawValue()); return Address(baseReg, index * sizeof(QV4::Value)); } @@ -338,8 +349,9 @@ void Assembler<TargetConfiguration>::loadStringRef(RegisterID reg, const QString template <typename TargetConfiguration> void Assembler<TargetConfiguration>::storeValue(TargetPrimitive value, IR::Expr *destination) { - Address addr = loadAddress(ScratchRegister, destination); - storeValue(value, addr); + WriteBarrier::Type barrier; + Address addr = loadAddressForWriting(ScratchRegister, destination, &barrier); + storeValue(value, addr, barrier); } template <typename TargetConfiguration> @@ -428,7 +440,7 @@ typename Assembler<TargetConfiguration>::Jump Assembler<TargetConfiguration>::ge // It's not a number type, so it cannot be in a register. Q_ASSERT(src->asArgLocal() || src->asTemp()->kind != IR::Temp::PhysicalRegister || src->type == IR::BoolType); - Assembler::Pointer tagAddr = loadAddress(Assembler::ScratchRegister, src); + Assembler::Pointer tagAddr = loadAddressForReading(Assembler::ScratchRegister, src); tagAddr.offset += 4; load32(tagAddr, Assembler::ScratchRegister); @@ -548,7 +560,7 @@ public: ~QIODevicePrintStream() {} - void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0) + void vprintf(const char* format, va_list argList) override WTF_ATTRIBUTE_PRINTF(2, 0) { const int written = qvsnprintf(buf.data(), buf.size(), format, argList); if (written > 0) @@ -556,7 +568,7 @@ public: memset(buf.data(), 0, qMin(written, buf.size())); } - void flush() + void flush() override {} private: diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 8b5b307e84..9e38696d7a 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -57,6 +57,7 @@ #include "private/qv4value_p.h" #include "private/qv4context_p.h" #include "private/qv4engine_p.h" +#include "private/qv4writebarrier_p.h" #include "qv4targetplatform_p.h" #include <config.h> @@ -152,38 +153,86 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo using TrustedImm64 = typename JITAssembler::TrustedImm64; using Jump = typename JITAssembler::Jump; using Label = typename JITAssembler::Label; - using ValueTypeInternal = Value::ValueTypeInternal_32; using TargetPrimitive = TargetPrimitive32; + static void emitSetGrayBit(JITAssembler *as, RegisterID base) + { + bool returnValueUsed = (base == TargetPlatform::ReturnValueRegister); + + as->push(TargetPlatform::EngineRegister); // free up one register for work + + RegisterID grayBitmap = returnValueUsed ? TargetPlatform::ScratchRegister : TargetPlatform::ReturnValueRegister; + as->move(base, grayBitmap); + Q_ASSERT(base != grayBitmap); + as->urshift32(TrustedImm32(Chunk::ChunkShift), grayBitmap); + as->lshift32(TrustedImm32(Chunk::ChunkShift), grayBitmap); + Q_STATIC_ASSERT(offsetof(Chunk, grayBitmap) == 0); + + RegisterID index = base; + as->move(base, index); + as->sub32(grayBitmap, index); + as->urshift32(TrustedImm32(Chunk::SlotSizeShift), index); + RegisterID grayIndex = TargetPlatform::EngineRegister; + as->move(index, grayIndex); + as->urshift32(TrustedImm32(Chunk::BitShift), grayIndex); + as->lshift32(TrustedImm32(2), grayIndex); // 4 bytes per quintptr + as->add32(grayIndex, grayBitmap); + as->and32(TrustedImm32(Chunk::Bits - 1), index); + + RegisterID bit = TargetPlatform::EngineRegister; + as->move(TrustedImm32(1), bit); + as->lshift32(index, bit); + + as->load32(Pointer(grayBitmap, 0), index); + as->or32(bit, index); + as->store32(index, Pointer(grayBitmap, 0)); + + as->pop(TargetPlatform::EngineRegister); + } + +#if WRITEBARRIER(none) + static Q_ALWAYS_INLINE void emitWriteBarrier(JITAssembler *, Address) {} +#endif + static void loadDouble(JITAssembler *as, Address addr, FPRegisterID dest) { as->MacroAssembler::loadDouble(addr, dest); } - static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr) + static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr, WriteBarrier::Type barrier) { as->MacroAssembler::storeDouble(source, addr); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, addr); } static void storeDouble(JITAssembler *as, FPRegisterID source, IR::Expr* target) { - Pointer ptr = as->loadAddress(TargetPlatform::ScratchRegister, target); - as->storeDouble(source, ptr); + WriteBarrier::Type barrier; + Pointer ptr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier); + as->storeDouble(source, ptr, barrier); } - static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination) + static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination, WriteBarrier::Type barrier) { as->store32(TrustedImm32(value.value()), destination); destination.offset += 4; as->store32(TrustedImm32(value.tag()), destination); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, destination); } template <typename Source, typename Destination> - static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination) + static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination, WriteBarrier::Type barrier) { as->loadDouble(source, TargetPlatform::FPGpr0); - as->storeDouble(TargetPlatform::FPGpr0, destination); + // We need to pass NoBarrier to storeDouble and call emitWriteBarrier ourselves, as the + // code in storeDouble assumes the type we're storing is actually a double, something + // that isn't always the case here. + as->storeDouble(TargetPlatform::FPGpr0, destination, WriteBarrier::NoBarrier); + if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, destination); } static void loadDoubleConstant(JITAssembler *as, IR::Const *c, FPRegisterID target) @@ -196,12 +245,14 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo as->moveIntsToDouble(TargetPlatform::LowReturnValueRegister, TargetPlatform::HighReturnValueRegister, dest, TargetPlatform::FPGpr0); } - static void storeReturnValue(JITAssembler *as, const Pointer &dest) + static void storeReturnValue(JITAssembler *as, const Pointer &dest, WriteBarrier::Type barrier) { Address destination = dest; as->store32(TargetPlatform::LowReturnValueRegister, destination); destination.offset += 4; as->store32(TargetPlatform::HighReturnValueRegister, destination); + if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, dest); } static void setFunctionReturnValueFromTemp(JITAssembler *as, IR::Temp *t) @@ -237,7 +288,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Q_UNREACHABLE(); } } else { - Pointer addr = as->loadAddress(TargetPlatform::ScratchRegister, t); + Pointer addr = as->loadAddressForReading(TargetPlatform::ScratchRegister, t); as->load32(addr, lowReg); addr.offset += 4; as->load32(addr, highReg); @@ -298,7 +349,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo IR::BasicBlock *nextBlock, IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock) { - Pointer tagAddr = as->loadAddress(scratchRegister, right); + Pointer tagAddr = as->loadAddressForReading(scratchRegister, right); as->load32(tagAddr, tagRegister); Jump j = as->branch32(JITAssembler::invert(cond), tagRegister, TrustedImm32(0)); as->addPatch(falseBlock, j); @@ -315,7 +366,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo { Q_ASSERT(source->type == IR::VarType); // load the tag: - Pointer addr = as->loadAddress(TargetPlatform::ScratchRegister, source); + Pointer addr = as->loadAddressForReading(TargetPlatform::ScratchRegister, source); Pointer tagAddr = addr; tagAddr.offset += 4; as->load32(tagAddr, TargetPlatform::ReturnValueRegister); @@ -326,10 +377,13 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo IR::Temp *targetTemp = target->asTemp(); if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) { as->load32(addr, TargetPlatform::ReturnValueRegister); - Pointer targetAddr = as->loadAddress(TargetPlatform::ScratchRegister, target); + WriteBarrier::Type barrier; + Pointer targetAddr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier); as->store32(TargetPlatform::ReturnValueRegister, targetAddr); targetAddr.offset += 4; as->store32(TrustedImm32(quint32(Value::ValueTypeInternal_32::Integer)), targetAddr); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, targetAddr); } else { as->load32(addr, (RegisterID) targetTemp->index); } @@ -338,17 +392,19 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo // not an int: fallback.link(as); generateRuntimeCall(as, TargetPlatform::ReturnValueRegister, toInt, - as->loadAddress(TargetPlatform::ScratchRegister, source)); + as->loadAddressForReading(TargetPlatform::ScratchRegister, source)); as->storeInt32(TargetPlatform::ReturnValueRegister, target); intDone.link(as); } - static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr) + static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr, WriteBarrier::Type barrier) { as->store32(registerWithPtr, destAddr); destAddr.offset += 4; as->store32(TrustedImm32(QV4::Value::Managed_Type_Internal_32), destAddr); + if (WriteBarrier::isRequired<WriteBarrier::Object>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, destAddr); } static Jump generateIsDoubleCheck(JITAssembler *as, RegisterID tagOrValueRegister) @@ -393,10 +449,48 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo using BranchTruncateType = typename JITAssembler::BranchTruncateType; using Jump = typename JITAssembler::Jump; using Label = typename JITAssembler::Label; - using ValueTypeInternal = Value::ValueTypeInternal_64; using TargetPrimitive = TargetPrimitive64; + static void emitSetGrayBit(JITAssembler *as, RegisterID base) + { + bool returnValueUsed = (base == TargetPlatform::ReturnValueRegister); + + as->push(TargetPlatform::EngineRegister); // free up one register for work + + RegisterID grayBitmap = returnValueUsed ? TargetPlatform::ScratchRegister : TargetPlatform::ReturnValueRegister; + as->move(base, grayBitmap); + Q_ASSERT(base != grayBitmap); + as->urshift64(TrustedImm32(Chunk::ChunkShift), grayBitmap); + as->lshift64(TrustedImm32(Chunk::ChunkShift), grayBitmap); + Q_STATIC_ASSERT(offsetof(Chunk, grayBitmap) == 0); + + RegisterID index = base; + as->move(base, index); + as->sub64(grayBitmap, index); + as->urshift64(TrustedImm32(Chunk::SlotSizeShift), index); + RegisterID grayIndex = TargetPlatform::EngineRegister; + as->move(index, grayIndex); + as->urshift64(TrustedImm32(Chunk::BitShift), grayIndex); + as->lshift64(TrustedImm32(3), grayIndex); // 8 bytes per quintptr + as->add64(grayIndex, grayBitmap); + as->and64(TrustedImm32(Chunk::Bits - 1), index); + + RegisterID bit = TargetPlatform::EngineRegister; + as->move(TrustedImm32(1), bit); + as->lshift64(index, bit); + + as->load64(Pointer(grayBitmap, 0), index); + as->or64(bit, index); + as->store64(index, Pointer(grayBitmap, 0)); + + as->pop(TargetPlatform::EngineRegister); + } + +#if WRITEBARRIER(none) + static Q_ALWAYS_INLINE void emitWriteBarrier(JITAssembler *, Address) {} +#endif + static void loadDouble(JITAssembler *as, Address addr, FPRegisterID dest) { as->load64(addr, TargetPlatform::ReturnValueRegister); @@ -404,19 +498,24 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo as->move64ToDouble(TargetPlatform::ReturnValueRegister, dest); } - static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr) + static void storeDouble(JITAssembler *as, FPRegisterID source, Address addr, WriteBarrier::Type barrier) { as->moveDoubleTo64(source, TargetPlatform::ReturnValueRegister); as->xor64(TargetPlatform::DoubleMaskRegister, TargetPlatform::ReturnValueRegister); as->store64(TargetPlatform::ReturnValueRegister, addr); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, addr); } static void storeDouble(JITAssembler *as, FPRegisterID source, IR::Expr* target) { as->moveDoubleTo64(source, TargetPlatform::ReturnValueRegister); as->xor64(TargetPlatform::DoubleMaskRegister, TargetPlatform::ReturnValueRegister); - Pointer ptr = as->loadAddress(TargetPlatform::ScratchRegister, target); + WriteBarrier::Type barrier; + Pointer ptr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier); as->store64(TargetPlatform::ReturnValueRegister, ptr); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, ptr); } static void storeReturnValue(JITAssembler *as, FPRegisterID dest) @@ -425,9 +524,11 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo as->move64ToDouble(TargetPlatform::ReturnValueRegister, dest); } - static void storeReturnValue(JITAssembler *as, const Pointer &dest) + static void storeReturnValue(JITAssembler *as, const Pointer &dest, WriteBarrier::Type barrier) { as->store64(TargetPlatform::ReturnValueRegister, dest); + if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, dest); } static void setFunctionReturnValueFromTemp(JITAssembler *as, IR::Temp *t) @@ -468,7 +569,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo TargetPlatform::ReturnValueRegister); } } else { - as->copyValue(TargetPlatform::ReturnValueRegister, t); + as->copyValue(TargetPlatform::ReturnValueRegister, t, WriteBarrier::NoBarrier); } } @@ -477,18 +578,20 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo as->move(TrustedImm64(retVal.rawValue()), TargetPlatform::ReturnValueRegister); } - static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination) + static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination, WriteBarrier::Type barrier) { as->store64(TrustedImm64(value.rawValue()), destination); + if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, destination); } template <typename Source, typename Destination> - static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination) + static void copyValueViaRegisters(JITAssembler *as, Source source, Destination destination, WriteBarrier::Type barrier) { // Use ReturnValueRegister as "scratch" register because loadArgument // and storeArgument are functions that may need a scratch register themselves. loadArgumentInRegister(as, source, TargetPlatform::ReturnValueRegister, 0); - as->storeReturnValue(destination); + as->storeReturnValue(destination, barrier); } static void loadDoubleConstant(JITAssembler *as, IR::Const *c, FPRegisterID target) @@ -524,7 +627,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Q_UNUSED(argumentNumber); if (al) { - Pointer addr = as->loadArgLocalAddress(dest, al); + Pointer addr = as->loadArgLocalAddressForReading(dest, al); as->load64(addr, dest); } else { auto undefined = TargetPrimitive::undefinedValue(); @@ -593,7 +696,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo IR::BasicBlock *nextBlock, IR::BasicBlock *currentBlock, IR::BasicBlock *trueBlock, IR::BasicBlock *falseBlock) { - Pointer addr = as->loadAddress(scratchRegister, right); + Pointer addr = as->loadAddressForReading(scratchRegister, right); as->load64(addr, tagRegister); const TrustedImm64 tag(0); generateCJumpOnCompare(as, cond, tagRegister, tag, nextBlock, currentBlock, trueBlock, falseBlock); @@ -602,7 +705,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo static void convertVarToSInt32(JITAssembler *as, IR::Expr *source, IR::Expr *target) { Q_ASSERT(source->type == IR::VarType); - Pointer addr = as->loadAddress(TargetPlatform::ScratchRegister, source); + Pointer addr = as->loadAddressForReading(TargetPlatform::ScratchRegister, source); as->load64(addr, TargetPlatform::ScratchRegister); as->move(TargetPlatform::ScratchRegister, TargetPlatform::ReturnValueRegister); @@ -626,25 +729,30 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo // not an int: fallback.link(as); generateRuntimeCall(as, TargetPlatform::ReturnValueRegister, toInt, - as->loadAddress(TargetPlatform::ScratchRegister, source)); + as->loadAddressForReading(TargetPlatform::ScratchRegister, source)); isIntConvertible.link(as); success.link(as); IR::Temp *targetTemp = target->asTemp(); if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) { - Pointer targetAddr = as->loadAddress(TargetPlatform::ScratchRegister, target); + WriteBarrier::Type barrier; + Pointer targetAddr = as->loadAddressForWriting(TargetPlatform::ScratchRegister, target, &barrier); as->store32(TargetPlatform::ReturnValueRegister, targetAddr); targetAddr.offset += 4; as->store32(TrustedImm32(quint32(Value::ValueTypeInternal_64::Integer)), targetAddr); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, targetAddr); } else { as->storeInt32(TargetPlatform::ReturnValueRegister, target); } } - static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr) + static void loadManagedPointer(JITAssembler *as, RegisterID registerWithPtr, Pointer destAddr, WriteBarrier::Type barrier) { as->store64(registerWithPtr, destAddr); + if (WriteBarrier::isRequired<WriteBarrier::Object>() && barrier == WriteBarrier::Barrier) + emitWriteBarrier(as, destAddr); } static Jump generateIsDoubleCheck(JITAssembler *as, RegisterID tagOrValueRegister) @@ -990,9 +1098,16 @@ public: Jump branchDouble(bool invertCondition, IR::AluOp op, IR::Expr *left, IR::Expr *right); Jump branchInt32(bool invertCondition, IR::AluOp op, IR::Expr *left, IR::Expr *right); - Pointer loadAddress(RegisterID tmp, IR::Expr *t); + Pointer loadAddressForWriting(RegisterID tmp, IR::Expr *t, WriteBarrier::Type *barrier); + Pointer loadAddressForReading(RegisterID tmp, IR::Expr *t) { + return loadAddressForWriting(tmp, t, 0); + } + Pointer loadTempAddress(IR::Temp *t); - Pointer loadArgLocalAddress(RegisterID baseReg, IR::ArgLocal *al); + Pointer loadArgLocalAddressForWriting(RegisterID baseReg, IR::ArgLocal *al, WriteBarrier::Type *barrier); + Pointer loadArgLocalAddressForReading(RegisterID baseReg, IR::ArgLocal *al) { + return loadArgLocalAddressForWriting(baseReg, al, 0); + } Pointer loadStringAddress(RegisterID reg, const QString &string); Address loadConstant(IR::Const *c, RegisterID baseReg); Address loadConstant(const TargetPrimitive &v, RegisterID baseReg); @@ -1014,16 +1129,16 @@ public: Pointer addr(_stackLayout->savedRegPointer(argumentNumber)); switch (t->type) { case IR::BoolType: - storeBool((RegisterID) t->index, addr); + storeBool((RegisterID) t->index, addr, WriteBarrier::NoBarrier); break; case IR::SInt32Type: - storeInt32((RegisterID) t->index, addr); + storeInt32((RegisterID) t->index, addr, WriteBarrier::NoBarrier); break; case IR::UInt32Type: - storeUInt32((RegisterID) t->index, addr); + storeUInt32((RegisterID) t->index, addr, WriteBarrier::NoBarrier); break; case IR::DoubleType: - storeDouble((FPRegisterID) t->index, addr); + storeDouble((FPRegisterID) t->index, addr, WriteBarrier::NoBarrier); break; default: Q_UNIMPLEMENTED(); @@ -1054,7 +1169,7 @@ public: if (!temp.value) { RegisterSizeDependentOps::zeroRegister(this, dest); } else { - Pointer addr = toAddress(dest, temp.value, argumentNumber); + Pointer addr = toAddress(dest, temp.value, argumentNumber, 0); loadArgumentInRegister(addr, dest, argumentNumber); } } @@ -1067,7 +1182,7 @@ public: void loadArgumentInRegister(Reference temp, RegisterID dest, int argumentNumber) { Q_ASSERT(temp.value); - Pointer addr = loadAddress(dest, temp.value); + Pointer addr = loadAddressForReading(dest, temp.value); loadArgumentInRegister(addr, dest, argumentNumber); } @@ -1100,8 +1215,10 @@ public: move(imm32, dest); } - void storeReturnValue(RegisterID dest) + void storeReturnValue(RegisterID dest, WriteBarrier::Type barrier = WriteBarrier::NoBarrier) { + Q_UNUSED(barrier); + Q_ASSERT(barrier == WriteBarrier::NoBarrier); move(ReturnValueRegister, dest); } @@ -1109,7 +1226,7 @@ public: { subPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister); Pointer tmp(StackPointerRegister, 0); - storeReturnValue(tmp); + storeReturnValue(tmp, WriteBarrier::NoBarrier); toUInt32Register(tmp, dest); addPtr(TrustedImm32(sizeof(QV4::Value)), StackPointerRegister); } @@ -1119,9 +1236,9 @@ public: RegisterSizeDependentOps::storeReturnValue(this, dest); } - void storeReturnValue(const Pointer &dest) + void storeReturnValue(const Pointer &dest, WriteBarrier::Type barrier) { - RegisterSizeDependentOps::storeReturnValue(this, dest); + RegisterSizeDependentOps::storeReturnValue(this, dest, barrier); } void storeReturnValue(IR::Expr *target) @@ -1129,22 +1246,19 @@ public: if (!target) return; - if (IR::Temp *temp = target->asTemp()) { - if (temp->kind == IR::Temp::PhysicalRegister) { - if (temp->type == IR::DoubleType) - storeReturnValue((FPRegisterID) temp->index); - else if (temp->type == IR::UInt32Type) - storeUInt32ReturnValue((RegisterID) temp->index); - else - storeReturnValue((RegisterID) temp->index); - return; - } else { - Pointer addr = loadTempAddress(temp); - storeReturnValue(addr); - } - } else if (IR::ArgLocal *al = target->asArgLocal()) { - Pointer addr = loadArgLocalAddress(ScratchRegister, al); - storeReturnValue(addr); + IR::Temp *temp = target->asTemp(); + if (temp && temp->kind == IR::Temp::PhysicalRegister) { + if (temp->type == IR::DoubleType) + storeReturnValue((FPRegisterID) temp->index); + else if (temp->type == IR::UInt32Type) + storeUInt32ReturnValue((RegisterID) temp->index); + else + storeReturnValue((RegisterID) temp->index); + return; + } else { + WriteBarrier::Type barrier; + Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier); + storeReturnValue(addr, barrier); } } @@ -1181,7 +1295,7 @@ public: void loadArgumentOnStack(PointerToValue temp, int argumentNumber) { if (temp.value) { - Pointer ptr = toAddress(ScratchRegister, temp.value, argumentNumber); + Pointer ptr = toAddress(ScratchRegister, temp.value, argumentNumber, 0); loadArgumentOnStack<StackSlot>(ptr, argumentNumber); } else { RegisterSizeDependentOps::zeroStackSlot(this, StackSlot); @@ -1201,7 +1315,7 @@ public: { Q_ASSERT (temp.value); - Pointer ptr = loadAddress(ScratchRegister, temp.value); + Pointer ptr = loadAddressForReading(ScratchRegister, temp.value); loadArgumentOnStack<StackSlot>(ptr, argumentNumber); } @@ -1212,7 +1326,7 @@ public: moveDouble((FPRegisterID) sourceTemp->index, dest); return; } - Pointer ptr = loadAddress(ScratchRegister, source); + Pointer ptr = loadAddressForReading(ScratchRegister, source); loadDouble(ptr, dest); } @@ -1231,46 +1345,65 @@ public: RegisterSizeDependentOps::loadDouble(this, addr, dest); } - void storeDouble(FPRegisterID source, Address addr) + void storeDouble(FPRegisterID source, Address addr, WriteBarrier::Type barrier) { - RegisterSizeDependentOps::storeDouble(this, source, addr); + RegisterSizeDependentOps::storeDouble(this, source, addr, barrier); } template <typename Result, typename Source> - void copyValue(Result result, Source source); + void copyValue(Result result, Source source, WriteBarrier::Type barrier); template <typename Result> - void copyValue(Result result, IR::Expr* source); + void copyValue(Result result, IR::Expr* source, WriteBarrier::Type barrier); // The scratch register is used to calculate the temp address for the source. - void memcopyValue(Pointer target, IR::Expr *source, RegisterID scratchRegister) + void memcopyValue(Pointer target, IR::Expr *source, RegisterID scratchRegister, WriteBarrier::Type barrier) { Q_ASSERT(!source->asTemp() || source->asTemp()->kind != IR::Temp::PhysicalRegister); Q_ASSERT(target.base != scratchRegister); - TargetConfiguration::MacroAssembler::loadDouble(loadAddress(scratchRegister, source), FPGpr0); - TargetConfiguration::MacroAssembler::storeDouble(FPGpr0, target); + loadRawValue(loadAddressForReading(scratchRegister, source), FPGpr0); + storeRawValue(FPGpr0, target, barrier); } // The scratch register is used to calculate the temp address for the source. void memcopyValue(IR::Expr *target, Pointer source, FPRegisterID fpScratchRegister, RegisterID scratchRegister) { - TargetConfiguration::MacroAssembler::loadDouble(source, fpScratchRegister); - TargetConfiguration::MacroAssembler::storeDouble(fpScratchRegister, loadAddress(scratchRegister, target)); + loadRawValue(source, fpScratchRegister); + WriteBarrier::Type barrier; + Pointer dest = loadAddressForWriting(scratchRegister, target, &barrier); + storeRawValue(fpScratchRegister, dest, barrier); + } + + void loadRawValue(Pointer source, FPRegisterID dest) + { + TargetConfiguration::MacroAssembler::loadDouble(source, dest); } - void storeValue(TargetPrimitive value, Address destination) + void storeRawValue(FPRegisterID source, Pointer dest, WriteBarrier::Type barrier) { - RegisterSizeDependentOps::storeValue(this, value, destination); + TargetConfiguration::MacroAssembler::storeDouble(source, dest); + if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier) + RegisterSizeDependentOps::emitWriteBarrier(this, dest); + } + + void storeValue(TargetPrimitive value, Address destination, WriteBarrier::Type barrier) + { + RegisterSizeDependentOps::storeValue(this, value, destination, barrier); } void storeValue(TargetPrimitive value, IR::Expr* temp); + void emitWriteBarrier(Address addr, WriteBarrier::Type barrier) { + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + RegisterSizeDependentOps::emitWriteBarrier(this, addr); + } + void enterStandardStackFrame(const RegisterInformation ®ularRegistersToSave, const RegisterInformation &fpRegistersToSave); void leaveStandardStackFrame(const RegisterInformation ®ularRegistersToSave, const RegisterInformation &fpRegistersToSave); void checkException() { - load32(Address(EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, hasException))), ScratchRegister); + this->load8(Address(EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, hasException))), ScratchRegister); Jump exceptionThrown = branch32(RelationalCondition::NotEqual, ScratchRegister, TrustedImm32(0)); if (catchBlock) addPatch(catchBlock, exceptionThrown); @@ -1333,7 +1466,7 @@ public: // load the table from the context loadPtr(Address(EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), ScratchRegister); - loadPtr(Address(ScratchRegister, targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, lookups))), + loadPtr(Address(ScratchRegister, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, lookups))), lookupCall.addr.base); // pre-calculate the indirect address for the lookupCall table: if (lookupCall.addr.offset) @@ -1426,8 +1559,10 @@ public: generateFunctionCallImp(needsExceptionCheck, r, functionName, function, arg1, VoidType(), VoidType(), VoidType(), VoidType(), VoidType()); } - Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset) + Pointer toAddress(RegisterID tmpReg, IR::Expr *e, int offset, WriteBarrier::Type *barrier) { + if (barrier) + *barrier = WriteBarrier::NoBarrier; if (IR::Const *c = e->asConst()) { Address addr = _stackLayout->savedRegPointer(offset); Address tagAddr = addr; @@ -1443,14 +1578,16 @@ public: if (t->kind == IR::Temp::PhysicalRegister) return Pointer(_stackLayout->savedRegPointer(offset)); - return loadAddress(tmpReg, e); + return loadAddressForWriting(tmpReg, e, barrier); } - void storeBool(RegisterID reg, Pointer addr) + void storeBool(RegisterID reg, Pointer addr, WriteBarrier::Type barrier) { store32(reg, addr); addr.offset += 4; store32(TrustedImm32(TargetPrimitive::fromBoolean(0).tag()), addr); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + RegisterSizeDependentOps::emitWriteBarrier(this, addr); } void storeBool(RegisterID src, RegisterID dest) @@ -1467,8 +1604,9 @@ public: } } - Pointer addr = loadAddress(ScratchRegister, target); - storeBool(reg, addr); + WriteBarrier::Type barrier; + Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier); + storeBool(reg, addr, barrier); } void storeBool(bool value, IR::Expr *target) { @@ -1490,25 +1628,24 @@ public: move(src, dest); } - void storeInt32(RegisterID reg, Pointer addr) + void storeInt32(RegisterID reg, Pointer addr, WriteBarrier::Type barrier) { store32(reg, addr); addr.offset += 4; store32(TrustedImm32(TargetPrimitive::fromInt32(0).tag()), addr); + if (WriteBarrier::isRequired<WriteBarrier::Primitive>() && barrier == WriteBarrier::Barrier) + RegisterSizeDependentOps::emitWriteBarrier(this, addr); } void storeInt32(RegisterID reg, IR::Expr *target) { - if (IR::Temp *targetTemp = target->asTemp()) { - if (targetTemp->kind == IR::Temp::PhysicalRegister) { - move(reg, (RegisterID) targetTemp->index); - } else { - Pointer addr = loadTempAddress(targetTemp); - storeInt32(reg, addr); - } - } else if (IR::ArgLocal *al = target->asArgLocal()) { - Pointer addr = loadArgLocalAddress(ScratchRegister, al); - storeInt32(reg, addr); + IR::Temp *targetTemp = target->asTemp(); + if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) { + move(reg, (RegisterID) targetTemp->index); + } else { + WriteBarrier::Type barrier; + Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier); + storeInt32(reg, addr, barrier); } } @@ -1517,15 +1654,15 @@ public: move(src, dest); } - void storeUInt32(RegisterID reg, Pointer addr) + void storeUInt32(RegisterID reg, Pointer addr, WriteBarrier::Type barrier) { // The UInt32 representation in QV4::Value is really convoluted. See also toUInt32Register. Jump intRange = branch32(RelationalCondition::GreaterThanOrEqual, reg, TrustedImm32(0)); convertUInt32ToDouble(reg, FPGpr0, ReturnValueRegister); - storeDouble(FPGpr0, addr); + storeDouble(FPGpr0, addr, barrier); Jump done = jump(); intRange.link(this); - storeInt32(reg, addr); + storeInt32(reg, addr, barrier); done.link(this); } @@ -1535,8 +1672,9 @@ public: if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) { move(reg, (RegisterID) targetTemp->index); } else { - Pointer addr = loadAddress(ScratchRegister, target); - storeUInt32(reg, addr); + WriteBarrier::Type barrier; + Pointer addr = loadAddressForWriting(ScratchRegister, target, &barrier); + storeUInt32(reg, addr, barrier); } } @@ -1571,7 +1709,7 @@ public: if (t->kind == IR::Temp::PhysicalRegister) return (RegisterID) t->index; - return toInt32Register(loadAddress(scratchReg, e), scratchReg); + return toInt32Register(loadAddressForReading(scratchReg, e), scratchReg); } RegisterID toInt32Register(Pointer addr, RegisterID scratchReg) @@ -1591,7 +1729,7 @@ public: if (t->kind == IR::Temp::PhysicalRegister) return (RegisterID) t->index; - return toUInt32Register(loadAddress(scratchReg, e), scratchReg); + return toUInt32Register(loadAddressForReading(scratchReg, e), scratchReg); } RegisterID toUInt32Register(Pointer addr, RegisterID scratchReg) @@ -1666,31 +1804,31 @@ const typename Assembler<TargetConfiguration>::VoidType Assembler<TargetConfigur template <typename TargetConfiguration> template <typename Result, typename Source> -void Assembler<TargetConfiguration>::copyValue(Result result, Source source) +void Assembler<TargetConfiguration>::copyValue(Result result, Source source, WriteBarrier::Type barrier) { - RegisterSizeDependentOps::copyValueViaRegisters(this, source, result); + RegisterSizeDependentOps::copyValueViaRegisters(this, source, result, barrier); } template <typename TargetConfiguration> template <typename Result> -void Assembler<TargetConfiguration>::copyValue(Result result, IR::Expr* source) +void Assembler<TargetConfiguration>::copyValue(Result result, IR::Expr* source, WriteBarrier::Type barrier) { if (source->type == IR::BoolType) { RegisterID reg = toInt32Register(source, ScratchRegister); - storeBool(reg, result); + storeBool(reg, result, barrier); } else if (source->type == IR::SInt32Type) { RegisterID reg = toInt32Register(source, ScratchRegister); - storeInt32(reg, result); + storeInt32(reg, result, barrier); } else if (source->type == IR::UInt32Type) { RegisterID reg = toUInt32Register(source, ScratchRegister); - storeUInt32(reg, result); + storeUInt32(reg, result, barrier); } else if (source->type == IR::DoubleType) { - storeDouble(toDoubleRegister(source), result); + storeDouble(toDoubleRegister(source), result, barrier); } else if (source->asTemp() || source->asArgLocal()) { - RegisterSizeDependentOps::copyValueViaRegisters(this, source, result); + RegisterSizeDependentOps::copyValueViaRegisters(this, source, result, barrier); } else if (IR::Const *c = source->asConst()) { auto v = convertToValue<TargetPrimitive>(c); - storeValue(v, result); + storeValue(v, result, barrier); } else { Q_UNREACHABLE(); } diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp index feb30ee298..a1c65f644c 100644 --- a/src/qml/jit/qv4binop.cpp +++ b/src/qml/jit/qv4binop.cpp @@ -492,7 +492,7 @@ bool Binop<JITAssembler>::int32Binop(IR::Expr *leftSource, IR::Expr *rightSource return false; } } else if (inplaceOpWithAddress) { // All cases of X = X op [address-of-Y] - Pointer rhsAddr = as->loadAddress(JITAssembler::ScratchRegister, rightSource); + Pointer rhsAddr = as->loadAddressForReading(JITAssembler::ScratchRegister, rightSource); switch (op) { case IR::OpBitAnd: as->and32(rhsAddr, targetReg); break; case IR::OpBitOr: as->or32 (rhsAddr, targetReg); break; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 50d40f6f98..7784eb364e 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -133,7 +133,7 @@ void InstructionSelection<JITAssembler>::run(int functionIndex) if (s->location.isValid()) { if (int(s->location.startLine) != lastLine) { _as->loadPtr(Address(JITTargetPlatform::EngineRegister, JITAssembler::targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ScratchRegister); - Address lineAddr(JITTargetPlatform::ScratchRegister, JITAssembler::targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, lineNumber))); + Address lineAddr(JITTargetPlatform::ScratchRegister, JITAssembler::targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, lineNumber))); _as->store32(TrustedImm32(s->location.startLine), lineAddr); lastLine = s->location.startLine; } @@ -350,11 +350,11 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr bool isData = it->expr->asConst()->value; it = it->next; - _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr); + _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier); if (!isData) { it = it->next; - _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr); + _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier); } } @@ -376,10 +376,10 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr ++arrayValueCount; // Index - _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++)); + _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier); // Value - _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr); + _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier); it = it->next; } @@ -400,14 +400,14 @@ void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr ++arrayGetterSetterCount; // Index - _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++)); + _as->storeValue(JITAssembler::TargetPrimitive::fromUInt32(index), _as->stackLayout().argumentAddressForCall(argc++), WriteBarrier::NoBarrier); // Getter - _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr); + _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier); it = it->next; // Setter - _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr); + _as->copyValue(_as->stackLayout().argumentAddressForCall(argc++), it->expr, WriteBarrier::NoBarrier); it = it->next; } @@ -447,9 +447,11 @@ void InstructionSelection<JITAssembler>::callValue(IR::Expr *value, IR::ExprList template <typename JITAssembler> void InstructionSelection<JITAssembler>::loadThisObject(IR::Expr *temp) { - _as->loadPtr(Address(JITTargetPlatform::EngineRegister, JITAssembler::targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ScratchRegister); - _as->loadPtr(Address(JITTargetPlatform::ScratchRegister, JITAssembler::targetStructureOffset(Heap::ExecutionContext::baseOffset + offsetof(Heap::ExecutionContextData, callData))), JITTargetPlatform::ScratchRegister); - _as->copyValue(temp, Address(JITTargetPlatform::ScratchRegister, offsetof(CallData, thisObject))); + WriteBarrier::Type barrier; + Pointer addr = _as->loadAddressForWriting(JITTargetPlatform::ScratchRegister, temp, &barrier); + _as->loadPtr(Address(JITTargetPlatform::EngineRegister, JITAssembler::targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ReturnValueRegister); + _as->loadPtr(Address(JITTargetPlatform::ReturnValueRegister,JITAssembler::targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, callData))), JITTargetPlatform::ReturnValueRegister); + _as->copyValue(addr, Address(JITTargetPlatform::ReturnValueRegister, offsetof(CallData, thisObject)), barrier); } template <typename JITAssembler> @@ -503,8 +505,9 @@ void InstructionSelection<JITAssembler>::loadString(const QString &str, IR::Expr { Pointer srcAddr = _as->loadStringAddress(JITTargetPlatform::ReturnValueRegister, str); _as->loadPtr(srcAddr, JITTargetPlatform::ReturnValueRegister); - Pointer destAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, target); - JITAssembler::RegisterSizeDependentOps::loadManagedPointer(_as, JITTargetPlatform::ReturnValueRegister, destAddr); + WriteBarrier::Type barrier; + Pointer destAddr = _as->loadAddressForWriting(JITTargetPlatform::ScratchRegister, target, &barrier); + JITAssembler::RegisterSizeDependentOps::loadManagedPointer(_as, JITTargetPlatform::ReturnValueRegister, destAddr, barrier); } template <typename JITAssembler> @@ -621,6 +624,7 @@ void InstructionSelection<JITAssembler>::getElement(IR::Expr *base, IR::Expr *in if (0 && useFastLookups) { uint lookup = registerIndexedGetterLookup(); generateLookupCall(target, lookup, offsetof(QV4::Lookup, indexedGetter), + JITTargetPlatform::EngineRegister, PointerToValue(base), PointerToValue(index)); return; @@ -636,6 +640,7 @@ void InstructionSelection<JITAssembler>::setElement(IR::Expr *source, IR::Expr * if (0 && useFastLookups) { uint lookup = registerIndexedSetterLookup(); generateLookupCall(JITAssembler::Void, lookup, offsetof(QV4::Lookup, indexedSetter), + JITTargetPlatform::EngineRegister, PointerToValue(targetBase), PointerToValue(targetIndex), PointerToValue(source)); return; @@ -711,8 +716,10 @@ void InstructionSelection<JITAssembler>::copyValue(IR::Expr *source, IR::Expr *t } } + WriteBarrier::Type barrier; + Pointer addr = _as->loadAddressForWriting(JITTargetPlatform::ReturnValueRegister, target, &barrier); // The target is not a physical register, nor is the source. So we can do a memory-to-memory copy: - _as->memcopyValue(_as->loadAddress(JITTargetPlatform::ReturnValueRegister, target), source, JITTargetPlatform::ScratchRegister); + _as->memcopyValue(addr, source, JITTargetPlatform::ScratchRegister, barrier); } template <typename JITAssembler> @@ -739,14 +746,13 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr * } else if (!sourceTemp || sourceTemp->kind == IR::Temp::StackSlot) { if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) { // Note: a swap for two stack-slots can involve different types. - Pointer sAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source); - Pointer tAddr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, target); - // use the implementation in JSC::MacroAssembler, as it doesn't do bit swizzling - auto platformAs = static_cast<typename JITAssembler::MacroAssembler*>(_as); - platformAs->loadDouble(sAddr, JITTargetPlatform::FPGpr0); - platformAs->loadDouble(tAddr, JITTargetPlatform::FPGpr1); - platformAs->storeDouble(JITTargetPlatform::FPGpr1, sAddr); - platformAs->storeDouble(JITTargetPlatform::FPGpr0, tAddr); + WriteBarrier::Type barrierForSource, barrierForTarget; + Pointer sAddr = _as->loadAddressForWriting(JITTargetPlatform::ScratchRegister, source, &barrierForSource); + Pointer tAddr = _as->loadAddressForWriting(JITTargetPlatform::ReturnValueRegister, target, &barrierForTarget); + _as->loadRawValue(sAddr, JITTargetPlatform::FPGpr0); + _as->loadRawValue(tAddr, JITTargetPlatform::FPGpr1); + _as->storeRawValue(JITTargetPlatform::FPGpr1, sAddr, barrierForSource); + _as->storeRawValue(JITTargetPlatform::FPGpr0, tAddr, barrierForTarget); return; } } @@ -757,14 +763,15 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr * Q_ASSERT(memExpr); Q_ASSERT(regTemp); - Pointer addr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, memExpr); + WriteBarrier::Type barrier; + Pointer addr = _as->loadAddressForWriting(JITTargetPlatform::ReturnValueRegister, memExpr, &barrier); if (regTemp->type == IR::DoubleType) { _as->loadDouble(addr, JITTargetPlatform::FPGpr0); - _as->storeDouble((FPRegisterID) regTemp->index, addr); + _as->storeDouble((FPRegisterID) regTemp->index, addr, barrier); _as->moveDouble(JITTargetPlatform::FPGpr0, (FPRegisterID) regTemp->index); } else if (regTemp->type == IR::UInt32Type) { _as->toUInt32Register(addr, JITTargetPlatform::ScratchRegister); - _as->storeUInt32((RegisterID) regTemp->index, addr); + _as->storeUInt32((RegisterID) regTemp->index, addr, barrier); _as->move(JITTargetPlatform::ScratchRegister, (RegisterID) regTemp->index); } else { _as->load32(addr, JITTargetPlatform::ScratchRegister); @@ -784,6 +791,7 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr * Q_UNREACHABLE(); } _as->store32(TrustedImm32(tag), addr); + _as->emitWriteBarrier(addr, barrier); } _as->move(JITTargetPlatform::ScratchRegister, (RegisterID) regTemp->index); } @@ -913,13 +921,13 @@ void InstructionSelection<JITAssembler>::convertTypeToDouble(IR::Expr *source, I convertUIntToDouble(source, target); break; case IR::UndefinedType: - _as->loadDouble(_as->loadAddress(JITTargetPlatform::ScratchRegister, source), JITTargetPlatform::FPGpr0); + _as->loadDouble(_as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source), JITTargetPlatform::FPGpr0); _as->storeDouble(JITTargetPlatform::FPGpr0, target); break; case IR::StringType: case IR::VarType: { // load the tag: - Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source); + Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source); tagAddr.offset += 4; _as->load32(tagAddr, JITTargetPlatform::ScratchRegister); @@ -938,7 +946,7 @@ void InstructionSelection<JITAssembler>::convertTypeToDouble(IR::Expr *source, I // it is a double: isDbl.link(_as); - Pointer addr2 = _as->loadAddress(JITTargetPlatform::ScratchRegister, source); + Pointer addr2 = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source); IR::Temp *targetTemp = target->asTemp(); if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) { _as->memcopyValue(target, addr2, JITTargetPlatform::FPGpr0, JITTargetPlatform::ReturnValueRegister); @@ -997,7 +1005,7 @@ void InstructionSelection<JITAssembler>::convertTypeToBool(IR::Expr *source, IR: Q_FALLTHROUGH(); case IR::VarType: default: - Pointer addr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source); + Pointer addr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source); Pointer tagAddr = addr; tagAddr.offset += 4; _as->load32(tagAddr, JITTargetPlatform::ReturnValueRegister); @@ -1062,7 +1070,7 @@ void InstructionSelection<JITAssembler>::convertTypeToSInt32(IR::Expr *source, I case IR::StringType: default: generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toInt, - _as->loadAddress(JITTargetPlatform::ScratchRegister, source)); + _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source)); _as->storeInt32(JITTargetPlatform::ReturnValueRegister, target); break; } // switch (source->type) @@ -1074,21 +1082,21 @@ void InstructionSelection<JITAssembler>::convertTypeToUInt32(IR::Expr *source, I switch (source->type) { case IR::VarType: { // load the tag: - Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source); + Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source); tagAddr.offset += 4; _as->load32(tagAddr, JITTargetPlatform::ScratchRegister); // check if it's an int32: Jump isNoInt = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister, TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer))); - Pointer addr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source); + Pointer addr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source); _as->storeUInt32(_as->toInt32Register(addr, JITTargetPlatform::ScratchRegister), target); Jump intDone = _as->jump(); // not an int: isNoInt.link(_as); generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toUInt, - _as->loadAddress(JITTargetPlatform::ScratchRegister, source)); + _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, source)); _as->storeInt32(JITTargetPlatform::ReturnValueRegister, target); intDone.link(_as); @@ -1193,7 +1201,7 @@ void InstructionSelection<JITAssembler>::visitCJump(IR::CJump *s) reg = JITTargetPlatform::ReturnValueRegister; _as->toInt32Register(t, reg); } else { - Address temp = _as->loadAddress(JITTargetPlatform::ScratchRegister, s->cond); + Address temp = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, s->cond); Address tag = temp; tag.offset += QV4::Value::tagOffset(); Jump booleanConversion = _as->branch32(RelationalCondition::NotEqual, tag, @@ -1299,9 +1307,9 @@ int InstructionSelection<JITAssembler>::prepareVariableArguments(IR::ExprList* a Q_ASSERT(arg != 0); Pointer dst(_as->stackLayout().argumentAddressForCall(i)); if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister) - _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister); + _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister, WriteBarrier::NoBarrier); else - _as->copyValue(dst, arg); + _as->copyValue(dst, arg, WriteBarrier::NoBarrier); } return argc; @@ -1321,9 +1329,9 @@ int InstructionSelection<JITAssembler>::prepareCallData(IR::ExprList* args, IR:: _as->store32(TrustedImm32(argc), p); p = _as->stackLayout().callDataAddress(offsetof(CallData, thisObject)); if (!thisObject) - _as->storeValue(JITAssembler::TargetPrimitive::undefinedValue(), p); + _as->storeValue(JITAssembler::TargetPrimitive::undefinedValue(), p, WriteBarrier::NoBarrier); else - _as->copyValue(p, thisObject); + _as->copyValue(p, thisObject, WriteBarrier::NoBarrier); int i = 0; for (IR::ExprList *it = args; it; it = it->next, ++i) { @@ -1331,9 +1339,9 @@ int InstructionSelection<JITAssembler>::prepareCallData(IR::ExprList* args, IR:: Q_ASSERT(arg != 0); Pointer dst(_as->stackLayout().argumentAddressForCall(i)); if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister) - _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister); + _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister, WriteBarrier::NoBarrier); else - _as->copyValue(dst, arg); + _as->copyValue(dst, arg, WriteBarrier::NoBarrier); } return argc; } @@ -1451,7 +1459,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpStrictNull(IR::Binop *binop, return true; } - Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, varSrc); + Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, varSrc); tagAddr.offset += 4; const RegisterID tagReg = JITTargetPlatform::ScratchRegister; _as->load32(tagAddr, tagReg); @@ -1534,7 +1542,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpStrictBool(IR::Binop *binop, return true; } - Pointer otherAddr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, otherSrc); + Pointer otherAddr = _as->loadAddressForReading(JITTargetPlatform::ReturnValueRegister, otherSrc); otherAddr.offset += 4; // tag address // check if the tag of the var operand is indicates 'boolean' @@ -1583,7 +1591,7 @@ bool InstructionSelection<JITAssembler>::visitCJumpNullUndefined(IR::Type nullOr return true; } - Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, varSrc); + Pointer tagAddr = _as->loadAddressForReading(JITTargetPlatform::ScratchRegister, varSrc); tagAddr.offset += 4; const RegisterID tagReg = JITTargetPlatform::ReturnValueRegister; _as->load32(tagAddr, tagReg); diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 0992e96e8b..7019a117a2 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -209,7 +209,7 @@ private: _as->convertInt32ToDouble((RegisterID) sourceTemp->index, (FPRegisterID) targetTemp->index); } else { - _as->convertInt32ToDouble(_as->loadAddress(JITTargetPlatform::ReturnValueRegister, sourceTemp), + _as->convertInt32ToDouble(_as->loadAddressForReading(JITTargetPlatform::ReturnValueRegister, sourceTemp), (FPRegisterID) targetTemp->index); } } else { @@ -223,7 +223,7 @@ private: _as->convertInt32ToDouble(_as->toInt32Register(source, JITTargetPlatform::ScratchRegister), JITTargetPlatform::FPGpr0); - _as->storeDouble(JITTargetPlatform::FPGpr0, _as->loadAddress(JITTargetPlatform::ReturnValueRegister, target)); + _as->storeDouble(JITTargetPlatform::FPGpr0, target); } void convertUIntToDouble(IR::Expr *source, IR::Expr *target) @@ -240,7 +240,7 @@ private: _as->convertUInt32ToDouble(_as->toUInt32Register(source, tmpReg), JITTargetPlatform::FPGpr0, tmpReg); - _as->storeDouble(JITTargetPlatform::FPGpr0, _as->loadAddress(tmpReg, target)); + _as->storeDouble(JITTargetPlatform::FPGpr0, target); } void convertIntToBool(IR::Expr *source, IR::Expr *target) @@ -260,8 +260,8 @@ private: void calculateRegistersToSave(const RegisterInformation &used); - template <typename Retval, typename Arg1, typename Arg2, typename Arg3> - void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3) + template <typename Retval, typename Arg1, typename Arg2, typename Arg3, typename Arg4> + void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) { // Note: using the return value register is intentional: for ABIs where the first parameter // goes into the same register as the return value (currently only ARM), the prepareCall @@ -271,7 +271,7 @@ private: _as->generateFunctionCallImp(true, retval, "lookup getter/setter", typename JITAssembler::LookupCall(lookupAddr, getterSetterOffset), lookupAddr, - arg1, arg2, arg3); + arg1, arg2, arg3, arg4); } template <typename Retval, typename Arg1, typename Arg2> @@ -280,6 +280,12 @@ private: generateLookupCall(retval, index, getterSetterOffset, arg1, arg2, typename JITAssembler::VoidType()); } + template <typename Retval, typename Arg1, typename Arg2, typename Arg3> + void generateLookupCall(Retval retval, uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2, Arg3 arg3) + { + generateLookupCall(retval, index, getterSetterOffset, arg1, arg2, arg3, typename JITAssembler::VoidType()); + } + IR::BasicBlock *_block; BitVector _removableJumps; JITAssembler* _as; |