aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit/qv4isel_masm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jit/qv4isel_masm.cpp')
-rw-r--r--src/qml/jit/qv4isel_masm.cpp1201
1 files changed, 522 insertions, 679 deletions
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 20752b5c34..69d6951bb9 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -39,11 +39,7 @@
#include "qv4isel_masm_p.h"
#include "qv4runtime_p.h"
-#include "qv4object_p.h"
-#include "qv4functionobject_p.h"
-#include "qv4regexpobject_p.h"
#include "qv4lookup_p.h"
-#include "qv4function_p.h"
#include "qv4ssa_p.h"
#include "qv4regalloc_p.h"
#include "qv4assembler_p.h"
@@ -68,7 +64,8 @@ using namespace QV4;
using namespace QV4::JIT;
-InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
+template <typename JITAssembler>
+InstructionSelection<JITAssembler>::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, IR::Module *module, Compiler::JSUnitGenerator *jsGenerator, EvalISelFactory *iselFactory)
: EvalInstructionSelection(execAllocator, module, jsGenerator, iselFactory)
, _block(0)
, _as(0)
@@ -79,12 +76,14 @@ InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::Ex
module->unitFlags |= QV4::CompiledData::Unit::ContainsMachineCode;
}
-InstructionSelection::~InstructionSelection()
+template <typename JITAssembler>
+InstructionSelection<JITAssembler>::~InstructionSelection()
{
delete _as;
}
-void InstructionSelection::run(int functionIndex)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::run(int functionIndex)
{
IR::Function *function = irModule->functions[functionIndex];
qSwap(_function, function);
@@ -93,8 +92,8 @@ void InstructionSelection::run(int functionIndex)
opt.run(qmlEngine);
static const bool withRegisterAllocator = qEnvironmentVariableIsEmpty("QV4_NO_REGALLOC");
- if (Assembler::RegAllocIsSupported && opt.isInSSA() && withRegisterAllocator) {
- RegisterAllocator regalloc(Assembler::getRegisterInfo());
+ if (JITTargetPlatform::RegAllocIsSupported && opt.isInSSA() && withRegisterAllocator) {
+ RegisterAllocator regalloc(JITTargetPlatform::getRegisterInfo());
regalloc.run(_function, opt);
calculateRegistersToSave(regalloc.usedRegisters());
} else {
@@ -103,49 +102,24 @@ void InstructionSelection::run(int functionIndex)
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
IR::Optimizer::showMeTheCode(_function, "After stack slot allocation");
- calculateRegistersToSave(Assembler::getRegisterInfo()); // FIXME: this saves all registers. We can probably do with a subset: those that are not used by the register allocator.
+ calculateRegistersToSave(JITTargetPlatform::getRegisterInfo()); // FIXME: this saves all registers. We can probably do with a subset: those that are not used by the register allocator.
}
BitVector removableJumps = opt.calculateOptionalJumps();
qSwap(_removableJumps, removableJumps);
- Assembler* oldAssembler = _as;
- _as = new Assembler(jsGenerator, _function, executableAllocator);
+ JITAssembler* oldAssembler = _as;
+ _as = new JITAssembler(jsGenerator, _function, executableAllocator);
_as->setStackLayout(6, // 6 == max argc for calls to built-ins with an argument array
regularRegistersToSave.size(),
fpRegistersToSave.size());
_as->enterStandardStackFrame(regularRegistersToSave, fpRegistersToSave);
-#ifdef ARGUMENTS_IN_REGISTERS
- _as->move(_as->registerForArgument(0), Assembler::EngineRegister);
-#else
- _as->loadPtr(addressForArgument(0), Assembler::EngineRegister);
-#endif
-
- const int locals = _as->stackLayout().calculateJSStackFrameSize();
- if (locals > 0) {
- _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
-#ifdef VALUE_FITS_IN_REGISTER
- _as->move(Assembler::TrustedImm64(0), Assembler::ReturnValueRegister);
- _as->move(Assembler::TrustedImm32(locals), Assembler::ScratchRegister);
- Assembler::Label loop = _as->label();
- _as->store64(Assembler::ReturnValueRegister, Assembler::Address(Assembler::LocalsRegister));
- _as->add64(Assembler::TrustedImm32(8), Assembler::LocalsRegister);
- Assembler::Jump jump = _as->branchSub32(Assembler::NonZero, Assembler::TrustedImm32(1), Assembler::ScratchRegister);
- jump.linkTo(loop, _as);
-#else
- _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
- _as->move(Assembler::TrustedImm32(locals), Assembler::ScratchRegister);
- Assembler::Label loop = _as->label();
- _as->store32(Assembler::ReturnValueRegister, Assembler::Address(Assembler::LocalsRegister));
- _as->add32(Assembler::TrustedImm32(4), Assembler::LocalsRegister);
- _as->store32(Assembler::ReturnValueRegister, Assembler::Address(Assembler::LocalsRegister));
- _as->add32(Assembler::TrustedImm32(4), Assembler::LocalsRegister);
- Assembler::Jump jump = _as->branchSub32(Assembler::NonZero, Assembler::TrustedImm32(1), Assembler::ScratchRegister);
- jump.linkTo(loop, _as);
-#endif
- _as->storePtr(Assembler::LocalsRegister, Address(Assembler::EngineRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
- }
+ if (JITTargetPlatform::RegisterArgumentCount > 0)
+ _as->move(_as->registerForArgument(0), JITTargetPlatform::EngineRegister);
+ else
+ _as->loadPtr(addressForArgument(0), JITTargetPlatform::EngineRegister);
+ _as->initializeLocalVariables();
int lastLine = 0;
for (int i = 0, ei = _function->basicBlockCount(); i != ei; ++i) {
@@ -158,9 +132,9 @@ void InstructionSelection::run(int functionIndex)
for (IR::Stmt *s : _block->statements()) {
if (s->location.isValid()) {
if (int(s->location.startLine) != lastLine) {
- _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
- Assembler::Address lineAddr(Assembler::ScratchRegister, qOffsetOf(QV4::ExecutionContext::Data, lineNumber));
- _as->store32(Assembler::TrustedImm32(s->location.startLine), lineAddr);
+ _as->loadPtr(Address(JITTargetPlatform::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), JITTargetPlatform::ScratchRegister);
+ Address lineAddr(JITTargetPlatform::ScratchRegister, qOffsetOf(QV4::ExecutionContext::Data, lineNumber));
+ _as->store32(TrustedImm32(s->location.startLine), lineAddr);
lastLine = s->location.startLine;
}
}
@@ -181,165 +155,187 @@ void InstructionSelection::run(int functionIndex)
qSwap(_removableJumps, removableJumps);
}
-QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection::backendCompileStep()
+template <typename JITAssembler>
+QQmlRefPointer<QV4::CompiledData::CompilationUnit> InstructionSelection<JITAssembler>::backendCompileStep()
{
QQmlRefPointer<QV4::CompiledData::CompilationUnit> result;
result.adopt(compilationUnit.take());
return result;
}
-void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
prepareCallData(args, 0);
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
- generateRuntimeCall(result, callGlobalLookup,
- Assembler::EngineRegister,
- Assembler::TrustedImm32(index),
+ generateRuntimeCall(_as, result, callGlobalLookup,
+ JITTargetPlatform::EngineRegister,
+ TrustedImm32(index),
baseAddressForCallData());
} else {
- generateRuntimeCall(result, callActivationProperty,
- Assembler::EngineRegister,
- Assembler::StringToIndex(*func->id),
+ generateRuntimeCall(_as, result, callActivationProperty,
+ JITTargetPlatform::EngineRegister,
+ StringToIndex(*func->id),
baseAddressForCallData());
}
}
-void InstructionSelection::callBuiltinTypeofQmlContextProperty(IR::Expr *base,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinTypeofQmlContextProperty(IR::Expr *base,
IR::Member::MemberKind kind,
int propertyIndex, IR::Expr *result)
{
if (kind == IR::Member::MemberOfQmlScopeObject) {
- generateRuntimeCall(result, typeofScopeObjectProperty, Assembler::EngineRegister,
- Assembler::PointerToValue(base),
- Assembler::TrustedImm32(propertyIndex));
+ generateRuntimeCall(_as, result, typeofScopeObjectProperty, JITTargetPlatform::EngineRegister,
+ PointerToValue(base),
+ TrustedImm32(propertyIndex));
} else if (kind == IR::Member::MemberOfQmlContextObject) {
- generateRuntimeCall(result, typeofContextObjectProperty,
- Assembler::EngineRegister, Assembler::PointerToValue(base),
- Assembler::TrustedImm32(propertyIndex));
+ generateRuntimeCall(_as, result, typeofContextObjectProperty,
+ JITTargetPlatform::EngineRegister, PointerToValue(base),
+ TrustedImm32(propertyIndex));
} else {
Q_UNREACHABLE();
}
}
-void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
IR::Expr *result)
{
- generateRuntimeCall(result, typeofMember, Assembler::EngineRegister,
- Assembler::PointerToValue(base), Assembler::StringToIndex(name));
+ generateRuntimeCall(_as, result, typeofMember, JITTargetPlatform::EngineRegister,
+ PointerToValue(base), StringToIndex(name));
}
-void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
IR::Expr *result)
{
- generateRuntimeCall(result, typeofElement,
- Assembler::EngineRegister,
- Assembler::PointerToValue(base), Assembler::PointerToValue(index));
+ generateRuntimeCall(_as, result, typeofElement,
+ JITTargetPlatform::EngineRegister,
+ PointerToValue(base), PointerToValue(index));
}
-void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinTypeofName(const QString &name, IR::Expr *result)
{
- generateRuntimeCall(result, typeofName, Assembler::EngineRegister,
- Assembler::StringToIndex(name));
+ generateRuntimeCall(_as, result, typeofName, JITTargetPlatform::EngineRegister,
+ StringToIndex(name));
}
-void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result)
{
- generateRuntimeCall(result, typeofValue, Assembler::EngineRegister,
- Assembler::PointerToValue(value));
+ generateRuntimeCall(_as, result, typeofValue, JITTargetPlatform::EngineRegister,
+ PointerToValue(value));
}
-void InstructionSelection::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result)
{
- generateRuntimeCall(result, deleteMember, Assembler::EngineRegister,
- Assembler::Reference(base), Assembler::StringToIndex(name));
+ generateRuntimeCall(_as, result, deleteMember, JITTargetPlatform::EngineRegister,
+ Reference(base), StringToIndex(name));
}
-void InstructionSelection::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index,
IR::Expr *result)
{
- generateRuntimeCall(result, deleteElement, Assembler::EngineRegister,
- Assembler::Reference(base), Assembler::PointerToValue(index));
+ generateRuntimeCall(_as, result, deleteElement, JITTargetPlatform::EngineRegister,
+ Reference(base), PointerToValue(index));
}
-void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinDeleteName(const QString &name, IR::Expr *result)
{
- generateRuntimeCall(result, deleteName, Assembler::EngineRegister,
- Assembler::StringToIndex(name));
+ generateRuntimeCall(_as, result, deleteName, JITTargetPlatform::EngineRegister,
+ StringToIndex(name));
}
-void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinDeleteValue(IR::Expr *result)
{
_as->storeValue(Primitive::fromBoolean(false), result);
}
-void InstructionSelection::callBuiltinThrow(IR::Expr *arg)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinThrow(IR::Expr *arg)
{
- generateRuntimeCall(Assembler::ReturnValueRegister, throwException, Assembler::EngineRegister,
- Assembler::PointerToValue(arg));
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, throwException, JITTargetPlatform::EngineRegister,
+ PointerToValue(arg));
}
-void InstructionSelection::callBuiltinReThrow()
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinReThrow()
{
_as->jumpToExceptionHandler();
}
-void InstructionSelection::callBuiltinUnwindException(IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinUnwindException(IR::Expr *result)
{
- generateRuntimeCall(result, unwindException, Assembler::EngineRegister);
+ generateRuntimeCall(_as, result, unwindException, JITTargetPlatform::EngineRegister);
}
-void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionName)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinPushCatchScope(const QString &exceptionName)
{
- generateRuntimeCall(Assembler::Void, pushCatchScope, Assembler::EngineRegister, Assembler::StringToIndex(exceptionName));
+ generateRuntimeCall(_as, JITAssembler::Void, pushCatchScope, JITTargetPlatform::EngineRegister, StringToIndex(exceptionName));
}
-void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result)
{
Q_ASSERT(arg);
Q_ASSERT(result);
- generateRuntimeCall(result, foreachIterator, Assembler::EngineRegister, Assembler::PointerToValue(arg));
+ generateRuntimeCall(_as, result, foreachIterator, JITTargetPlatform::EngineRegister, PointerToValue(arg));
}
-void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result)
{
Q_ASSERT(arg);
Q_ASSERT(result);
- generateRuntimeCall(result, foreachNextPropertyName, Assembler::Reference(arg));
+ generateRuntimeCall(_as, result, foreachNextPropertyName, Reference(arg));
}
-void InstructionSelection::callBuiltinPushWithScope(IR::Expr *arg)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinPushWithScope(IR::Expr *arg)
{
Q_ASSERT(arg);
- generateRuntimeCall(Assembler::Void, pushWithScope, Assembler::Reference(arg), Assembler::EngineRegister);
+ generateRuntimeCall(_as, JITAssembler::Void, pushWithScope, Reference(arg), JITTargetPlatform::EngineRegister);
}
-void InstructionSelection::callBuiltinPopScope()
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinPopScope()
{
- generateRuntimeCall(Assembler::Void, popScope, Assembler::EngineRegister);
+ generateRuntimeCall(_as, JITAssembler::Void, popScope, JITTargetPlatform::EngineRegister);
}
-void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinDeclareVar(bool deletable, const QString &name)
{
- generateRuntimeCall(Assembler::Void, declareVar, Assembler::EngineRegister,
- Assembler::TrustedImm32(deletable), Assembler::StringToIndex(name));
+ generateRuntimeCall(_as, JITAssembler::Void, declareVar, JITTargetPlatform::EngineRegister,
+ TrustedImm32(deletable), StringToIndex(name));
}
-void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args)
{
Q_ASSERT(result);
int length = prepareVariableArguments(args);
- generateRuntimeCall(result, arrayLiteral, Assembler::EngineRegister,
- baseAddressForCallArguments(), Assembler::TrustedImm32(length));
+ generateRuntimeCall(_as, result, arrayLiteral, JITTargetPlatform::EngineRegister,
+ baseAddressForCallArguments(), TrustedImm32(length));
}
-void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinDefineObjectLiteral(IR::Expr *result, int keyValuePairCount, IR::ExprList *keyValuePairs, IR::ExprList *arrayEntries, bool needSparseArray)
{
Q_ASSERT(result);
@@ -415,81 +411,83 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int
it = it->next;
}
- generateRuntimeCall(result, objectLiteral, Assembler::EngineRegister,
- baseAddressForCallArguments(), Assembler::TrustedImm32(classId),
- Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount | (needSparseArray << 30)));
+ generateRuntimeCall(_as, result, objectLiteral, JITTargetPlatform::EngineRegister,
+ baseAddressForCallArguments(), TrustedImm32(classId),
+ TrustedImm32(arrayValueCount), TrustedImm32(arrayGetterSetterCount | (needSparseArray << 30)));
}
-void InstructionSelection::callBuiltinSetupArgumentObject(IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinSetupArgumentObject(IR::Expr *result)
{
- generateRuntimeCall(result, setupArgumentsObject, Assembler::EngineRegister);
+ generateRuntimeCall(_as, result, setupArgumentsObject, JITTargetPlatform::EngineRegister);
}
-void InstructionSelection::callBuiltinConvertThisToObject()
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callBuiltinConvertThisToObject()
{
- generateRuntimeCall(Assembler::Void, convertThisToObject, Assembler::EngineRegister);
+ generateRuntimeCall(_as, JITAssembler::Void, convertThisToObject, JITTargetPlatform::EngineRegister);
}
-void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(value);
prepareCallData(args, 0);
if (value->asConst())
- generateRuntimeCall(result, callValue, Assembler::EngineRegister,
- Assembler::PointerToValue(value),
+ generateRuntimeCall(_as, result, callValue, JITTargetPlatform::EngineRegister,
+ PointerToValue(value),
baseAddressForCallData());
else
- generateRuntimeCall(result, callValue, Assembler::EngineRegister,
- Assembler::Reference(value),
+ generateRuntimeCall(_as, result, callValue, JITTargetPlatform::EngineRegister,
+ Reference(value),
baseAddressForCallData());
}
-void InstructionSelection::loadThisObject(IR::Expr *temp)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::loadThisObject(IR::Expr *temp)
{
- _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
- _as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionContext::Data, callData)), Assembler::ScratchRegister);
-#if defined(VALUE_FITS_IN_REGISTER)
- _as->load64(Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)),
- Assembler::ReturnValueRegister);
- _as->storeReturnValue(temp);
-#else
- _as->copyValue(temp, Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)));
-#endif
+ _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)));
}
-void InstructionSelection::loadQmlContext(IR::Expr *temp)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::loadQmlContext(IR::Expr *temp)
{
- generateRuntimeCall(temp, getQmlContext, Assembler::EngineRegister);
+ generateRuntimeCall(_as, temp, getQmlContext, JITTargetPlatform::EngineRegister);
}
-void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::loadQmlImportedScripts(IR::Expr *temp)
{
- generateRuntimeCall(temp, getQmlImportedScripts, Assembler::EngineRegister);
+ generateRuntimeCall(_as, temp, getQmlImportedScripts, JITTargetPlatform::EngineRegister);
}
-void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::loadQmlSingleton(const QString &name, IR::Expr *temp)
{
- generateRuntimeCall(temp, getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name));
+ generateRuntimeCall(_as, temp, getQmlSingleton, JITTargetPlatform::EngineRegister, StringToIndex(name));
}
-void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::loadConst(IR::Const *sourceConst, IR::Expr *target)
{
if (IR::Temp *targetTemp = target->asTemp()) {
if (targetTemp->kind == IR::Temp::PhysicalRegister) {
if (targetTemp->type == IR::DoubleType) {
Q_ASSERT(sourceConst->type == IR::DoubleType);
- _as->toDoubleRegister(sourceConst, (Assembler::FPRegisterID) targetTemp->index);
+ _as->toDoubleRegister(sourceConst, (FPRegisterID) targetTemp->index);
} else if (targetTemp->type == IR::SInt32Type) {
Q_ASSERT(sourceConst->type == IR::SInt32Type);
- _as->toInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ _as->toInt32Register(sourceConst, (RegisterID) targetTemp->index);
} else if (targetTemp->type == IR::UInt32Type) {
Q_ASSERT(sourceConst->type == IR::UInt32Type);
- _as->toUInt32Register(sourceConst, (Assembler::RegisterID) targetTemp->index);
+ _as->toUInt32Register(sourceConst, (RegisterID) targetTemp->index);
} else if (targetTemp->type == IR::BoolType) {
Q_ASSERT(sourceConst->type == IR::BoolType);
- _as->move(Assembler::TrustedImm32(convertToValue(sourceConst).int_32()),
- (Assembler::RegisterID) targetTemp->index);
+ _as->move(TrustedImm32(convertToValue(sourceConst).int_32()),
+ (RegisterID) targetTemp->index);
} else {
Q_UNREACHABLE();
}
@@ -500,147 +498,155 @@ void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
_as->storeValue(convertToValue(sourceConst), target);
}
-void InstructionSelection::loadString(const QString &str, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::loadString(const QString &str, IR::Expr *target)
{
- Pointer srcAddr = _as->loadStringAddress(Assembler::ReturnValueRegister, str);
- _as->loadPtr(srcAddr, Assembler::ReturnValueRegister);
- Pointer destAddr = _as->loadAddress(Assembler::ScratchRegister, target);
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- _as->store64(Assembler::ReturnValueRegister, destAddr);
-#else
- _as->store32(Assembler::ReturnValueRegister, destAddr);
- destAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(QV4::Value::Managed_Type_Internal), destAddr);
-#endif
+ 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);
}
-void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target)
{
int id = registerRegExp(sourceRegexp);
- generateRuntimeCall(target, regexpLiteral, Assembler::EngineRegister, Assembler::TrustedImm32(id));
+ generateRuntimeCall(_as, target, regexpLiteral, JITTargetPlatform::EngineRegister, TrustedImm32(id));
}
-void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
if (useFastLookups && name->global) {
uint index = registerGlobalGetterLookup(*name->id);
- generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::EngineRegister, Assembler::Void);
+ generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), JITTargetPlatform::EngineRegister, JITAssembler::Void);
return;
}
- generateRuntimeCall(target, getActivationProperty, Assembler::EngineRegister, Assembler::StringToIndex(*name->id));
+ generateRuntimeCall(_as, target, getActivationProperty, JITTargetPlatform::EngineRegister, StringToIndex(*name->id));
}
-void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::setActivationProperty(IR::Expr *source, const QString &targetName)
{
// ### should use a lookup call here
- generateRuntimeCall(Assembler::Void, setActivationProperty,
- Assembler::EngineRegister, Assembler::StringToIndex(targetName), Assembler::PointerToValue(source));
+ generateRuntimeCall(_as, JITAssembler::Void, setActivationProperty,
+ JITTargetPlatform::EngineRegister, StringToIndex(targetName), PointerToValue(source));
}
-void InstructionSelection::initClosure(IR::Closure *closure, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::initClosure(IR::Closure *closure, IR::Expr *target)
{
int id = closure->value;
- generateRuntimeCall(target, closure, Assembler::EngineRegister, Assembler::TrustedImm32(id));
+ generateRuntimeCall(_as, target, closure, JITTargetPlatform::EngineRegister, TrustedImm32(id));
}
-void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::getProperty(IR::Expr *base, const QString &name, IR::Expr *target)
{
if (useFastLookups) {
uint index = registerGetterLookup(name);
- generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::Void);
+ generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), JITTargetPlatform::EngineRegister, PointerToValue(base), JITAssembler::Void);
} else {
- generateRuntimeCall(target, getProperty, Assembler::EngineRegister,
- Assembler::PointerToValue(base), Assembler::StringToIndex(name));
+ generateRuntimeCall(_as, target, getProperty, JITTargetPlatform::EngineRegister,
+ PointerToValue(base), StringToIndex(name));
}
}
-void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, bool captureRequired, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, bool captureRequired, IR::Expr *target)
{
if (kind == IR::Member::MemberOfQmlScopeObject)
- generateRuntimeCall(target, getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index), Assembler::TrustedImm32(captureRequired));
+ generateRuntimeCall(_as, target, getQmlScopeObjectProperty, JITTargetPlatform::EngineRegister, PointerToValue(base), TrustedImm32(index), TrustedImm32(captureRequired));
else if (kind == IR::Member::MemberOfQmlContextObject)
- generateRuntimeCall(target, getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index), Assembler::TrustedImm32(captureRequired));
+ generateRuntimeCall(_as, target, getQmlContextObjectProperty, JITTargetPlatform::EngineRegister, PointerToValue(base), TrustedImm32(index), TrustedImm32(captureRequired));
else if (kind == IR::Member::MemberOfIdObjectsArray)
- generateRuntimeCall(target, getQmlIdObject, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index));
+ generateRuntimeCall(_as, target, getQmlIdObject, JITTargetPlatform::EngineRegister, PointerToValue(base), TrustedImm32(index));
else
Q_ASSERT(false);
}
-void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0)
- generateRuntimeCall(target, getQmlAttachedProperty, Assembler::EngineRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
+ generateRuntimeCall(_as, target, getQmlAttachedProperty, JITTargetPlatform::EngineRegister, TrustedImm32(attachedPropertiesId), TrustedImm32(propertyIndex));
else if (isSingleton)
- generateRuntimeCall(target, getQmlSingletonQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
- Assembler::TrustedImm32(captureRequired));
+ generateRuntimeCall(_as, target, getQmlSingletonQObjectProperty, JITTargetPlatform::EngineRegister, PointerToValue(base), TrustedImm32(propertyIndex),
+ TrustedImm32(captureRequired));
else
- generateRuntimeCall(target, getQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
- Assembler::TrustedImm32(captureRequired));
+ generateRuntimeCall(_as, target, getQmlQObjectProperty, JITTargetPlatform::EngineRegister, PointerToValue(base), TrustedImm32(propertyIndex),
+ TrustedImm32(captureRequired));
}
-void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::setProperty(IR::Expr *source, IR::Expr *targetBase,
const QString &targetName)
{
if (useFastLookups) {
uint index = registerSetterLookup(targetName);
- generateLookupCall(Assembler::Void, index, qOffsetOf(QV4::Lookup, setter),
- Assembler::EngineRegister,
- Assembler::PointerToValue(targetBase),
- Assembler::PointerToValue(source));
+ generateLookupCall(JITAssembler::Void, index, qOffsetOf(QV4::Lookup, setter),
+ JITTargetPlatform::EngineRegister,
+ PointerToValue(targetBase),
+ PointerToValue(source));
} else {
- generateRuntimeCall(Assembler::Void, setProperty, Assembler::EngineRegister,
- Assembler::PointerToValue(targetBase), Assembler::StringToIndex(targetName),
- Assembler::PointerToValue(source));
+ generateRuntimeCall(_as, JITAssembler::Void, setProperty, JITTargetPlatform::EngineRegister,
+ PointerToValue(targetBase), StringToIndex(targetName),
+ PointerToValue(source));
}
}
-void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex)
{
if (kind == IR::Member::MemberOfQmlScopeObject)
- generateRuntimeCall(Assembler::Void, setQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
- Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ generateRuntimeCall(_as, JITAssembler::Void, setQmlScopeObjectProperty, JITTargetPlatform::EngineRegister, PointerToValue(targetBase),
+ TrustedImm32(propertyIndex), PointerToValue(source));
else if (kind == IR::Member::MemberOfQmlContextObject)
- generateRuntimeCall(Assembler::Void, setQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
- Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ generateRuntimeCall(_as, JITAssembler::Void, setQmlContextObjectProperty, JITTargetPlatform::EngineRegister, PointerToValue(targetBase),
+ TrustedImm32(propertyIndex), PointerToValue(source));
else
Q_ASSERT(false);
}
-void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
- generateRuntimeCall(Assembler::Void, setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
- Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
+ generateRuntimeCall(_as, JITAssembler::Void, setQmlQObjectProperty, JITTargetPlatform::EngineRegister, PointerToValue(targetBase),
+ TrustedImm32(propertyIndex), PointerToValue(source));
}
-void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target)
{
if (useFastLookups) {
uint lookup = registerIndexedGetterLookup();
generateLookupCall(target, lookup, qOffsetOf(QV4::Lookup, indexedGetter),
- Assembler::PointerToValue(base),
- Assembler::PointerToValue(index));
+ PointerToValue(base),
+ PointerToValue(index));
return;
}
- generateRuntimeCall(target, getElement, Assembler::EngineRegister,
- Assembler::PointerToValue(base), Assembler::PointerToValue(index));
+ generateRuntimeCall(_as, target, getElement, JITTargetPlatform::EngineRegister,
+ PointerToValue(base), PointerToValue(index));
}
-void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex)
{
if (useFastLookups) {
uint lookup = registerIndexedSetterLookup();
- generateLookupCall(Assembler::Void, lookup, qOffsetOf(QV4::Lookup, indexedSetter),
- Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
- Assembler::PointerToValue(source));
+ generateLookupCall(JITAssembler::Void, lookup, qOffsetOf(QV4::Lookup, indexedSetter),
+ PointerToValue(targetBase), PointerToValue(targetIndex),
+ PointerToValue(source));
return;
}
- generateRuntimeCall(Assembler::Void, setElement, Assembler::EngineRegister,
- Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
- Assembler::PointerToValue(source));
+ generateRuntimeCall(_as, JITAssembler::Void, setElement, JITTargetPlatform::EngineRegister,
+ PointerToValue(targetBase), PointerToValue(targetIndex),
+ PointerToValue(source));
}
-void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::copyValue(IR::Expr *source, IR::Expr *target)
{
IR::Temp *sourceTemp = source->asTemp();
IR::Temp *targetTemp = target->asTemp();
@@ -655,25 +661,25 @@ void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister) {
if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) {
if (sourceTemp->type == IR::DoubleType)
- _as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
- (Assembler::FPRegisterID) targetTemp->index);
+ _as->moveDouble((FPRegisterID) sourceTemp->index,
+ (FPRegisterID) targetTemp->index);
else
- _as->move((Assembler::RegisterID) sourceTemp->index,
- (Assembler::RegisterID) targetTemp->index);
+ _as->move((RegisterID) sourceTemp->index,
+ (RegisterID) targetTemp->index);
return;
} else {
switch (sourceTemp->type) {
case IR::DoubleType:
- _as->storeDouble((Assembler::FPRegisterID) sourceTemp->index, target);
+ _as->storeDouble((FPRegisterID) sourceTemp->index, target);
break;
case IR::SInt32Type:
- _as->storeInt32((Assembler::RegisterID) sourceTemp->index, target);
+ _as->storeInt32((RegisterID) sourceTemp->index, target);
break;
case IR::UInt32Type:
- _as->storeUInt32((Assembler::RegisterID) sourceTemp->index, target);
+ _as->storeUInt32((RegisterID) sourceTemp->index, target);
break;
case IR::BoolType:
- _as->storeBool((Assembler::RegisterID) sourceTemp->index, target);
+ _as->storeBool((RegisterID) sourceTemp->index, target);
break;
default:
Q_ASSERT(!"Unreachable");
@@ -685,19 +691,19 @@ void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
switch (targetTemp->type) {
case IR::DoubleType:
Q_ASSERT(source->type == IR::DoubleType);
- _as->toDoubleRegister(source, (Assembler::FPRegisterID) targetTemp->index);
+ _as->toDoubleRegister(source, (FPRegisterID) targetTemp->index);
return;
case IR::BoolType:
Q_ASSERT(source->type == IR::BoolType);
- _as->toInt32Register(source, (Assembler::RegisterID) targetTemp->index);
+ _as->toInt32Register(source, (RegisterID) targetTemp->index);
return;
case IR::SInt32Type:
Q_ASSERT(source->type == IR::SInt32Type);
- _as->toInt32Register(source, (Assembler::RegisterID) targetTemp->index);
+ _as->toInt32Register(source, (RegisterID) targetTemp->index);
return;
case IR::UInt32Type:
Q_ASSERT(source->type == IR::UInt32Type);
- _as->toUInt32Register(source, (Assembler::RegisterID) targetTemp->index);
+ _as->toUInt32Register(source, (RegisterID) targetTemp->index);
return;
default:
Q_ASSERT(!"Unreachable");
@@ -706,10 +712,11 @@ void InstructionSelection::copyValue(IR::Expr *source, IR::Expr *target)
}
// The target is not a physical register, nor is the source. So we can do a memory-to-memory copy:
- _as->memcopyValue(_as->loadAddress(Assembler::ReturnValueRegister, target), source, Assembler::ScratchRegister);
+ _as->memcopyValue(_as->loadAddress(JITTargetPlatform::ReturnValueRegister, target), source, JITTargetPlatform::ScratchRegister);
}
-void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::swapValues(IR::Expr *source, IR::Expr *target)
{
IR::Temp *sourceTemp = source->asTemp();
IR::Temp *targetTemp = target->asTemp();
@@ -719,26 +726,27 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
Q_ASSERT(sourceTemp->type == targetTemp->type);
if (sourceTemp->type == IR::DoubleType) {
- _as->moveDouble((Assembler::FPRegisterID) targetTemp->index, Assembler::FPGpr0);
- _as->moveDouble((Assembler::FPRegisterID) sourceTemp->index,
- (Assembler::FPRegisterID) targetTemp->index);
- _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) sourceTemp->index);
+ _as->moveDouble((FPRegisterID) targetTemp->index, JITTargetPlatform::FPGpr0);
+ _as->moveDouble((FPRegisterID) sourceTemp->index,
+ (FPRegisterID) targetTemp->index);
+ _as->moveDouble(JITTargetPlatform::FPGpr0, (FPRegisterID) sourceTemp->index);
} else {
- _as->swap((Assembler::RegisterID) sourceTemp->index,
- (Assembler::RegisterID) targetTemp->index);
+ _as->swap((RegisterID) sourceTemp->index,
+ (RegisterID) targetTemp->index);
}
return;
}
} 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.
- Assembler::Pointer sAddr = _as->loadAddress(Assembler::ScratchRegister, source);
- Assembler::Pointer tAddr = _as->loadAddress(Assembler::ReturnValueRegister, target);
+ 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
- _as->JSC::MacroAssembler::loadDouble(sAddr, Assembler::FPGpr0);
- _as->JSC::MacroAssembler::loadDouble(tAddr, Assembler::FPGpr1);
- _as->JSC::MacroAssembler::storeDouble(Assembler::FPGpr1, sAddr);
- _as->JSC::MacroAssembler::storeDouble(Assembler::FPGpr0, tAddr);
+ 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);
return;
}
}
@@ -749,18 +757,18 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
Q_ASSERT(memExpr);
Q_ASSERT(regTemp);
- Assembler::Pointer addr = _as->loadAddress(Assembler::ReturnValueRegister, memExpr);
+ Pointer addr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, memExpr);
if (regTemp->type == IR::DoubleType) {
- _as->loadDouble(addr, Assembler::FPGpr0);
- _as->storeDouble((Assembler::FPRegisterID) regTemp->index, addr);
- _as->moveDouble(Assembler::FPGpr0, (Assembler::FPRegisterID) regTemp->index);
+ _as->loadDouble(addr, JITTargetPlatform::FPGpr0);
+ _as->storeDouble((FPRegisterID) regTemp->index, addr);
+ _as->moveDouble(JITTargetPlatform::FPGpr0, (FPRegisterID) regTemp->index);
} else if (regTemp->type == IR::UInt32Type) {
- _as->toUInt32Register(addr, Assembler::ScratchRegister);
- _as->storeUInt32((Assembler::RegisterID) regTemp->index, addr);
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) regTemp->index);
+ _as->toUInt32Register(addr, JITTargetPlatform::ScratchRegister);
+ _as->storeUInt32((RegisterID) regTemp->index, addr);
+ _as->move(JITTargetPlatform::ScratchRegister, (RegisterID) regTemp->index);
} else {
- _as->load32(addr, Assembler::ScratchRegister);
- _as->store32((Assembler::RegisterID) regTemp->index, addr);
+ _as->load32(addr, JITTargetPlatform::ScratchRegister);
+ _as->store32((RegisterID) regTemp->index, addr);
if (regTemp->type != memExpr->type) {
addr.offset += 4;
quint32 tag;
@@ -775,55 +783,59 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target)
tag = 31337; // bogus value
Q_UNREACHABLE();
}
- _as->store32(Assembler::TrustedImm32(tag), addr);
+ _as->store32(TrustedImm32(tag), addr);
}
- _as->move(Assembler::ScratchRegister, (Assembler::RegisterID) regTemp->index);
+ _as->move(JITTargetPlatform::ScratchRegister, (RegisterID) regTemp->index);
}
}
#define setOp(op, opName, operation) \
do { \
- op = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \
+ op = typename JITAssembler::RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \
needsExceptionCheck = QV4::Runtime::Method_##operation##_NeedsExceptionCheck; \
} while (0)
#define setOpContext(op, opName, operation) \
do { \
- opContext = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \
+ opContext = typename JITAssembler::RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); \
needsExceptionCheck = QV4::Runtime::Method_##operation##_NeedsExceptionCheck; \
} while (0)
-void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target)
{
- QV4::JIT::Unop unop(_as, oper);
+ QV4::JIT::Unop<JITAssembler> unop(_as, oper);
unop.generate(source, target);
}
-void InstructionSelection::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::binop(IR::AluOp oper, IR::Expr *leftSource, IR::Expr *rightSource, IR::Expr *target)
{
- QV4::JIT::Binop binop(_as, oper);
+ QV4::JIT::Binop<JITAssembler> binop(_as, oper);
binop.generate(leftSource, rightSource, target);
}
-void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int propertyIndex, IR::ExprList *args, IR::Expr *result)
{
prepareCallData(args, base);
if (kind == IR::Member::MemberOfQmlScopeObject)
- generateRuntimeCall(result, callQmlScopeObjectProperty,
- Assembler::EngineRegister,
- Assembler::TrustedImm32(propertyIndex),
+ generateRuntimeCall(_as, result, callQmlScopeObjectProperty,
+ JITTargetPlatform::EngineRegister,
+ TrustedImm32(propertyIndex),
baseAddressForCallData());
else if (kind == IR::Member::MemberOfQmlContextObject)
- generateRuntimeCall(result, callQmlContextObjectProperty,
- Assembler::EngineRegister,
- Assembler::TrustedImm32(propertyIndex),
+ generateRuntimeCall(_as, result, callQmlContextObjectProperty,
+ JITTargetPlatform::EngineRegister,
+ TrustedImm32(propertyIndex),
baseAddressForCallData());
else
Q_ASSERT(false);
}
-void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callProperty(IR::Expr *base, const QString &name, IR::ExprList *args,
IR::Expr *result)
{
Q_ASSERT(base != 0);
@@ -832,29 +844,31 @@ void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR:
if (useFastLookups) {
uint index = registerGetterLookup(name);
- generateRuntimeCall(result, callPropertyLookup,
- Assembler::EngineRegister,
- Assembler::TrustedImm32(index),
+ generateRuntimeCall(_as, result, callPropertyLookup,
+ JITTargetPlatform::EngineRegister,
+ TrustedImm32(index),
baseAddressForCallData());
} else {
- generateRuntimeCall(result, callProperty, Assembler::EngineRegister,
- Assembler::StringToIndex(name),
+ generateRuntimeCall(_as, result, callProperty, JITTargetPlatform::EngineRegister,
+ StringToIndex(name),
baseAddressForCallData());
}
}
-void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::callSubscript(IR::Expr *base, IR::Expr *index, IR::ExprList *args,
IR::Expr *result)
{
Q_ASSERT(base != 0);
prepareCallData(args, base);
- generateRuntimeCall(result, callElement, Assembler::EngineRegister,
- Assembler::PointerToValue(index),
+ generateRuntimeCall(_as, result, callElement, JITTargetPlatform::EngineRegister,
+ PointerToValue(index),
baseAddressForCallData());
}
-void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::convertType(IR::Expr *source, IR::Expr *target)
{
switch (target->type) {
case IR::DoubleType:
@@ -875,7 +889,8 @@ void InstructionSelection::convertType(IR::Expr *source, IR::Expr *target)
}
}
-void InstructionSelection::convertTypeSlowPath(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::convertTypeSlowPath(IR::Expr *source, IR::Expr *target)
{
Q_ASSERT(target->type != IR::BoolType);
@@ -885,7 +900,8 @@ void InstructionSelection::convertTypeSlowPath(IR::Expr *source, IR::Expr *targe
copyValue(source, target);
}
-void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::convertTypeToDouble(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::SInt32Type:
@@ -897,51 +913,37 @@ void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *targe
convertUIntToDouble(source, target);
break;
case IR::UndefinedType:
- _as->loadDouble(_as->loadAddress(Assembler::ScratchRegister, source), Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, target);
+ _as->loadDouble(_as->loadAddress(JITTargetPlatform::ScratchRegister, source), JITTargetPlatform::FPGpr0);
+ _as->storeDouble(JITTargetPlatform::FPGpr0, target);
break;
case IR::StringType:
case IR::VarType: {
// load the tag:
- Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, source);
+ Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ScratchRegister);
+ _as->load32(tagAddr, JITTargetPlatform::ScratchRegister);
// check if it's an int32:
- Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::Integer_Type_Internal));
+ Jump isNoInt = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister,
+ TrustedImm32(Value::Integer_Type_Internal));
convertIntToDouble(source, target);
- Assembler::Jump intDone = _as->jump();
+ Jump intDone = _as->jump();
// not an int, check if it's NOT a double:
isNoInt.link(_as);
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- _as->rshift32(Assembler::TrustedImm32(Value::IsDoubleTag_Shift), Assembler::ScratchRegister);
- Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(0));
-#else
- _as->and32(Assembler::TrustedImm32(Value::NotDouble_Mask), Assembler::ScratchRegister);
- Assembler::Jump isDbl = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::NotDouble_Mask));
-#endif
+ Jump isDbl = _as->generateIsDoubleCheck(JITTargetPlatform::ScratchRegister);
- generateRuntimeCall(target, toDouble, Assembler::PointerToValue(source));
- Assembler::Jump noDoubleDone = _as->jump();
+ generateRuntimeCall(_as, target, toDouble, PointerToValue(source));
+ Jump noDoubleDone = _as->jump();
// it is a double:
isDbl.link(_as);
- Assembler::Pointer addr2 = _as->loadAddress(Assembler::ScratchRegister, source);
+ Pointer addr2 = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
IR::Temp *targetTemp = target->asTemp();
if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
-#if Q_PROCESSOR_WORDSIZE == 8
- _as->load64(addr2, Assembler::ScratchRegister);
- _as->store64(Assembler::ScratchRegister, _as->loadAddress(Assembler::ReturnValueRegister, target));
-#else
- _as->loadDouble(addr2, Assembler::FPGpr0);
- _as->storeDouble(Assembler::FPGpr0, _as->loadAddress(Assembler::ReturnValueRegister, target));
-#endif
+ _as->memcopyValue(target, addr2, JITTargetPlatform::FPGpr0, JITTargetPlatform::ReturnValueRegister);
} else {
- _as->loadDouble(addr2, (Assembler::FPRegisterID) targetTemp->index);
+ _as->loadDouble(addr2, (FPRegisterID) targetTemp->index);
}
noDoubleDone.link(_as);
@@ -953,7 +955,8 @@ void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *targe
}
}
-void InstructionSelection::convertTypeToBool(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::convertTypeToBool(IR::Expr *source, IR::Expr *target)
{
IR::Temp *sourceTemp = source->asTemp();
switch (source->type) {
@@ -965,16 +968,16 @@ void InstructionSelection::convertTypeToBool(IR::Expr *source, IR::Expr *target)
// The source is in a register if the register allocator is used. If the register
// allocator was not used, then that means that we can use any register for to
// load the double into.
- Assembler::FPRegisterID reg;
+ FPRegisterID reg;
if (sourceTemp && sourceTemp->kind == IR::Temp::PhysicalRegister)
- reg = (Assembler::FPRegisterID) sourceTemp->index;
+ reg = (FPRegisterID) sourceTemp->index;
else
- reg = _as->toDoubleRegister(source, (Assembler::FPRegisterID) 1);
- Assembler::Jump nonZero = _as->branchDoubleNonZero(reg, Assembler::FPGpr0);
+ reg = _as->toDoubleRegister(source, (FPRegisterID) 1);
+ Jump nonZero = _as->branchDoubleNonZero(reg, JITTargetPlatform::FPGpr0);
// it's 0, so false:
_as->storeBool(false, target);
- Assembler::Jump done = _as->jump();
+ Jump done = _as->jump();
// it's non-zero, so true:
nonZero.link(_as);
@@ -988,283 +991,220 @@ void InstructionSelection::convertTypeToBool(IR::Expr *source, IR::Expr *target)
_as->storeBool(false, target);
break;
case IR::StringType:
- generateRuntimeCall(Assembler::ReturnValueRegister, toBoolean,
- Assembler::PointerToValue(source));
- _as->storeBool(Assembler::ReturnValueRegister, target);
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toBoolean,
+ PointerToValue(source));
+ _as->storeBool(JITTargetPlatform::ReturnValueRegister, target);
case IR::VarType:
default:
- Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
- Assembler::Pointer tagAddr = addr;
+ Pointer addr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
+ Pointer tagAddr = addr;
tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ReturnValueRegister);
+ _as->load32(tagAddr, JITTargetPlatform::ReturnValueRegister);
// checkif it's a bool:
- Assembler::Jump notBool = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
- Assembler::TrustedImm32(Value::Boolean_Type_Internal));
- _as->load32(addr, Assembler::ReturnValueRegister);
- Assembler::Jump boolDone = _as->jump();
+ Jump notBool = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ReturnValueRegister,
+ TrustedImm32(Value::Boolean_Type_Internal));
+ _as->load32(addr, JITTargetPlatform::ReturnValueRegister);
+ Jump boolDone = _as->jump();
// check if it's an int32:
notBool.link(_as);
- Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
- Assembler::TrustedImm32(Value::Integer_Type_Internal));
- _as->load32(addr, Assembler::ReturnValueRegister);
- Assembler::Jump isZero = _as->branch32(Assembler::Equal, Assembler::ReturnValueRegister,
- Assembler::TrustedImm32(0));
- _as->move(Assembler::TrustedImm32(1), Assembler::ReturnValueRegister);
- Assembler::Jump intDone = _as->jump();
+ Jump fallback = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ReturnValueRegister,
+ TrustedImm32(Value::Integer_Type_Internal));
+ _as->load32(addr, JITTargetPlatform::ReturnValueRegister);
+ Jump isZero = _as->branch32(RelationalCondition::Equal, JITTargetPlatform::ReturnValueRegister,
+ TrustedImm32(0));
+ _as->move(TrustedImm32(1), JITTargetPlatform::ReturnValueRegister);
+ Jump intDone = _as->jump();
// not an int:
fallback.link(_as);
- generateRuntimeCall(Assembler::ReturnValueRegister, toBoolean,
- Assembler::PointerToValue(source));
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toBoolean,
+ PointerToValue(source));
isZero.link(_as);
intDone.link(_as);
boolDone.link(_as);
- _as->storeBool(Assembler::ReturnValueRegister, target);
+ _as->storeBool(JITTargetPlatform::ReturnValueRegister, target);
break;
}
}
-void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::convertTypeToSInt32(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::VarType: {
-
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
- _as->load64(addr, Assembler::ScratchRegister);
- _as->move(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
-
- // check if it's integer convertible
- _as->urshift64(Assembler::TrustedImm32(QV4::Value::IsIntegerConvertible_Shift), Assembler::ScratchRegister);
- Assembler::Jump isIntConvertible = _as->branch32(Assembler::Equal, Assembler::ScratchRegister, Assembler::TrustedImm32(3));
-
- // nope, not integer convertible, so check for a double:
- _as->urshift64(Assembler::TrustedImm32(
- QV4::Value::IsDoubleTag_Shift - QV4::Value::IsIntegerConvertible_Shift),
- Assembler::ScratchRegister);
- Assembler::Jump fallback = _as->branch32(Assembler::GreaterThan, Assembler::ScratchRegister, Assembler::TrustedImm32(0));
-
- // it's a double
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- _as->move64ToDouble(Assembler::ReturnValueRegister, Assembler::FPGpr0);
- Assembler::Jump success =
- _as->branchTruncateDoubleToInt32(Assembler::FPGpr0, Assembler::ReturnValueRegister,
- Assembler::BranchIfTruncateSuccessful);
-
- // not an int:
- fallback.link(_as);
- generateRuntimeCall(Assembler::ReturnValueRegister, toInt,
- _as->loadAddress(Assembler::ScratchRegister, source));
-
- isIntConvertible.link(_as);
- success.link(_as);
- IR::Temp *targetTemp = target->asTemp();
- if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
- Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
- _as->store32(Assembler::ReturnValueRegister, targetAddr);
- targetAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(Value::Integer_Type_Internal), targetAddr);
- } else {
- _as->storeInt32(Assembler::ReturnValueRegister, target);
- }
-#else
- // load the tag:
- Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
- Assembler::Pointer tagAddr = addr;
- tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ReturnValueRegister);
-
- // check if it's an int32:
- Assembler::Jump fallback = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
- Assembler::TrustedImm32(Value::Integer_Type_Internal));
- IR::Temp *targetTemp = target->asTemp();
- if (!targetTemp || targetTemp->kind == IR::Temp::StackSlot) {
- _as->load32(addr, Assembler::ReturnValueRegister);
- Assembler::Pointer targetAddr = _as->loadAddress(Assembler::ScratchRegister, target);
- _as->store32(Assembler::ReturnValueRegister, targetAddr);
- targetAddr.offset += 4;
- _as->store32(Assembler::TrustedImm32(Value::Integer_Type_Internal), targetAddr);
- } else {
- _as->load32(addr, (Assembler::RegisterID) targetTemp->index);
- }
- Assembler::Jump intDone = _as->jump();
-
- // not an int:
- fallback.link(_as);
- generateRuntimeCall(Assembler::ReturnValueRegister, toInt,
- _as->loadAddress(Assembler::ScratchRegister, source));
- _as->storeInt32(Assembler::ReturnValueRegister, target);
-
- intDone.link(_as);
-#endif
-
+ JITAssembler::RegisterSizeDependentOps::convertVarToSInt32(_as, source, target);
} break;
case IR::DoubleType: {
- Assembler::Jump success =
+ Jump success =
_as->branchTruncateDoubleToInt32(_as->toDoubleRegister(source),
- Assembler::ReturnValueRegister,
- Assembler::BranchIfTruncateSuccessful);
- generateRuntimeCall(Assembler::ReturnValueRegister, doubleToInt,
- Assembler::PointerToValue(source));
+ JITTargetPlatform::ReturnValueRegister,
+ BranchTruncateType::BranchIfTruncateSuccessful);
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, doubleToInt,
+ PointerToValue(source));
success.link(_as);
- _as->storeInt32(Assembler::ReturnValueRegister, target);
+ _as->storeInt32(JITTargetPlatform::ReturnValueRegister, target);
} break;
case IR::UInt32Type:
- _as->storeInt32(_as->toUInt32Register(source, Assembler::ReturnValueRegister), target);
+ _as->storeInt32(_as->toUInt32Register(source, JITTargetPlatform::ReturnValueRegister), target);
break;
case IR::NullType:
case IR::UndefinedType:
- _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
- _as->storeInt32(Assembler::ReturnValueRegister, target);
+ _as->move(TrustedImm32(0), JITTargetPlatform::ReturnValueRegister);
+ _as->storeInt32(JITTargetPlatform::ReturnValueRegister, target);
break;
case IR::BoolType:
- _as->storeInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
+ _as->storeInt32(_as->toInt32Register(source, JITTargetPlatform::ReturnValueRegister), target);
break;
case IR::StringType:
default:
- generateRuntimeCall(Assembler::ReturnValueRegister, toInt,
- _as->loadAddress(Assembler::ScratchRegister, source));
- _as->storeInt32(Assembler::ReturnValueRegister, target);
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toInt,
+ _as->loadAddress(JITTargetPlatform::ScratchRegister, source));
+ _as->storeInt32(JITTargetPlatform::ReturnValueRegister, target);
break;
} // switch (source->type)
}
-void InstructionSelection::convertTypeToUInt32(IR::Expr *source, IR::Expr *target)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::convertTypeToUInt32(IR::Expr *source, IR::Expr *target)
{
switch (source->type) {
case IR::VarType: {
// load the tag:
- Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, source);
+ Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
tagAddr.offset += 4;
- _as->load32(tagAddr, Assembler::ScratchRegister);
+ _as->load32(tagAddr, JITTargetPlatform::ScratchRegister);
// check if it's an int32:
- Assembler::Jump isNoInt = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(Value::Integer_Type_Internal));
- Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, source);
- _as->storeUInt32(_as->toInt32Register(addr, Assembler::ScratchRegister), target);
- Assembler::Jump intDone = _as->jump();
+ Jump isNoInt = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister,
+ TrustedImm32(Value::Integer_Type_Internal));
+ Pointer addr = _as->loadAddress(JITTargetPlatform::ScratchRegister, source);
+ _as->storeUInt32(_as->toInt32Register(addr, JITTargetPlatform::ScratchRegister), target);
+ Jump intDone = _as->jump();
// not an int:
isNoInt.link(_as);
- generateRuntimeCall(Assembler::ReturnValueRegister, toUInt,
- _as->loadAddress(Assembler::ScratchRegister, source));
- _as->storeInt32(Assembler::ReturnValueRegister, target);
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toUInt,
+ _as->loadAddress(JITTargetPlatform::ScratchRegister, source));
+ _as->storeInt32(JITTargetPlatform::ReturnValueRegister, target);
intDone.link(_as);
} break;
case IR::DoubleType: {
- Assembler::FPRegisterID reg = _as->toDoubleRegister(source);
- Assembler::Jump success =
- _as->branchTruncateDoubleToUint32(reg, Assembler::ReturnValueRegister,
- Assembler::BranchIfTruncateSuccessful);
- generateRuntimeCall(Assembler::ReturnValueRegister, doubleToUInt,
- Assembler::PointerToValue(source));
+ FPRegisterID reg = _as->toDoubleRegister(source);
+ Jump success =
+ _as->branchTruncateDoubleToUint32(reg, JITTargetPlatform::ReturnValueRegister,
+ BranchTruncateType::BranchIfTruncateSuccessful);
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, doubleToUInt,
+ PointerToValue(source));
success.link(_as);
- _as->storeUInt32(Assembler::ReturnValueRegister, target);
+ _as->storeUInt32(JITTargetPlatform::ReturnValueRegister, target);
} break;
case IR::NullType:
case IR::UndefinedType:
- _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
- _as->storeUInt32(Assembler::ReturnValueRegister, target);
+ _as->move(TrustedImm32(0), JITTargetPlatform::ReturnValueRegister);
+ _as->storeUInt32(JITTargetPlatform::ReturnValueRegister, target);
break;
case IR::StringType:
- generateRuntimeCall(Assembler::ReturnValueRegister, toUInt,
- Assembler::PointerToValue(source));
- _as->storeUInt32(Assembler::ReturnValueRegister, target);
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toUInt,
+ PointerToValue(source));
+ _as->storeUInt32(JITTargetPlatform::ReturnValueRegister, target);
break;
case IR::SInt32Type:
case IR::BoolType:
- _as->storeUInt32(_as->toInt32Register(source, Assembler::ReturnValueRegister), target);
+ _as->storeUInt32(_as->toInt32Register(source, JITTargetPlatform::ReturnValueRegister), target);
break;
default:
break;
} // switch (source->type)
}
-void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::constructActivationProperty(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(func != 0);
prepareCallData(args, 0);
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
- generateRuntimeCall(result, constructGlobalLookup,
- Assembler::EngineRegister,
- Assembler::TrustedImm32(index), baseAddressForCallData());
+ generateRuntimeCall(_as, result, constructGlobalLookup,
+ JITTargetPlatform::EngineRegister,
+ TrustedImm32(index), baseAddressForCallData());
return;
}
- generateRuntimeCall(result, constructActivationProperty,
- Assembler::EngineRegister,
- Assembler::StringToIndex(*func->id),
+ generateRuntimeCall(_as, result, constructActivationProperty,
+ JITTargetPlatform::EngineRegister,
+ StringToIndex(*func->id),
baseAddressForCallData());
}
-void InstructionSelection::constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::constructProperty(IR::Expr *base, const QString &name, IR::ExprList *args, IR::Expr *result)
{
prepareCallData(args, base);
if (useFastLookups) {
uint index = registerGetterLookup(name);
- generateRuntimeCall(result, constructPropertyLookup,
- Assembler::EngineRegister,
- Assembler::TrustedImm32(index),
+ generateRuntimeCall(_as, result, constructPropertyLookup,
+ JITTargetPlatform::EngineRegister,
+ TrustedImm32(index),
baseAddressForCallData());
return;
}
- generateRuntimeCall(result, constructProperty, Assembler::EngineRegister,
- Assembler::StringToIndex(name),
+ generateRuntimeCall(_as, result, constructProperty, JITTargetPlatform::EngineRegister,
+ StringToIndex(name),
baseAddressForCallData());
}
-void InstructionSelection::constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::constructValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
{
Q_ASSERT(value != 0);
prepareCallData(args, 0);
- generateRuntimeCall(result, constructValue,
- Assembler::EngineRegister,
- Assembler::Reference(value),
+ generateRuntimeCall(_as, result, constructValue,
+ JITTargetPlatform::EngineRegister,
+ Reference(value),
baseAddressForCallData());
}
-void InstructionSelection::visitJump(IR::Jump *s)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::visitJump(IR::Jump *s)
{
if (!_removableJumps.at(_block->index()))
_as->jumpToBlock(_block, s->target);
}
-void InstructionSelection::visitCJump(IR::CJump *s)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::visitCJump(IR::CJump *s)
{
IR::Temp *t = s->cond->asTemp();
if (t || s->cond->asArgLocal()) {
- Assembler::RegisterID reg;
+ RegisterID reg;
if (t && t->kind == IR::Temp::PhysicalRegister) {
Q_ASSERT(t->type == IR::BoolType);
- reg = (Assembler::RegisterID) t->index;
+ reg = (RegisterID) t->index;
} else if (t && t->kind == IR::Temp::StackSlot && t->type == IR::BoolType) {
- reg = Assembler::ReturnValueRegister;
+ reg = JITTargetPlatform::ReturnValueRegister;
_as->toInt32Register(t, reg);
} else {
- Address temp = _as->loadAddress(Assembler::ScratchRegister, s->cond);
+ Address temp = _as->loadAddress(JITTargetPlatform::ScratchRegister, s->cond);
Address tag = temp;
tag.offset += QV4::Value::tagOffset();
- Assembler::Jump booleanConversion = _as->branch32(Assembler::NotEqual, tag, Assembler::TrustedImm32(QV4::Value::Boolean_Type_Internal));
+ Jump booleanConversion = _as->branch32(RelationalCondition::NotEqual, tag, TrustedImm32(QV4::Value::Boolean_Type_Internal));
Address data = temp;
data.offset += QV4::Value::valueOffset();
- _as->load32(data, Assembler::ReturnValueRegister);
- Assembler::Jump testBoolean = _as->jump();
+ _as->load32(data, JITTargetPlatform::ReturnValueRegister);
+ Jump testBoolean = _as->jump();
booleanConversion.link(_as);
- reg = Assembler::ReturnValueRegister;
- generateRuntimeCall(reg, toBoolean, Assembler::Reference(s->cond));
+ reg = JITTargetPlatform::ReturnValueRegister;
+ generateRuntimeCall(_as, reg, toBoolean, Reference(s->cond));
testBoolean.link(_as);
}
@@ -1274,9 +1214,9 @@ void InstructionSelection::visitCJump(IR::CJump *s)
} else if (IR::Const *c = s->cond->asConst()) {
// TODO: SSA optimization for constant condition evaluation should remove this.
// See also visitCJump() in RegAllocInfo.
- generateRuntimeCall(Assembler::ReturnValueRegister, toBoolean,
- Assembler::PointerToValue(c));
- _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, toBoolean,
+ PointerToValue(c));
+ _as->generateCJumpOnNonZero(JITTargetPlatform::ReturnValueRegister, _block, s->iftrue, s->iffalse);
return;
} else if (IR::Binop *b = s->cond->asBinop()) {
if (b->left->type == IR::DoubleType && b->right->type == IR::DoubleType
@@ -1296,8 +1236,8 @@ void InstructionSelection::visitCJump(IR::CJump *s)
return;
}
- RuntimeCall op;
- RuntimeCall opContext;
+ typename JITAssembler::RuntimeCall op;
+ typename JITAssembler::RuntimeCall opContext;
const char *opName = 0;
bool needsExceptionCheck;
switch (b->op) {
@@ -1321,165 +1261,30 @@ void InstructionSelection::visitCJump(IR::CJump *s)
// elimination (which isn't there either) would remove the whole else block.
if (opContext.isValid())
_as->generateFunctionCallImp(needsExceptionCheck,
- Assembler::ReturnValueRegister, opName, opContext,
- Assembler::EngineRegister,
- Assembler::PointerToValue(b->left),
- Assembler::PointerToValue(b->right));
+ JITTargetPlatform::ReturnValueRegister, opName, opContext,
+ JITTargetPlatform::EngineRegister,
+ PointerToValue(b->left),
+ PointerToValue(b->right));
else
_as->generateFunctionCallImp(needsExceptionCheck,
- Assembler::ReturnValueRegister, opName, op,
- Assembler::PointerToValue(b->left),
- Assembler::PointerToValue(b->right));
+ JITTargetPlatform::ReturnValueRegister, opName, op,
+ PointerToValue(b->left),
+ PointerToValue(b->right));
- _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
+ _as->generateCJumpOnNonZero(JITTargetPlatform::ReturnValueRegister, _block, s->iftrue, s->iffalse);
return;
}
Q_UNREACHABLE();
}
-void InstructionSelection::visitRet(IR::Ret *s)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::visitRet(IR::Ret *s)
{
- if (!s) {
- // this only happens if the method doesn't have a return statement and can
- // only exit through an exception
- } else if (IR::Temp *t = s->expr->asTemp()) {
-#if CPU(X86) || CPU(ARM) || CPU(MIPS)
-
-# if CPU(X86)
- Assembler::RegisterID lowReg = JSC::X86Registers::eax;
- Assembler::RegisterID highReg = JSC::X86Registers::edx;
-# elif CPU(MIPS)
- Assembler::RegisterID lowReg = JSC::MIPSRegisters::v0;
- Assembler::RegisterID highReg = JSC::MIPSRegisters::v1;
-# else // CPU(ARM)
- Assembler::RegisterID lowReg = JSC::ARMRegisters::r0;
- Assembler::RegisterID highReg = JSC::ARMRegisters::r1;
-# endif
-
- if (t->kind == IR::Temp::PhysicalRegister) {
- switch (t->type) {
- case IR::DoubleType:
- _as->moveDoubleToInts((Assembler::FPRegisterID) t->index, lowReg, highReg);
- break;
- case IR::UInt32Type: {
- Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
- Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
- _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
- _as->moveDoubleToInts(Assembler::FPGpr0, lowReg, highReg);
- Assembler::Jump done = _as->jump();
- intRange.link(_as);
- _as->move(srcReg, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::Integer_Type_Internal), highReg);
- done.link(_as);
- } break;
- case IR::SInt32Type:
- _as->move((Assembler::RegisterID) t->index, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::Integer_Type_Internal), highReg);
- break;
- case IR::BoolType:
- _as->move((Assembler::RegisterID) t->index, lowReg);
- _as->move(Assembler::TrustedImm32(QV4::Value::Boolean_Type_Internal), highReg);
- break;
- default:
- Q_UNREACHABLE();
- }
- } else {
- Pointer addr = _as->loadAddress(Assembler::ScratchRegister, t);
- _as->load32(addr, lowReg);
- addr.offset += 4;
- _as->load32(addr, highReg);
- }
-#else
- if (t->kind == IR::Temp::PhysicalRegister) {
- if (t->type == IR::DoubleType) {
- _as->moveDoubleTo64((Assembler::FPRegisterID) t->index,
- Assembler::ReturnValueRegister);
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask),
- Assembler::ScratchRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- } else if (t->type == IR::UInt32Type) {
- Assembler::RegisterID srcReg = (Assembler::RegisterID) t->index;
- Assembler::Jump intRange = _as->branch32(Assembler::GreaterThanOrEqual, srcReg, Assembler::TrustedImm32(0));
- _as->convertUInt32ToDouble(srcReg, Assembler::FPGpr0, Assembler::ReturnValueRegister);
- _as->moveDoubleTo64(Assembler::FPGpr0, Assembler::ReturnValueRegister);
- _as->move(Assembler::TrustedImm64(QV4::Value::NaNEncodeMask), Assembler::ScratchRegister);
- _as->xor64(Assembler::ScratchRegister, Assembler::ReturnValueRegister);
- Assembler::Jump done = _as->jump();
- intRange.link(_as);
- _as->zeroExtend32ToPtr(srcReg, Assembler::ReturnValueRegister);
- quint64 tag = QV4::Value::Integer_Type_Internal;
- _as->or64(Assembler::TrustedImm64(tag << 32),
- Assembler::ReturnValueRegister);
- done.link(_as);
- } else {
- _as->zeroExtend32ToPtr((Assembler::RegisterID) t->index, Assembler::ReturnValueRegister);
- quint64 tag;
- switch (t->type) {
- case IR::SInt32Type:
- tag = QV4::Value::Integer_Type_Internal;
- break;
- case IR::BoolType:
- tag = QV4::Value::Boolean_Type_Internal;
- break;
- default:
- tag = 31337; // bogus value
- Q_UNREACHABLE();
- }
- _as->or64(Assembler::TrustedImm64(tag << 32),
- Assembler::ReturnValueRegister);
- }
- } else {
- _as->copyValue(Assembler::ReturnValueRegister, t);
- }
-#endif
- } else if (IR::Const *c = s->expr->asConst()) {
- QV4::Primitive retVal = convertToValue(c);
-#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
-#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::ARMRegisters::r1);
-#elif CPU(MIPS)
- _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::MIPSRegisters::v0);
- _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::MIPSRegisters::v1);
-#else
- _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
-#endif
- } else {
- Q_UNREACHABLE();
- Q_UNUSED(s);
- }
-
- Assembler::Label leaveStackFrame = _as->label();
-
- const int locals = _as->stackLayout().calculateJSStackFrameSize();
- _as->subPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
- _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
- _as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionContext::Data, engine)), Assembler::ScratchRegister);
- _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
-
- _as->leaveStandardStackFrame(regularRegistersToSave, fpRegistersToSave);
- _as->ret();
-
- _as->exceptionReturnLabel = _as->label();
- QV4::Primitive retVal = Primitive::undefinedValue();
-#if CPU(X86)
- _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::X86Registers::eax);
- _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::X86Registers::edx);
-#elif CPU(ARM)
- _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::ARMRegisters::r0);
- _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::ARMRegisters::r1);
-#elif CPU(MIPS)
- _as->move(Assembler::TrustedImm32(retVal.int_32()), JSC::MIPSRegisters::v0);
- _as->move(Assembler::TrustedImm32(retVal.tag()), JSC::MIPSRegisters::v1);
-#else
- _as->move(Assembler::TrustedImm64(retVal.rawValue()), Assembler::ReturnValueRegister);
-#endif
- _as->jump(leaveStackFrame);
+ _as->returnFromFunction(s, regularRegistersToSave, fpRegistersToSave);
}
-int InstructionSelection::prepareVariableArguments(IR::ExprList* args)
+template <typename JITAssembler>
+int InstructionSelection<JITAssembler>::prepareVariableArguments(IR::ExprList* args)
{
int argc = 0;
for (IR::ExprList *it = args; it; it = it->next) {
@@ -1492,7 +1297,7 @@ int InstructionSelection::prepareVariableArguments(IR::ExprList* args)
Q_ASSERT(arg != 0);
Pointer dst(_as->stackLayout().argumentAddressForCall(i));
if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister)
- _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
+ _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister);
else
_as->copyValue(dst, arg);
}
@@ -1500,7 +1305,8 @@ int InstructionSelection::prepareVariableArguments(IR::ExprList* args)
return argc;
}
-int InstructionSelection::prepareCallData(IR::ExprList* args, IR::Expr *thisObject)
+template <typename JITAssembler>
+int InstructionSelection<JITAssembler>::prepareCallData(IR::ExprList* args, IR::Expr *thisObject)
{
int argc = 0;
for (IR::ExprList *it = args; it; it = it->next) {
@@ -1508,9 +1314,9 @@ int InstructionSelection::prepareCallData(IR::ExprList* args, IR::Expr *thisObje
}
Pointer p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, tag));
- _as->store32(Assembler::TrustedImm32(QV4::Value::Integer_Type_Internal), p);
+ _as->store32(TrustedImm32(QV4::Value::Integer_Type_Internal), p);
p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, argc));
- _as->store32(Assembler::TrustedImm32(argc), p);
+ _as->store32(TrustedImm32(argc), p);
p = _as->stackLayout().callDataAddress(qOffsetOf(CallData, thisObject));
if (!thisObject)
_as->storeValue(QV4::Primitive::undefinedValue(), p);
@@ -1523,25 +1329,24 @@ int InstructionSelection::prepareCallData(IR::ExprList* args, IR::Expr *thisObje
Q_ASSERT(arg != 0);
Pointer dst(_as->stackLayout().argumentAddressForCall(i));
if (arg->asTemp() && arg->asTemp()->kind != IR::Temp::PhysicalRegister)
- _as->memcopyValue(dst, arg->asTemp(), Assembler::ScratchRegister);
+ _as->memcopyValue(dst, arg->asTemp(), JITTargetPlatform::ScratchRegister);
else
_as->copyValue(dst, arg);
}
return argc;
}
-void InstructionSelection::calculateRegistersToSave(const RegisterInformation &used)
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::calculateRegistersToSave(const RegisterInformation &used)
{
regularRegistersToSave.clear();
fpRegistersToSave.clear();
- for (const RegisterInfo &ri : Assembler::getRegisterInfo()) {
-#if defined(RESTORE_EBX_ON_CALL)
- if (ri.isRegularRegister() && ri.reg<JSC::X86Registers::RegisterID>() == JSC::X86Registers::ebx) {
+ for (const RegisterInfo &ri : JITTargetPlatform::getRegisterInfo()) {
+ if (JITTargetPlatform::gotRegister != -1 && ri.isRegularRegister() && ri.reg<RegisterID>() == JITTargetPlatform::gotRegister) {
regularRegistersToSave.append(ri);
continue;
}
-#endif // RESTORE_EBX_ON_CALL
if (ri.isCallerSaved())
continue;
if (ri.isRegularRegister()) {
@@ -1564,35 +1369,38 @@ bool operator==(const Primitive &v1, const Primitive &v2)
} // QV4 namespace
QT_END_NAMESPACE
-bool InstructionSelection::visitCJumpDouble(IR::AluOp op, IR::Expr *left, IR::Expr *right,
+template <typename JITAssembler>
+bool InstructionSelection<JITAssembler>::visitCJumpDouble(IR::AluOp op, IR::Expr *left, IR::Expr *right,
IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
{
if (_as->nextBlock() == iftrue) {
- Assembler::Jump target = _as->branchDouble(true, op, left, right);
+ Jump target = _as->branchDouble(true, op, left, right);
_as->addPatch(iffalse, target);
} else {
- Assembler::Jump target = _as->branchDouble(false, op, left, right);
+ Jump target = _as->branchDouble(false, op, left, right);
_as->addPatch(iftrue, target);
_as->jumpToBlock(_block, iffalse);
}
return true;
}
-bool InstructionSelection::visitCJumpSInt32(IR::AluOp op, IR::Expr *left, IR::Expr *right,
+template <typename JITAssembler>
+bool InstructionSelection<JITAssembler>::visitCJumpSInt32(IR::AluOp op, IR::Expr *left, IR::Expr *right,
IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
{
if (_as->nextBlock() == iftrue) {
- Assembler::Jump target = _as->branchInt32(true, op, left, right);
+ Jump target = _as->branchInt32(true, op, left, right);
_as->addPatch(iffalse, target);
} else {
- Assembler::Jump target = _as->branchInt32(false, op, left, right);
+ Jump target = _as->branchInt32(false, op, left, right);
_as->addPatch(iftrue, target);
_as->jumpToBlock(_block, iffalse);
}
return true;
}
-void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *trueBlock,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *trueBlock,
IR::BasicBlock *falseBlock)
{
Q_ASSERT(binop->op == IR::OpStrictEqual || binop->op == IR::OpStrictNotEqual);
@@ -1607,15 +1415,16 @@ void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *tr
IR::Expr *left = binop->left;
IR::Expr *right = binop->right;
- generateRuntimeCall(Assembler::ReturnValueRegister, compareStrictEqual,
- Assembler::PointerToValue(left), Assembler::PointerToValue(right));
- _as->generateCJumpOnCompare(binop->op == IR::OpStrictEqual ? Assembler::NotEqual : Assembler::Equal,
- Assembler::ReturnValueRegister, Assembler::TrustedImm32(0),
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, compareStrictEqual,
+ PointerToValue(left), PointerToValue(right));
+ _as->generateCJumpOnCompare(binop->op == IR::OpStrictEqual ? RelationalCondition::NotEqual : RelationalCondition::Equal,
+ JITTargetPlatform::ReturnValueRegister, TrustedImm32(0),
_block, trueBlock, falseBlock);
}
// Only load the non-null temp.
-bool InstructionSelection::visitCJumpStrictNull(IR::Binop *binop,
+template <typename JITAssembler>
+bool InstructionSelection<JITAssembler>::visitCJumpStrictNull(IR::Binop *binop,
IR::BasicBlock *trueBlock,
IR::BasicBlock *falseBlock)
{
@@ -1640,19 +1449,20 @@ bool InstructionSelection::visitCJumpStrictNull(IR::Binop *binop,
return true;
}
- Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
+ Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, varSrc);
tagAddr.offset += 4;
- const Assembler::RegisterID tagReg = Assembler::ScratchRegister;
+ const RegisterID tagReg = JITTargetPlatform::ScratchRegister;
_as->load32(tagAddr, tagReg);
- Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
- : Assembler::NotEqual;
- const Assembler::TrustedImm32 tag(QV4::Value::Null_Type_Internal);
+ RelationalCondition cond = binop->op == IR::OpStrictEqual ? RelationalCondition::Equal
+ : RelationalCondition::NotEqual;
+ const TrustedImm32 tag(QV4::Value::Null_Type_Internal);
_as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
return true;
}
-bool InstructionSelection::visitCJumpStrictUndefined(IR::Binop *binop,
+template <typename JITAssembler>
+bool InstructionSelection<JITAssembler>::visitCJumpStrictUndefined(IR::Binop *binop,
IR::BasicBlock *trueBlock,
IR::BasicBlock *falseBlock)
{
@@ -1677,28 +1487,15 @@ bool InstructionSelection::visitCJumpStrictUndefined(IR::Binop *binop,
return true;
}
- Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
- : Assembler::NotEqual;
- const Assembler::RegisterID tagReg = Assembler::ReturnValueRegister;
-#ifdef QV4_USE_64_BIT_VALUE_ENCODING
- Assembler::Pointer addr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
- _as->load64(addr, tagReg);
- const Assembler::TrustedImm64 tag(0);
-#else // !QV4_USE_64_BIT_VALUE_ENCODING
- Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
- _as->load32(tagAddr, tagReg);
- Assembler::Jump j = _as->branch32(Assembler::invert(cond), tagReg, Assembler::TrustedImm32(0));
- _as->addPatch(falseBlock, j);
-
- tagAddr.offset += 4;
- _as->load32(tagAddr, tagReg);
- const Assembler::TrustedImm32 tag(QV4::Value::Managed_Type_Internal);
-#endif
- _as->generateCJumpOnCompare(cond, tagReg, tag, _block, trueBlock, falseBlock);
+ RelationalCondition cond = binop->op == IR::OpStrictEqual ? RelationalCondition::Equal
+ : RelationalCondition::NotEqual;
+ const RegisterID tagReg = JITTargetPlatform::ReturnValueRegister;
+ _as->generateCJumpOnUndefined(cond, varSrc, JITTargetPlatform::ScratchRegister, tagReg, _block, trueBlock, falseBlock);
return true;
}
-bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock *trueBlock,
+template <typename JITAssembler>
+bool InstructionSelection<JITAssembler>::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock *trueBlock,
IR::BasicBlock *falseBlock)
{
IR::Expr *boolSrc = 0, *otherSrc = 0;
@@ -1712,13 +1509,20 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock
// neither operands are statically typed as bool, so bail out.
return false;
}
+ if (otherSrc->type == IR::UnknownType) {
+ // Ok, we really need to call into the runtime.
+ // (This case doesn't happen when the optimizer ran, because everything will be typed (yes,
+ // possibly as "var" meaning anything), but it does happen for $0===true, which is generated
+ // for things where the optimizer didn't run (like functions with a try block).)
+ return false;
+ }
- Assembler::RelationalCondition cond = binop->op == IR::OpStrictEqual ? Assembler::Equal
- : Assembler::NotEqual;
+ RelationalCondition cond = binop->op == IR::OpStrictEqual ? RelationalCondition::Equal
+ : RelationalCondition::NotEqual;
if (otherSrc->type == IR::BoolType) { // both are boolean
- Assembler::RegisterID one = _as->toBoolRegister(boolSrc, Assembler::ReturnValueRegister);
- Assembler::RegisterID two = _as->toBoolRegister(otherSrc, Assembler::ScratchRegister);
+ RegisterID one = _as->toBoolRegister(boolSrc, JITTargetPlatform::ReturnValueRegister);
+ RegisterID two = _as->toBoolRegister(otherSrc, JITTargetPlatform::ScratchRegister);
_as->generateCJumpOnCompare(cond, one, two, _block, trueBlock, falseBlock);
return true;
}
@@ -1728,13 +1532,13 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock
return true;
}
- Assembler::Pointer otherAddr = _as->loadAddress(Assembler::ReturnValueRegister, otherSrc);
+ Pointer otherAddr = _as->loadAddress(JITTargetPlatform::ReturnValueRegister, otherSrc);
otherAddr.offset += 4; // tag address
// check if the tag of the var operand is indicates 'boolean'
- _as->load32(otherAddr, Assembler::ScratchRegister);
- Assembler::Jump noBool = _as->branch32(Assembler::NotEqual, Assembler::ScratchRegister,
- Assembler::TrustedImm32(QV4::Value::Boolean_Type_Internal));
+ _as->load32(otherAddr, JITTargetPlatform::ScratchRegister);
+ Jump noBool = _as->branch32(RelationalCondition::NotEqual, JITTargetPlatform::ScratchRegister,
+ TrustedImm32(QV4::Value::Boolean_Type_Internal));
if (binop->op == IR::OpStrictEqual)
_as->addPatch(falseBlock, noBool);
else
@@ -1742,14 +1546,15 @@ bool InstructionSelection::visitCJumpStrictBool(IR::Binop *binop, IR::BasicBlock
// ok, both are boolean, so let's load them and compare them.
otherAddr.offset -= 4; // int_32 address
- _as->load32(otherAddr, Assembler::ReturnValueRegister);
- Assembler::RegisterID boolReg = _as->toBoolRegister(boolSrc, Assembler::ScratchRegister);
- _as->generateCJumpOnCompare(cond, boolReg, Assembler::ReturnValueRegister, _block, trueBlock,
+ _as->load32(otherAddr, JITTargetPlatform::ReturnValueRegister);
+ RegisterID boolReg = _as->toBoolRegister(boolSrc, JITTargetPlatform::ScratchRegister);
+ _as->generateCJumpOnCompare(cond, boolReg, JITTargetPlatform::ReturnValueRegister, _block, trueBlock,
falseBlock);
return true;
}
-bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
+template <typename JITAssembler>
+bool InstructionSelection<JITAssembler>::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Binop *binop,
IR::BasicBlock *trueBlock,
IR::BasicBlock *falseBlock)
{
@@ -1776,18 +1581,18 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin
return true;
}
- Assembler::Pointer tagAddr = _as->loadAddress(Assembler::ScratchRegister, varSrc);
+ Pointer tagAddr = _as->loadAddress(JITTargetPlatform::ScratchRegister, varSrc);
tagAddr.offset += 4;
- const Assembler::RegisterID tagReg = Assembler::ReturnValueRegister;
+ const RegisterID tagReg = JITTargetPlatform::ReturnValueRegister;
_as->load32(tagAddr, tagReg);
if (binop->op == IR::OpNotEqual)
qSwap(trueBlock, falseBlock);
- Assembler::Jump isNull = _as->branch32(Assembler::Equal, tagReg, Assembler::TrustedImm32(int(QV4::Value::Null_Type_Internal)));
- Assembler::Jump isNotUndefinedTag = _as->branch32(Assembler::NotEqual, tagReg, Assembler::TrustedImm32(int(QV4::Value::Managed_Type_Internal)));
+ Jump isNull = _as->branch32(RelationalCondition::Equal, tagReg, TrustedImm32(int(QV4::Value::Null_Type_Internal)));
+ Jump isNotUndefinedTag = _as->branch32(RelationalCondition::NotEqual, tagReg, TrustedImm32(int(QV4::Value::Managed_Type_Internal)));
tagAddr.offset -= 4;
_as->load32(tagAddr, tagReg);
- Assembler::Jump isNotUndefinedValue = _as->branch32(Assembler::NotEqual, tagReg, Assembler::TrustedImm32(0));
+ Jump isNotUndefinedValue = _as->branch32(RelationalCondition::NotEqual, tagReg, TrustedImm32(0));
_as->addPatch(trueBlock, isNull);
_as->addPatch(falseBlock, isNotUndefinedTag);
_as->addPatch(falseBlock, isNotUndefinedValue);
@@ -1797,7 +1602,8 @@ bool InstructionSelection::visitCJumpNullUndefined(IR::Type nullOrUndef, IR::Bin
}
-void InstructionSelection::visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *trueBlock,
+template <typename JITAssembler>
+void InstructionSelection<JITAssembler>::visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *trueBlock,
IR::BasicBlock *falseBlock)
{
Q_ASSERT(binop->op == IR::OpEqual || binop->op == IR::OpNotEqual);
@@ -1808,18 +1614,55 @@ void InstructionSelection::visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *tru
IR::Expr *left = binop->left;
IR::Expr *right = binop->right;
- generateRuntimeCall(Assembler::ReturnValueRegister, compareEqual,
- Assembler::PointerToValue(left), Assembler::PointerToValue(right));
- _as->generateCJumpOnCompare(binop->op == IR::OpEqual ? Assembler::NotEqual : Assembler::Equal,
- Assembler::ReturnValueRegister, Assembler::TrustedImm32(0),
+ generateRuntimeCall(_as, JITTargetPlatform::ReturnValueRegister, compareEqual,
+ PointerToValue(left), PointerToValue(right));
+ _as->generateCJumpOnCompare(binop->op == IR::OpEqual ? RelationalCondition::NotEqual : RelationalCondition::Equal,
+ JITTargetPlatform::ReturnValueRegister, TrustedImm32(0),
_block, trueBlock, falseBlock);
}
-QQmlRefPointer<CompiledData::CompilationUnit> ISelFactory::createUnitForLoading()
+template <typename JITAssembler>
+QQmlRefPointer<CompiledData::CompilationUnit> ISelFactory<JITAssembler>::createUnitForLoading()
{
QQmlRefPointer<CompiledData::CompilationUnit> result;
result.adopt(new JIT::CompilationUnit);
return result;
}
+QT_BEGIN_NAMESPACE
+namespace QV4 { namespace JIT {
+template class Q_QML_EXPORT InstructionSelection<>;
+template class Q_QML_EXPORT ISelFactory<>;
+#if defined(V4_BOOTSTRAP)
+
+Q_QML_EXPORT QV4::EvalISelFactory *createISelForArchitecture(const QString &architecture)
+{
+ using ARMv7CrossAssembler = QV4::JIT::Assembler<AssemblerTargetConfiguration<JSC::MacroAssemblerARMv7, NoOperatingSystemSpecialization>>;
+ using ARM64CrossAssembler = QV4::JIT::Assembler<AssemblerTargetConfiguration<JSC::MacroAssemblerARM64, NoOperatingSystemSpecialization>>;
+
+ if (architecture == QLatin1String("armv7"))
+ return new ISelFactory<ARMv7CrossAssembler>;
+ else if (architecture == QLatin1String("armv8"))
+ return new ISelFactory<ARM64CrossAssembler>;
+
+ QString hostArch;
+#if CPU(ARM_THUMB2)
+ hostArch = QStringLiteral("armv7");
+#elif CPU(MIPS)
+ hostArch = QStringLiteral("mips");
+#elif CPU(X86)
+ hostArch = QStringLiteral("x86");
+#elif CPU(X86_64)
+ hostArch = QStringLiteral("x86_64");
+#endif
+ if (!hostArch.isEmpty() && architecture == hostArch)
+ return new ISelFactory<>;
+
+ return nullptr;
+}
+
+#endif
+} }
+QT_END_NAMESPACE
+
#endif // ENABLE(ASSEMBLER)