diff options
Diffstat (limited to 'src/qml/jit/qv4assembler.cpp')
-rw-r--r-- | src/qml/jit/qv4assembler.cpp | 98 |
1 files changed, 55 insertions, 43 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); } |