aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2017-08-03 12:11:41 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-08-03 11:15:48 +0000
commit40aa22e0fd8234a7a71abf0ef8f42524d306e0df (patch)
treefce9a4448cc348dcbf99eebca2e1827c21b0d6c6
parenta88bc4e5aa0dfbf71cbe53c1dd8bfbae4d2a90f6 (diff)
Store arguments in the stack frame before the locals/temps
All escaping arguments will still be loaded/stored from/to the CallData, but this is not the common case. In a subsequent patch we can make the caller prepare the stack frame, and for the common case we don't even need to copy arguments around. Change-Id: I3fbb6fe575a564d05a9fd5dcc0c8f4129eac3bc2 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp5
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h1
-rw-r--r--src/qml/compiler/qv4codegen.cpp130
-rw-r--r--src/qml/compiler/qv4codegen_p.h31
-rw-r--r--src/qml/compiler/qv4compileddata_p.h1
-rw-r--r--src/qml/compiler/qv4compiler.cpp2
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h2
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp28
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h65
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp144
10 files changed, 166 insertions, 243 deletions
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
index 1fa1852d80..c9b7c4ae7e 100644
--- a/src/qml/compiler/qv4bytecodegenerator.cpp
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -75,11 +75,6 @@ QByteArray BytecodeGenerator::finalize()
{
QByteArray code;
- Instruction::InitStackFrame init;
- init.instructionType = Instr::InitStackFrame;
- init.value = regCount;
- code.append(reinterpret_cast<const char *>(&init), InstrMeta<Instr::InitStackFrame>::Size);
-
// content
QVector<int> instructionOffsets;
instructionOffsets.reserve(instructions.size());
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
index bfb1ada6e4..81b64f96da 100644
--- a/src/qml/compiler/qv4bytecodegenerator_p.h
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -195,6 +195,7 @@ public:
int newRegister();
int newRegisterArray(int n);
+ int registerCount() const { return regCount; }
QByteArray finalize();
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index d3cfdbb7fc..82270ee086 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -619,7 +619,7 @@ bool Codegen::visit(ArrayLiteral *ast)
Instruction::CallBuiltinDefineArray call;
call.argc = argc;
- call.args = Moth::StackSlot::create(args);
+ call.args = Moth::StackSlot::createRegister(args);
bytecodeGenerator->addInstruction(call);
_expr.setResult(Reference::fromAccumulator(this));
@@ -1089,7 +1089,7 @@ Moth::StackSlot Codegen::pushArgs(ArgumentList *args)
++argc;
}
- return Moth::StackSlot::create(calldata);
+ return Moth::StackSlot::createRegister(calldata);
}
bool Codegen::visit(ConditionalExpression *ast)
@@ -1133,11 +1133,11 @@ bool Codegen::visit(DeleteExpression *ast)
switch (expr.type) {
case Reference::StackSlot:
- if (!expr.stackSlotIsLocal)
+ if (!expr.stackSlotIsLocalOrArgument)
break;
// fall through
- case Reference::Local:
- case Reference::Argument:
+ case Reference::ScopedArgument:
+ case Reference::ScopedLocal:
// Trying to delete a function argument might throw.
if (_context->isStrict) {
throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode."));
@@ -1219,7 +1219,7 @@ bool Codegen::visit(FunctionExpression *ast)
Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
{
- uint scope = 0;
+ int scope = 0;
Context *c = _context;
while (c->parent) {
@@ -1228,7 +1228,8 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
Context::Member m = c->findMember(name);
if (m.type != Context::UndefinedMember) {
- Reference r = m.canEscape ? Reference::fromLocal(this, m.index, scope) : Reference::fromStackSlot(this, m.index, true /*isLocal*/);
+ Reference r = m.canEscape ? Reference::fromScopedLocal(this, m.index, scope)
+ : Reference::fromStackSlot(this, m.index, true /*isLocal*/);
if (name == QLatin1String("arguments") || name == QLatin1String("eval")) {
r.isArgOrEval = true;
if (isLhs && c->isStrict)
@@ -1238,8 +1239,14 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
return r;
}
const int argIdx = c->findArgument(name);
- if (argIdx != -1)
- return Reference::fromArgument(this, argIdx, scope);
+ if (argIdx != -1) {
+ if (c->argumentsCanEscape || c->usesArgumentsObject == Context::ArgumentsObjectUsed) {
+ return Reference::fromScopedArgument(this, argIdx, scope);
+ } else {
+ Q_ASSERT(scope == 0);
+ return Reference::fromArgument(this, argIdx);
+ }
+ }
if (!c->isStrict && c->hasDirectEval)
goto loadByName;
@@ -1487,7 +1494,7 @@ bool Codegen::visit(ObjectLiteral *ast)
call.internalClassId = classId;
call.arrayValueCount = arrayKeyWithValue.size();
call.arrayGetterSetterCountAndFlags = arrayGetterSetterCountAndFlags;
- call.args = Moth::StackSlot::create(args);
+ call.args = Moth::StackSlot::createRegister(args);
bytecodeGenerator->addInstruction(call);
_expr.setResult(Reference::fromAccumulator(this));
@@ -1770,7 +1777,8 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
Reference::fromName(this, member.function->name.toString()).storeConsumeAccumulator();
} else {
Q_ASSERT(member.index >= 0);
- Reference local = member.canEscape ? Reference::fromLocal(this, member.index, 0) : Reference::fromStackSlot(this, member.index, true);
+ Reference local = member.canEscape ? Reference::fromScopedLocal(this, member.index, 0)
+ : Reference::fromStackSlot(this, member.index, true);
local.storeConsumeAccumulator();
}
}
@@ -1800,9 +1808,11 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
}
_context->code = bytecodeGenerator->finalize();
+ _context->registerCount = bytecodeGenerator->registerCount();
static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
if (showCode) {
- qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict;
+ qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict
+ << "register count" << _context->registerCount;
QV4::Moth::dumpBytecode(_context->code);
qDebug();
}
@@ -2442,7 +2452,7 @@ bool Codegen::throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r,
if (str == QLatin1String("eval") || str == QLatin1String("arguments")) {
isArgOrEval = true;
}
- } else if (r.type == Reference::Local || r.type == Reference::StackSlot) {
+ } else if (r.type == Reference::ScopedLocal || r.isRegister()) {
isArgOrEval = r.isArgOrEval;
}
if (isArgOrEval)
@@ -2544,7 +2554,7 @@ bool Codegen::RValue::operator==(const RValue &other) const
}
}
-Codegen::RValue Codegen::RValue::storeInTemp() const
+Codegen::RValue Codegen::RValue::storeOnStack() const
{
switch (type) {
case Accumulator:
@@ -2574,8 +2584,8 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
case StackSlot:
theStackSlot = other.theStackSlot;
break;
- case Local:
- case Argument:
+ case ScopedLocal:
+ case ScopedArgument:
index = other.index;
scope = other.scope;
break;
@@ -2611,7 +2621,7 @@ Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
isArgOrEval = other.isArgOrEval;
codegen = other.codegen;
isReadonly = other.isReadonly;
- stackSlotIsLocal = other.stackSlotIsLocal;
+ stackSlotIsLocalOrArgument = other.stackSlotIsLocalOrArgument;
global = other.global;
return *this;
}
@@ -2626,8 +2636,8 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const
break;
case StackSlot:
return theStackSlot == other.theStackSlot;
- case Local:
- case Argument:
+ case ScopedLocal:
+ case ScopedArgument:
return index == other.index && scope == other.scope;
case Name:
return unqualifiedNameIndex == other.unqualifiedNameIndex;
@@ -2675,14 +2685,14 @@ Codegen::Reference Codegen::Reference::asLValue() const
case Member:
if (!propertyBase.isStackSlot()) {
Reference r = *this;
- r.propertyBase = propertyBase.storeInTemp();
+ r.propertyBase = propertyBase.storeOnStack();
return r;
}
return *this;
case Subscript:
if (!elementSubscript.isStackSlot()) {
Reference r = *this;
- r.elementSubscript = elementSubscript.storeInTemp();
+ r.elementSubscript = elementSubscript.storeOnStack();
return r;
}
return *this;
@@ -2750,8 +2760,8 @@ bool Codegen::Reference::storeWipesAccumulator() const
Q_UNREACHABLE();
return false;
case StackSlot:
- case Local:
- case Argument:
+ case ScopedLocal:
+ case ScopedArgument:
return false;
case Name:
case Member:
@@ -2772,30 +2782,20 @@ void Codegen::Reference::storeAccumulator() const
codegen->bytecodeGenerator->addInstruction(store);
return;
}
- case Local:
- if (scope == 0) {
- Instruction::StoreLocal store;
- store.index = index;
- codegen->bytecodeGenerator->addInstruction(store);
- } else {
- Instruction::StoreScopedLocal store;
- store.index = index;
- store.scope = scope;
- codegen->bytecodeGenerator->addInstruction(store);
- }
+ case ScopedLocal: {
+ Instruction::StoreScopedLocal store;
+ store.index = index;
+ store.scope = scope;
+ codegen->bytecodeGenerator->addInstruction(store);
return;
- case Argument:
- if (scope == 0) {
- Instruction::StoreArg store;
- store.index = index;
- codegen->bytecodeGenerator->addInstruction(store);
- } else {
- Instruction::StoreScopedArg store;
- store.index = index;
- store.scope = scope;
- codegen->bytecodeGenerator->addInstruction(store);
- }
+ }
+ case ScopedArgument: {
+ Instruction::StoreScopedArgument store;
+ store.index = index;
+ store.scope = scope;
+ codegen->bytecodeGenerator->addInstruction(store);
return;
+ }
case Name: {
Instruction::StoreName store;
store.name = unqualifiedNameIndex;
@@ -2859,30 +2859,20 @@ void Codegen::Reference::loadInAccumulator() const
load.reg = stackSlot();
codegen->bytecodeGenerator->addInstruction(load);
} return;
- case Local:
- if (scope == 0) {
- Instruction::LoadLocal load;
- load.index = index;
- codegen->bytecodeGenerator->addInstruction(load);
- } else {
- Instruction::LoadScopedLocal load;
- load.index = index;
- load.scope = scope;
- codegen->bytecodeGenerator->addInstruction(load);
- }
+ case ScopedLocal: {
+ Instruction::LoadScopedLocal load;
+ load.index = index;
+ load.scope = scope;
+ codegen->bytecodeGenerator->addInstruction(load);
return;
- case Argument:
- if (scope == 0) {
- Instruction::LoadArg load;
- load.index = index;
- codegen->bytecodeGenerator->addInstruction(load);
- } else {
- Instruction::LoadScopedArg load;
- load.index = index;
- load.scope = scope;
- codegen->bytecodeGenerator->addInstruction(load);
- }
+ }
+ case ScopedArgument: {
+ Instruction::LoadScopedArgument load;
+ load.index = index;
+ load.scope = scope;
+ codegen->bytecodeGenerator->addInstruction(load);
return;
+ }
case Name:
if (codegen->useFastLookups && global) {
Instruction::GetGlobalLookup load;
@@ -2902,7 +2892,7 @@ void Codegen::Reference::loadInAccumulator() const
codegen->bytecodeGenerator->addInstruction(load);
} else {
Instruction::GetLookup load;
- load.base = propertyBase.storeInTemp().stackSlot();
+ load.base = propertyBase.storeOnStack().stackSlot();
load.index = codegen->registerGetterLookup(propertyNameIndex);
codegen->bytecodeGenerator->addInstruction(load);
}
@@ -2913,7 +2903,7 @@ void Codegen::Reference::loadInAccumulator() const
codegen->bytecodeGenerator->addInstruction(load);
} else {
Instruction::LoadProperty load;
- load.base = propertyBase.storeInTemp().stackSlot();
+ load.base = propertyBase.storeOnStack().stackSlot();
load.name = propertyNameIndex;
codegen->bytecodeGenerator->addInstruction(load);
}
@@ -2932,7 +2922,7 @@ void Codegen::Reference::loadInAccumulator() const
} else {
Instruction::LoadElement load;
load.base = elementBase;
- load.index = elementSubscript.storeInTemp().stackSlot();
+ load.index = elementSubscript.storeOnStack().stackSlot();
codegen->bytecodeGenerator->addInstruction(load);
}
} return;
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 2a482196ca..56bed33c19 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -155,15 +155,15 @@ public:
return constant;
}
- Q_REQUIRED_RESULT RValue storeInTemp() const;
+ Q_REQUIRED_RESULT RValue storeOnStack() const;
};
struct Reference {
enum Type {
Invalid,
Accumulator,
StackSlot,
- Local,
- Argument,
+ ScopedLocal,
+ ScopedArgument,
Name,
Member,
Subscript,
@@ -202,6 +202,9 @@ public:
bool isConst() const { return type == Const; }
bool isAccumulator() const { return type == Accumulator; }
bool isStackSlot() const { return type == StackSlot; }
+ bool isRegister() const {
+ return isStackSlot() && theStackSlot.isRegister();
+ }
static Reference fromAccumulator(Codegen *cg) {
return Reference(cg, Accumulator);
@@ -210,18 +213,24 @@ public:
Reference r(cg, StackSlot);
if (tempIndex == -1)
tempIndex = cg->bytecodeGenerator->newRegister();
- r.theStackSlot = Moth::StackSlot::create(tempIndex);
- r.stackSlotIsLocal = isLocal;
+ r.theStackSlot = Moth::StackSlot::createRegister(tempIndex);
+ r.stackSlotIsLocalOrArgument = isLocal;
+ return r;
+ }
+ static Reference fromArgument(Codegen *cg, int index) {
+ Reference r(cg, StackSlot);
+ r.theStackSlot = Moth::StackSlot::createArgument(index);
+ r.stackSlotIsLocalOrArgument = true;
return r;
}
- static Reference fromLocal(Codegen *cg, uint index, uint scope) {
- Reference r(cg, Local);
+ static Reference fromScopedLocal(Codegen *cg, int index, int scope) {
+ Reference r(cg, ScopedLocal);
r.index = index;
r.scope = scope;
return r;
}
- static Reference fromArgument(Codegen *cg, uint index, uint scope) {
- Reference r(cg, Argument);
+ static Reference fromScopedArgument(Codegen *cg, int index, int scope) {
+ Reference r(cg, ScopedArgument);
r.index = index;
r.scope = scope;
return r;
@@ -298,7 +307,7 @@ public:
Moth::StackSlot theStackSlot;
QV4::ReturnedValue constant;
int unqualifiedNameIndex;
- struct { // Argument/Local
+ struct { // Scoped arguments/Local
int index;
int scope;
};
@@ -320,7 +329,7 @@ public:
};
mutable bool isArgOrEval = false;
bool isReadonly = false;
- bool stackSlotIsLocal = false;
+ bool stackSlotIsLocalOrArgument = false;
bool global = false;
Codegen *codegen;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 5f83c1bd19..9ffd2b2b1d 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -223,6 +223,7 @@ struct Function
LEUInt32 nLocals;
LEUInt32 localsOffset;
LEUInt32 nInnerFunctions;
+ LEUInt32 nRegisters;
Location location;
// Qml Extensions Begin
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 8c15be5477..3d42dff662 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -336,6 +336,8 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
function->nInnerFunctions = irFunction->nestedContexts.size();
+ function->nRegisters = irFunction->registerCount;
+
function->nDependingIdObjects = 0;
function->nDependingContextProperties = 0;
function->nDependingScopeProperties = 0;
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index f3481f0251..0a204d8c24 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -103,7 +103,7 @@ struct Context {
QString name;
int line = 0;
int column = 0;
-
+ int registerCount = 0;
int functionIndex = -1;
enum MemberType {
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index e2bd3c73b9..9f5413bcf2 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -142,22 +142,6 @@ void dumpBytecode(const char *code, int len)
d << instr.destTemp << ", C" << instr.constIndex;
MOTH_END_INSTR(MoveConst)
- MOTH_BEGIN_INSTR(LoadLocal)
- d << "$" << instr.index;
- MOTH_END_INSTR(LoadLocal)
-
- MOTH_BEGIN_INSTR(StoreLocal)
- d << "$" << instr.index;
- MOTH_END_INSTR(StoreLocal)
-
- MOTH_BEGIN_INSTR(LoadArg)
- d << "#" << instr.index;
- MOTH_END_INSTR(LoadArg)
-
- MOTH_BEGIN_INSTR(StoreArg)
- d << "#" << instr.index;
- MOTH_END_INSTR(StoreArg)
-
MOTH_BEGIN_INSTR(LoadScopedLocal)
d << "$" << instr.index << "@" << instr.scope;
MOTH_END_INSTR(LoadScopedLocal)
@@ -166,13 +150,13 @@ void dumpBytecode(const char *code, int len)
d << ", " << "$" << instr.index << "@" << instr.scope;
MOTH_END_INSTR(StoreScopedLocal)
- MOTH_BEGIN_INSTR(LoadScopedArg)
+ MOTH_BEGIN_INSTR(LoadScopedArgument)
d << "#" << instr.index << "@" << instr.scope;
- MOTH_END_INSTR(LoadScopedArg)
+ MOTH_END_INSTR(LoadScopedArgument)
- MOTH_BEGIN_INSTR(StoreScopedArg)
+ MOTH_BEGIN_INSTR(StoreScopedArgument)
d << "#" << instr.index << "@" << instr.scope;
- MOTH_END_INSTR(StoreScopedArg)
+ MOTH_END_INSTR(StoreScopedArgument)
MOTH_BEGIN_INSTR(LoadRuntimeString)
d << instr.stringId;
@@ -262,10 +246,6 @@ void dumpBytecode(const char *code, int len)
d << instr.base << "[" << instr.index << "]";
MOTH_END_INSTR(LoadIdObject)
- MOTH_BEGIN_INSTR(InitStackFrame)
- d << instr.value;
- MOTH_END_INSTR(InitStackFrame)
-
MOTH_BEGIN_INSTR(CallValue)
d << instr.dest << "(" << instr.callData << ")";
MOTH_END_INSTR(CallValue)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index c22be0c0fe..19d521dbe3 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -76,14 +76,10 @@ QT_BEGIN_NAMESPACE
F(LoadReg, loadReg) \
F(StoreReg, storeReg) \
F(MoveReg, moveReg) \
- F(LoadLocal, loadLocal) \
- F(StoreLocal, storeLocal) \
- F(LoadArg, loadArg) \
- F(StoreArg, storeArg) \
F(LoadScopedLocal, loadScopedLocal) \
F(StoreScopedLocal, storeScopedLocal) \
- F(LoadScopedArg, loadScopedArg) \
- F(StoreScopedArg, storeScopedArg) \
+ F(LoadScopedArgument, loadScopedArgument) \
+ F(StoreScopedArgument, storeScopedArgument) \
F(LoadRuntimeString, loadRuntimeString) \
F(LoadRegExp, loadRegExp) \
F(LoadClosure, loadClosure) \
@@ -106,7 +102,6 @@ QT_BEGIN_NAMESPACE
F(LoadScopeObjectProperty, loadScopeObjectProperty) \
F(LoadContextObjectProperty, loadContextObjectProperty) \
F(LoadIdObject, loadIdObject) \
- F(InitStackFrame, initStackFrame) \
F(CallValue, callValue) \
F(CallProperty, callProperty) \
F(CallPropertyLookup, callPropertyLookup) \
@@ -190,12 +185,33 @@ class StackSlot {
int index;
public:
- static StackSlot create(int index) {
+ static StackSlot createRegister(int index) {
+ Q_ASSERT(index >= 0);
StackSlot t;
t.index = index;
return t;
}
+ static StackSlot createArgument(int index) {
+ Q_ASSERT(index >= 0);
+ StackSlot t;
+ t.index = -index - 1;
+ return t;
+ }
+
+ bool isRegister() const { return index >= 0; }
+ bool isArgument() const { return index < 0; }
+
+// int tempIndex() const {
+// Q_ASSERT(isTemp());
+// return index;
+// }
+
+// int argIndex() const {
+// Q_ASSERT(isArg());
+// return -index - 1;
+// }
+
int stackSlot() const { return index; }
};
@@ -258,22 +274,6 @@ union Instr
StackSlot srcReg;
StackSlot destReg;
};
- struct instr_loadLocal {
- MOTH_INSTR_HEADER
- int index;
- };
- struct instr_storeLocal {
- MOTH_INSTR_HEADER
- int index;
- };
- struct instr_loadArg {
- MOTH_INSTR_HEADER
- int index;
- };
- struct instr_storeArg {
- MOTH_INSTR_HEADER
- int index;
- };
struct instr_loadScopedLocal {
MOTH_INSTR_HEADER
int scope;
@@ -284,12 +284,12 @@ union Instr
int scope;
int index;
};
- struct instr_loadScopedArg {
+ struct instr_loadScopedArgument {
MOTH_INSTR_HEADER
int scope;
int index;
};
- struct instr_storeScopedArg {
+ struct instr_storeScopedArgument {
MOTH_INSTR_HEADER
int scope;
int index;
@@ -399,10 +399,6 @@ union Instr
StackSlot base;
StackSlot index;
};
- struct instr_initStackFrame {
- MOTH_INSTR_HEADER
- int value;
- };
struct instr_callValue {
MOTH_INSTR_HEADER
StackSlot callData;
@@ -682,14 +678,10 @@ union Instr
instr_loadReg loadReg;
instr_storeReg storeReg;
instr_moveReg moveReg;
- instr_loadLocal loadLocal;
- instr_storeLocal storeLocal;
- instr_loadArg loadArg;
- instr_storeArg storeArg;
instr_loadScopedLocal loadScopedLocal;
instr_storeScopedLocal storeScopedLocal;
- instr_loadScopedArg loadScopedArg;
- instr_storeScopedArg storeScopedArg;
+ instr_loadScopedArgument loadScopedArgument;
+ instr_storeScopedArgument storeScopedArgument;
instr_loadRuntimeString loadRuntimeString;
instr_loadRegExp loadRegExp;
instr_loadClosure loadClosure;
@@ -712,7 +704,6 @@ union Instr
instr_setLookup setLookup;
instr_storeScopeObjectProperty storeScopeObjectProperty;
instr_storeContextObjectProperty storeContextObjectProperty;
- instr_initStackFrame initStackFrame;
instr_callValue callValue;
instr_callProperty callProperty;
instr_callPropertyLookup callPropertyLookup;
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 4ccd133d73..348751f0cb 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -393,25 +393,46 @@ static inline QV4::Heap::ExecutionContext *getScope(QV4::Heap::ExecutionContext
return scope;
}
-static inline void storeLocal(ExecutionEngine *engine, QV4::Heap::ExecutionContext *scope,
- QV4::Value *slot, QV4::Value value)
+static inline ReturnedValue loadScopedLocal(ExecutionEngine *engine, int index, int scope)
{
- Q_ASSERT(scope->type == QV4::Heap::ExecutionContext::Type_CallContext);
+ auto ctxt = getScope(engine->current, scope);
+ Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
+ auto cc = static_cast<Heap::CallContext *>(ctxt);
+ return cc->locals[index].asReturnedValue();
+}
+
+static inline void storeScopedLocal(ExecutionEngine *engine, int index, int scope,
+ const QV4::Value &value)
+{
+ auto ctxt = getScope(engine->current, scope);
+ Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
+ auto cc = static_cast<Heap::CallContext *>(ctxt);
+
if (Q_UNLIKELY(engine->writeBarrierActive))
- QV4::WriteBarrier::write(engine, scope, slot, value);
+ QV4::WriteBarrier::write(engine, cc, cc->locals.values + index, value);
else
- *slot = value;
+ *(cc->locals.values + index) = value;
}
-static inline void storeArg(ExecutionEngine *engine, QV4::Heap::ExecutionContext *scope,
- QV4::Value *slot, QV4::Value value)
+static inline ReturnedValue loadScopedArg(ExecutionEngine *engine, int index, int scope)
{
- Q_ASSERT(scope->type == QV4::Heap::ExecutionContext::Type_SimpleCallContext
- || scope->type == QV4::Heap::ExecutionContext::Type_CallContext);
+ auto ctxt = getScope(engine->current, scope);
+ Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
+ auto cc = static_cast<Heap::CallContext *>(ctxt);
+ return cc->callData->args[index].asReturnedValue();
+}
+
+static inline void storeScopedArg(ExecutionEngine *engine, int index, int scope,
+ const QV4::Value &value)
+{
+ auto ctxt = getScope(engine->current, scope);
+ Q_ASSERT(ctxt->type == QV4::Heap::ExecutionContext::Type_CallContext);
+ auto cc = static_cast<Heap::CallContext *>(ctxt);
+
if (Q_UNLIKELY(engine->writeBarrierActive))
- QV4::WriteBarrier::write(engine, scope, slot, value);
+ QV4::WriteBarrier::write(engine, cc, cc->callData->args + index, value);
else
- *slot = value;
+ *(cc->callData->args + index) = value;
}
static inline const QV4::Value &constant(Function *function, int index)
@@ -421,10 +442,6 @@ static inline const QV4::Value &constant(Function *function, int index)
QV4::ReturnedValue VME::exec(Function *function)
{
-#ifdef DO_TRACE_INSTR
- qDebug("Starting VME with context=%p and code=%p", context, code);
-#endif // DO_TRACE_INSTR
-
qt_v4ResolvePendingBreakpointsHook();
#ifdef MOTH_THREADED_INTERPRETER
@@ -436,38 +453,20 @@ QV4::ReturnedValue VME::exec(Function *function)
#endif
ExecutionEngine *engine = function->internalClass->engine;
-
- // Arguments/locals are used a *lot*, and pre-fetching them removes a whole bunch of triple
- // (or quadruple) indirect loads.
- QV4::Value *arguments = nullptr;
- QV4::Value *locals = nullptr;
- QV4::Value *argumentsScope1 = nullptr;
- QV4::Value *localsScope1 = nullptr;
- QV4::Heap::ExecutionContext *functionScope = nullptr;
- QV4::Heap::ExecutionContext *functionScope1 = nullptr;
- { // setup args/locals/etc
- functionScope = engine->current;
- arguments = functionScope->callData->args;
- if (functionScope->type == QV4::Heap::ExecutionContext::Type_CallContext)
- locals = static_cast<QV4::Heap::CallContext *>(functionScope)->locals.values;
-
- functionScope1 = functionScope->outer;
- if (functionScope1) {
- argumentsScope1 = functionScope1->callData->args;
- if (functionScope1->type == QV4::Heap::ExecutionContext::Type_CallContext)
- localsScope1 = static_cast<QV4::Heap::CallContext *>(functionScope1)->locals.values;
- }
- }
-
QV4::Value accumulator = Primitive::undefinedValue();
- QV4::Value *stack = 0;
- unsigned stackSize = 0;
-
+ QV4::Value *stack = nullptr;
const uchar *exceptionHandler = 0;
QV4::Scope scope(engine);
- engine->current->lineNumber = -1;
+ {
+ int nFormals = function->nFormals;
+ stack = scope.alloc(function->compiledFunction->nRegisters + nFormals) + nFormals;
+ auto cc = engine->current;
+ for (int i = 0, ei = std::min<int>(cc->callData->argc, nFormals); i != ei; ++i)
+ stack[-i-1] = cc->callData->args[i];
+ }
+ engine->current->lineNumber = -1;
if (QV4::Debugging::Debugger *debugger = engine->debugger())
debugger->enteringFunction();
@@ -501,58 +500,23 @@ QV4::ReturnedValue VME::exec(Function *function)
STACK_VALUE(instr.destReg) = STACK_VALUE(instr.srcReg);
MOTH_END_INSTR(MoveReg)
- MOTH_BEGIN_INSTR(LoadLocal)
- accumulator = locals[instr.index];
- MOTH_END_INSTR(LoadLocal)
-
- MOTH_BEGIN_INSTR(StoreLocal)
- CHECK_EXCEPTION;
- storeLocal(engine, functionScope, locals + instr.index, accumulator);
- MOTH_END_INSTR(StoreLocal)
-
- MOTH_BEGIN_INSTR(LoadArg)
- accumulator = arguments[instr.index];
- MOTH_END_INSTR(LoadArg)
-
- MOTH_BEGIN_INSTR(StoreArg)
- CHECK_EXCEPTION;
- storeArg(engine, functionScope, arguments + instr.index, accumulator);
- MOTH_END_INSTR(StoreArg)
-
MOTH_BEGIN_INSTR(LoadScopedLocal)
- if (Q_LIKELY(instr.scope == 1))
- accumulator = localsScope1[instr.index];
- else
- accumulator = static_cast<QV4::Heap::CallContext *>(getScope(functionScope, instr.scope))->locals[instr.index];
+ accumulator = loadScopedLocal(engine, instr.index, instr.scope);
MOTH_END_INSTR(LoadScopedLocal)
MOTH_BEGIN_INSTR(StoreScopedLocal)
CHECK_EXCEPTION;
- if (Q_LIKELY(instr.scope == 1)) {
- storeLocal(engine, functionScope1, localsScope1 + instr.index, accumulator);
- } else {
- QV4::Heap::ExecutionContext *scope = getScope(functionScope, instr.scope);
- QV4::Heap::CallContext *cc = static_cast<QV4::Heap::CallContext *>(scope);
- storeLocal(engine, cc, cc->locals.values + instr.index, accumulator);
- }
+ storeScopedLocal(engine, instr.index, instr.scope, accumulator);
MOTH_END_INSTR(StoreScopedLocal)
- MOTH_BEGIN_INSTR(LoadScopedArg)
- if (Q_LIKELY(instr.scope == 1))
- accumulator = argumentsScope1[instr.index];
- else
- accumulator = getScope(functionScope, instr.scope)->callData->args[instr.index];
- MOTH_END_INSTR(LoadScopedArg);
+ MOTH_BEGIN_INSTR(LoadScopedArgument)
+ accumulator = loadScopedArg(engine, instr.index, instr.scope);
+ MOTH_END_INSTR(LoadScopedArgument)
- MOTH_BEGIN_INSTR(StoreScopedArg)
+ MOTH_BEGIN_INSTR(StoreScopedArgument)
CHECK_EXCEPTION;
- if (Q_LIKELY(instr.scope == 1)) {
- storeArg(engine, functionScope1, argumentsScope1 + instr.index, accumulator);
- } else {
- QV4::Heap::ExecutionContext *scope = getScope(functionScope, instr.scope);
- storeLocal(engine, scope, scope->callData->args + instr.index, accumulator);
- }
- MOTH_END_INSTR(StoreScopedArg)
+ storeScopedArg(engine, instr.index, instr.scope, accumulator);
+ MOTH_END_INSTR(StoreScopedArgument)
MOTH_BEGIN_INSTR(LoadRuntimeString)
accumulator = function->compilationUnit->runtimeStrings[instr.stringId];
@@ -655,11 +619,6 @@ QV4::ReturnedValue VME::exec(Function *function)
STORE_ACCUMULATOR(Runtime::method_getQmlIdObject(engine, STACK_VALUE(instr.base), instr.index));
MOTH_END_INSTR(LoadIdObject)
- MOTH_BEGIN_INSTR(InitStackFrame)
- stackSize = unsigned(instr.value);
- stack = scope.alloc(instr.value);
- MOTH_END_INSTR(InitStackFrame)
-
MOTH_BEGIN_INSTR(CallValue)
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot());
STORE_ACCUMULATOR(Runtime::method_callValue(engine, STACK_VALUE(instr.dest), callData));
@@ -763,7 +722,6 @@ QV4::ReturnedValue VME::exec(Function *function)
MOTH_END_INSTR(CallBuiltinDeclareVar)
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
- Q_ASSERT(instr.args.stackSlot() + instr.argc <= stackSize);
QV4::Value *args = stack + instr.args.stackSlot();
STORE_ACCUMULATOR(Runtime::method_arrayLiteral(engine, args, instr.argc));
MOTH_END_INSTR(CallBuiltinDefineArray)
@@ -789,7 +747,6 @@ QV4::ReturnedValue VME::exec(Function *function)
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
- Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot());
callData->tag = quint32(Value::ValueTypeInternal::Integer);
callData->argc = instr.argc;
@@ -798,7 +755,6 @@ QV4::ReturnedValue VME::exec(Function *function)
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(ConstructPropertyLookup)
- Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot());
callData->tag = quint32(Value::ValueTypeInternal::Integer);
callData->argc = instr.argc;
@@ -807,7 +763,6 @@ QV4::ReturnedValue VME::exec(Function *function)
MOTH_END_INSTR(ConstructPropertyLookup)
MOTH_BEGIN_INSTR(CreateActivationProperty)
- Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot());
callData->tag = quint32(Value::ValueTypeInternal::Integer);
callData->argc = instr.argc;
@@ -816,7 +771,6 @@ QV4::ReturnedValue VME::exec(Function *function)
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
- Q_ASSERT(instr.callData.stackSlot() + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData.stackSlot());
callData->tag = quint32(Value::ValueTypeInternal::Integer);
callData->argc = instr.argc;