From: Erik Verbruggen Date: Tue, 4 Dec 2012 11:00:23 +0000 (+0100) Subject: Allow only the ExecutionEngine's StringPool to create Strings. X-Git-Tag: upstream/5.2.1~669^2~659^2~757 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=955f5f03afd9915b7f43ff07ce4b624a86c58a1a;p=platform%2Fupstream%2Fqtdeclarative.git Allow only the ExecutionEngine's StringPool to create Strings. Strings are the only non-Object Values living on the heap. So by tracking creation, we can help the future GC a lot. Change-Id: I5d5044f9ff10da42aeb75dd4a556d6ab3d839b1a Reviewed-by: Lars Knoll --- diff --git a/main.cpp b/main.cpp index 9090cd2..a516953 100644 --- a/main.cpp +++ b/main.cpp @@ -186,7 +186,7 @@ int compile(const QString &fileName, const QString &source, QQmlJS::LLVMOutputTy Codegen cg(0); // FIXME: if the program is empty, we should we generate an empty %entry, or give an error? - /*IR::Function *globalCode =*/ cg(program, &module); + /*IR::Function *globalCode =*/ cg(fileName, program, &module); int (*exec)(void *) = outputType == LLVMOutputJit ? executeLLVMCode : 0; return compileWithLLVM(&module, fileName, outputType, exec); diff --git a/qmljs_environment.cpp b/qmljs_environment.cpp index ce1bf9d..94a8775 100644 --- a/qmljs_environment.cpp +++ b/qmljs_environment.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include #include "debugging.h" #include #include @@ -48,27 +49,30 @@ namespace QQmlJS { namespace VM { DiagnosticMessage::DiagnosticMessage() - : fileName(0) - , offset(0) + : offset(0) , length(0) , startLine(0) , startColumn(0) , type(0) - , message(0) , next(0) {} +DiagnosticMessage::~DiagnosticMessage() +{ + delete next; +} + String *DiagnosticMessage::buildFullMessage(ExecutionContext *ctx) const { QString msg; - if (fileName) - msg = fileName->toQString() + QLatin1Char(':'); + if (!fileName.isEmpty()) + msg = fileName + QLatin1Char(':'); msg += QString::number(startLine) + QLatin1Char(':') + QString::number(startColumn) + QLatin1String(": "); if (type == QQmlJS::VM::DiagnosticMessage::Error) msg += QLatin1String("error"); else msg += QLatin1String("warning"); - msg += ": " + message->toQString(); + msg += ": " + message; return ctx->engine->newString(msg); } diff --git a/qmljs_environment.h b/qmljs_environment.h index 3457771..eb10b66 100644 --- a/qmljs_environment.h +++ b/qmljs_environment.h @@ -56,16 +56,17 @@ struct DiagnosticMessage { enum { Error, Warning }; - String *fileName; + QString fileName; quint32 offset; quint32 length; quint32 startLine; unsigned startColumn: 31; unsigned type: 1; - String *message; + QString message; DiagnosticMessage *next; DiagnosticMessage(); + ~DiagnosticMessage(); String *buildFullMessage(ExecutionContext *ctx) const; }; diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp index e2cb5cf..f12999b 100644 --- a/qmljs_objects.cpp +++ b/qmljs_objects.cpp @@ -543,14 +543,14 @@ QQmlJS::IR::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ct VM::DiagnosticMessage *error = 0, **errIt = &error; foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) { if (m.isError()) { - *errIt = new VM::DiagnosticMessage; // FIXME: should we ask the engine to create this object? - (*errIt)->fileName = ctx->engine->newString(fileName); + *errIt = new VM::DiagnosticMessage; + (*errIt)->fileName = fileName; (*errIt)->offset = m.loc.offset; (*errIt)->length = m.loc.length; (*errIt)->startLine = m.loc.startLine; (*errIt)->startColumn = m.loc.startColumn; (*errIt)->type = VM::DiagnosticMessage::Error; - (*errIt)->message = ctx->engine->newString(m.message); + (*errIt)->message = m.message; errIt = &(*errIt)->next; } else { std::cerr << qPrintable(fileName) << ':' << m.loc.startLine << ':' << m.loc.startColumn @@ -570,7 +570,7 @@ QQmlJS::IR::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ct } Codegen cg(ctx); - globalCode = cg(program, &module, mode); + globalCode = cg(fileName, program, &module, mode); if (globalCode) { // only generate other functions if global code generation succeeded. foreach (IR::Function *function, module.functions) { diff --git a/qmljs_objects.h b/qmljs_objects.h index cd9c243..2590b01 100644 --- a/qmljs_objects.h +++ b/qmljs_objects.h @@ -94,9 +94,6 @@ struct TypeErrorPrototype; struct URIErrorPrototype; struct String { - String(const QString &text) - : _text(text), _hashValue(0) {} - inline bool isEqualTo(const String *other) const { if (this == other) return true; @@ -117,6 +114,11 @@ struct String { } private: + friend struct StringPool; + String(const QString &text) + : _text(text), _hashValue(0) {} + +private: QString _text; mutable unsigned _hashValue; }; @@ -613,6 +615,7 @@ struct ReferenceErrorObject: ErrorObject { struct SyntaxErrorObject: ErrorObject { SyntaxErrorObject(ExecutionContext *ctx, DiagnosticMessage *msg); + ~SyntaxErrorObject() { delete msg; } virtual QString className() { return QStringLiteral("SyntaxError"); } virtual SyntaxErrorObject *asSyntaxError() { return this; } diff --git a/qv4codegen.cpp b/qv4codegen.cpp index 893bbb1..34c785d 100644 --- a/qv4codegen.cpp +++ b/qv4codegen.cpp @@ -371,10 +371,11 @@ Codegen::Codegen(VM::ExecutionContext *context) { } -IR::Function *Codegen::operator()(Program *node, IR::Module *module, Mode mode) +IR::Function *Codegen::operator()(const QString &fileName, Program *node, IR::Module *module, Mode mode) { assert(node); + _fileName = fileName; _module = module; _env = 0; @@ -399,8 +400,9 @@ IR::Function *Codegen::operator()(Program *node, IR::Module *module, Mode mode) return globalCode; } -IR::Function *Codegen::operator()(AST::FunctionExpression *ast, IR::Module *module) +IR::Function *Codegen::operator()(const QString &fileName, AST::FunctionExpression *ast, IR::Module *module) { + _fileName = fileName; _module = module; _env = 0; @@ -2270,9 +2272,10 @@ bool Codegen::visit(UiSourceElement *) void Codegen::throwSyntaxError(const SourceLocation &loc, const QString &detail) { VM::DiagnosticMessage *msg = new VM::DiagnosticMessage; + msg->fileName = _fileName; msg->offset = loc.begin(); msg->startLine = loc.startLine; msg->startColumn = loc.startColumn; - msg->message = new VM::String(detail); + msg->message = detail; _context->throwSyntaxError(msg); } diff --git a/qv4codegen_p.h b/qv4codegen_p.h index f1dca06..474e558 100644 --- a/qv4codegen_p.h +++ b/qv4codegen_p.h @@ -69,8 +69,8 @@ public: FunctionCode }; - IR::Function *operator()(AST::Program *ast, IR::Module *module, Mode mode = GlobalCode); - IR::Function *operator()(AST::FunctionExpression *ast, IR::Module *module); + IR::Function *operator()(const QString &fileName, AST::Program *ast, IR::Module *module, Mode mode = GlobalCode); + IR::Function *operator()(const QString &fileName, AST::FunctionExpression *ast, IR::Module *module); protected: enum Format { ex, cx, nx }; @@ -336,6 +336,7 @@ protected: void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail); private: + QString _fileName; Result _expr; QString _property; UiMember _uiMember; diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp index 99375d2..607c1f1 100644 --- a/qv4ecmaobjects.cpp +++ b/qv4ecmaobjects.cpp @@ -1893,7 +1893,7 @@ Value FunctionCtor::construct(ExecutionContext *ctx) IR::Module module; Codegen cg(ctx); - IR::Function *irf = cg(fe, &module); + IR::Function *irf = cg(QString(), fe, &module); EvalInstructionSelection *isel = ctx->engine->iselFactory->create(ctx->engine); isel->run(irf); @@ -2779,16 +2779,14 @@ Value ErrorPrototype::method_toString(ExecutionContext *ctx) if (!o) __qmljs_throw_type_error(ctx); - String n(QString::fromLatin1("name")); - Value name = o->__get__(ctx, &n); + Value name = o->__get__(ctx, ctx->engine->newString(QString::fromLatin1("name"))); QString qname; if (name.isUndefined()) qname = QString::fromLatin1("Error"); else qname = __qmljs_to_string(name, ctx).stringValue()->toQString(); - String m(QString::fromLatin1("message")); - Value message = o->__get__(ctx, &m); + Value message = o->__get__(ctx, ctx->engine->newString(QString::fromLatin1("message"))); QString qmessage; if (!message.isUndefined()) qmessage = __qmljs_to_string(message, ctx).stringValue()->toQString();