Source

Target

Commits (27)
Showing with 273 additions and 119 deletions
......@@ -223,8 +223,8 @@ Rectangle {
lowp vec4 tr = texture2D(source, qt_TexCoord0 + vec2(delta.x, -delta.y));
lowp vec4 bl = texture2D(source, qt_TexCoord0 - vec2(delta.x, -delta.y));
lowp vec4 br = texture2D(source, qt_TexCoord0 + delta);
lowp vec4 gx = (tl + bl) - (tr + br);
lowp vec4 gy = (tl + tr) - (bl + br);
mediump vec4 gx = (tl + bl) - (tr + br);
mediump vec4 gy = (tl + tr) - (bl + br);
gl_FragColor.xyz = vec3(0.);
gl_FragColor.w = clamp(dot(sqrt(gx * gx + gy * gy), vec4(1.)), 0., 1.) * qt_Opacity;
}"
......
......@@ -37,16 +37,14 @@
// ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
// instruction address on the platform (for example, check any alignment requirements).
// (Disabled checks on Android/ARM because we want to intermix thumb and arm)
#if CPU(ARM_THUMB2) && !defined(Q_OS_ANDROID)
#if CPU(ARM_THUMB2)
// ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded
// into the processor are decorated with the bottom bit set, indicating that this is
// thumb code (as oposed to 32-bit traditional ARM). The first test checks for both
// decorated and undectorated null, and the second test ensures that the pointer is
// decorated.
#define ASSERT_VALID_CODE_POINTER(ptr) \
ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1); \
ASSERT(reinterpret_cast<intptr_t>(ptr) & 1)
ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1);
#define ASSERT_VALID_CODE_OFFSET(offset) \
ASSERT(!(offset & 1)) // Must be multiple of 2.
#else
......
......@@ -197,6 +197,11 @@ public:
return Call(m_assembler.call(), Call::Linkable);
}
void callToRetrieveIP()
{
m_assembler.call();
}
// Address is a memory location containing the address to jump to
void jump(AbsoluteAddress address)
{
......
......@@ -136,6 +136,11 @@ public:
return result;
}
void callToRetrieveIP()
{
m_assembler.call();
}
// Address is a memory location containing the address to jump to
void jump(AbsoluteAddress address)
{
......
......@@ -116,8 +116,10 @@ static Opcode32GroupInitializer opcode32BitGroupList[] = {
OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeDataProcessingShiftedReg),
OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVSinglePrecision),
OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVDoublePrecision),
OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVLDRVSTR),
OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeFPTransfer),
OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVMSR),
OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVADDVSUB),
OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingModifiedImmediate),
OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeConditionalBranchT3),
OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchOrBranchLink),
......@@ -1561,6 +1563,45 @@ const char* ARMv7DOpcodeVMSR::format()
return m_formatBuffer;
}
const char* ARMv7DOpcodeVADDVSUB::format()
{
char regPrefix = sz() ? 'd' : 's';
if (isSub())
appendInstructionName("vsub");
else
appendInstructionName("vadd");
appendFPRegisterName(regPrefix, vd());
appendSeparator();
appendFPRegisterName(regPrefix, vn());
appendSeparator();
appendFPRegisterName(regPrefix, vm());
return m_formatBuffer;
}
const char* ARMv7DOpcodeVLDRVSTR::format()
{
appendInstructionName(opName());
char regPrefix = sz() ? 'd' : 's';
appendFPRegisterName(regPrefix, vd());
appendSeparator();
appendCharacter('[');
appendRegisterName(rn());
if (immediate8() || !uBit()) {
appendSeparator();
if (uBit())
appendUnsignedImmediate(immediate8() << 2);
else
appendSignedImmediate(0 - static_cast<int>(immediate8() << 2));
}
appendCharacter(']');
return m_formatBuffer;
}
} } // namespace JSC::ARMv7Disassembler
#endif // #if USE(ARMV7_DISASSEMBLER)
......@@ -1132,6 +1132,42 @@ protected:
unsigned rt() { return (m_opcode >> 12) & 0xf; }
};
class ARMv7DOpcodeVADDVSUB : public ARMv7D32BitOpcode {
public:
static const uint32_t s_mask = 0xffb00e50;
static const uint32_t s_pattern = 0xee300a00;
DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVADDVSUB, thisObj);
protected:
const char* format();
unsigned sz() { return (m_opcode >> 8) & 0x1; }
unsigned isSub() { return (m_opcode >> 6) & 0x1; }
unsigned vm() { return (m_opcode & 0xf) | ((m_opcode >> 1) & 0x10); }
unsigned vn() { return ((m_opcode >> 16) & 0xf) | ((m_opcode >> 3) & 0x10); }
unsigned vd() { return ((m_opcode >> 12) & 0xf) | ((m_opcode >> 18) & 0x10); }
};
class ARMv7DOpcodeVLDRVSTR : public ARMv7D32BitOpcode {
public:
static const uint32_t s_mask = 0xff200a00;
static const uint32_t s_pattern = 0xed000a00;
DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVLDRVSTR, thisObj);
protected:
const char* format();
const char *opName() { return op() ? "vldr" : "vstr"; }
unsigned sz() { return (m_opcode >> 8) & 0x1; }
unsigned op() { return (m_opcode >> 20) & 0x1; }
unsigned uBit() { return (m_opcode >> 23) & 0x1; }
unsigned rn() { return (m_opcode >> 16) & 0xf; }
unsigned vd() { return ((m_opcode >> 12) & 0xf) | ((m_opcode >> 18) & 0x10); }
unsigned immediate8() { return m_opcode & 0xff; }
};
} } // namespace JSC::ARMv7Disassembler
......
wince*: CONFIG += disable_jit
ios: CONFIG += disable_jit
if(win*:isEqual(QT_ARCH, "x86_64")): CONFIG += disable_jit
equals(ANDROID_TARGET_ARCH, armeabi): CONFIG += disable_jit
disable_jit: DEFINES += ENABLE_YARR_JIT=0
else: DEFINES += V4_ENABLE_JIT ENABLE_YARR_JIT=1
# On Qt/Android/ARM release builds are thumb and debug builds arm,
# but we'll force the JIT to always generate thumb2
contains(DEFINES, V4_ENABLE_JIT):android:isEqual(QT_ARCH, "arm") {
DEFINES += WTF_CPU_ARM_THUMB2
}
DEFINES += WTF_EXPORT_PRIVATE="" JS_EXPORT_PRIVATE=""
win*: DEFINES += NOMINMAX
......@@ -22,11 +8,8 @@ DEFINES += ENABLE_LLINT=0
DEFINES += ENABLE_DFG_JIT=0
DEFINES += ENABLE_DFG_JIT_UTILITY_METHODS=1
DEFINES += ENABLE_JIT_CONSTANT_BLINDING=0
DEFINES += ENABLE_ASSEMBLER=1
DEFINES += BUILDING_QT__
DEFINES += ENABLE_JIT=1
INCLUDEPATH += $$PWD/jit
INCLUDEPATH += $$PWD/assembler
INCLUDEPATH += $$PWD/runtime
......@@ -47,3 +30,5 @@ INCLUDEPATH += $$PWD/disassembler/udis86
INCLUDEPATH += $$_OUT_PWD
win32-msvc2008|wince*: INCLUDEPATH += $$PWD/stubs/compat
CONFIG(release, debug|release): DEFINES += NDEBUG
contains(DEFINES, V4_ENABLE_JIT) {
HEADERS += $$PWD/assembler/*.h
SOURCES += $$PWD/assembler/ARMAssembler.cpp
SOURCES += $$PWD/assembler/ARMv7Assembler.cpp
SOURCES += $$PWD/assembler/MacroAssemblerARM.cpp
SOURCES += $$PWD/assembler/MacroAssemblerSH4.cpp
SOURCES += $$PWD/assembler/LinkBuffer.cpp
}
HEADERS += $$PWD/assembler/*.h
SOURCES += $$PWD/assembler/ARMv7Assembler.cpp
SOURCES += $$PWD/assembler/LinkBuffer.cpp
HEADERS += $$PWD/wtf/*.h
SOURCES += $$PWD/wtf/PrintStream.cpp
......
......@@ -109,8 +109,9 @@ void dataLogFString(const char* str)
extern "C" {
void WTFReportAssertionFailure(const char* /*file*/, int /*line*/, const char* /*function*/, const char* /*assertion*/)
void WTFReportAssertionFailure(const char* file, int line, const char* function, const char*assertion)
{
fprintf(stderr, "WTF failing assertion in %s, line %d, function %s: %s\n", file, line, function, assertion);
}
void WTFReportBacktrace()
......
......@@ -123,6 +123,7 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x
#if COMPILER(MSVC)
#if _MSC_VER < 1800
// We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss.
static double round(double num)
{
......@@ -138,6 +139,7 @@ static float roundf(float num)
return integer - num > 0.5f ? integer - 1.0f : integer;
return integer - num >= 0.5f ? integer - 1.0f : integer;
}
#endif
inline long long llround(double num) { return static_cast<long long>(round(num)); }
inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); }
inline long lround(double num) { return static_cast<long>(round(num)); }
......
......@@ -28,6 +28,10 @@
#ifndef WTF_Platform_h
#define WTF_Platform_h
#if defined(__cplusplus)
#include <private/qv4global_p.h>
#endif
/* Include compiler specific macros */
#include <wtf/Compiler.h>
......@@ -767,7 +771,8 @@
#endif
/* If the jit is not available, enable the LLInt C Loop: */
#if !ENABLE(JIT)
/* Not for Qml. We have our own interpreter. */
#if 0 /* !ENABLE(JIT) */
#undef ENABLE_LLINT /* Undef so that we can redefine it. */
#undef ENABLE_LLINT_C_LOOP /* Undef so that we can redefine it. */
#undef ENABLE_DFG_JIT /* Undef so that we can redefine it. */
......@@ -778,7 +783,7 @@
/* Do a sanity check to make sure that we at least have one execution engine in
use: */
#if !(ENABLE(JIT) || ENABLE(LLINT))
#if 0 /* !(ENABLE(JIT) || ENABLE(LLINT)) */
#error You have to have at least one execution model enabled to build JSC
#endif
......
......@@ -37,7 +37,7 @@ HEADERS += \
qquickfontdialog_p.h \
qquickabstractdialog_p.h
QML_FILES += \
DIALOGS_QML_FILES += \
DefaultMessageDialog.qml \
WidgetMessageDialog.qml \
DefaultFileDialog.qml \
......@@ -76,7 +76,7 @@ RESOURCE_CONTENT = \
"<RCC>" \
"<qresource prefix=\"/QtQuick/Dialogs\">"
for(resourcefile, QML_FILES) {
for(resourcefile, DIALOGS_QML_FILES) {
resourcefileabsolutepath = $$absolute_path($$resourcefile)
relativepath_in = $$relative_path($$resourcefileabsolutepath, $$_PRO_FILE_PWD_)
relativepath_out = $$relative_path($$resourcefileabsolutepath, $$OUT_PWD)
......@@ -91,4 +91,7 @@ write_file($$GENERATED_RESOURCE_FILE, RESOURCE_CONTENT)|error("Aborting.")
RESOURCES += $$GENERATED_RESOURCE_FILE
# In case of a debug build, deploy the QML files too
CONFIG(debug, debug|release): QML_FILES += $$DIALOGS_QML_FILES
load(qml_plugin)
......@@ -193,9 +193,11 @@ void QQuickFolderListModelPrivate::_q_sortFinished(const QList<FileProperty> &li
Q_Q(QQuickFolderListModel);
QModelIndex parent;
q->beginRemoveRows(parent, 0, data.size()-1);
data.clear();
q->endRemoveRows();
if (data.size() > 0) {
q->beginRemoveRows(parent, 0, data.size()-1);
data.clear();
q->endRemoveRows();
}
q->beginInsertRows(parent, 0, list.size()-1);
data = list;
......
......@@ -322,6 +322,35 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx)
return result.asReturnedValue();
}
struct TransactionRollback {
QSqlDatabase *db;
bool *inTransactionFlag;
TransactionRollback(QSqlDatabase *database, bool *transactionFlag)
: db(database)
, inTransactionFlag(transactionFlag)
{
if (inTransactionFlag)
*inTransactionFlag = true;
}
~TransactionRollback()
{
if (inTransactionFlag)
*inTransactionFlag = false;
if (db)
db->rollback();
}
void clear() {
db = 0;
if (inTransactionFlag)
*inTransactionFlag = false;
inTransactionFlag = 0;
}
};
static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx)
{
if (ctx->callData->argc < 2)
......@@ -349,7 +378,6 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx)
w->type = QQmlSqlDatabaseWrapper::Query;
w->database = db;
w->version = r->version;
w->inTransaction = true;
bool ok = true;
if (!!callback) {
......@@ -359,12 +387,10 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx)
ScopedCallData callData(scope, 1);
callData->thisObject = engine->global();
callData->args[0] = w;
try {
callback->call(callData);
} catch (...) {
db.rollback();
ctx->rethrowException();
}
TransactionRollback rollbackOnException(&db, &w->inTransaction);
callback->call(callData);
rollbackOnException.clear();
if (!db.commit()) {
db.rollback();
V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR,QQmlEngine::tr("SQL transaction failed"));
......@@ -373,8 +399,6 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx)
}
}
w->inTransaction = false;
if (ok) {
w->version = to_version;
#ifndef QT_NO_SETTINGS
......@@ -408,22 +432,15 @@ static ReturnedValue qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, b
w->database = db;
w->version = r->version;
w->readonly = readOnly;
w->inTransaction = true;
db.transaction();
if (callback) {
ScopedCallData callData(scope, 1);
callData->thisObject = engine->global();
callData->args[0] = w;
try {
callback->call(callData);
} catch (...) {
w->inTransaction = false;
db.rollback();
ctx->rethrowException();
}
w->inTransaction = false;
TransactionRollback rollbackOnException(&db, &w->inTransaction);
callback->call(callData);
rollbackOnException.clear();
if (!db.commit())
db.rollback();
......
......@@ -204,7 +204,7 @@ static const char vertexShaderCode[] =
"}\n";
static const char fragmentShaderCode[] =
"uniform sampler2D texture;\n"
"uniform sampler2D _qt_texture;\n"
"uniform lowp float qt_Opacity;\n"
"\n"
"#if defined(SPRITE)\n"
......@@ -224,21 +224,21 @@ static const char fragmentShaderCode[] =
"\n"
"void main() {\n"
"#if defined(SPRITE)\n"
" gl_FragColor = mix(texture2D(texture, fTexS.xy), texture2D(texture, fTexS.zw), tt.y)\n"
" gl_FragColor = mix(texture2D(_qt_texture, fTexS.xy), texture2D(_qt_texture, fTexS.zw), tt.y)\n"
" * fColor\n"
" * texture2D(colortable, tt)\n"
" * qt_Opacity;\n"
"#elif defined(TABLE)\n"
" gl_FragColor = texture2D(texture, fTex)\n"
" gl_FragColor = texture2D(_qt_texture, fTex)\n"
" * fColor\n"
" * texture2D(colortable, tt)\n"
" * qt_Opacity;\n"
"#elif defined(DEFORM)\n"
" gl_FragColor = (texture2D(texture, fTex)) * fColor * qt_Opacity;\n"
" gl_FragColor = (texture2D(_qt_texture, fTex)) * fColor * qt_Opacity;\n"
"#elif defined(COLOR)\n"
" gl_FragColor = (texture2D(texture, gl_PointCoord)) * fColor * qt_Opacity;\n"
" gl_FragColor = (texture2D(_qt_texture, gl_PointCoord)) * fColor * qt_Opacity;\n"
"#else\n"
" gl_FragColor = texture2D(texture, gl_PointCoord) * (fFade * qt_Opacity);\n"
" gl_FragColor = texture2D(_qt_texture, gl_PointCoord) * (fFade * qt_Opacity);\n"
"#endif\n"
"}\n";
......@@ -296,7 +296,7 @@ public:
void initialize() {
QSGSimpleMaterialShader<TabledMaterialData>::initialize();
program()->bind();
program()->setUniformValue("texture", 0);
program()->setUniformValue("_qt_texture", 0);
program()->setUniformValue("colortable", 1);
glFuncs = QOpenGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
......@@ -358,7 +358,7 @@ public:
void initialize() {
QSGSimpleMaterialShader<DeformableMaterialData>::initialize();
program()->bind();
program()->setUniformValue("texture", 0);
program()->setUniformValue("_qt_texture", 0);
glFuncs = QOpenGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
m_entry_id = program()->uniformLocation("entry");
......@@ -409,7 +409,7 @@ public:
void initialize() {
QSGSimpleMaterialShader<SpriteMaterialData>::initialize();
program()->bind();
program()->setUniformValue("texture", 0);
program()->setUniformValue("_qt_texture", 0);
program()->setUniformValue("colortable", 1);
glFuncs = QOpenGLContext::currentContext()->functions();
//Don't actually expose the animSheetSize in the shader, it's currently only used for CPU calculations.
......@@ -488,7 +488,7 @@ public:
void initialize() {
QSGSimpleMaterialShader<ColoredMaterialData>::initialize();
program()->bind();
program()->setUniformValue("texture", 0);
program()->setUniformValue("_qt_texture", 0);
glFuncs = QOpenGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
m_entry_id = program()->uniformLocation("entry");
......@@ -552,7 +552,7 @@ public:
void initialize() {
QSGSimpleMaterialShader<SimpleMaterialData>::initialize();
program()->bind();
program()->setUniformValue("texture", 0);
program()->setUniformValue("_qt_texture", 0);
glFuncs = QOpenGLContext::currentContext()->functions();
m_timestamp_id = program()->uniformLocation("timestamp");
m_entry_id = program()->uniformLocation("entry");
......
......@@ -14,7 +14,8 @@ HEADERS += \
$$PWD/qv4isel_util_p.h \
$$PWD/qv4ssa_p.h \
$$PWD/qv4regalloc_p.h \
$$PWD/qqmlcodegenerator_p.h
$$PWD/qqmlcodegenerator_p.h \
$$PWD/qv4isel_masm_p.h
SOURCES += \
$$PWD/qv4compileddata.cpp \
......@@ -26,11 +27,7 @@ SOURCES += \
$$PWD/qv4jsir.cpp \
$$PWD/qv4ssa.cpp \
$$PWD/qv4regalloc.cpp \
$$PWD/qqmlcodegenerator.cpp
contains(DEFINES, V4_ENABLE_JIT) {
HEADERS += $$PWD/qv4isel_masm_p.h
SOURCES += $$PWD/qv4isel_masm.cpp
}
$$PWD/qqmlcodegenerator.cpp \
$$PWD/qv4isel_masm.cpp
include(../../3rdparty/masm/masm.pri)
......@@ -118,6 +118,7 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
output->program = program;
qSwap(_imports, output->imports);
qSwap(_pragmas, output->pragmas);
qSwap(_objects, output->objects);
qSwap(_functions, output->functions);
qSwap(_typeReferences, output->typeReferences);
......@@ -147,6 +148,7 @@ bool QQmlCodeGenerator::generateFromQml(const QString &code, const QUrl &url, co
collectTypeReferences();
qSwap(_imports, output->imports);
qSwap(_pragmas, output->pragmas);
qSwap(_objects, output->objects);
qSwap(_functions, output->functions);
qSwap(_typeReferences, output->typeReferences);
......@@ -403,6 +405,11 @@ bool QQmlCodeGenerator::visit(AST::UiImport *node)
error.setColumn(node->importIdToken.startColumn);
errors << error;
return false;
} else {
// For backward compatibility in how the imports are loaded we
// must otherwise initialize the major and minor version to -1.
import->majorVersion = -1;
import->minorVersion = -1;
}
import->location.line = node->importToken.startLine;
......@@ -415,9 +422,38 @@ bool QQmlCodeGenerator::visit(AST::UiImport *node)
return false;
}
bool QQmlCodeGenerator::visit(AST::UiPragma *ast)
bool QQmlCodeGenerator::visit(AST::UiPragma *node)
{
return true;
Pragma *pragma = New<Pragma>();
// For now the only valid pragma is Singleton, so lets validate the input
if (!node->pragmaType->name.isNull())
{
if (QLatin1String("Singleton") == node->pragmaType->name)
{
pragma->type = Pragma::PragmaSingleton;
} else {
QQmlError error;
error.setDescription(QCoreApplication::translate("QQmlParser","Pragma requires a valid qualifier"));
error.setLine(node->pragmaToken.startLine);
error.setColumn(node->pragmaToken.startColumn);
errors << error;
return false;
}
} else {
QQmlError error;
error.setDescription(QCoreApplication::translate("QQmlParser","Pragma requires a valid qualifier"));
error.setLine(node->pragmaToken.startLine);
error.setColumn(node->pragmaToken.startColumn);
errors << error;
return false;
}
pragma->location.line = node->pragmaToken.startLine;
pragma->location.column = node->pragmaToken.startColumn;
_pragmas.append(pragma);
return false;
}
static QStringList astNodeToStringList(QQmlJS::AST::Node *node)
......@@ -1146,6 +1182,14 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(ParsedQML &output, const
objectPtr += signalTableSize;
}
// enable flag if we encountered pragma Singleton
foreach (Pragma *p, output.pragmas) {
if (p->type == Pragma::PragmaSingleton) {
qmlUnit->header.flags |= QV4::CompiledData::Unit::IsSingleton;
break;
}
}
return qmlUnit;
}
......@@ -1180,7 +1224,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fil
scan.end();
_env = 0;
_function = defineFunction(QString("context scope"), qmlRoot, 0, 0);
_function = _module->functions.at(defineFunction(QString("context scope"), qmlRoot, 0, 0));
for (int i = 0; i < functions.count(); ++i) {
AST::Node *node = functions.at(i);
......@@ -1212,10 +1256,10 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QString &fil
body = body->finish();
}
V4IR::Function *irFunc = defineFunction(name, node,
function ? function->formals : 0,
body);
runtimeFunctionIndices[i] = _module->functions.indexOf(irFunc); // ###
int idx = defineFunction(name, node,
function ? function->formals : 0,
body);
runtimeFunctionIndices[i] = idx;
}
qDeleteAll(_envMap);
......
......@@ -154,6 +154,16 @@ struct QmlObject
void dump(DebugStream &out);
};
struct Pragma
{
enum PragmaType {
PragmaSingleton = 0x1
};
quint32 type;
QV4::CompiledData::Location location;
};
struct ParsedQML
{
ParsedQML()
......@@ -163,6 +173,7 @@ struct ParsedQML
QQmlJS::Engine jsParserEngine;
V4IR::Module jsModule;
QList<QV4::CompiledData::Import*> imports;
QList<Pragma*> pragmas;
AST::UiProgram *program;
int indexOfRootObject;
QList<QmlObject*> objects;
......@@ -253,6 +264,7 @@ public:
QList<QQmlError> errors;
QList<QV4::CompiledData::Import*> _imports;
QList<Pragma*> _pragmas;
QList<QmlObject*> _objects;
QList<AST::Node*> _functions;
......
......@@ -413,7 +413,7 @@ Codegen::Codegen(bool strict)
{
}
V4IR::Function *Codegen::generateFromProgram(const QString &fileName,
void Codegen::generateFromProgram(const QString &fileName,
const QString &sourceCode,
Program *node,
V4IR::Module *module,
......@@ -430,18 +430,15 @@ V4IR::Function *Codegen::generateFromProgram(const QString &fileName,
ScanFunctions scan(this, sourceCode, mode);
scan(node);
V4IR::Function *globalCode = defineFunction(QStringLiteral("%entry"), node, 0,
node->elements, inheritedLocals);
defineFunction(QStringLiteral("%entry"), node, 0, node->elements, inheritedLocals);
qDeleteAll(_envMap);
_envMap.clear();
return globalCode;
}
V4IR::Function *Codegen::generateFromFunctionExpression(const QString &fileName,
const QString &sourceCode,
AST::FunctionExpression *ast,
V4IR::Module *module)
void Codegen::generateFromFunctionExpression(const QString &fileName,
const QString &sourceCode,
AST::FunctionExpression *ast,
V4IR::Module *module)
{
_module = module;
_module->setFileName(fileName);
......@@ -453,12 +450,10 @@ V4IR::Function *Codegen::generateFromFunctionExpression(const QString &fileName,
scan(ast);
scan.leaveEnvironment();
V4IR::Function *function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
qDeleteAll(_envMap);
_envMap.clear();
return function;
}
......@@ -1339,7 +1334,7 @@ bool Codegen::visit(FieldMemberExpression *ast)
bool Codegen::visit(FunctionExpression *ast)
{
V4IR::Function *function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
int function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
_expr.code = _block->CLOSURE(function);
return false;
}
......@@ -1460,9 +1455,18 @@ bool Codegen::visit(NumericLiteral *ast)
}
struct ObjectPropertyValue {
ObjectPropertyValue()
: value(0)
, getter(-1)
, setter(-1)
{}
V4IR::Expr *value;
V4IR::Function *getter;
V4IR::Function *setter;
int getter; // index in _module->functions or -1 if not set
int setter;
bool hasGetter() const { return getter >= 0; }
bool hasSetter() const { return setter >= 0; }
};
bool Codegen::visit(ObjectLiteral *ast)
......@@ -1474,18 +1478,18 @@ bool Codegen::visit(ObjectLiteral *ast)
QString name = propertyName(nv->name);
Result value = expression(nv->value);
ObjectPropertyValue &v = valueMap[name];
if (v.getter || v.setter || (_function->isStrict && v.value))
if (v.hasGetter() || v.hasSetter() || (_function->isStrict && v.value))
throwSyntaxError(nv->lastSourceLocation(),
QCoreApplication::translate("qv4codegen", "Illegal duplicate key '%1' in object literal").arg(name));
valueMap[name].value = *value;
} else if (PropertyGetterSetter *gs = AST::cast<AST::PropertyGetterSetter *>(it->assignment)) {
QString name = propertyName(gs->name);
V4IR::Function *function = defineFunction(name, gs, gs->formals, gs->functionBody ? gs->functionBody->elements : 0);
const int function = defineFunction(name, gs, gs->formals, gs->functionBody ? gs->functionBody->elements : 0);
ObjectPropertyValue &v = valueMap[name];
if (v.value ||
(gs->type == PropertyGetterSetter::Getter && v.getter) ||
(gs->type == PropertyGetterSetter::Setter && v.setter))
(gs->type == PropertyGetterSetter::Getter && v.hasGetter()) ||
(gs->type == PropertyGetterSetter::Setter && v.hasSetter()))
throwSyntaxError(gs->lastSourceLocation(),
QCoreApplication::translate("qv4codegen", "Illegal duplicate key '%1' in object literal").arg(name));
if (gs->type == PropertyGetterSetter::Getter)
......@@ -1535,8 +1539,8 @@ bool Codegen::visit(ObjectLiteral *ast)
unsigned getter = _block->newTemp();
unsigned setter = _block->newTemp();
move(_block->TEMP(getter), it->getter ? _block->CLOSURE(it->getter) : _block->CONST(V4IR::UndefinedType, 0));
move(_block->TEMP(setter), it->setter ? _block->CLOSURE(it->setter) : _block->CONST(V4IR::UndefinedType, 0));
move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(V4IR::UndefinedType, 0));
move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(V4IR::UndefinedType, 0));
current->next = _function->New<V4IR::ExprList>();
current = current->next;
......@@ -1581,8 +1585,8 @@ bool Codegen::visit(ObjectLiteral *ast)
getter = _block->newTemp();
setter = _block->newTemp();
}
move(_block->TEMP(getter), it->getter ? _block->CLOSURE(it->getter) : _block->CONST(V4IR::UndefinedType, 0));
move(_block->TEMP(setter), it->setter ? _block->CLOSURE(it->setter) : _block->CONST(V4IR::UndefinedType, 0));
move(_block->TEMP(getter), it->hasGetter() ? _block->CLOSURE(it->getter) : _block->CONST(V4IR::UndefinedType, 0));
move(_block->TEMP(setter), it->hasSetter() ? _block->CLOSURE(it->setter) : _block->CONST(V4IR::UndefinedType, 0));
// __qmljs_builtin_define_getter_setter(Value object, String *name, Value getter, Value setter, ExecutionContext *ctx);
......@@ -1750,10 +1754,10 @@ bool Codegen::visit(FunctionDeclaration * ast)
return false;
}
V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
AST::SourceElements *body,
const QStringList &inheritedLocals)
int Codegen::defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
AST::SourceElements *body,
const QStringList &inheritedLocals)
{
Loop *loop = 0;
qSwap(_loop, loop);
......@@ -1762,6 +1766,7 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
enterEnvironment(ast);
V4IR::Function *function = _module->newFunction(name, _function);
int functionIndex = _module->functions.count() - 1;
V4IR::BasicBlock *entryBlock = function->newBasicBlock(groupStartBlock());
V4IR::BasicBlock *exitBlock = function->newBasicBlock(groupStartBlock(), V4IR::Function::DontInsertBlock);
......@@ -1840,8 +1845,8 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
foreach (const Environment::Member &member, _env->members) {
if (member.function) {
V4IR::Function *function = defineFunction(member.function->name.toString(), member.function, member.function->formals,
member.function->body ? member.function->body->elements : 0);
const int function = defineFunction(member.function->name.toString(), member.function, member.function->formals,
member.function->body ? member.function->body->elements : 0);
if (! _env->parent || _env->compilationMode == QmlBinding) {
move(_block->NAME(member.function->name.toString(), member.function->identifierToken.startLine, member.function->identifierToken.startColumn),
_block->CLOSURE(function));
......@@ -1873,7 +1878,7 @@ V4IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
leaveEnvironment();
return function;
return functionIndex;
}
bool Codegen::visit(IdentifierPropertyName *ast)
......
......@@ -75,13 +75,13 @@ public:
QmlBinding
};
V4IR::Function *generateFromProgram(const QString &fileName,
void generateFromProgram(const QString &fileName,
const QString &sourceCode,
AST::Program *ast,
V4IR::Module *module,
CompilationMode mode = GlobalCode,
const QStringList &inheritedLocals = QStringList());
V4IR::Function *generateFromFunctionExpression(const QString &fileName,
void generateFromFunctionExpression(const QString &fileName,
const QString &sourceCode,
AST::FunctionExpression *ast,
V4IR::Module *module);
......@@ -283,10 +283,11 @@ protected:
void move(V4IR::Expr *target, V4IR::Expr *source, V4IR::AluOp op = V4IR::OpInvalid);
void cjump(V4IR::Expr *cond, V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse);
V4IR::Function *defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
AST::SourceElements *body,
const QStringList &inheritedLocals = QStringList());
// Returns index in _module->functions
int defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
AST::SourceElements *body,
const QStringList &inheritedLocals = QStringList());
void unwindException(ScopeAndFinally *outest);
......