aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.cpp10
-rw-r--r--moth/qv4instr_moth_p.h84
-rw-r--r--moth/qv4isel_moth.cpp282
-rw-r--r--moth/qv4isel_moth_p.h13
-rw-r--r--moth/qv4vme_moth.cpp100
-rw-r--r--moth/qv4vme_moth_p.h2
-rw-r--r--qmljs_objects.cpp4
-rw-r--r--qv4ir_p.h8
-rw-r--r--qv4isel_x86_64.cpp2
9 files changed, 468 insertions, 37 deletions
diff --git a/main.cpp b/main.cpp
index ed4985feac..777c8999c3 100644
--- a/main.cpp
+++ b/main.cpp
@@ -213,6 +213,9 @@ void evaluate(QQmlJS::VM::ExecutionEngine *vm, const QString &fileName, const QS
x86_64::InstructionSelection isel(vm, &module, code);
foreach (IR::Function *function, module.functions)
isel(function);
+
+ if (! protect(code, codeSize))
+ Q_UNREACHABLE();
}
}
@@ -220,11 +223,6 @@ void evaluate(QQmlJS::VM::ExecutionEngine *vm, const QString &fileName, const QS
return;
}
- if (!useMoth) {
- if (! protect(code, codeSize))
- Q_UNREACHABLE();
- }
-
VM::Context *ctx = vm->rootContext;
ctx->varCount = globalCode->locals.size();
@@ -240,7 +238,7 @@ void evaluate(QQmlJS::VM::ExecutionEngine *vm, const QString &fileName, const QS
Moth::VME vme;
vme(ctx, code);
} else {
- globalCode->code(ctx);
+ globalCode->code(ctx, globalCode->codeData);
}
if (ctx->hasUncaughtException) {
diff --git a/moth/qv4instr_moth_p.h b/moth/qv4instr_moth_p.h
index e582bb4ab6..d9f2c11cdd 100644
--- a/moth/qv4instr_moth_p.h
+++ b/moth/qv4instr_moth_p.h
@@ -2,10 +2,26 @@
#define QV4INSTR_MOTH_P_H
#include <QtCore/qglobal.h>
+#include "qmljs_objects.h"
#define FOR_EACH_MOTH_INSTR(F) \
- F(Nop, common) \
- F(Done, common) \
+ F(Ret, ret) \
+ F(LoadUndefined, common) \
+ F(LoadNull, common) \
+ F(LoadFalse, common) \
+ F(LoadTrue, common) \
+ F(LoadNumber, loadNumber) \
+ F(LoadString, loadString) \
+ F(LoadClosure, loadClosure) \
+ F(StoreTemp, storeTemp) \
+ F(LoadTemp, loadTemp) \
+ F(MoveTemp, moveTemp) \
+ F(LoadName, loadName) \
+ F(Push, push) \
+ F(Call, call) \
+ F(Jump, jump) \
+ F(CJump, jump) \
+ F(Binop, binop) \
#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
# define MOTH_THREADED_INTERPRETER
@@ -35,8 +51,72 @@ union Instr
struct instr_common {
MOTH_INSTR_HEADER
};
+ struct instr_ret {
+ MOTH_INSTR_HEADER
+ int tempIndex;
+ };
+ struct instr_storeTemp {
+ MOTH_INSTR_HEADER
+ int tempIndex;
+ };
+ struct instr_loadTemp {
+ MOTH_INSTR_HEADER
+ int tempIndex;
+ };
+ struct instr_moveTemp {
+ MOTH_INSTR_HEADER
+ int fromTempIndex;
+ int toTempIndex;
+ };
+ struct instr_loadNumber {
+ MOTH_INSTR_HEADER
+ double value;
+ };
+ struct instr_loadString {
+ MOTH_INSTR_HEADER
+ VM::String *value;
+ };
+ struct instr_loadClosure {
+ MOTH_INSTR_HEADER
+ IR::Function *value;
+ };
+ struct instr_loadName {
+ MOTH_INSTR_HEADER
+ VM::String *value;
+ };
+ struct instr_push {
+ MOTH_INSTR_HEADER
+ quint32 value;
+ };
+ struct instr_call {
+ MOTH_INSTR_HEADER
+ quint32 argc;
+ quint32 args;
+ };
+ struct instr_jump {
+ MOTH_INSTR_HEADER
+ ptrdiff_t offset;
+ };
+ struct instr_binop {
+ MOTH_INSTR_HEADER
+ int lhsTempIndex;
+ int rhsTempIndex;
+ void (*alu)(VM::Context *, VM::Value *, const VM::Value *, const VM::Value *);
+ };
instr_common common;
+ instr_ret ret;
+ instr_storeTemp storeTemp;
+ instr_loadTemp loadTemp;
+ instr_moveTemp moveTemp;
+ instr_loadNumber loadNumber;
+ instr_loadString loadString;
+ instr_loadClosure loadClosure;
+ instr_loadName loadName;
+ instr_push push;
+ instr_call call;
+ instr_jump jump;
+ instr_binop binop;
static int size(Type type);
};
diff --git a/moth/qv4isel_moth.cpp b/moth/qv4isel_moth.cpp
index 628e2f0a91..95db21620d 100644
--- a/moth/qv4isel_moth.cpp
+++ b/moth/qv4isel_moth.cpp
@@ -6,7 +6,7 @@ using namespace QQmlJS::Moth;
InstructionSelection::InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module,
uchar *code)
-: _code(code), _ccode(code)
+: _engine(engine), _code(code), _ccode(code)
{
}
@@ -18,52 +18,305 @@ void InstructionSelection::operator()(IR::Function *function)
{
qSwap(_function, function);
+ _function->code = VME::exec;
+ _function->codeData = _ccode;
+
+ int locals = _function->tempCount - _function->locals.size() + _function->maxNumberOfArguments;
+ assert(locals >= 0);
+
+ Instruction::Push push;
+ push.value = quint32(locals);
+ addInstruction(push);
+
foreach (_block, _function->basicBlocks) {
+ _addrs.insert(_block, _ccode - _code);
+
foreach (IR::Stmt *s, _block->statements)
s->accept(this);
}
- addInstruction(Instruction::Done());
+ for (QHash<IR::BasicBlock *, QVector<ptrdiff_t> >::ConstIterator iter = _patches.begin();
+ iter != _patches.end(); ++iter) {
+
+ Q_ASSERT(_addrs.contains(iter.key()));
+ ptrdiff_t target = _addrs.value(iter.key());
+
+ const QVector<ptrdiff_t> &patchList = iter.value();
+ for (int ii = 0; ii < patchList.count(); ++ii) {
+ ptrdiff_t patch = patchList.at(ii);
+
+ *((ptrdiff_t *)(_code + patch)) = target;
+ }
+ }
qSwap(_function, function);
}
-void InstructionSelection::visitExp(IR::Exp *)
+void InstructionSelection::visitExp(IR::Exp *s)
{
- qWarning("%s", __PRETTY_FUNCTION__);
+ if (IR::Call *c = s->expr->asCall()) {
+ if (IR::Name *n = c->base->asName()) {
+ if (n->builtin == IR::Name::builtin_invalid) {
+ Instruction::LoadName load;
+ load.value = _engine->newString(*n->id);
+ addInstruction(load);
+ } else {
+ Q_UNIMPLEMENTED();
+ }
+ } else if (IR::Member *m = c->base->asMember()) {
+ Q_UNIMPLEMENTED();
+ } else if (IR::Temp *t = c->base->asTemp()) {
+ Instruction::LoadTemp load;
+ load.tempIndex = t->index;
+ addInstruction(load);
+ } else {
+ Q_UNREACHABLE();
+ }
+
+ call(c->args);
+ } else {
+ Q_UNREACHABLE();
+ }
+}
+
+void InstructionSelection::call(IR::ExprList *e)
+{
+ Instruction::Call call;
+ call.argc = 0;
+ call.args = 0;
+
+ int locals = _function->tempCount - _function->locals.size() + _function->maxNumberOfArguments;
+
+ if (e && e->next == 0 && e->expr->asTemp()->index >= 0 && e->expr->asTemp()->index < locals) {
+ // We pass single arguments as references to the stack
+ call.argc = 1;
+ call.args = e->expr->asTemp()->index;
+ } else if (e) {
+ // We need to move all the temps into the function arg array
+ int argLocation = _function->tempCount - _function->locals.size();
+ assert(argLocation >= 0);
+ call.args = argLocation;
+ while (e) {
+ Instruction::MoveTemp move;
+ move.fromTempIndex = e->expr->asTemp()->index;
+ move.toTempIndex = argLocation;
+ addInstruction(move);
+ ++argLocation;
+ ++call.argc;
+ e = e->next;
+ }
+ }
+
+ addInstruction(call);
}
void InstructionSelection::visitEnter(IR::Enter *)
{
qWarning("%s", __PRETTY_FUNCTION__);
+ Q_UNREACHABLE();
}
void InstructionSelection::visitLeave(IR::Leave *)
{
qWarning("%s", __PRETTY_FUNCTION__);
+ Q_UNREACHABLE();
}
-void InstructionSelection::visitMove(IR::Move *)
+void InstructionSelection::visitMove(IR::Move *s)
{
- qWarning("%s", __PRETTY_FUNCTION__);
+ if (s->op == IR::OpInvalid)
+ simpleMove(s);
+ else
+ qWarning("UNKNOWN MOVE");
}
-void InstructionSelection::visitJump(IR::Jump *)
+typedef void (*ALUFunction)(VM::Context*, VM::Value*, const VM::Value*, const VM::Value *);
+ALUFunction aluOpFunction(IR::AluOp op)
{
- qWarning("%s", __PRETTY_FUNCTION__);
+ switch (op) {
+ case IR::OpInvalid:
+ return 0;
+ case IR::OpIfTrue:
+ return 0;
+ case IR::OpNot:
+ return 0;
+ case IR::OpUMinus:
+ return 0;
+ case IR::OpUPlus:
+ return 0;
+ case IR::OpCompl:
+ return 0;
+ case IR::OpBitAnd:
+ return 0;
+ case IR::OpBitOr:
+ return 0;
+ case IR::OpBitXor:
+ return 0;
+ case IR::OpAdd:
+ return VM::__qmljs_add;
+ case IR::OpSub:
+ return VM::__qmljs_sub;
+ case IR::OpMul:
+ return VM::__qmljs_mul;
+ case IR::OpDiv:
+ return VM::__qmljs_div;
+ case IR::OpMod:
+ return VM::__qmljs_mod;
+ case IR::OpLShift:
+ return VM::__qmljs_shl;
+ case IR::OpRShift:
+ return VM::__qmljs_shr;
+ case IR::OpURShift:
+ return VM::__qmljs_ushr;
+ case IR::OpGt:
+ return VM::__qmljs_gt;
+ case IR::OpLt:
+ return VM::__qmljs_lt;
+ case IR::OpGe:
+ return VM::__qmljs_ge;
+ case IR::OpLe:
+ return VM::__qmljs_le;
+ case IR::OpEqual:
+ return VM::__qmljs_eq;
+ case IR::OpNotEqual:
+ return VM::__qmljs_ne;
+ case IR::OpStrictEqual:
+ return VM::__qmljs_se;
+ case IR::OpStrictNotEqual:
+ return VM::__qmljs_sne;
+ case IR::OpInstanceof:
+ return 0;
+ case IR::OpIn:
+ return 0;
+ case IR::OpAnd:
+ return 0;
+ case IR::OpOr:
+ return 0;
+ default:
+ assert(!"Unknown AluOp");
+ return 0;
+ }
+};
+
+// A move that doesn't involve an inplace operation
+void InstructionSelection::simpleMove(IR::Move *s)
+{
+ if (IR::Name *n = s->target->asName()) {
+ qWarning("NAME");
+ } else if (IR::Temp *t = s->target->asTemp()) {
+
+ if (IR::Name *n = s->source->asName()) {
+ qWarning(" NAME");
+ } else if (IR::Const *c = s->source->asConst()) {
+ switch (c->type) {
+ case IR::UndefinedType:
+ addInstruction(Instruction::LoadUndefined());
+ break;
+ case IR::NullType:
+ addInstruction(Instruction::LoadNull());
+ break;
+ case IR::BoolType:
+ if (c->value) addInstruction(Instruction::LoadTrue());
+ else addInstruction(Instruction::LoadFalse());
+ break;
+ case IR::NumberType: {
+ Instruction::LoadNumber load;
+ load.value = c->value;
+ addInstruction(load);
+ } break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ } else if (IR::Temp *t2 = s->source->asTemp()) {
+ Instruction::LoadTemp load;
+ load.tempIndex = t2->index;
+ addInstruction(load);
+ } else if (IR::String *str = s->source->asString()) {
+ Instruction::LoadString load;
+ load.value = _engine->newString(*str->value);
+ addInstruction(load);
+ } else if (IR::Closure *clos = s->source->asClosure()) {
+ Instruction::LoadClosure load;
+ load.value = clos->value;
+ addInstruction(load);
+ } else if (IR::New *ctor = s->source->asNew()) {
+ qWarning(" NEW");
+ } else if (IR::Member *m = s->source->asMember()) {
+ qWarning(" MEMBER");
+ } else if (IR::Subscript *ss = s->source->asSubscript()) {
+ qWarning(" SUBSCRIPT");
+ } else if (IR::Unop *u = s->source->asUnop()) {
+ qWarning(" UNOP");
+ } else if (IR::Binop *b = s->source->asBinop()) {
+ Instruction::Binop binop;
+ binop.alu = aluOpFunction(b->op);
+ binop.lhsTempIndex = b->left->index;
+ binop.rhsTempIndex = b->right->index;
+ addInstruction(binop);
+ } else if (IR::Call *c = s->source->asCall()) {
+ qWarning(" CALL");
+ }
+
+ Instruction::StoreTemp st;
+ st.tempIndex = t->index;
+ addInstruction(st);
+
+ } else if (IR::Member *m = s->target->asMember()) {
+ qWarning("MEMBER");
+ } else if (IR::Subscript *ss = s->target->asSubscript()) {
+ qWarning("SUBSCRIPT");
+ } else {
+ Q_UNREACHABLE();
+ }
}
-void InstructionSelection::visitCJump(IR::CJump *)
+void InstructionSelection::visitJump(IR::Jump *s)
{
- qWarning("%s", __PRETTY_FUNCTION__);
+ Instruction::Jump jump;
+ jump.offset = 0;
+ ptrdiff_t loc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
+
+ _patches[s->target].append(loc);
}
-void InstructionSelection::visitRet(IR::Ret *)
+void InstructionSelection::visitCJump(IR::CJump *s)
{
- qWarning("%s", __PRETTY_FUNCTION__);
+ if (IR::Temp *t = s->cond->asTemp()) {
+ Instruction::LoadTemp load;
+ load.tempIndex = t->index;
+ addInstruction(load);
+ } else if (IR::Binop *b = s->cond->asBinop()) {
+ Instruction::Binop binop;
+ binop.alu = aluOpFunction(b->op);
+ binop.lhsTempIndex = b->left->index;
+ binop.rhsTempIndex = b->right->index;
+ addInstruction(binop);
+ } else {
+ Q_UNREACHABLE();
+ }
+
+ Instruction::CJump jump;
+ jump.offset = 0;
+ ptrdiff_t tl = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
+ _patches[s->iftrue].append(tl);
+
+ if (_block->index + 1 != s->iffalse->index) {
+ Instruction::Jump jump;
+ jump.offset = 0;
+ ptrdiff_t fl = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
+ _patches[s->iffalse].append(fl);
+ }
+}
+
+void InstructionSelection::visitRet(IR::Ret *s)
+{
+ Instruction::Ret ret;
+ ret.tempIndex = s->expr->index;
+ addInstruction(ret);
}
-int InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr)
+ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr)
{
#ifdef MOTH_THREADED_INTERPRETER
instr.common.code = VME::instructionJumpTable()[static_cast<int>(type)];
@@ -71,8 +324,7 @@ int InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr)
instr.common.instructionType = type;
#endif
- // XXX - int is wrong size for both of these
- int ptrOffset = (int)(_ccode - _code);
+ ptrdiff_t ptrOffset = _ccode - _code;
int size = Instr::size(type);
::memcpy(_ccode, reinterpret_cast<const char *>(&instr), size);
diff --git a/moth/qv4isel_moth_p.h b/moth/qv4isel_moth_p.h
index d8e56cac70..009d0b3a36 100644
--- a/moth/qv4isel_moth_p.h
+++ b/moth/qv4isel_moth_p.h
@@ -34,19 +34,26 @@ private:
Instruction();
};
+ void simpleMove(IR::Move *);
+ void call(IR::ExprList *);
+
template <int Instr>
- inline int addInstruction(const InstrData<Instr> &data);
- int addInstructionHelper(Instr::Type type, Instr &instr);
+ inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
+ ptrdiff_t addInstructionHelper(Instr::Type type, Instr &instr);
+ VM::ExecutionEngine *_engine;
IR::Function *_function;
IR::BasicBlock *_block;
+ QHash<IR::BasicBlock *, QVector<ptrdiff_t> > _patches;
+ QHash<IR::BasicBlock *, ptrdiff_t> _addrs;
+
uchar *_code;
uchar *_ccode;
};
template<int InstrT>
-int InstructionSelection::addInstruction(const InstrData<InstrT> &data)
+ptrdiff_t InstructionSelection::addInstruction(const InstrData<InstrT> &data)
{
Instr genericInstr;
InstrMeta<InstrT>::setData(genericInstr, data);
diff --git a/moth/qv4vme_moth.cpp b/moth/qv4vme_moth.cpp
index c14a61cb9c..98ea922e7e 100644
--- a/moth/qv4vme_moth.cpp
+++ b/moth/qv4vme_moth.cpp
@@ -38,7 +38,21 @@ using namespace QQmlJS::Moth;
#endif
-void VME::operator()(QQmlJS::VM::Context *, const uchar *code
+static inline VM::Value *tempValue(QQmlJS::VM::Context *context, QVector<VM::Value> &stack, int index)
+{
+ if (index < 0) {
+ const int arg = -index - 1;
+ return context->arguments + arg;
+ } else if (index < stack.count()) {
+ return stack.data() + index;
+ } else {
+ return context->locals + index - stack.count();
+ }
+}
+
+#define TEMP(index) *tempValue(context, stack, index)
+
+void VME::operator()(QQmlJS::VM::Context *context, const uchar *basecode
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable
#endif
@@ -57,6 +71,11 @@ void VME::operator()(QQmlJS::VM::Context *, const uchar *code
}
#endif
+ const uchar *code = basecode;
+
+ QVector<VM::Value> stack;
+ VM::Value tempRegister;
+
#ifdef MOTH_THREADED_INTERPRETER
const Instr *genericInstr = reinterpret_cast<const Instr *>(code);
goto *genericInstr->common.code;
@@ -66,13 +85,76 @@ void VME::operator()(QQmlJS::VM::Context *, const uchar *code
switch (genericInstr->common.instructionType) {
#endif
- MOTH_BEGIN_INSTR(Nop)
- qWarning("NOP");
- MOTH_END_INSTR(Nop)
+ MOTH_BEGIN_INSTR(StoreTemp)
+ TEMP(instr.tempIndex) = tempRegister;
+ MOTH_END_INSTR(StoreTemp)
+
+ MOTH_BEGIN_INSTR(LoadTemp)
+ tempRegister = TEMP(instr.tempIndex);
+ MOTH_END_INSTR(LoadTemp)
+
+ MOTH_BEGIN_INSTR(MoveTemp)
+ TEMP(instr.toTempIndex) = TEMP(instr.fromTempIndex);
+ MOTH_END_INSTR(MoveTemp)
+
+ MOTH_BEGIN_INSTR(LoadUndefined)
+ tempRegister = VM::Value::undefinedValue();
+ MOTH_END_INSTR(LoadUndefined)
+
+ MOTH_BEGIN_INSTR(LoadNull)
+ tempRegister = VM::Value::nullValue();
+ MOTH_END_INSTR(LoadNull)
+
+ MOTH_BEGIN_INSTR(LoadTrue)
+ tempRegister = VM::Value::fromBoolean(true);
+ MOTH_END_INSTR(LoadTrue)
+
+ MOTH_BEGIN_INSTR(LoadFalse)
+ tempRegister = VM::Value::fromBoolean(false);
+ MOTH_END_INSTR(LoadFalse)
- MOTH_BEGIN_INSTR(Done)
+ MOTH_BEGIN_INSTR(LoadNumber)
+ tempRegister = VM::Value::fromNumber(instr.value);
+ MOTH_END_INSTR(LoadNumber)
+
+ MOTH_BEGIN_INSTR(LoadString)
+ tempRegister = VM::Value::fromString(instr.value);
+ MOTH_END_INSTR(LoadString)
+
+ MOTH_BEGIN_INSTR(LoadClosure)
+ __qmljs_init_closure(context, &tempRegister, instr.value);
+ MOTH_END_INSTR(LoadClosure)
+
+ MOTH_BEGIN_INSTR(LoadName)
+ __qmljs_get_activation_property(context, &tempRegister, instr.value);
+ MOTH_END_INSTR(LoadName)
+
+ MOTH_BEGIN_INSTR(Push)
+ stack.resize(instr.value);
+ MOTH_END_INSTR(Push)
+
+ MOTH_BEGIN_INSTR(Call)
+ VM::Value *args = stack.data() + instr.args;
+ __qmljs_call_value(context, &tempRegister, /*thisObject=*/0, &tempRegister, args, instr.argc);
+ MOTH_END_INSTR(Call)
+
+ MOTH_BEGIN_INSTR(Jump)
+ code = basecode + instr.offset;
+ MOTH_END_INSTR(Jump)
+
+ MOTH_BEGIN_INSTR(CJump)
+ if (__qmljs_to_boolean(context, &tempRegister))
+ code = basecode + instr.offset;
+ MOTH_END_INSTR(CJump)
+
+ MOTH_BEGIN_INSTR(Binop)
+ instr.alu(context, &tempRegister, &TEMP(instr.lhsTempIndex), &TEMP(instr.rhsTempIndex));
+ MOTH_END_INSTR(Binop)
+
+ MOTH_BEGIN_INSTR(Ret)
+ context->result = TEMP(instr.tempIndex);
return;
- MOTH_END_INSTR(Done)
+ MOTH_END_INSTR(Ret)
#ifdef MOTH_THREADED_INTERPRETER
// nothing to do
@@ -98,3 +180,9 @@ void **VME::instructionJumpTable()
}
#endif
+void VME::exec(VM::Context *ctxt, const uchar *code)
+{
+ VME vme;
+ vme(ctxt, code);
+}
+
diff --git a/moth/qv4vme_moth_p.h b/moth/qv4vme_moth_p.h
index 5055407ca2..db1507d84d 100644
--- a/moth/qv4vme_moth_p.h
+++ b/moth/qv4vme_moth_p.h
@@ -10,6 +10,8 @@ namespace Moth {
class VME
{
public:
+ static void exec(VM::Context *, const uchar *);
+
void operator()(QQmlJS::VM::Context *, const uchar *code
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable = 0
diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp
index 94df898277..9746d8d358 100644
--- a/qmljs_objects.cpp
+++ b/qmljs_objects.cpp
@@ -185,7 +185,7 @@ ScriptFunction::~ScriptFunction()
void ScriptFunction::call(VM::Context *ctx)
{
- function->code(ctx);
+ function->code(ctx, function->codeData);
}
void ScriptFunction::construct(VM::Context *ctx)
@@ -195,7 +195,7 @@ void ScriptFunction::construct(VM::Context *ctx)
if (proto.isObject())
obj->prototype = proto.objectValue;
__qmljs_init_object(&ctx->thisObject, obj);
- function->code(ctx);
+ function->code(ctx, function->codeData);
}
Value *ActivationObject::getPropertyDescriptor(Context *ctx, String *name, PropertyAttributes *attributes)
diff --git a/qv4ir_p.h b/qv4ir_p.h
index ef9d801310..67b26d556a 100644
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -505,7 +505,7 @@ struct Jump: Stmt {
};
struct CJump: Stmt {
- Expr *cond;
+ Expr *cond; // Temp, Binop
BasicBlock *iftrue;
BasicBlock *iffalse;
@@ -558,7 +558,10 @@ struct Function {
QList<const QString *> formals;
QList<const QString *> locals;
IR::BasicBlock *handlersBlock;
- void (*code)(VM::Context *);
+
+ void (*code)(VM::Context *, const uchar *);
+ const uchar *codeData;
+
bool hasDirectEval: 1;
bool hasNestedFunctions: 1;
@@ -571,6 +574,7 @@ struct Function {
, maxNumberOfArguments(0)
, handlersBlock(0)
, code(0)
+ , codeData(0)
, hasDirectEval(false)
, hasNestedFunctions(false)
{ this->name = newString(name); }
diff --git a/qv4isel_x86_64.cpp b/qv4isel_x86_64.cpp
index 2a18ba962e..8846c29004 100644
--- a/qv4isel_x86_64.cpp
+++ b/qv4isel_x86_64.cpp
@@ -108,7 +108,7 @@ void InstructionSelection::operator()(IR::Function *function)
_code = _codePtr;
_code = (uchar *) ((size_t(_code) + 15) & ~15);
- _function->code = (void (*)(VM::Context *)) _code;
+ _function->code = (void (*)(VM::Context *, const uchar *)) _code;
_codePtr = _code;
_patches.clear();
_addrs.clear();