diff options
Diffstat (limited to 'src/qml/jit')
-rw-r--r-- | src/qml/jit/qv4assembler.cpp | 98 | ||||
-rw-r--r-- | src/qml/jit/qv4assembler_p.h | 455 | ||||
-rw-r--r-- | src/qml/jit/qv4binop.cpp | 12 | ||||
-rw-r--r-- | src/qml/jit/qv4binop_p.h | 4 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm.cpp | 153 | ||||
-rw-r--r-- | src/qml/jit/qv4isel_masm_p.h | 20 | ||||
-rw-r--r-- | src/qml/jit/qv4targetplatform_p.h | 6 | ||||
-rw-r--r-- | src/qml/jit/qv4unop.cpp | 2 |
8 files changed, 467 insertions, 283 deletions
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index e658977da1..d062f3bbb2 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -95,6 +95,12 @@ bool CompilationUnit::memoryMapCode(QString *errorString) JSC::MacroAssemblerCodeRef codeRef = JSC::MacroAssemblerCodeRef::createSelfManagedCodeRef(JSC::MacroAssemblerCodePtr(codePtr)); JSC::ExecutableAllocator::makeExecutable(codePtr, compiledFunction->codeSize); codeRefs[i] = codeRef; + + static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM"); + if (showCode) { + WTF::dataLogF("Mapped JIT code for %s\n", qPrintable(stringAt(compiledFunction->nameIndex))); + disassemble(codeRef.code(), compiledFunction->codeSize, " ", WTF::dataFile()); + } } return true; @@ -150,9 +156,6 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const CompiledData::Unit } template <typename TargetConfiguration> -const typename Assembler<TargetConfiguration>::VoidType Assembler<TargetConfiguration>::Void; - -template <typename TargetConfiguration> Assembler<TargetConfiguration>::Assembler(QV4::Compiler::JSUnitGenerator *jsGenerator, IR::Function* function, QV4::ExecutableAllocator *executableAllocator) : _function(function) , _nextBlock(0) @@ -246,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> @@ -265,29 +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, qOffsetOf(ExecutionEngine, current)), baseReg); - if (scope) { - loadPtr(Address(baseReg, qOffsetOf(ExecutionContext::Data, outer)), baseReg); + loadPtr(Address(EngineRegister, targetStructureOffset(offsetof(EngineBase, current))), baseReg); + + 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); + + while (scope) { + loadPtr(Address(baseReg, outerOffset), baseReg); --scope; - while (scope) { - loadPtr(Address(baseReg, qOffsetOf(ExecutionContext::Data, outer)), baseReg); - --scope; - } } switch (al->kind) { case IR::ArgLocal::Formal: case IR::ArgLocal::ScopedFormal: { - loadPtr(Address(baseReg, qOffsetOf(ExecutionContext::Data, callData)), 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: { - loadPtr(Address(baseReg, qOffsetOf(CallContext::Data, locals)), baseReg); - offset = al->index * sizeof(Value); + offset = localsOffset + al->index * sizeof(Value); } break; default: Q_UNREACHABLE(); @@ -298,25 +317,25 @@ typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>: template <typename TargetConfiguration> typename Assembler<TargetConfiguration>::Pointer Assembler<TargetConfiguration>::loadStringAddress(RegisterID reg, const QString &string) { - loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister); - loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, compilationUnit)), Assembler::ScratchRegister); - loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg); + loadPtr(Address(Assembler::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), 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 * sizeof(QV4::String*)); + return Pointer(reg, id * RegisterSize); } template <typename TargetConfiguration> typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(IR::Const *c, RegisterID baseReg) { - return loadConstant(convertToValue(c), baseReg); + return loadConstant(convertToValue<TargetPrimitive>(c), baseReg); } template <typename TargetConfiguration> -typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(const Primitive &v, RegisterID baseReg) +typename Assembler<TargetConfiguration>::Address Assembler<TargetConfiguration>::loadConstant(const TargetPrimitive &v, RegisterID baseReg) { - loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), baseReg); - loadPtr(Address(baseReg, qOffsetOf(QV4::Heap::ExecutionContext, constantTable)), baseReg); - const int index = _jsGenerator->registerConstant(v.asReturnedValue()); + loadPtr(Address(Assembler::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), 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)); } @@ -328,10 +347,11 @@ void Assembler<TargetConfiguration>::loadStringRef(RegisterID reg, const QString } template <typename TargetConfiguration> -void Assembler<TargetConfiguration>::storeValue(QV4::Primitive value, IR::Expr *destination) +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> @@ -420,25 +440,19 @@ 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); // check if it's an int32: Assembler::Jump isNoInt = branch32(Assembler::NotEqual, Assembler::ScratchRegister, - Assembler::TrustedImm32(Value::Integer_Type_Internal)); + Assembler::TrustedImm32(quint32(ValueTypeInternal::Integer))); convertInt32ToDouble(toInt32Register(src, Assembler::ScratchRegister), dest); Assembler::Jump intDone = jump(); // not an int, check if it's a double: isNoInt.link(this); -#ifdef QV4_USE_64_BIT_VALUE_ENCODING - rshift32(TrustedImm32(Value::IsDoubleTag_Shift), ScratchRegister); - Assembler::Jump isNoDbl = branch32(RelationalCondition::Equal, JITTargetPlatform::ScratchRegister, TrustedImm32(0)); -#else - and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister); - Assembler::Jump isNoDbl = branch32(RelationalCondition::Equal, JITTargetPlatform::ScratchRegister, TrustedImm32(Value::NotDouble_Mask)); -#endif + Assembler::Jump isNoDbl = RegisterSizeDependentOps::checkIfTagRegisterIsDouble(this, ScratchRegister); toDoubleRegister(src, dest); intDone.link(this); @@ -507,7 +521,7 @@ void Assembler<TargetConfiguration>::returnFromFunction(IR::Ret *s, RegisterInfo } else if (IR::Temp *t = s->expr->asTemp()) { RegisterSizeDependentOps::setFunctionReturnValueFromTemp(this, t); } else if (IR::Const *c = s->expr->asConst()) { - QV4::Primitive retVal = convertToValue(c); + auto retVal = convertToValue<TargetPrimitive>(c); RegisterSizeDependentOps::setFunctionReturnValueFromConst(this, retVal); } else { Q_UNREACHABLE(); @@ -518,15 +532,13 @@ void Assembler<TargetConfiguration>::returnFromFunction(IR::Ret *s, RegisterInfo const int locals = stackLayout().calculateJSStackFrameSize(); subPtr(TrustedImm32(sizeof(QV4::Value)*locals), JITTargetPlatform::LocalsRegister); - loadPtr(Address(JITTargetPlatform::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), JITTargetPlatform::ScratchRegister); - loadPtr(Address(JITTargetPlatform::ScratchRegister, qOffsetOf(ExecutionContext::Data, engine)), JITTargetPlatform::ScratchRegister); - storePtr(JITTargetPlatform::LocalsRegister, Address(JITTargetPlatform::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop))); + storePtr(JITTargetPlatform::LocalsRegister, Address(JITTargetPlatform::EngineRegister, targetStructureOffset(offsetof(EngineBase, jsStackTop)))); leaveStandardStackFrame(regularRegistersToSave, fpRegistersToSave); ret(); exceptionReturnLabel = label(); - QV4::Primitive retVal = Primitive::undefinedValue(); + auto retVal = TargetPrimitive::undefinedValue(); RegisterSizeDependentOps::setFunctionReturnValueFromConst(this, retVal); jump(leaveStackFrame); } diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 720c522e1d..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> @@ -131,7 +132,7 @@ typedef AssemblerTargetConfiguration<DefaultPlatformMacroAssembler, NoOperatingS #define isel_stringIfy(s) isel_stringIfyx(s) #define generateRuntimeCall(as, t, function, ...) \ - as->generateFunctionCallImp(Runtime::Method_##function##_NeedsExceptionCheck, t, "Runtime::" isel_stringIfy(function), typename JITAssembler::RuntimeCall(qOffsetOf(QV4::Runtime, function)), __VA_ARGS__) + as->generateFunctionCallImp(Runtime::Method_##function##_NeedsExceptionCheck, t, "Runtime::" isel_stringIfy(function), typename JITAssembler::RuntimeCall(QV4::Runtime::function), __VA_ARGS__) template <typename JITAssembler, typename MacroAssembler, typename TargetPlatform, int RegisterSize> @@ -152,35 +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, QV4::Primitive value, Address destination) + static void storeValue(JITAssembler *as, TargetPrimitive value, Address destination, WriteBarrier::Type barrier) { - as->store32(TrustedImm32(value.int_32()), destination); + 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) @@ -193,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) @@ -219,31 +273,31 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Jump done = as->jump(); intRange.link(as); as->move(srcReg, lowReg); - as->move(TrustedImm32(QV4::Value::Integer_Type_Internal), highReg); + as->move(TrustedImm32(quint32(QV4::Value::ValueTypeInternal_32::Integer)), highReg); done.link(as); } break; case IR::SInt32Type: as->move((RegisterID) t->index, lowReg); - as->move(TrustedImm32(QV4::Value::Integer_Type_Internal), highReg); + as->move(TrustedImm32(quint32(QV4::Value::ValueTypeInternal_32::Integer)), highReg); break; case IR::BoolType: as->move((RegisterID) t->index, lowReg); - as->move(TrustedImm32(QV4::Value::Boolean_Type_Internal), highReg); + as->move(TrustedImm32(quint32(QV4::Value::ValueTypeInternal_32::Boolean)), highReg); break; default: 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); } } - static void setFunctionReturnValueFromConst(JITAssembler *as, QV4::Primitive retVal) + static void setFunctionReturnValueFromConst(JITAssembler *as, TargetPrimitive retVal) { - as->move(TrustedImm32(retVal.int_32()), TargetPlatform::LowReturnValueRegister); + as->move(TrustedImm32(retVal.value()), TargetPlatform::LowReturnValueRegister); as->move(TrustedImm32(retVal.tag()), TargetPlatform::HighReturnValueRegister); } @@ -295,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); @@ -312,21 +366,24 @@ 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); // check if it's an int32: Jump fallback = as->branch32(RelationalCondition::NotEqual, TargetPlatform::ReturnValueRegister, - TrustedImm32(Value::Integer_Type_Internal)); + TrustedImm32(quint32(Value::ValueTypeInternal_32::Integer))); 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(Value::Integer_Type_Internal), targetAddr); + 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); } @@ -335,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) @@ -367,6 +426,13 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Jump jump = as->branchSub32(ResultCondition::NonZero, TrustedImm32(1), TargetPlatform::ScratchRegister); jump.linkTo(loop, as); } + + static Jump checkIfTagRegisterIsDouble(JITAssembler *as, RegisterID tagRegister) + { + as->and32(TrustedImm32(Value::NotDouble_Mask), tagRegister); + Jump isNoDbl = as->branch32(RelationalCondition::Equal, tagRegister, TrustedImm32(Value::NotDouble_Mask)); + return isNoDbl; + } }; template <typename JITAssembler, typename MacroAssembler, typename TargetPlatform> @@ -383,6 +449,47 @@ 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) { @@ -391,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) @@ -412,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) @@ -433,7 +547,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Jump done = as->jump(); intRange.link(as); as->zeroExtend32ToPtr(srcReg, TargetPlatform::ReturnValueRegister); - quint64 tag = QV4::Value::Integer_Type_Internal; + quint64 tag = quint64(QV4::Value::ValueTypeInternal_64::Integer); as->or64(TrustedImm64(tag << 32), TargetPlatform::ReturnValueRegister); done.link(as); @@ -442,10 +556,10 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo quint64 tag; switch (t->type) { case IR::SInt32Type: - tag = QV4::Value::Integer_Type_Internal; + tag = quint64(QV4::Value::ValueTypeInternal_64::Integer); break; case IR::BoolType: - tag = QV4::Value::Boolean_Type_Internal; + tag = quint64(QV4::Value::ValueTypeInternal_64::Boolean); break; default: tag = 31337; // bogus value @@ -455,27 +569,29 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo TargetPlatform::ReturnValueRegister); } } else { - as->copyValue(TargetPlatform::ReturnValueRegister, t); + as->copyValue(TargetPlatform::ReturnValueRegister, t, WriteBarrier::NoBarrier); } } - static void setFunctionReturnValueFromConst(JITAssembler *as, QV4::Primitive retVal) + static void setFunctionReturnValueFromConst(JITAssembler *as, TargetPrimitive retVal) { as->move(TrustedImm64(retVal.rawValue()), TargetPlatform::ReturnValueRegister); } - static void storeValue(JITAssembler *as, QV4::Primitive 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) @@ -501,7 +617,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Pointer addr = as->loadTempAddress(temp); as->load64(addr, dest); } else { - QV4::Value undefined = QV4::Primitive::undefinedValue(); + auto undefined = TargetPrimitive::undefinedValue(); as->move(TrustedImm64(undefined.rawValue()), dest); } } @@ -511,10 +627,10 @@ 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 { - QV4::Value undefined = QV4::Primitive::undefinedValue(); + auto undefined = TargetPrimitive::undefinedValue(); as->move(TrustedImm64(undefined.rawValue()), dest); } } @@ -523,7 +639,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo { Q_UNUSED(argumentNumber); - QV4::Value v = convertToValue(c); + auto v = convertToValue<TargetPrimitive64>(c); as->move(TrustedImm64(v.rawValue()), dest); } @@ -532,7 +648,7 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Q_UNUSED(argumentNumber); if (!expr) { - QV4::Value undefined = QV4::Primitive::undefinedValue(); + auto undefined = TargetPrimitive::undefinedValue(); as->move(TrustedImm64(undefined.rawValue()), dest); } else if (IR::Temp *t = expr->asTemp()){ loadArgumentInRegister(as, t, dest, argumentNumber); @@ -580,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); @@ -589,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); @@ -613,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(Value::Integer_Type_Internal), targetAddr); + 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) @@ -651,6 +772,13 @@ struct RegisterSizeDependentAssembler<JITAssembler, MacroAssembler, TargetPlatfo Jump jump = as->branchSub32(ResultCondition::NonZero, TrustedImm32(1), TargetPlatform::ScratchRegister); jump.linkTo(loop, as); } + + static Jump checkIfTagRegisterIsDouble(JITAssembler *as, RegisterID tagRegister) + { + as->rshift32(TrustedImm32(Value::IsDoubleTag_Shift), tagRegister); + Jump isNoDbl = as->branch32(RelationalCondition::Equal, tagRegister, TrustedImm32(0)); + return isNoDbl; + } }; template <typename TargetConfiguration> @@ -713,7 +841,11 @@ public: using JITTargetPlatform::platformFinishEnteringStandardStackFrame; using JITTargetPlatform::platformLeaveStandardStackFrame; - using RegisterSizeDependentOps = RegisterSizeDependentAssembler<Assembler<TargetConfiguration>, MacroAssembler, JITTargetPlatform, RegisterSize>; + static qint32 targetStructureOffset(qint32 hostOffset) + { + Q_ASSERT(hostOffset % QT_POINTER_SIZE == 0); + return (hostOffset * RegisterSize) / QT_POINTER_SIZE; + } struct LookupCall { Address addr; @@ -728,7 +860,7 @@ public: struct RuntimeCall { Address addr; - inline RuntimeCall(uint offset = uint(INT_MIN)); + inline RuntimeCall(Runtime::RuntimeMethods method = Runtime::InvalidRuntimeMethod); bool isValid() const { return addr.offset >= 0; } }; @@ -745,6 +877,10 @@ public: {} }; + using RegisterSizeDependentOps = RegisterSizeDependentAssembler<Assembler<TargetConfiguration>, MacroAssembler, JITTargetPlatform, RegisterSize>; + using ValueTypeInternal = typename RegisterSizeDependentOps::ValueTypeInternal; + using TargetPrimitive = typename RegisterSizeDependentOps::TargetPrimitive; + // V4 uses two stacks: one stack with QV4::Value items, which is checked by the garbage // collector, and one stack used by the native C/C++/ABI code. This C++ stack is not scanned // by the garbage collector, so if any JS object needs to be retained, it should be put on the @@ -962,12 +1098,19 @@ 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 Primitive &v, RegisterID baseReg); + Address loadConstant(const TargetPrimitive &v, RegisterID baseReg); void loadStringRef(RegisterID reg, const QString &string); Pointer stackSlotPointer(IR::Temp *t) const { @@ -986,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(); @@ -1026,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); } } @@ -1039,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); } @@ -1072,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); } @@ -1081,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); } @@ -1091,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) @@ -1101,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); } } @@ -1153,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); @@ -1173,7 +1315,7 @@ public: { Q_ASSERT (temp.value); - Pointer ptr = loadAddress(ScratchRegister, temp.value); + Pointer ptr = loadAddressForReading(ScratchRegister, temp.value); loadArgumentOnStack<StackSlot>(ptr, argumentNumber); } @@ -1184,7 +1326,7 @@ public: moveDouble((FPRegisterID) sourceTemp->index, dest); return; } - Pointer ptr = loadAddress(ScratchRegister, source); + Pointer ptr = loadAddressForReading(ScratchRegister, source); loadDouble(ptr, dest); } @@ -1203,45 +1345,57 @@ 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 storeValue(QV4::Primitive value, RegisterID destination) + void loadRawValue(Pointer source, FPRegisterID dest) { - Q_UNUSED(value); - Q_UNUSED(destination); - Q_UNREACHABLE(); + TargetConfiguration::MacroAssembler::loadDouble(source, dest); + } + + void storeRawValue(FPRegisterID source, Pointer dest, WriteBarrier::Type barrier) + { + TargetConfiguration::MacroAssembler::storeDouble(source, dest); + if (WriteBarrier::isRequired<WriteBarrier::Unknown>() && barrier == WriteBarrier::Barrier) + RegisterSizeDependentOps::emitWriteBarrier(this, dest); } - void storeValue(QV4::Primitive value, Address destination) + void storeValue(TargetPrimitive value, Address destination, WriteBarrier::Type barrier) { - RegisterSizeDependentOps::storeValue(this, value, destination); + RegisterSizeDependentOps::storeValue(this, value, destination, barrier); } - void storeValue(QV4::Primitive value, IR::Expr* temp); + 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); @@ -1249,7 +1403,7 @@ public: const RegisterInformation &fpRegistersToSave); void checkException() { - load32(Address(EngineRegister, qOffsetOf(QV4::ExecutionEngine, 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); @@ -1270,13 +1424,7 @@ public: if (argumentNumber < RegisterArgumentCount) loadArgumentInRegister(value, registerForArgument(argumentNumber), argumentNumber); else -#if OS(WINDOWS) && CPU(X86_64) - loadArgumentOnStack<argumentNumber>(value, argumentNumber); -#elif CPU(MIPS) // Stack space for 4 arguments needs to be allocated for MIPS platforms. - loadArgumentOnStack<argumentNumber>(value, argumentNumber + 4); -#else // Sanity: - loadArgumentOnStack<argumentNumber - RegisterArgumentCount>(value, argumentNumber); -#endif + loadArgumentOnStack<argumentNumber - RegisterArgumentCount + (StackShadowSpace / RegisterSize)>(value, argumentNumber); } template <int argumentNumber> @@ -1300,7 +1448,7 @@ public: template <int ArgumentIndex, typename Parameter> struct SizeOnStack { - enum { Size = Select<ArgumentIndex >= RegisterArgumentCount, sizeof(void*), 0>::Chosen }; + enum { Size = Select<ArgumentIndex >= RegisterArgumentCount, RegisterSize, 0>::Chosen }; }; template <int ArgumentIndex> @@ -1317,8 +1465,8 @@ public: // IMPORTANT! See generateLookupCall in qv4isel_masm_p.h for details! // load the table from the context - loadPtr(Address(EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), ScratchRegister); - loadPtr(Address(ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, lookups)), + loadPtr(Address(EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), ScratchRegister); + 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) @@ -1411,15 +1559,17 @@ 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; tagAddr.offset += 4; - QV4::Primitive v = convertToValue(c); - store32(TrustedImm32(v.int_32()), addr); + auto v = convertToValue<TargetPrimitive>(c); + store32(TrustedImm32(v.value()), addr); store32(TrustedImm32(v.tag()), tagAddr); return Pointer(addr); } @@ -1428,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(QV4::Primitive::fromBoolean(0).tag()), addr); + 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) @@ -1452,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) { @@ -1475,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(QV4::Primitive::fromInt32(0).tag()), addr); + 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); } } @@ -1502,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); } @@ -1520,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); } } @@ -1548,7 +1701,7 @@ public: RegisterID toInt32Register(IR::Expr *e, RegisterID scratchReg) { if (IR::Const *c = e->asConst()) { - move(TrustedImm32(convertToValue(c).int_32()), scratchReg); + move(TrustedImm32(convertToValue<Primitive>(c).int_32()), scratchReg); return scratchReg; } @@ -1556,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) @@ -1576,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) @@ -1587,11 +1740,11 @@ public: Pointer tagAddr = addr; tagAddr.offset += 4; load32(tagAddr, scratchReg); - Jump inIntRange = branch32(RelationalCondition::Equal, scratchReg, TrustedImm32(QV4::Value::Integer_Type_Internal)); + Jump inIntRange = branch32(RelationalCondition::Equal, scratchReg, TrustedImm32(quint32(ValueTypeInternal::Integer))); // it's not in signed int range, so load it as a double, and truncate it down loadDouble(addr, FPGpr0); - Address inversionAddress = loadConstant(QV4::Primitive::fromDouble(double(INT_MAX) + 1), scratchReg); + Address inversionAddress = loadConstant(TargetPrimitive::fromDouble(double(INT_MAX) + 1), scratchReg); subDouble(inversionAddress, FPGpr0); Jump canNeverHappen = branchTruncateDoubleToUint32(FPGpr0, scratchReg); canNeverHappen.link(this); @@ -1616,9 +1769,9 @@ public: const int locals = _stackLayout->calculateJSStackFrameSize(); if (locals <= 0) return; - loadPtr(Address(JITTargetPlatform::EngineRegister, qOffsetOf(ExecutionEngine, jsStackTop)), JITTargetPlatform::LocalsRegister); + loadPtr(Address(JITTargetPlatform::EngineRegister, targetStructureOffset(offsetof(EngineBase, jsStackTop))), JITTargetPlatform::LocalsRegister); RegisterSizeDependentOps::initializeLocalVariables(this, locals); - storePtr(JITTargetPlatform::LocalsRegister, Address(JITTargetPlatform::EngineRegister, qOffsetOf(ExecutionEngine, jsStackTop))); + storePtr(JITTargetPlatform::LocalsRegister, Address(JITTargetPlatform::EngineRegister, targetStructureOffset(offsetof(EngineBase, jsStackTop)))); } Label exceptionReturnLabel; @@ -1647,40 +1800,44 @@ private: }; template <typename TargetConfiguration> +const typename Assembler<TargetConfiguration>::VoidType Assembler<TargetConfiguration>::Void; + +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()) { - QV4::Primitive v = convertToValue(c); - storeValue(v, result); + auto v = convertToValue<TargetPrimitive>(c); + storeValue(v, result, barrier); } else { Q_UNREACHABLE(); } } template <typename TargetConfiguration> -inline Assembler<TargetConfiguration>::RuntimeCall::RuntimeCall(uint offset) - : addr(Assembler::EngineRegister, offset + qOffsetOf(QV4::ExecutionEngine, runtime)) +inline Assembler<TargetConfiguration>::RuntimeCall::RuntimeCall(Runtime::RuntimeMethods method) + : addr(Assembler::EngineRegister, + method == Runtime::InvalidRuntimeMethod ? -1 : (Assembler<TargetConfiguration>::targetStructureOffset(offsetof(EngineBase, runtime) + Runtime::runtimeMethodOffset(method)))) { } diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp index 22067bbb13..a1c65f644c 100644 --- a/src/qml/jit/qv4binop.cpp +++ b/src/qml/jit/qv4binop.cpp @@ -165,17 +165,17 @@ struct ArchitectureSpecificBinaryOperation<Assembler<AssemblerTargetConfiguratio #endif #define OP(op) \ - { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, 0, 0, QV4::Runtime::Method_##op##_NeedsExceptionCheck } + { "Runtime::" isel_stringIfy(op), QV4::Runtime::op, QV4::Runtime::InvalidRuntimeMethod, 0, 0, QV4::Runtime::Method_##op##_NeedsExceptionCheck } #define OPCONTEXT(op) \ - { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), 0, 0, QV4::Runtime::Method_##op##_NeedsExceptionCheck } + { "Runtime::" isel_stringIfy(op), QV4::Runtime::InvalidRuntimeMethod, QV4::Runtime::op, 0, 0, QV4::Runtime::Method_##op##_NeedsExceptionCheck } #define INLINE_OP(op, memOp, immOp) \ - { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, memOp, immOp, QV4::Runtime::Method_##op##_NeedsExceptionCheck } + { "Runtime::" isel_stringIfy(op), QV4::Runtime::op, QV4::Runtime::InvalidRuntimeMethod, memOp, immOp, QV4::Runtime::Method_##op##_NeedsExceptionCheck } #define INLINE_OPCONTEXT(op, memOp, immOp) \ - { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), memOp, immOp, QV4::Runtime::Method_##op##_NeedsExceptionCheck } + { "Runtime::" isel_stringIfy(op), QV4::Runtime::InvalidRuntimeMethod, QV4::Runtime::op, memOp, immOp, QV4::Runtime::Method_##op##_NeedsExceptionCheck } #define NULL_OP \ - { 0, 0, 0, 0, 0, false } + { 0, QV4::Runtime::InvalidRuntimeMethod, QV4::Runtime::InvalidRuntimeMethod, 0, 0, false } template <typename JITAssembler> const typename Binop<JITAssembler>::OpInfo Binop<JITAssembler>::operations[IR::LastAluOp + 1] = { @@ -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/qv4binop_p.h b/src/qml/jit/qv4binop_p.h index d2d9ba7753..1b1ab7f24d 100644 --- a/src/qml/jit/qv4binop_p.h +++ b/src/qml/jit/qv4binop_p.h @@ -88,8 +88,8 @@ struct Binop { struct OpInfo { const char *name; - int fallbackImplementation; // offsetOf(Runtime,...) - int contextImplementation; // offsetOf(Runtime,...) + Runtime::RuntimeMethods fallbackImplementation; + Runtime::RuntimeMethods contextImplementation; MemRegOp inlineMemRegOp; ImmRegOp inlineImmRegOp; bool needsExceptionCheck; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index 69d6951bb9..599370f73d 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -132,8 +132,8 @@ void InstructionSelection<JITAssembler>::run(int functionIndex) for (IR::Stmt *s : _block->statements()) { if (s->location.isValid()) { if (int(s->location.startLine) != lastLine) { - _as->loadPtr(Address(JITTargetPlatform::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), JITTargetPlatform::ScratchRegister); - Address lineAddr(JITTargetPlatform::ScratchRegister, qOffsetOf(QV4::ExecutionContext::Data, lineNumber)); + _as->loadPtr(Address(JITTargetPlatform::EngineRegister, JITAssembler::targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ScratchRegister); + Address lineAddr(JITTargetPlatform::ScratchRegister, JITAssembler::targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, lineNumber))); _as->store32(TrustedImm32(s->location.startLine), lineAddr); lastLine = s->location.startLine; } @@ -256,7 +256,7 @@ void InstructionSelection<JITAssembler>::callBuiltinDeleteName(const QString &na template <typename JITAssembler> void InstructionSelection<JITAssembler>::callBuiltinDeleteValue(IR::Expr *result) { - _as->storeValue(Primitive::fromBoolean(false), result); + _as->storeValue(JITAssembler::TargetPrimitive::fromBoolean(false), result); } template <typename JITAssembler> @@ -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(QV4::Primitive::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(QV4::Primitive::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, qOffsetOf(QV4::ExecutionEngine, current)), JITTargetPlatform::ScratchRegister); - _as->loadPtr(Address(JITTargetPlatform::ScratchRegister, qOffsetOf(ExecutionContext::Data, callData)), JITTargetPlatform::ScratchRegister); - _as->copyValue(temp, Address(JITTargetPlatform::ScratchRegister, qOffsetOf(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> @@ -486,7 +488,7 @@ void InstructionSelection<JITAssembler>::loadConst(IR::Const *sourceConst, IR::E _as->toUInt32Register(sourceConst, (RegisterID) targetTemp->index); } else if (targetTemp->type == IR::BoolType) { Q_ASSERT(sourceConst->type == IR::BoolType); - _as->move(TrustedImm32(convertToValue(sourceConst).int_32()), + _as->move(TrustedImm32(convertToValue<Primitive>(sourceConst).int_32()), (RegisterID) targetTemp->index); } else { Q_UNREACHABLE(); @@ -495,7 +497,7 @@ void InstructionSelection<JITAssembler>::loadConst(IR::Const *sourceConst, IR::E } } - _as->storeValue(convertToValue(sourceConst), target); + _as->storeValue(convertToValue<typename JITAssembler::TargetPrimitive>(sourceConst), target); } 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> @@ -519,7 +522,7 @@ void InstructionSelection<JITAssembler>::getActivationProperty(const IR::Name *n { if (useFastLookups && name->global) { uint index = registerGlobalGetterLookup(*name->id); - generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), JITTargetPlatform::EngineRegister, JITAssembler::Void); + generateLookupCall(target, index, offsetof(QV4::Lookup, globalGetter), JITTargetPlatform::EngineRegister, JITAssembler::Void); return; } generateRuntimeCall(_as, target, getActivationProperty, JITTargetPlatform::EngineRegister, StringToIndex(*name->id)); @@ -545,7 +548,7 @@ void InstructionSelection<JITAssembler>::getProperty(IR::Expr *base, const QStri { if (useFastLookups) { uint index = registerGetterLookup(name); - generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), JITTargetPlatform::EngineRegister, PointerToValue(base), JITAssembler::Void); + generateLookupCall(target, index, offsetof(QV4::Lookup, getter), JITTargetPlatform::EngineRegister, PointerToValue(base), JITAssembler::Void); } else { generateRuntimeCall(_as, target, getProperty, JITTargetPlatform::EngineRegister, PointerToValue(base), StringToIndex(name)); @@ -584,7 +587,7 @@ void InstructionSelection<JITAssembler>::setProperty(IR::Expr *source, IR::Expr { if (useFastLookups) { uint index = registerSetterLookup(targetName); - generateLookupCall(JITAssembler::Void, index, qOffsetOf(QV4::Lookup, setter), + generateLookupCall(JITAssembler::Void, index, offsetof(QV4::Lookup, setter), JITTargetPlatform::EngineRegister, PointerToValue(targetBase), PointerToValue(source)); @@ -620,7 +623,8 @@ void InstructionSelection<JITAssembler>::getElement(IR::Expr *base, IR::Expr *in { if (useFastLookups) { uint lookup = registerIndexedGetterLookup(); - generateLookupCall(target, lookup, qOffsetOf(QV4::Lookup, indexedGetter), + generateLookupCall(target, lookup, offsetof(QV4::Lookup, indexedGetter), + JITTargetPlatform::EngineRegister, PointerToValue(base), PointerToValue(index)); return; @@ -635,7 +639,8 @@ void InstructionSelection<JITAssembler>::setElement(IR::Expr *source, IR::Expr * { if (useFastLookups) { uint lookup = registerIndexedSetterLookup(); - generateLookupCall(JITAssembler::Void, lookup, qOffsetOf(QV4::Lookup, indexedSetter), + 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); @@ -774,16 +781,17 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr * quint32 tag; switch (regTemp->type) { case IR::BoolType: - tag = QV4::Value::Boolean_Type_Internal; + tag = quint32(JITAssembler::ValueTypeInternal::Boolean); break; case IR::SInt32Type: - tag = QV4::Value::Integer_Type_Internal; + tag = quint32(JITAssembler::ValueTypeInternal::Integer); break; default: tag = 31337; // bogus value Q_UNREACHABLE(); } _as->store32(TrustedImm32(tag), addr); + _as->emitWriteBarrier(addr, barrier); } _as->move(JITTargetPlatform::ScratchRegister, (RegisterID) regTemp->index); } @@ -791,12 +799,12 @@ void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr * #define setOp(op, opName, operation) \ do { \ - op = typename JITAssembler::RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \ + op = typename JITAssembler::RuntimeCall(QV4::Runtime::operation); opName = "Runtime::" isel_stringIfy(operation); \ needsExceptionCheck = QV4::Runtime::Method_##operation##_NeedsExceptionCheck; \ } while (0) #define setOpContext(op, opName, operation) \ do { \ - opContext = typename JITAssembler::RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \ + opContext = typename JITAssembler::RuntimeCall(QV4::Runtime::operation); opName = "Runtime::" isel_stringIfy(operation); \ needsExceptionCheck = QV4::Runtime::Method_##operation##_NeedsExceptionCheck; \ } while (0) @@ -913,19 +921,19 @@ 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); // check if it's an int32: Jump isNoInt = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister, - TrustedImm32(Value::Integer_Type_Internal)); + TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer))); convertIntToDouble(source, target); Jump intDone = _as->jump(); @@ -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); @@ -996,20 +1004,20 @@ void InstructionSelection<JITAssembler>::convertTypeToBool(IR::Expr *source, IR: _as->storeBool(JITTargetPlatform::ReturnValueRegister, target); 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); // checkif it's a bool: Jump notBool = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ReturnValueRegister, - TrustedImm32(Value::Boolean_Type_Internal)); + TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Boolean))); _as->load32(addr, JITTargetPlatform::ReturnValueRegister); Jump boolDone = _as->jump(); // check if it's an int32: notBool.link(_as); Jump fallback = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ReturnValueRegister, - TrustedImm32(Value::Integer_Type_Internal)); + TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer))); _as->load32(addr, JITTargetPlatform::ReturnValueRegister); Jump isZero = _as->branch32(RelationalCondition::Equal, JITTargetPlatform::ReturnValueRegister, TrustedImm32(0)); @@ -1061,7 +1069,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) @@ -1073,21 +1081,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(Value::Integer_Type_Internal)); - Pointer addr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source); + TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer))); + 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); @@ -1192,10 +1200,11 @@ 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, TrustedImm32(QV4::Value::Boolean_Type_Internal)); + Jump booleanConversion = _as->branch32(RelationalCondition::NotEqual, tag, + TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Boolean))); Address data = temp; data.offset += QV4::Value::valueOffset(); @@ -1297,9 +1306,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; @@ -1313,15 +1322,15 @@ int InstructionSelection<JITAssembler>::prepareCallData(IR::ExprList* args, IR:: ++argc; } - Pointer p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, tag)); - _as->store32(TrustedImm32(QV4::Value::Integer_Type_Internal), p); - p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, argc)); + Pointer p = _as->stackLayout().callDataAddress(offsetof(CallData, tag)); + _as->store32(TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Integer)), p); + p = _as->stackLayout().callDataAddress(offsetof(CallData, argc)); _as->store32(TrustedImm32(argc), p); - p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, thisObject)); + p = _as->stackLayout().callDataAddress(offsetof(CallData, thisObject)); if (!thisObject) - _as->storeValue(QV4::Primitive::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) { @@ -1329,9 +1338,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; } @@ -1449,14 +1458,14 @@ 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); RelationalCondition cond = binop->op == IR::OpStrictEqual ? RelationalCondition::Equal : RelationalCondition::NotEqual; - const TrustedImm32 tag(QV4::Value::Null_Type_Internal); + const TrustedImm32 tag{quint32(JITAssembler::ValueTypeInternal::Null)}; _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock); return true; } @@ -1532,13 +1541,13 @@ 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' _as->load32(otherAddr, JITTargetPlatform::ScratchRegister); Jump noBool = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister, - TrustedImm32(QV4::Value::Boolean_Type_Internal)); + TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Boolean))); if (binop->op == IR::OpStrictEqual) _as->addPatch(falseBlock, noBool); else @@ -1581,14 +1590,14 @@ 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); if (binop->op == IR::OpNotEqual) qSwap(trueBlock, falseBlock); - Jump isNull = _as->branch32(RelationalCondition::Equal, tagReg, TrustedImm32(int(QV4::Value::Null_Type_Internal))); + Jump isNull = _as->branch32(RelationalCondition::Equal, tagReg, TrustedImm32(quint32(JITAssembler::ValueTypeInternal::Null))); Jump isNotUndefinedTag = _as->branch32(RelationalCondition::NotEqual, tagReg, TrustedImm32(int(QV4::Value::Managed_Type_Internal))); tagAddr.offset -= 4; _as->load32(tagAddr, tagReg); @@ -1640,18 +1649,18 @@ Q_QML_EXPORT QV4::EvalISelFactory *createISelForArchitecture(const QString &arch using ARMv7CrossAssembler = QV4::JIT::Assembler<AssemblerTargetConfiguration<JSC::MacroAssemblerARMv7, NoOperatingSystemSpecialization>>; using ARM64CrossAssembler = QV4::JIT::Assembler<AssemblerTargetConfiguration<JSC::MacroAssemblerARM64, NoOperatingSystemSpecialization>>; - if (architecture == QLatin1String("armv7")) + if (architecture == QLatin1String("arm")) return new ISelFactory<ARMv7CrossAssembler>; - else if (architecture == QLatin1String("armv8")) + else if (architecture == QLatin1String("arm64")) return new ISelFactory<ARM64CrossAssembler>; QString hostArch; #if CPU(ARM_THUMB2) - hostArch = QStringLiteral("armv7"); + hostArch = QStringLiteral("arm"); #elif CPU(MIPS) hostArch = QStringLiteral("mips"); #elif CPU(X86) - hostArch = QStringLiteral("x86"); + hostArch = QStringLiteral("i386"); #elif CPU(X86_64) hostArch = QStringLiteral("x86_64"); #endif diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 5c046cb397..7019a117a2 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -160,7 +160,7 @@ protected: // FramePointerRegister points to its old value on the stack, and above // it we have the return address, hence the need to step over two // values before reaching the first argument. - return Address(JITTargetPlatform::FramePointerRegister, (index + 2) * sizeof(void*)); + return Address(JITTargetPlatform::FramePointerRegister, (index + 2) * JITTargetPlatform::RegisterSize); } Pointer baseAddressForCallArguments() @@ -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; diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h index d9f8034b1f..6d788f4a93 100644 --- a/src/qml/jit/qv4targetplatform_p.h +++ b/src/qml/jit/qv4targetplatform_p.h @@ -370,7 +370,7 @@ public: // There are two designated frame-pointer registers on ARM, depending on which instruction set // is used for the subroutine: r7 for Thumb or Thumb2, and r11 for ARM. We assign the constants // accordingly, and assign the locals-register to the "other" register. -#if CPU(ARM_THUMB2) +#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP) static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7; static const RegisterID LocalsRegister = JSC::ARMRegisters::r11; #else // Thumbs down @@ -397,7 +397,7 @@ public: << RI(JSC::ARMRegisters::r4, QStringLiteral("r4"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) << RI(JSC::ARMRegisters::r5, QStringLiteral("r5"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) << RI(JSC::ARMRegisters::r6, QStringLiteral("r6"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) -#if !CPU(ARM_THUMB2) +#if !CPU(ARM_THUMB2) && !defined(V4_BOOTSTRAP) << RI(JSC::ARMRegisters::r7, QStringLiteral("r7"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) #endif << RI(JSC::ARMRegisters::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) @@ -405,7 +405,7 @@ public: << RI(JSC::ARMRegisters::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc) #endif << RI(JSC::ARMRegisters::r10, QStringLiteral("r10"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) -#if CPU(ARM_THUMB2) +#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP) << RI(JSC::ARMRegisters::r11, QStringLiteral("r11"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined) #endif << RI(JSC::ARMRegisters::d2, QStringLiteral("d2"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc) diff --git a/src/qml/jit/qv4unop.cpp b/src/qml/jit/qv4unop.cpp index 76c6457d67..896be07ed5 100644 --- a/src/qml/jit/qv4unop.cpp +++ b/src/qml/jit/qv4unop.cpp @@ -48,7 +48,7 @@ using namespace JIT; #define stringIfy(s) stringIfyx(s) #define setOp(operation) \ do { \ - call = typename JITAssembler::RuntimeCall(qOffsetOf(QV4::Runtime, operation)); name = "Runtime::" stringIfy(operation); \ + call = typename JITAssembler::RuntimeCall(QV4::Runtime::operation); name = "Runtime::" stringIfy(operation); \ needsExceptionCheck = Runtime::Method_##operation##_NeedsExceptionCheck; \ } while (0) |