aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h24
-rw-r--r--src/qml/compiler/qv4codegen.cpp135
-rw-r--r--src/qml/compiler/qv4codegen_p.h3
-rw-r--r--src/qml/compiler/qv4compilercontrolflow_p.h74
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp9
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h17
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp13
7 files changed, 210 insertions, 65 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
index 81b64f96da..f53a720d2c 100644
--- a/src/qml/compiler/qv4bytecodegenerator_p.h
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -77,6 +77,14 @@ public:
index(generator->labels.size()) {
generator->labels.append(mode == LinkNow ? generator->instructions.size() : -1);
}
+ static Label returnLabel() {
+ Label l;
+ l.index = INT_MAX;
+ return l;
+ }
+ bool isReturn() const {
+ return index == INT_MAX;
+ }
void link() {
Q_ASSERT(index >= 0);
@@ -176,6 +184,22 @@ public:
return addJumpInstruction(data);
}
+ Q_REQUIRED_RESULT Jump jumpStrictEqualStackSlotInt(const StackSlot &lhs, int rhs)
+ {
+ Instruction::JumpStrictEqualStackSlotInt data;
+ data.lhs = lhs;
+ data.rhs = rhs;
+ return addJumpInstruction(data);
+ }
+
+ Q_REQUIRED_RESULT Jump jumpStrictNotEqualStackSlotInt(const StackSlot &lhs, int rhs)
+ {
+ Instruction::JumpStrictNotEqualStackSlotInt data;
+ data.lhs = lhs;
+ data.rhs = rhs;
+ return addJumpInstruction(data);
+ }
+
void setExceptionHandler(ExceptionHandler *handler)
{
currentExceptionHandler = handler;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 4fb34a677f..c795841f00 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -214,7 +214,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
return Reference::fromAccumulator(this);
}
case PostIncrement:
- if (!_expr.accept(nx)) {
+ if (!_expr.accept(nx) || requiresReturnValue) {
Reference e = expr.asLValue();
e.loadInAccumulator();
Instruction::UPlus uplus;
@@ -239,7 +239,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
return e.storeRetainAccumulator();
}
case PostDecrement:
- if (!_expr.accept(nx)) {
+ if (!_expr.accept(nx) || requiresReturnValue) {
Reference e = expr.asLValue();
e.loadInAccumulator();
Instruction::UPlus uplus;
@@ -361,13 +361,33 @@ void Codegen::program(Program *ast)
void Codegen::sourceElements(SourceElements *ast)
{
+ bool _requiresReturnValue = false;
+ qSwap(_requiresReturnValue, requiresReturnValue);
for (SourceElements *it = ast; it; it = it->next) {
+ if (!it->next)
+ qSwap(_requiresReturnValue, requiresReturnValue);
sourceElement(it->element);
if (hasError)
return;
}
}
+void Codegen::statementList(StatementList *ast)
+{
+ bool _requiresReturnValue = requiresReturnValue;
+ requiresReturnValue = false;
+ for (StatementList *it = ast; it; it = it->next) {
+ if (!it->next ||
+ it->next->statement->kind == Statement::Kind_BreakStatement ||
+ it->next->statement->kind == Statement::Kind_ContinueStatement ||
+ it->next->statement->kind == Statement::Kind_ReturnStatement)
+ requiresReturnValue = _requiresReturnValue;
+ statement(it->statement);
+ requiresReturnValue = false;
+ }
+ requiresReturnValue = _requiresReturnValue;
+}
+
void Codegen::variableDeclaration(VariableDeclaration *ast)
{
RegisterScope scope(this);
@@ -1761,14 +1781,39 @@ bool Codegen::visit(FunctionDeclaration * ast)
RegisterScope scope(this);
- if (_context->compilationMode == QmlBinding) {
+ if (_context->compilationMode == QmlBinding)
Reference::fromName(this, ast->name.toString()).loadInAccumulator();
- Reference::fromStackSlot(this, _returnAddress).storeConsumeAccumulator();
- }
_expr.accept(nx);
return false;
}
+static bool endsWithReturn(Node *node)
+{
+ if (!node)
+ return false;
+ if (AST::cast<ReturnStatement *>(node))
+ return true;
+ if (Program *p = AST::cast<Program *>(node))
+ return endsWithReturn(p->elements);
+ if (SourceElements *se = AST::cast<SourceElements *>(node)) {
+ while (se->next)
+ se = se->next;
+ return endsWithReturn(se->element);
+ }
+ if (StatementSourceElement *sse = AST::cast<StatementSourceElement *>(node))
+ return endsWithReturn(sse->statement);
+ if (StatementList *sl = AST::cast<StatementList *>(node)) {
+ while (sl->next)
+ sl = sl->next;
+ return endsWithReturn(sl->statement);
+ }
+ if (Block *b = AST::cast<Block *>(node))
+ return endsWithReturn(b->statements);
+ if (IfStatement *is = AST::cast<IfStatement *>(node))
+ return is->ko && endsWithReturn(is->ok) && endsWithReturn(is->ko);
+ return false;
+}
+
int Codegen::defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
AST::SourceElements *body)
@@ -1797,8 +1842,11 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
// allocate the js stack frame (Context & js Function & accumulator)
bytecodeGenerator->newRegisterArray(sizeof(JSStackFrame)/sizeof(Value));
- int returnAddress = bytecodeGenerator->newRegister();
-
+ int returnAddress = -1;
+ bool _requiresReturnValue = (_context->compilationMode == QmlBinding || _context->compilationMode == EvalCode);
+ qSwap(requiresReturnValue, _requiresReturnValue);
+ if (requiresReturnValue)
+ returnAddress = bytecodeGenerator->newRegister();
if (!_context->parent || _context->usesArgumentsObject == Context::ArgumentsObjectUnknown)
_context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
if (_context->usesArgumentsObject == Context::ArgumentsObjectUsed)
@@ -1830,11 +1878,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
}
}
- auto exitBlock = bytecodeGenerator->newLabel();
-
- qSwap(_exitBlock, exitBlock);
qSwap(_returnAddress, returnAddress);
-
for (const Context::Member &member : qAsConst(_context->members)) {
if (member.function) {
const int function = defineFunction(member.function->name.toString(), member.function, member.function->formals,
@@ -1870,13 +1914,17 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
sourceElements(body);
- _exitBlock.link();
- bytecodeGenerator->setLocation(ast->lastSourceLocation());
-
- {
- Instruction::Ret ret;
- ret.result = Reference::fromStackSlot(this, _returnAddress).theStackSlot;
- bytecodeGenerator->addInstruction(ret);
+ if (hasError || !endsWithReturn(body)) {
+ if (requiresReturnValue) {
+ if (_returnAddress >= 0) {
+ Instruction::LoadReg load;
+ load.reg = Moth::StackSlot::createRegister(_returnAddress);
+ bytecodeGenerator->addInstruction(load);
+ }
+ } else {
+ Reference::fromConst(this, Encode::undefined()).loadInAccumulator();
+ }
+ bytecodeGenerator->addInstruction(Instruction::Ret());
}
_context->code = bytecodeGenerator->finalize();
@@ -1889,9 +1937,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
qDebug();
}
- qSwap(_exitBlock, exitBlock);
qSwap(_returnAddress, returnAddress);
-
+ qSwap(requiresReturnValue, _requiresReturnValue);
bytecodeGenerator = savedBytecodeGenerator;
return leaveContext();
@@ -1922,9 +1969,7 @@ bool Codegen::visit(Block *ast)
RegisterScope scope(this);
- for (StatementList *it = ast->statements; it; it = it->next) {
- statement(it->statement);
- }
+ statementList(ast->statements);
return false;
}
@@ -2022,7 +2067,7 @@ bool Codegen::visit(ExpressionStatement *ast)
RegisterScope scope(this);
- if (_context->compilationMode == EvalCode || _context->compilationMode == QmlBinding) {
+ if (requiresReturnValue) {
Reference e = expression(ast->expression);
if (hasError)
return false;
@@ -2122,10 +2167,15 @@ bool Codegen::visit(IfStatement *ast)
trueLabel.link();
statement(ast->ok);
if (ast->ko) {
- BytecodeGenerator::Jump jump_endif = bytecodeGenerator->jump();
- falseLabel.link();
- statement(ast->ko);
- jump_endif.link();
+ if (endsWithReturn(ast)) {
+ falseLabel.link();
+ statement(ast->ko);
+ } else {
+ BytecodeGenerator::Jump jump_endif = bytecodeGenerator->jump();
+ falseLabel.link();
+ statement(ast->ko);
+ jump_endif.link();
+ }
} else {
falseLabel.link();
}
@@ -2253,19 +2303,25 @@ bool Codegen::visit(ReturnStatement *ast)
throwSyntaxError(ast->returnToken, QStringLiteral("Return statement outside of function"));
return false;
}
+ Reference expr;
if (ast->expression) {
- Reference expr = expression(ast->expression);
+ expr = expression(ast->expression);
if (hasError)
return false;
- expr.loadInAccumulator();
- Reference::fromStackSlot(this, _returnAddress).storeConsumeAccumulator();
+ } else {
+ expr = Reference::fromConst(this, Encode::undefined());
}
- if (_context->controlFlow) {
+ if (_context->controlFlow && _context->controlFlow->returnRequiresUnwind()) {
+ if (_returnAddress >= 0)
+ (void) expr.storeOnStack(_returnAddress);
+ else
+ expr.loadInAccumulator();
ControlFlow::Handler h = _context->controlFlow->getHandler(ControlFlow::Return);
_context->controlFlow->jumpToHandler(h);
} else {
- bytecodeGenerator->jump().link(_exitBlock);
+ expr.loadInAccumulator();
+ bytecodeGenerator->addInstruction(Instruction::Ret());
}
return false;
}
@@ -2324,24 +2380,21 @@ bool Codegen::visit(SwitchStatement *ast)
CaseClause *clause = it->clause;
blockMap[clause].link();
- for (StatementList *it2 = clause->statements; it2; it2 = it2->next)
- statement(it2->statement);
+ statementList(clause->statements);
}
if (ast->block->defaultClause) {
DefaultClause *clause = ast->block->defaultClause;
blockMap[clause].link();
- for (StatementList *it2 = clause->statements; it2; it2 = it2->next)
- statement(it2->statement);
+ statementList(clause->statements);
}
for (CaseClauses *it = ast->block->moreClauses; it; it = it->next) {
CaseClause *clause = it->clause;
blockMap[clause].link();
- for (StatementList *it2 = clause->statements; it2; it2 = it2->next)
- statement(it2->statement);
+ statementList(clause->statements);
}
switchEnd.link();
@@ -2437,6 +2490,8 @@ bool Codegen::visit(WhileStatement *ast)
if (hasError)
return true;
+ RegisterScope scope(this);
+
BytecodeGenerator::Label start = bytecodeGenerator->newLabel();
BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
BytecodeGenerator::Label cond = bytecodeGenerator->label();
@@ -2449,7 +2504,6 @@ bool Codegen::visit(WhileStatement *ast)
bytecodeGenerator->jump().link(cond);
end.link();
-
return false;
}
@@ -3037,4 +3091,3 @@ void Codegen::Reference::loadInAccumulator() const
Q_ASSERT(false);
Q_UNREACHABLE();
}
-
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index f55ef026a8..0d63854ed1 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -484,6 +484,7 @@ protected:
void functionBody(AST::FunctionBody *ast);
void program(AST::Program *ast);
void sourceElements(AST::SourceElements *ast);
+ void statementList(AST::StatementList *ast);
void variableDeclaration(AST::VariableDeclaration *ast);
void variableDeclarationList(AST::VariableDeclarationList *ast);
@@ -623,7 +624,6 @@ protected:
friend struct ControlFlowFinally;
Result _expr;
Module *_module;
- BytecodeGenerator::Label _exitBlock;
int _returnAddress;
Context *_context;
AST::LabelledStatement *_labelledStatement;
@@ -631,6 +631,7 @@ protected:
BytecodeGenerator *bytecodeGenerator = 0;
bool _strictMode;
bool useFastLookups = true;
+ bool requiresReturnValue = false;
bool _fileNameIsUrl;
bool hasError;
diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h
index f8efd010a3..354015a542 100644
--- a/src/qml/compiler/qv4compilercontrolflow_p.h
+++ b/src/qml/compiler/qv4compilercontrolflow_p.h
@@ -103,10 +103,34 @@ struct ControlFlow {
cg->_context->controlFlow = parent;
}
+ void emitReturnStatement() const {
+ if (cg->_returnAddress >= 0) {
+ Instruction::LoadReg load;
+ load.reg = Moth::StackSlot::createRegister(cg->_returnAddress);
+ generator()->addInstruction(load);
+ }
+ Instruction::Ret ret;
+ cg->bytecodeGenerator->addInstruction(ret);
+ }
+
void jumpToHandler(const Handler &h) {
- if (h.tempIndex >= 0)
- Reference::storeConstOnStack(cg, QV4::Encode(h.value), h.tempIndex);
- cg->bytecodeGenerator->jump().link(h.linkLabel);
+ if (h.linkLabel.isReturn()) {
+ emitReturnStatement();
+ } else {
+ if (h.tempIndex >= 0)
+ Reference::storeConstOnStack(cg, QV4::Encode(h.value), h.tempIndex);
+ cg->bytecodeGenerator->jump().link(h.linkLabel);
+ }
+ }
+
+ bool returnRequiresUnwind() const {
+ const ControlFlow *f = this;
+ while (f) {
+ if (f->type == Finally)
+ return true;
+ f = f->parent;
+ }
+ return false;
}
virtual QString label() const { return QString(); }
@@ -124,7 +148,7 @@ struct ControlFlow {
return { Invalid, QString(), {}, -1, 0 };
case Return:
case Throw:
- return { type, QString(), cg->_exitBlock, -1, 0 };
+ return { type, QString(), BytecodeGenerator::Label::returnLabel(), -1, 0 };
case Invalid:
break;
}
@@ -132,17 +156,17 @@ struct ControlFlow {
Q_UNREACHABLE();
}
- virtual Handler getHandler(HandlerType type, const QString &label = QString()) {
- return getParentHandler(type, label);
- }
+ virtual Handler getHandler(HandlerType type, const QString &label = QString()) = 0;
- virtual BytecodeGenerator::ExceptionHandler *exceptionHandler() {
- return parent ? parent->exceptionHandler() : 0;
- }
BytecodeGenerator::ExceptionHandler *parentExceptionHandler() {
return parent ? parent->exceptionHandler() : 0;
}
+ virtual BytecodeGenerator::ExceptionHandler *exceptionHandler() {
+ return parentExceptionHandler();
+ }
+
+
virtual void handleThrow(const Reference &expr) {
Reference e = expr;
Handler h = getHandler(ControlFlow::Throw);
@@ -199,7 +223,7 @@ struct ControlFlowLoop : public ControlFlow
Q_ASSERT(false);
Q_UNREACHABLE();
}
- return ControlFlow::getHandler(type, label);
+ return getParentHandler(type, label);
}
};
@@ -226,21 +250,24 @@ struct ControlFlowUnwind : public ControlFlow
Reference temp = Reference::fromStackSlot(cg, controlFlowTemp);
for (const auto &h : qAsConst(handlers)) {
- Codegen::RegisterScope tempScope(cg);
Handler parentHandler = getParentHandler(h.type, h.label);
if (h.type == Throw || parentHandler.tempIndex >= 0) {
BytecodeGenerator::Label skip = generator()->newLabel();
- Reference::fromConst(cg, QV4::Encode(h.value)).loadInAccumulator();
- generator()->jumpStrictNotEqual(temp.stackSlot()).link(skip);
+ generator()->jumpStrictNotEqualStackSlotInt(temp.stackSlot(), h.value).link(skip);
if (h.type == Throw)
emitForThrowHandling();
- Reference::storeConstOnStack(cg, QV4::Encode(parentHandler.value), parentHandler.tempIndex);
- generator()->jump().link(parentHandler.linkLabel);
+ jumpToHandler(parentHandler);
skip.link();
} else {
- Reference::fromConst(cg, QV4::Encode(h.value)).loadInAccumulator();
- generator()->jumpStrictEqual(temp.stackSlot()).link(parentHandler.linkLabel);
+ if (parentHandler.linkLabel.isReturn()) {
+ BytecodeGenerator::Label skip = generator()->newLabel();
+ generator()->jumpStrictNotEqualStackSlotInt(temp.stackSlot(), h.value).link(skip);
+ emitReturnStatement();
+ skip.link();
+ } else {
+ generator()->jumpStrictEqualStackSlotInt(temp.stackSlot(), h.value).link(parentHandler.linkLabel);
+ }
}
}
}
@@ -389,7 +416,7 @@ struct ControlFlowFinally : public ControlFlowUnwind
// if we're inside the finally block, any exceptions etc. should
// go directly to the parent handler
if (insideFinally)
- return ControlFlow::getHandler(type, label);
+ return getParentHandler(type, label);
return ControlFlowUnwind::getHandler(type, label);
}
@@ -403,6 +430,11 @@ struct ControlFlowFinally : public ControlFlowUnwind
Codegen::RegisterScope scope(cg);
+ Moth::StackSlot retVal = Moth::StackSlot::createRegister(generator()->newRegister());
+ Instruction::StoreReg storeRetVal;
+ storeRetVal.reg = retVal;
+ generator()->addInstruction(storeRetVal);
+
insideFinally = true;
exceptionTemp = generator()->newRegister();
Instruction::GetException instr;
@@ -413,6 +445,10 @@ struct ControlFlowFinally : public ControlFlowUnwind
cg->statement(finally->statement);
insideFinally = false;
+ Instruction::LoadReg loadRetVal;
+ loadRetVal.reg = retVal;
+ generator()->addInstruction(loadRetVal);
+
emitUnwindHandler();
}
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index b3034e8b81..ed2f556e01 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -405,6 +405,14 @@ void dumpBytecode(const char *code, int len, int nFormals)
d << instr.lhs.dump(nFormals) << " " << absoluteInstructionOffset(start, instr);
MOTH_END_INSTR(JumpStrictNotEqual)
+ MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt)
+ d << instr.lhs.dump(nFormals) << ", " << instr.rhs << " " << absoluteInstructionOffset(start, instr);
+ MOTH_END_INSTR(JumpStrictEqualStackSlotInt)
+
+ MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt)
+ d << instr.lhs.dump(nFormals) << ", " << instr.rhs << " " << absoluteInstructionOffset(start, instr);
+ MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
+
MOTH_BEGIN_INSTR(UNot)
MOTH_END_INSTR(UNot)
@@ -484,7 +492,6 @@ void dumpBytecode(const char *code, int len, int nFormals)
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(Ret)
- d << instr.result.dump(nFormals);
MOTH_END_INSTR(Ret)
#ifndef QT_NO_QML_DEBUGGER
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 63b117dc0e..d07e44c41b 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -144,6 +144,8 @@ QT_BEGIN_NAMESPACE
F(CmpJmpLe, cmpJmpLe) \
F(JumpStrictEqual, jumpStrictEqual) \
F(JumpStrictNotEqual, jumpStrictNotEqual) \
+ F(JumpStrictEqualStackSlotInt, jumpStrictEqualStackSlotInt) \
+ F(JumpStrictNotEqualStackSlotInt, jumpStrictNotEqualStackSlotInt) \
F(UNot, unot) \
F(UPlus, uplus) \
F(UMinus, uminus) \
@@ -247,7 +249,6 @@ union Instr
};
struct instr_ret {
MOTH_INSTR_HEADER
- StackSlot result;
};
#ifndef QT_NO_QML_DEBUGGING
@@ -597,6 +598,18 @@ union Instr
ptrdiff_t offset;
StackSlot lhs;
};
+ struct instr_jumpStrictEqualStackSlotInt {
+ MOTH_INSTR_HEADER
+ ptrdiff_t offset;
+ StackSlot lhs;
+ int rhs;
+ };
+ struct instr_jumpStrictNotEqualStackSlotInt {
+ MOTH_INSTR_HEADER
+ ptrdiff_t offset;
+ StackSlot lhs;
+ int rhs;
+ };
struct instr_unot {
MOTH_INSTR_HEADER
};
@@ -770,6 +783,8 @@ union Instr
instr_cmpJmpLe cmpJmpLe;
instr_jumpStrictEqual jumpStrictEqual;
instr_jumpStrictNotEqual jumpStrictNotEqual;
+ instr_jumpStrictEqualStackSlotInt jumpStrictEqualStackSlotInt;
+ instr_jumpStrictNotEqualStackSlotInt jumpStrictNotEqualStackSlotInt;
instr_unot unot;
instr_uplus uplus;
instr_uminus uminus;
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index efab04b32d..b17341e5e5 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -640,7 +640,7 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat
MOTH_BEGIN_INSTR(ThrowException)
Runtime::method_throwException(engine, accumulator);
- CHECK_EXCEPTION;
+ goto catchException;
MOTH_END_INSTR(ThrowException)
MOTH_BEGIN_INSTR(GetException)
@@ -905,6 +905,16 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat
}
MOTH_END_INSTR(JumpStrictNotEqual)
+ MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt)
+ if (STACK_VALUE(instr.lhs).int_32() != instr.rhs || STACK_VALUE(instr.lhs).isUndefined())
+ code = reinterpret_cast<const uchar *>(&instr.offset) + instr.offset;
+ MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
+
+ MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt)
+ if (STACK_VALUE(instr.lhs).int_32() == instr.rhs && !STACK_VALUE(instr.lhs).isUndefined())
+ code = reinterpret_cast<const uchar *>(&instr.offset) + instr.offset;
+ MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt)
+
MOTH_BEGIN_INSTR(UNot)
if (accumulator.integerCompatible()) {
STORE_ACCUMULATOR(Encode(!static_cast<bool>(accumulator.int_32())))
@@ -1039,7 +1049,6 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(Ret)
- accumulator = STACK_VALUE(instr.result).asReturnedValue();
goto functionExit;
MOTH_END_INSTR(Ret)