diff options
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 161 |
1 files changed, 108 insertions, 53 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index e0d259bd0c..edd479a0bd 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -45,7 +45,9 @@ #include <QtCore/QStack> #include <QScopeGuard> #include <private/qqmljsast_p.h> -#include <private/qv4string_p.h> +#include <private/qqmljslexer_p.h> +#include <private/qqmljsparser_p.h> +#include <private/qv4stringtoarrayindex_p.h> #include <private/qv4value_p.h> #include <private/qv4compilercontext_p.h> #include <private/qv4compilercontrolflow_p.h> @@ -274,7 +276,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) case Not: return Reference::fromConst(this, Encode(!v.toBoolean())); case UMinus: - return Reference::fromConst(this, Runtime::method_uMinus(v)); + return Reference::fromConst(this, Runtime::UMinus::call(v)); case UPlus: return expr; case Compl: @@ -289,12 +291,12 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) case UMinus: { expr.loadInAccumulator(); Instruction::UMinus uminus = {}; - bytecodeGenerator->addTracingInstruction(uminus); + bytecodeGenerator->addInstruction(uminus); return Reference::fromAccumulator(this); } case UPlus: { expr.loadInAccumulator(); - Instruction::UPlus uplus; + Instruction::UPlus uplus = {}; bytecodeGenerator->addInstruction(uplus); return Reference::fromAccumulator(this); } @@ -314,11 +316,11 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) if (!exprAccept(nx) || requiresReturnValue) { Reference e = expr.asLValue(); e.loadInAccumulator(); - Instruction::UPlus uplus; + Instruction::UPlus uplus = {}; bytecodeGenerator->addInstruction(uplus); Reference originalValue = Reference::fromStackSlot(this).storeRetainAccumulator(); Instruction::Increment inc = {}; - bytecodeGenerator->addTracingInstruction(inc); + bytecodeGenerator->addInstruction(inc); e.storeConsumeAccumulator(); return originalValue; } else { @@ -330,7 +332,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) Reference e = expr.asLValue(); e.loadInAccumulator(); Instruction::Increment inc = {}; - bytecodeGenerator->addTracingInstruction(inc); + bytecodeGenerator->addInstruction(inc); if (exprAccept(nx)) return e.storeConsumeAccumulator(); else @@ -340,11 +342,11 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) if (!exprAccept(nx) || requiresReturnValue) { Reference e = expr.asLValue(); e.loadInAccumulator(); - Instruction::UPlus uplus; + Instruction::UPlus uplus = {}; bytecodeGenerator->addInstruction(uplus); Reference originalValue = Reference::fromStackSlot(this).storeRetainAccumulator(); Instruction::Decrement dec = {}; - bytecodeGenerator->addTracingInstruction(dec); + bytecodeGenerator->addInstruction(dec); e.storeConsumeAccumulator(); return originalValue; } else { @@ -356,7 +358,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) Reference e = expr.asLValue(); e.loadInAccumulator(); Instruction::Decrement dec = {}; - bytecodeGenerator->addTracingInstruction(dec); + bytecodeGenerator->addInstruction(dec); if (exprAccept(nx)) return e.storeConsumeAccumulator(); else @@ -1139,7 +1141,7 @@ bool Codegen::visit(ArrayPattern *ast) index.loadInAccumulator(); Instruction::Increment inc = {}; - bytecodeGenerator->addTracingInstruction(inc); + bytecodeGenerator->addInstruction(inc); index.storeConsumeAccumulator(); }; @@ -1190,16 +1192,18 @@ bool Codegen::visit(ArrayPattern *ast) ControlFlowLoop flow(this, &end, &in, cleanup); in.link(); + bytecodeGenerator->addLoopStart(in); iterator.loadInAccumulator(); Instruction::IteratorNext next; next.value = lhsValue.stackSlot(); next.done = iteratorDone.stackSlot(); bytecodeGenerator->addInstruction(next); - bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpTrue()).link(end); + bytecodeGenerator->addJumpInstruction(Instruction::JumpTrue()).link(end); lhsValue.loadInAccumulator(); pushAccumulator(); + bytecodeGenerator->checkException(); bytecodeGenerator->jump().link(in); end.link(); } @@ -1241,7 +1245,7 @@ bool Codegen::visit(ArrayMemberExpression *ast) return false; if (AST::StringLiteral *str = AST::cast<AST::StringLiteral *>(ast->expression)) { QString s = str->value.toString(); - uint arrayIndex = QV4::String::toArrayIndex(s); + uint arrayIndex = stringToArrayIndex(s); if (arrayIndex == UINT_MAX) { setExprResult(Reference::fromMember(base, str->value.toString())); return false; @@ -1486,20 +1490,20 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re right.loadInAccumulator(); Instruction::Add add; add.lhs = left.stackSlot(); - bytecodeGenerator->addTracingInstruction(add); + bytecodeGenerator->addInstruction(add); break; } case QSOperator::Sub: { if (right.isConstant() && right.constant == Encode(int(1))) { left.loadInAccumulator(); Instruction::Decrement dec = {}; - bytecodeGenerator->addTracingInstruction(dec); + bytecodeGenerator->addInstruction(dec); } else { left = left.storeOnStack(); right.loadInAccumulator(); Instruction::Sub sub; sub.lhs = left.stackSlot(); - bytecodeGenerator->addTracingInstruction(sub); + bytecodeGenerator->addInstruction(sub); } break; } @@ -1516,7 +1520,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re right.loadInAccumulator(); Instruction::Mul mul; mul.lhs = left.stackSlot(); - bytecodeGenerator->addTracingInstruction(mul); + bytecodeGenerator->addInstruction(mul); break; } case QSOperator::Div: { @@ -1532,7 +1536,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re right.loadInAccumulator(); Instruction::Mod mod; mod.lhs = left.stackSlot(); - bytecodeGenerator->addTracingInstruction(mod); + bytecodeGenerator->addInstruction(mod); break; } case QSOperator::BitAnd: @@ -1901,7 +1905,7 @@ bool Codegen::visit(CallExpression *ast) call.thisObject = baseObject.stackSlot(); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } else { Instruction::TailCall call; call.func = base.stackSlot(); @@ -1930,14 +1934,14 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio call.lookupIndex = registerGetterLookup(base.propertyNameIndex); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } else { Instruction::CallProperty call; call.base = base.propertyBase.stackSlot(); call.name = base.propertyNameIndex; call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } } else if (base.type == Reference::Subscript) { Instruction::CallElement call; @@ -1945,33 +1949,33 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio call.index = base.elementSubscript.stackSlot(); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } else if (base.type == Reference::Name) { if (base.name == QStringLiteral("eval")) { Instruction::CallPossiblyDirectEval call; call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } else if (!disable_lookups && useFastLookups && base.global) { if (base.qmlGlobal) { Instruction::CallQmlContextPropertyLookup call; call.index = registerQmlContextPropertyGetterLookup(base.nameAsIndex()); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } else { Instruction::CallGlobalLookup call; call.index = registerGlobalGetterLookup(base.nameAsIndex()); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } } else { Instruction::CallName call; call.name = base.nameAsIndex(); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } } else if (base.type == Reference::SuperProperty) { Reference receiver = base.baseObject(); @@ -1988,14 +1992,14 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio call.thisObject = receiver.stackSlot(); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } else { Q_ASSERT(base.isStackSlot()); Instruction::CallValue call; call.name = base.stackSlot(); call.argc = calldata.argc; call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + bytecodeGenerator->addInstruction(call); } setExprResult(Reference::fromAccumulator(this)); @@ -2511,7 +2515,7 @@ bool Codegen::visit(ObjectPattern *ast) if (cname || p->type != PatternProperty::Literal) break; QString name = p->name->asString(); - uint arrayIndex = QV4::String::toArrayIndex(name); + uint arrayIndex = stringToArrayIndex(name); if (arrayIndex != UINT_MAX) break; if (members.contains(name)) @@ -2731,14 +2735,14 @@ bool Codegen::visit(TemplateLiteral *ast) Instruction::Add instr; instr.lhs = temp2; - bytecodeGenerator->addTracingInstruction(instr); + bytecodeGenerator->addInstruction(instr); } else { expr.loadInAccumulator(); } Instruction::Add instr; instr.lhs = temp; - bytecodeGenerator->addTracingInstruction(instr); + bytecodeGenerator->addInstruction(instr); } auto r = Reference::fromAccumulator(this); @@ -2996,7 +3000,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, bool savedFunctionEndsWithReturn = functionEndsWithReturn; functionEndsWithReturn = endsWithReturn(_module, body); - bytecodeGenerator->setTracing(_functionContext->canUseTracingJit(), _context->arguments.size()); // reserve the js stack frame (Context & js Function & accumulator) bytecodeGenerator->newRegisterArray(sizeof(CallData)/sizeof(Value) - 1 + _context->arguments.size()); @@ -3083,7 +3086,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, Q_ASSERT(_context == _functionContext); bytecodeGenerator->finalize(_context); _context->registerCountInFunction = bytecodeGenerator->registerCount(); - _context->nTraceInfos = bytecodeGenerator->traceInfoCount(); static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE"); if (showCode) { qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict @@ -3189,22 +3191,28 @@ bool Codegen::visit(DoWhileStatement *ast) BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); ControlFlowLoop flow(this, &end, &cond); - bytecodeGenerator->jump().link(body); - - cond.link(); - bytecodeGenerator->addLoopStart(cond); - if (!AST::cast<TrueLiteral *>(ast->expression)) { - TailCallBlocker blockTailCalls(this); - condition(ast->expression, &body, &end, true); - } + // special case that is not a loop: + // do {...} while (false) + if (!AST::cast<FalseLiteral *>(ast->expression)) + bytecodeGenerator->addLoopStart(body); body.link(); statement(ast->statement); setJumpOutLocation(bytecodeGenerator, ast->statement, ast->semicolonToken); - if (!AST::cast<FalseLiteral *>(ast->expression)) - bytecodeGenerator->jump().link(cond); + cond.link(); + if (AST::cast<TrueLiteral *>(ast->expression)) { + // do {} while (true) -> just jump back to the loop body, no need to generate a condition + bytecodeGenerator->checkException(); + bytecodeGenerator->jump().link(body); + } else if (AST::cast<FalseLiteral *>(ast->expression)) { + // do {} while (false) -> fall through, no need to generate a condition + } else { + TailCallBlocker blockTailCalls(this); + bytecodeGenerator->checkException(); + condition(ast->expression, &body, &end, false); + } end.link(); @@ -3283,7 +3291,7 @@ bool Codegen::visit(ForEachStatement *ast) next.value = lhsValue.stackSlot(); next.done = iteratorDone.stackSlot(); bytecodeGenerator->addInstruction(next); - bytecodeGenerator->addTracingJumpInstruction(Instruction::JumpTrue()).link(end); + bytecodeGenerator->addJumpInstruction(Instruction::JumpTrue()).link(end); // each iteration gets it's own context, as per spec { @@ -3319,6 +3327,7 @@ bool Codegen::visit(ForEachStatement *ast) setJumpOutLocation(bytecodeGenerator, ast->statement, ast->forToken); } + bytecodeGenerator->checkException(); bytecodeGenerator->jump().link(in); error: @@ -3367,6 +3376,7 @@ bool Codegen::visit(ForStatement *ast) bytecodeGenerator->addInstruction(clone); } statement(ast->expression); + bytecodeGenerator->checkException(); bytecodeGenerator->jump().link(cond); end.link(); @@ -3649,6 +3659,8 @@ bool Codegen::visit(WhileStatement *ast) ControlFlowLoop flow(this, &end, &cond); bytecodeGenerator->addLoopStart(cond); + bytecodeGenerator->checkException(); + if (!AST::cast<TrueLiteral *>(ast->expression)) { TailCallBlocker blockTailCalls(this); condition(ast->expression, &start, &end, true); @@ -3790,6 +3802,49 @@ QQmlRefPointer<CompiledData::CompilationUnit> Codegen::createUnitForLoading() return result; } +QQmlRefPointer<CompiledData::CompilationUnit> Codegen::compileModule( + bool debugMode, const QString &url, const QString &sourceCode, + const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics) +{ + QQmlJS::Engine ee; + QQmlJS::Lexer lexer(&ee); + lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false); + QQmlJS::Parser parser(&ee); + + const bool parsed = parser.parseModule(); + + if (diagnostics) + *diagnostics = parser.diagnosticMessages(); + + if (!parsed) + return nullptr; + + QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast<QQmlJS::AST::ESModule*>(parser.rootNode()); + if (!moduleNode) { + // if parsing was successful, and we have no module, then + // the file was empty. + if (diagnostics) + diagnostics->clear(); + return nullptr; + } + + using namespace QV4::Compiler; + Compiler::Module compilerModule(debugMode); + compilerModule.unitFlags |= CompiledData::Unit::IsESModule; + compilerModule.sourceTimeStamp = sourceTimeStamp; + JSUnitGenerator jsGenerator(&compilerModule); + Codegen cg(&jsGenerator, /*strictMode*/true); + cg.generateFromModule(url, url, sourceCode, moduleNode, &compilerModule); + auto errors = cg.errors(); + if (diagnostics) + *diagnostics << errors; + + if (!errors.isEmpty()) + return nullptr; + + return cg.generateCompilationUnit(); +} + class Codegen::VolatileMemoryLocationScanner: protected QQmlJS::AST::Visitor { VolatileMemoryLocations locs; @@ -4220,7 +4275,7 @@ void Codegen::Reference::storeAccumulator() const Instruction::StoreElement store; store.base = elementBase; store.index = elementSubscript.stackSlot(); - codegen->bytecodeGenerator->addTracingInstruction(store); + codegen->bytecodeGenerator->addInstruction(store); } return; case Invalid: case Accumulator: @@ -4310,12 +4365,12 @@ QT_WARNING_POP if (!scope) { Instruction::LoadLocal load; load.index = index; - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadScopedLocal load; load.index = index; load.scope = scope; - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } tdzCheck(requiresTDZCheck); return; @@ -4339,16 +4394,16 @@ QT_WARNING_POP if (qmlGlobal) { Instruction::LoadQmlContextPropertyLookup load; load.index = codegen->registerQmlContextPropertyGetterLookup(nameAsIndex()); - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadGlobalLookup load; load.index = codegen->registerGlobalGetterLookup(nameAsIndex()); - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } } else { Instruction::LoadName load; load.name = nameAsIndex(); - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } return; case Member: @@ -4357,11 +4412,11 @@ QT_WARNING_POP if (!disable_lookups && codegen->useFastLookups) { Instruction::GetLookup load; load.index = codegen->registerGetterLookup(propertyNameIndex); - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } else { Instruction::LoadProperty load; load.name = propertyNameIndex; - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } return; case Import: { @@ -4376,7 +4431,7 @@ QT_WARNING_POP tdzCheck(subscriptRequiresTDZCheck); Instruction::LoadElement load; load.base = elementBase; - codegen->bytecodeGenerator->addTracingInstruction(load); + codegen->bytecodeGenerator->addInstruction(load); } return; case Invalid: break; |