V4: support calling constants.

Consider:
  function f() {
    var a;
    a();
  }

Here the constant propagation will propagate the value for a (undefined)
to the call site. This was not yet handled, resulting in Q_UNIMPLEMENTED
warnings when running a debug build.

Change-Id: I5f85f681d975b54df7a9e00bd5b50e6f4350139a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Erik Verbruggen 2014-05-09 13:10:16 +02:00 committed by The Qt Project
parent b366e5509b
commit bc9e86ef58
3 changed files with 22 additions and 6 deletions

View File

@ -239,7 +239,7 @@ void IRDecoder::visitExp(IR::Exp *s)
// These are calls where the result is ignored. // These are calls where the result is ignored.
if (c->base->asName()) { if (c->base->asName()) {
callBuiltin(c, 0); callBuiltin(c, 0);
} else if (c->base->asTemp() || c->base->asArgLocal()) { } else if (c->base->asTemp() || c->base->asArgLocal() || c->base->asConst()) {
callValue(c->base, c->args, 0); callValue(c->base, c->args, 0);
} else if (Member *member = c->base->asMember()) { } else if (Member *member = c->base->asMember()) {
Q_ASSERT(member->base->asTemp() || member->base->asArgLocal()); Q_ASSERT(member->base->asTemp() || member->base->asArgLocal());
@ -247,10 +247,10 @@ void IRDecoder::visitExp(IR::Exp *s)
} else if (Subscript *s = c->base->asSubscript()) { } else if (Subscript *s = c->base->asSubscript()) {
callSubscript(s->base, s->index, c->args, 0); callSubscript(s->base, s->index, c->args, 0);
} else { } else {
Q_UNIMPLEMENTED(); Q_UNREACHABLE();
} }
} else { } else {
Q_UNIMPLEMENTED(); Q_UNREACHABLE();
} }
} }

View File

@ -532,9 +532,14 @@ void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Ex
Q_ASSERT(value); Q_ASSERT(value);
prepareCallData(args, 0); prepareCallData(args, 0);
generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister, if (value->asConst())
Assembler::Reference(value), generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister,
baseAddressForCallData()); Assembler::PointerToValue(value),
baseAddressForCallData());
else
generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister,
Assembler::Reference(value),
baseAddressForCallData());
} }
void InstructionSelection::loadThisObject(IR::Expr *temp) void InstructionSelection::loadThisObject(IR::Expr *temp)

View File

@ -159,6 +159,8 @@ private slots:
void scopeOfEvaluate(); void scopeOfEvaluate();
void callConstants();
signals: signals:
void testSignal(); void testSignal();
}; };
@ -3050,6 +3052,15 @@ void tst_QJSEngine::scopeOfEvaluate()
QCOMPARE(result.toInt(), 42); QCOMPARE(result.toInt(), 42);
} }
void tst_QJSEngine::callConstants()
{
QJSEngine engine;
engine.evaluate("function f() {\n"
" var one; one();\n"
" var two = null; two();\n"
"}\n");
}
QTEST_MAIN(tst_QJSEngine) QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc" #include "tst_qjsengine.moc"