aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.cpp118
-rw-r--r--qmljs_objects.cpp144
-rw-r--r--qmljs_objects.h14
3 files changed, 158 insertions, 118 deletions
diff --git a/main.cpp b/main.cpp
index 2b69a4ffb0..12f0bb2a87 100644
--- a/main.cpp
+++ b/main.cpp
@@ -61,19 +61,6 @@
#include <sys/mman.h>
#include <iostream>
-static inline bool protect(const void *addr, size_t size)
-{
- size_t pageSize = sysconf(_SC_PAGESIZE);
- size_t iaddr = reinterpret_cast<size_t>(addr);
- size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
- int mode = PROT_READ | PROT_WRITE | PROT_EXEC;
- return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
-}
-
-static int evaluate(QQmlJS::VM::Context *ctx, const QString &fileName,
- const QString &source, bool useInterpreter,
- QQmlJS::Codegen::Mode mode = QQmlJS::Codegen::GlobalCode);
-
namespace builtins {
using namespace QQmlJS::VM;
@@ -94,20 +81,6 @@ struct Print: FunctionObject
}
};
-struct Eval: FunctionObject
-{
- Eval(Context *scope, bool useInterpreter): FunctionObject(scope), useInterpreter(useInterpreter) {}
-
- virtual void call(Context *ctx)
- {
- const QString code = ctx->argument(0).toString(ctx)->toQString();
- evaluate(ctx, QStringLiteral("eval code"), code, useInterpreter, QQmlJS::Codegen::EvalCode);
- }
-
-private:
- bool useInterpreter;
-};
-
struct TestHarnessError: FunctionObject
{
TestHarnessError(Context *scope, bool &errorInTestHarness): FunctionObject(scope), errorOccurred(errorInTestHarness) {}
@@ -226,92 +199,6 @@ int evaluateCompiledCode(const QStringList &files)
#endif
-static int evaluate(QQmlJS::VM::Context *ctx, const QString &fileName,
- const QString &source, bool useInterpreter,
- QQmlJS::Codegen::Mode mode)
-{
- using namespace QQmlJS;
-
- VM::ExecutionEngine *vm = ctx->engine;
- IR::Module module;
- IR::Function *globalCode = 0;
-
- const size_t codeSize = 400 * getpagesize();
- uchar *code = 0;
- if (posix_memalign((void**)&code, 16, codeSize))
- assert(!"memalign failed");
- assert(code);
- assert(! (size_t(code) & 15));
-
- {
- QQmlJS::Engine ee, *engine = &ee;
- Lexer lexer(engine);
- lexer.setCode(source, 1, false);
- Parser parser(engine);
-
- const bool parsed = parser.parseProgram();
-
- foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
- std::cerr << qPrintable(fileName) << ':' << m.loc.startLine << ':' << m.loc.startColumn
- << ": error: " << qPrintable(m.message) << std::endl;
- }
-
- if (parsed) {
- using namespace AST;
- Program *program = AST::cast<Program *>(parser.rootNode());
-
- Codegen cg;
- globalCode = cg(program, &module, mode);
-
- if (useInterpreter) {
- Moth::InstructionSelection isel(vm, &module, code);
- foreach (IR::Function *function, module.functions)
- isel(function);
- } else {
- foreach (IR::Function *function, module.functions) {
- MASM::InstructionSelection isel(vm, &module, code);
- isel(function);
- }
-
- if (! protect(code, codeSize))
- Q_UNREACHABLE();
- }
- }
-
- if (! globalCode)
- return EXIT_FAILURE;
- }
-
- if (!ctx->activation)
- ctx->activation = new QQmlJS::VM::Object();
-
- foreach (const QString *local, globalCode->locals) {
- ctx->activation->__put__(ctx, *local, QQmlJS::VM::Value::undefinedValue());
- }
-
- void * buf = __qmljs_create_exception_handler(ctx);
- if (setjmp(*(jmp_buf *)buf)) {
- if (VM::ErrorObject *e = ctx->result.asErrorObject())
- std::cerr << "Uncaught exception: " << qPrintable(e->value.toString(ctx)->toQString()) << std::endl;
- else
- std::cerr << "Uncaught exception: " << qPrintable(ctx->result.toString(ctx)->toQString()) << std::endl;
- return EXIT_FAILURE;
- }
-
- if (useInterpreter) {
- Moth::VME vme;
- vme(ctx, code);
- } else {
- globalCode->code(ctx, globalCode->codeData);
- }
-
- if (! ctx->result.isUndefined()) {
- if (! qgetenv("SHOW_EXIT_VALUE").isEmpty())
- std::cout << "exit value: " << qPrintable(ctx->result.toString(ctx)->toQString()) << std::endl;
- }
-
- return EXIT_SUCCESS;
-}
int main(int argc, char *argv[])
{
@@ -401,9 +288,6 @@ int main(int argc, char *argv[])
globalObject->__put__(ctx, vm.identifier(QStringLiteral("print")),
QQmlJS::VM::Value::fromObject(new builtins::Print(ctx)));
- globalObject->__put__(ctx, vm.identifier(QStringLiteral("eval")),
- QQmlJS::VM::Value::fromObject(new builtins::Eval(ctx, useInterpreter)));
-
bool errorInTestHarness = false;
if (!qgetenv("IN_TEST_HARNESS").isEmpty())
globalObject->__put__(ctx, vm.identifier(QStringLiteral("$ERROR")),
@@ -415,7 +299,7 @@ int main(int argc, char *argv[])
const QString code = QString::fromUtf8(file.readAll());
file.close();
- int exitCode = evaluate(vm.rootContext, fn, code, useInterpreter);
+ int exitCode = QQmlJS::VM::EvalFunction::evaluate(vm.rootContext, fn, code, useInterpreter, QQmlJS::Codegen::GlobalCode);
if (exitCode != EXIT_SUCCESS)
return exitCode;
if (errorInTestHarness)
diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp
index 574e1bd897..622ef621b1 100644
--- a/qmljs_objects.cpp
+++ b/qmljs_objects.cpp
@@ -43,10 +43,20 @@
#include "qmljs_objects.h"
#include "qv4ir_p.h"
#include "qv4ecmaobjects_p.h"
+
+#include <private/qqmljsengine_p.h>
+#include <private/qqmljslexer_p.h>
+#include <private/qqmljsparser_p.h>
+#include <private/qqmljsast_p.h>
+#include <qv4ir_p.h>
+#include <qv4codegen_p.h>
+#include <qv4isel_masm_p.h>
+
#include <QtCore/qmath.h>
#include <QtCore/QDebug>
#include <cassert>
#include <typeinfo>
+#include <iostream>
using namespace QQmlJS::VM;
@@ -448,6 +458,137 @@ void ScriptFunction::call(VM::Context *ctx)
function->code(ctx, function->codeData);
}
+
+Value EvalFunction::call(Context *context, Value thisObject, Value *args, int argc, bool strictMode)
+{
+ Value s = context->argument(0);
+ if (!s.isString()) {
+ context->result = s;
+ return s;
+ }
+ const QString code = context->argument(0).stringValue()->toQString();
+
+ // ### how to determine this correctly
+ bool directCall = true;
+
+ Context k, *ctx;
+ if (!directCall) {
+ // ###
+ } else if (strictMode) {
+ ctx = &k;
+ ctx->initCallContext(context, context->thisObject, this, args, argc);
+ } else {
+ ctx = context;
+ }
+ // ##### inline and do this in the correct scope
+ evaluate(ctx, QStringLiteral("eval code"), code, /*useInterpreter*/ false, QQmlJS::Codegen::EvalCode);
+
+ if (strictMode)
+ ctx->leaveCallContext();
+}
+
+static inline bool protect(const void *addr, size_t size)
+{
+ size_t pageSize = sysconf(_SC_PAGESIZE);
+ size_t iaddr = reinterpret_cast<size_t>(addr);
+ size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
+ int mode = PROT_READ | PROT_WRITE | PROT_EXEC;
+ return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
+}
+
+
+int EvalFunction::evaluate(QQmlJS::VM::Context *ctx, const QString &fileName,
+ const QString &source, bool useInterpreter,
+ QQmlJS::Codegen::Mode mode)
+{
+ using namespace QQmlJS;
+
+ VM::ExecutionEngine *vm = ctx->engine;
+ IR::Module module;
+ IR::Function *globalCode = 0;
+
+ const size_t codeSize = 400 * getpagesize();
+ uchar *code = 0;
+ if (posix_memalign((void**)&code, 16, codeSize))
+ assert(!"memalign failed");
+ assert(code);
+ assert(! (size_t(code) & 15));
+
+ {
+ QQmlJS::Engine ee, *engine = &ee;
+ Lexer lexer(engine);
+ lexer.setCode(source, 1, false);
+ Parser parser(engine);
+
+ const bool parsed = parser.parseProgram();
+
+ foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
+ std::cerr << qPrintable(fileName) << ':' << m.loc.startLine << ':' << m.loc.startColumn
+ << ": error: " << qPrintable(m.message) << std::endl;
+ }
+
+ if (parsed) {
+ using namespace AST;
+ Program *program = AST::cast<Program *>(parser.rootNode());
+
+ Codegen cg;
+ globalCode = cg(program, &module, mode);
+
+// if (useInterpreter) {
+// Moth::InstructionSelection isel(vm, &module, code);
+// foreach (IR::Function *function, module.functions)
+// isel(function);
+// } else
+ {
+ foreach (IR::Function *function, module.functions) {
+ MASM::InstructionSelection isel(vm, &module, code);
+ isel(function);
+ }
+
+ if (! protect(code, codeSize))
+ Q_UNREACHABLE();
+ }
+ }
+
+ if (! globalCode)
+ return EXIT_FAILURE;
+ }
+
+ if (!ctx->activation)
+ ctx->activation = new QQmlJS::VM::Object();
+
+ foreach (const QString *local, globalCode->locals) {
+ ctx->activation->__put__(ctx, *local, QQmlJS::VM::Value::undefinedValue());
+ }
+
+ if (mode == Codegen::GlobalCode) {
+ void * buf = __qmljs_create_exception_handler(ctx);
+ if (setjmp(*(jmp_buf *)buf)) {
+ if (VM::ErrorObject *e = ctx->result.asErrorObject())
+ std::cerr << "Uncaught exception: " << qPrintable(e->value.toString(ctx)->toQString()) << std::endl;
+ else
+ std::cerr << "Uncaught exception: " << qPrintable(ctx->result.toString(ctx)->toQString()) << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+// if (useInterpreter) {
+// Moth::VME vme;
+// vme(ctx, code);
+// } else
+ {
+ globalCode->code(ctx, globalCode->codeData);
+ }
+
+ if (! ctx->result.isUndefined()) {
+ if (! qgetenv("SHOW_EXIT_VALUE").isEmpty())
+ std::cout << "exit value: " << qPrintable(ctx->result.toString(ctx)->toQString()) << std::endl;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+
Value RegExpObject::__get__(Context *ctx, String *name)
{
QString n = name->toQString();
@@ -661,6 +802,9 @@ ExecutionEngine::ExecutionEngine()
glo->__put__(rootContext, identifier(QStringLiteral("undefined")), Value::undefinedValue());
glo->__put__(rootContext, identifier(QStringLiteral("NaN")), Value::fromDouble(nan("")));
glo->__put__(rootContext, identifier(QStringLiteral("Infinity")), Value::fromDouble(INFINITY));
+ glo->__put__(rootContext, identifier(QStringLiteral("eval")), Value::fromObject(new EvalFunction(rootContext)));
+
+
}
Context *ExecutionEngine::newContext()
diff --git a/qmljs_objects.h b/qmljs_objects.h
index 490eae2eef..3e06440b68 100644
--- a/qmljs_objects.h
+++ b/qmljs_objects.h
@@ -43,6 +43,7 @@
#include "qmljs_runtime.h"
#include "qv4array_p.h"
+#include "qv4codegen_p.h"
#include <QtCore/QString>
#include <QtCore/QHash>
@@ -494,7 +495,7 @@ struct FunctionObject: Object {
virtual bool hasInstance(Context *ctx, const Value &value);
Value construct(Context *context, Value *args, int argc);
- Value call(Context *context, Value thisObject, Value *args, int argc, bool strictMode = false);
+ virtual Value call(Context *context, Value thisObject, Value *args, int argc, bool strictMode = false);
protected:
virtual void call(Context *ctx);
@@ -519,6 +520,17 @@ struct ScriptFunction: FunctionObject {
virtual void construct(Context *ctx);
};
+struct EvalFunction : FunctionObject
+{
+ EvalFunction(Context *scope): FunctionObject(scope) {}
+
+ static int evaluate(QQmlJS::VM::Context *ctx, const QString &fileName,
+ const QString &source, bool useInterpreter,
+ QQmlJS::Codegen::Mode mode);
+
+ virtual Value call(Context *context, Value thisObject, Value *args, int argc, bool strictMode = false);
+};
+
struct RegExpObject: Object {
QRegularExpression value;
Value lastIndex;