aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit/qv4assembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jit/qv4assembler.cpp')
-rw-r--r--src/qml/jit/qv4assembler.cpp98
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);
}