aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4isel_moth.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4isel_moth.cpp')
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp505
1 files changed, 357 insertions, 148 deletions
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index c610ca6f02..ee7e8ce2e8 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -134,85 +134,31 @@ inline bool isNumberType(V4IR::Expr *e)
}
}
-} // anonymous namespace
-
-// TODO: extend to optimize out temp-to-temp moves, where the lifetime of one temp ends at that statement.
-// To handle that, add a hint when such a move will occur, and add a stmt for the hint.
-// Then when asked for a register, check if the active statement is the terminating statement, and if so, apply the hint.
-// This generalises the hint usage for Phi removal too, when the phi is passed in there as the current statement.
-class QQmlJS::Moth::StackSlotAllocator
+inline bool isIntegerType(V4IR::Expr *e)
{
- QHash<V4IR::Temp, int> _slotForTemp;
- QHash<V4IR::Temp, int> _hints;
- QVector<int> _activeSlots;
-
- QHash<V4IR::Temp, V4IR::LifeTimeInterval> _intervals;
-
-public:
- StackSlotAllocator(const QVector<V4IR::LifeTimeInterval> &ranges, int maxTempCount)
- : _activeSlots(maxTempCount)
- {
- _intervals.reserve(ranges.size());
- foreach (const V4IR::LifeTimeInterval &r, ranges)
- _intervals[r.temp()] = r;
- }
-
- void addHint(const V4IR::Temp &hintedSlotOfTemp, const V4IR::Temp &newTemp)
- {
- if (hintedSlotOfTemp.kind != V4IR::Temp::VirtualRegister
- || newTemp.kind != V4IR::Temp::VirtualRegister)
- return;
-
- if (_slotForTemp.contains(newTemp) || _hints.contains(newTemp))
- return;
-
- int hintedSlot = _slotForTemp.value(hintedSlotOfTemp, -1);
- Q_ASSERT(hintedSlot >= 0);
- _hints[newTemp] = hintedSlot;
- }
-
- int stackSlotFor(V4IR::Temp *t, V4IR::Stmt *currentStmt) {
- Q_ASSERT(t->kind == V4IR::Temp::VirtualRegister);
- Q_ASSERT(t->scope == 0);
- int idx = _slotForTemp.value(*t, -1);
- if (idx == -1)
- idx = allocateSlot(t, currentStmt);
- Q_ASSERT(idx >= 0);
- return idx;
+ switch (e->type) {
+ case V4IR::SInt32Type:
+ case V4IR::UInt32Type:
+ return true;
+ default:
+ return false;
}
+}
-private:
- int allocateSlot(V4IR::Temp *t, V4IR::Stmt *currentStmt) {
- Q_ASSERT(currentStmt->id > 0);
-
- const V4IR::LifeTimeInterval &interval = _intervals[*t];
- int idx = _hints.value(*t, -1);
- if (idx != -1 && _activeSlots[idx] == currentStmt->id) {
- _slotForTemp[*t] = idx;
- _activeSlots[idx] = interval.end();
- return idx;
- }
-
- for (int i = 0, ei = _activeSlots.size(); i != ei; ++i) {
- if (_activeSlots[i] < currentStmt->id) {
- _slotForTemp[*t] = i;
- _activeSlots[i] = interval.end();
- return i;
- }
- }
+inline bool isBoolType(V4IR::Expr *e)
+{
+ return (e->type == V4IR::BoolType);
+}
- return -1;
- }
-};
+} // anonymous namespace
-InstructionSelection::InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
+InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
: EvalInstructionSelection(execAllocator, module, jsGenerator)
- , _function(0)
+ , qmlEngine(qmlEngine)
, _block(0)
, _codeStart(0)
, _codeNext(0)
, _codeEnd(0)
- , _stackSlotAllocator(0)
, _currentStatement(0)
{
compilationUnit = new CompilationUnit;
@@ -246,14 +192,13 @@ void InstructionSelection::run(int functionIndex)
qSwap(codeEnd, _codeEnd);
V4IR::Optimizer opt(_function);
- opt.run();
- StackSlotAllocator *stackSlotAllocator = 0;
+ opt.run(qmlEngine);
if (opt.isInSSA()) {
- stackSlotAllocator = new StackSlotAllocator(opt.lifeRanges(), _function->tempCount);
opt.convertOutOfSSA();
+ opt.showMeTheCode(_function);
}
+ ConvertTemps().toStackSlots(_function);
- qSwap(_stackSlotAllocator, stackSlotAllocator);
QSet<V4IR::Jump *> removableJumps = opt.calculateOptionalJumps();
qSwap(_removableJumps, removableJumps);
@@ -263,6 +208,8 @@ void InstructionSelection::run(int functionIndex)
int locals = frameSize();
assert(locals >= 0);
+ V4IR::BasicBlock *exceptionHandler = 0;
+
Instruction::Push push;
push.value = quint32(locals);
addInstruction(push);
@@ -275,6 +222,18 @@ void InstructionSelection::run(int functionIndex)
_nextBlock = (i < ei - 1) ? _function->basicBlocks[i + 1] : 0;
_addrs.insert(_block, _codeNext - _codeStart);
+ if (_block->catchBlock != exceptionHandler) {
+ Instruction::SetExceptionHandler set;
+ set.offset = 0;
+ if (_block->catchBlock) {
+ ptrdiff_t loc = addInstruction(set) + (((const char *)&set.offset) - ((const char *)&set));
+ _patches[_block->catchBlock].append(loc);
+ } else {
+ addInstruction(set);
+ }
+ exceptionHandler = _block->catchBlock;
+ }
+
foreach (V4IR::Stmt *s, _block->statements) {
_currentStatement = s;
@@ -294,8 +253,6 @@ void InstructionSelection::run(int functionIndex)
qSwap(_currentStatement, cs);
qSwap(_removableJumps, removableJumps);
- qSwap(_stackSlotAllocator, stackSlotAllocator);
- delete stackSlotAllocator;
qSwap(_function, function);
qSwap(block, _block);
qSwap(nextBlock, _nextBlock);
@@ -330,14 +287,24 @@ void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4
void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args,
V4IR::Temp *result)
{
- // call the property on the loaded base
- Instruction::CallProperty call;
- call.base = getParam(base);
- call.name = registerString(name);
- prepareCallArgs(args, call.argc);
- call.callData = callDataStart();
- call.result = getResultParam(result);
- addInstruction(call);
+ if (useFastLookups) {
+ Instruction::CallPropertyLookup call;
+ call.base = getParam(base);
+ call.lookupIndex = registerGetterLookup(name);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ } else {
+ // call the property on the loaded base
+ Instruction::CallProperty call;
+ call.base = getParam(base);
+ call.name = registerString(name);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ }
}
void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args,
@@ -355,9 +322,6 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
{
- if (_stackSlotAllocator)
- _stackSlotAllocator->addHint(*source, *target);
-
// FIXME: do something more useful with this info
if (target->type & V4IR::NumberType)
unop(V4IR::OpUPlus, source, target);
@@ -369,6 +333,15 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func,
V4IR::ExprList *args,
V4IR::Temp *result)
{
+ if (useFastLookups && func->global) {
+ Instruction::ConstructGlobalLookup call;
+ call.index = registerGlobalGetterLookup(*func->id);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ return;
+ }
Instruction::CreateActivationProperty create;
create.name = registerString(*func->id);
prepareCallArgs(args, create.argc);
@@ -379,6 +352,16 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func,
void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result)
{
+ if (useFastLookups) {
+ Instruction::ConstructPropertyLookup call;
+ call.base = getParam(base);
+ call.index = registerGetterLookup(name);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ return;
+ }
Instruction::CreateProperty create;
create.base = getParam(base);
create.name = registerString(name);
@@ -405,14 +388,50 @@ void InstructionSelection::loadThisObject(V4IR::Temp *temp)
addInstruction(load);
}
+void InstructionSelection::loadQmlIdArray(V4IR::Temp *temp)
+{
+ Instruction::LoadQmlIdArray load;
+ load.result = getResultParam(temp);
+ addInstruction(load);
+}
+
+void InstructionSelection::loadQmlImportedScripts(V4IR::Temp *temp)
+{
+ Instruction::LoadQmlImportedScripts load;
+ load.result = getResultParam(temp);
+ addInstruction(load);
+}
+
+void InstructionSelection::loadQmlContextObject(V4IR::Temp *temp)
+{
+ Instruction::LoadQmlContextObject load;
+ load.result = getResultParam(temp);
+ addInstruction(load);
+}
+
+void InstructionSelection::loadQmlScopeObject(V4IR::Temp *temp)
+{
+ Instruction::LoadQmlScopeObject load;
+ load.result = getResultParam(temp);
+ addInstruction(load);
+}
+
+void InstructionSelection::loadQmlSingleton(const QString &name, V4IR::Temp *temp)
+{
+ Instruction::LoadQmlSingleton load;
+ load.result = getResultParam(temp);
+ load.name = registerString(name);
+ addInstruction(load);
+}
+
void InstructionSelection::loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp)
{
assert(sourceConst);
- Instruction::LoadValue load;
- load.value = getParam(sourceConst);
- load.result = getResultParam(targetTemp);
- addInstruction(load);
+ Instruction::Move move;
+ move.source = getParam(sourceConst);
+ move.result = getResultParam(targetTemp);
+ addInstruction(move);
}
void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp)
@@ -433,6 +452,13 @@ void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *ta
void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
{
+ if (useFastLookups && name->global) {
+ Instruction::GetGlobalLookup load;
+ load.index = registerGlobalGetterLookup(*name->id);
+ load.result = getResultParam(temp);
+ addInstruction(load);
+ return;
+ }
Instruction::LoadName load;
load.name = registerString(*name->id);
load.result = getResultParam(temp);
@@ -458,6 +484,14 @@ void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *targe
void InstructionSelection::getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target)
{
+ if (useFastLookups) {
+ Instruction::GetLookup load;
+ load.base = getParam(base);
+ load.index = registerGetterLookup(name);
+ load.result = getResultParam(target);
+ addInstruction(load);
+ return;
+ }
Instruction::LoadProperty load;
load.base = getParam(base);
load.name = registerString(name);
@@ -468,6 +502,14 @@ void InstructionSelection::getProperty(V4IR::Expr *base, const QString &name, V4
void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBase,
const QString &targetName)
{
+ if (useFastLookups) {
+ Instruction::SetLookup store;
+ store.base = getParam(targetBase);
+ store.index = registerSetterLookup(targetName);
+ store.source = getParam(source);
+ addInstruction(store);
+ return;
+ }
Instruction::StoreProperty store;
store.base = getParam(targetBase);
store.name = registerString(targetName);
@@ -475,6 +517,25 @@ void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBas
addInstruction(store);
}
+void InstructionSelection::setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex)
+{
+ Instruction::StoreQObjectProperty store;
+ store.base = getParam(targetBase);
+ store.propertyIndex = propertyIndex;
+ store.source = getParam(source);
+ addInstruction(store);
+}
+
+void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target)
+{
+ Instruction::LoadQObjectProperty load;
+ load.base = getParam(base);
+ load.propertyIndex = propertyIndex;
+ load.result = getResultParam(target);
+ load.captureRequired = captureRequired;
+ addInstruction(load);
+}
+
void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target)
{
Instruction::LoadElement load;
@@ -496,10 +557,7 @@ void InstructionSelection::setElement(V4IR::Expr *source, V4IR::Expr *targetBase
void InstructionSelection::copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
{
- if (_stackSlotAllocator)
- _stackSlotAllocator->addHint(*sourceTemp, *targetTemp);
-
- Instruction::MoveTemp move;
+ Instruction::Move move;
move.source = getParam(sourceTemp);
move.result = getResultParam(targetTemp);
if (move.source != move.result)
@@ -516,30 +574,79 @@ void InstructionSelection::swapValues(V4IR::Temp *sourceTemp, V4IR::Temp *target
void InstructionSelection::unop(V4IR::AluOp oper, V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp)
{
- if (_stackSlotAllocator)
- _stackSlotAllocator->addHint(*sourceTemp, *targetTemp);
-
- QV4::UnaryOpName op = 0;
switch (oper) {
- case V4IR::OpIfTrue: assert(!"unreachable"); break;
- case V4IR::OpNot: op = QV4::__qmljs_not; break;
- case V4IR::OpUMinus: op = QV4::__qmljs_uminus; break;
- case V4IR::OpUPlus: op = QV4::__qmljs_uplus; break;
- case V4IR::OpCompl: op = QV4::__qmljs_compl; break;
- case V4IR::OpIncrement: op = QV4::__qmljs_increment; break;
- case V4IR::OpDecrement: op = QV4::__qmljs_decrement; break;
- default: assert(!"unreachable"); break;
+ case V4IR::OpIfTrue:
+ Q_ASSERT(!"unreachable"); break;
+ case V4IR::OpNot: {
+ // ### enabling this fails in some cases, where apparently the value is not a bool at runtime
+ if (0 && isBoolType(sourceTemp)) {
+ Instruction::UNotBool unot;
+ unot.source = getParam(sourceTemp);
+ unot.result = getResultParam(targetTemp);
+ addInstruction(unot);
+ return;
+ }
+ Instruction::UNot unot;
+ unot.source = getParam(sourceTemp);
+ unot.result = getResultParam(targetTemp);
+ addInstruction(unot);
+ return;
+ }
+ case V4IR::OpUMinus: {
+ Instruction::UMinus uminus;
+ uminus.source = getParam(sourceTemp);
+ uminus.result = getResultParam(targetTemp);
+ addInstruction(uminus);
+ return;
+ }
+ case V4IR::OpUPlus: {
+ if (isNumberType(sourceTemp)) {
+ // use a move
+ Instruction::Move move;
+ move.source = getParam(sourceTemp);
+ move.result = getResultParam(targetTemp);
+ addInstruction(move);
+ return;
+ }
+ Instruction::UPlus uplus;
+ uplus.source = getParam(sourceTemp);
+ uplus.result = getResultParam(targetTemp);
+ addInstruction(uplus);
+ return;
+ }
+ case V4IR::OpCompl: {
+ // ### enabling this fails in some cases, where apparently the value is not a int at runtime
+ if (0 && isIntegerType(sourceTemp)) {
+ Instruction::UComplInt unot;
+ unot.source = getParam(sourceTemp);
+ unot.result = getResultParam(targetTemp);
+ addInstruction(unot);
+ return;
+ }
+ Instruction::UCompl ucompl;
+ ucompl.source = getParam(sourceTemp);
+ ucompl.result = getResultParam(targetTemp);
+ addInstruction(ucompl);
+ return;
+ }
+ case V4IR::OpIncrement: {
+ Instruction::Increment inc;
+ inc.source = getParam(sourceTemp);
+ inc.result = getResultParam(targetTemp);
+ addInstruction(inc);
+ return;
+ }
+ case V4IR::OpDecrement: {
+ Instruction::Decrement dec;
+ dec.source = getParam(sourceTemp);
+ dec.result = getResultParam(targetTemp);
+ addInstruction(dec);
+ return;
+ }
+ default: break;
} // switch
- if (op) {
- Instruction::Unop unop;
- unop.alu = op;
- unop.source = getParam(sourceTemp);
- unop.result = getResultParam(targetTemp);
- addInstruction(unop);
- } else {
- qWarning(" UNOP1");
- }
+ Q_ASSERT(!"unreachable");
}
void InstructionSelection::binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource, V4IR::Temp *target)
@@ -580,8 +687,84 @@ Param InstructionSelection::binopHelper(V4IR::AluOp oper, V4IR::Expr *leftSource
}
}
- if (_stackSlotAllocator && target && leftSource->asTemp())
- _stackSlotAllocator->addHint(*leftSource->asTemp(), *target);
+ if (oper == V4IR::OpAdd) {
+ Instruction::Add add;
+ add.lhs = getParam(leftSource);
+ add.rhs = getParam(rightSource);
+ add.result = getResultParam(target);
+ addInstruction(add);
+ return add.result;
+ }
+ if (oper == V4IR::OpSub) {
+ Instruction::Sub sub;
+ sub.lhs = getParam(leftSource);
+ sub.rhs = getParam(rightSource);
+ sub.result = getResultParam(target);
+ addInstruction(sub);
+ return sub.result;
+ }
+ if (oper == V4IR::OpMul) {
+ Instruction::Mul mul;
+ mul.lhs = getParam(leftSource);
+ mul.rhs = getParam(rightSource);
+ mul.result = getResultParam(target);
+ addInstruction(mul);
+ return mul.result;
+ }
+ if (oper == V4IR::OpBitAnd) {
+ if (leftSource->asConst())
+ qSwap(leftSource, rightSource);
+ if (V4IR::Const *c = rightSource->asConst()) {
+ Instruction::BitAndConst bitAnd;
+ bitAnd.lhs = getParam(leftSource);
+ bitAnd.rhs = convertToValue(c).Value::toInt32();
+ bitAnd.result = getResultParam(target);
+ addInstruction(bitAnd);
+ return bitAnd.result;
+ }
+ Instruction::BitAnd bitAnd;
+ bitAnd.lhs = getParam(leftSource);
+ bitAnd.rhs = getParam(rightSource);
+ bitAnd.result = getResultParam(target);
+ addInstruction(bitAnd);
+ return bitAnd.result;
+ }
+ if (oper == V4IR::OpBitOr) {
+ if (leftSource->asConst())
+ qSwap(leftSource, rightSource);
+ if (V4IR::Const *c = rightSource->asConst()) {
+ Instruction::BitOrConst bitOr;
+ bitOr.lhs = getParam(leftSource);
+ bitOr.rhs = convertToValue(c).Value::toInt32();
+ bitOr.result = getResultParam(target);
+ addInstruction(bitOr);
+ return bitOr.result;
+ }
+ Instruction::BitOr bitOr;
+ bitOr.lhs = getParam(leftSource);
+ bitOr.rhs = getParam(rightSource);
+ bitOr.result = getResultParam(target);
+ addInstruction(bitOr);
+ return bitOr.result;
+ }
+ if (oper == V4IR::OpBitXor) {
+ if (leftSource->asConst())
+ qSwap(leftSource, rightSource);
+ if (V4IR::Const *c = rightSource->asConst()) {
+ Instruction::BitXorConst bitXor;
+ bitXor.lhs = getParam(leftSource);
+ bitXor.rhs = convertToValue(c).Value::toInt32();
+ bitXor.result = getResultParam(target);
+ addInstruction(bitXor);
+ return bitXor.result;
+ }
+ Instruction::BitXor bitXor;
+ bitXor.lhs = getParam(leftSource);
+ bitXor.rhs = getParam(rightSource);
+ bitXor.result = getResultParam(target);
+ addInstruction(bitXor);
+ return bitXor.result;
+ }
if (oper == V4IR::OpInstanceof || oper == V4IR::OpIn || oper == V4IR::OpAdd) {
Instruction::BinopContext binop;
@@ -619,7 +802,7 @@ void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, qui
// We need to move all the temps into the function arg array
assert(argLocation >= 0);
while (e) {
- Instruction::MoveTemp move;
+ Instruction::Move move;
move.source = getParam(e->expr);
move.result = Param::createTemp(argLocation);
addInstruction(move);
@@ -684,24 +867,17 @@ void InstructionSelection::visitRet(V4IR::Ret *s)
addInstruction(ret);
}
-void InstructionSelection::visitTry(V4IR::Try *t)
-{
- Instruction::EnterTry enterTry;
- enterTry.tryOffset = 0;
- enterTry.catchOffset = 0;
- enterTry.exceptionVarName = registerString(*t->exceptionVarName);
- enterTry.exceptionVar = getParam(t->exceptionVar);
- ptrdiff_t enterTryLoc = addInstruction(enterTry);
-
- ptrdiff_t tryLoc = enterTryLoc + (((const char *)&enterTry.tryOffset) - ((const char *)&enterTry));
- _patches[t->tryBlock].append(tryLoc);
-
- ptrdiff_t catchLoc = enterTryLoc + (((const char *)&enterTry.catchOffset) - ((const char *)&enterTry));
- _patches[t->catchBlock].append(catchLoc);
-}
-
void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
+ if (useFastLookups && func->global) {
+ Instruction::CallGlobalLookup call;
+ call.index = registerGlobalGetterLookup(*func->id);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
+ call.result = getResultParam(result);
+ addInstruction(call);
+ return;
+ }
Instruction::CallActivationProperty call;
call.name = registerString(*func->id);
prepareCallArgs(args, call.argc);
@@ -775,10 +951,11 @@ void InstructionSelection::callBuiltinDeleteName(const QString &name, V4IR::Temp
void InstructionSelection::callBuiltinDeleteValue(V4IR::Temp *result)
{
- Instruction::LoadValue load;
- load.value = Param::createValue(QV4::Primitive::fromBoolean(false));
- load.result = getResultParam(result);
- addInstruction(load);
+ Instruction::Move move;
+ int idx = jsUnitGenerator()->registerConstant(QV4::Encode(false));
+ move.source = Param::createConstant(idx);
+ move.result = getResultParam(result);
+ addInstruction(move);
}
void InstructionSelection::callBuiltinThrow(V4IR::Expr *arg)
@@ -788,9 +965,35 @@ void InstructionSelection::callBuiltinThrow(V4IR::Expr *arg)
addInstruction(call);
}
-void InstructionSelection::callBuiltinFinishTry()
+void InstructionSelection::callBuiltinReThrow()
+{
+ if (_block->catchBlock) {
+ // jump to exception handler
+ Instruction::Jump jump;
+ jump.offset = 0;
+ ptrdiff_t loc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
+
+ _patches[_block->catchBlock].append(loc);
+ } else {
+ Instruction::Ret ret;
+ int idx = jsUnitGenerator()->registerConstant(QV4::Encode::undefined());
+ ret.result = Param::createConstant(idx);
+ addInstruction(ret);
+ }
+}
+
+void InstructionSelection::callBuiltinUnwindException(V4IR::Temp *result)
{
- Instruction::CallBuiltinFinishTry call;
+ Instruction::CallBuiltinUnwindException call;
+ call.result = getResultParam(result);
+ addInstruction(call);
+}
+
+
+void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionName)
+{
+ Instruction::CallBuiltinPushCatchScope call;
+ call.name = registerString(exceptionName);
addInstruction(call);
}
@@ -871,7 +1074,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4
bool isData = it->expr->asConst()->value;
it = it->next;
- Instruction::MoveTemp move;
+ Instruction::Move move;
move.source = getParam(it->expr);
move.result = Param::createTemp(argLocation);
addInstruction(move);
@@ -880,7 +1083,7 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4
if (!isData) {
it = it->next;
- Instruction::MoveTemp move;
+ Instruction::Move move;
move.source = getParam(it->expr);
move.result = Param::createTemp(argLocation);
addInstruction(move);
@@ -904,6 +1107,13 @@ void InstructionSelection::callBuiltinSetupArgumentObject(V4IR::Temp *result)
addInstruction(call);
}
+
+void QQmlJS::Moth::InstructionSelection::callBuiltinConvertThisToObject()
+{
+ Instruction::CallBuiltinConvertThisToObject call;
+ addInstruction(call);
+}
+
ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr)
{
#ifdef MOTH_THREADED_INTERPRETER
@@ -961,22 +1171,21 @@ QByteArray InstructionSelection::squeezeCode() const
}
Param InstructionSelection::getParam(V4IR::Expr *e) {
- typedef Param Param;
assert(e);
if (V4IR::Const *c = e->asConst()) {
- return Param::createValue(convertToValue(c));
+ int idx = jsUnitGenerator()->registerConstant(convertToValue(c).asReturnedValue());
+ return Param::createConstant(idx);
} else if (V4IR::Temp *t = e->asTemp()) {
switch (t->kind) {
case V4IR::Temp::Formal:
case V4IR::Temp::ScopedFormal: return Param::createArgument(t->index, t->scope);
case V4IR::Temp::Local: return Param::createLocal(t->index);
case V4IR::Temp::ScopedLocal: return Param::createScopedLocal(t->index, t->scope);
- case V4IR::Temp::VirtualRegister:
- return Param::createTemp(_stackSlotAllocator ?
- _stackSlotAllocator->stackSlotFor(t, _currentStatement) : t->index);
+ case V4IR::Temp::StackSlot:
+ return Param::createTemp(t->index);
default:
- Q_UNIMPLEMENTED();
+ Q_UNREACHABLE();
return Param();
}
} else {