aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4isel_masm_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4isel_masm_p.h')
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h117
1 files changed, 78 insertions, 39 deletions
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index bd4c564ab9..4b0d19df07 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -49,6 +49,7 @@
#include "private/qv4lookup_p.h"
#include <QtCore/QHash>
+#include <QtCore/QStack>
#include <config.h>
#include <wtf/Vector.h>
@@ -62,6 +63,7 @@ QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace MASM {
+
class InstructionSelection;
struct CompilationUnit : public QV4::CompiledData::CompilationUnit
@@ -88,6 +90,37 @@ struct RelativeCall {
{}
};
+
+template <typename T>
+struct ExceptionCheck {
+ enum { NeedsCheck = 1 };
+};
+// push_catch and pop context methods shouldn't check for exceptions
+template <>
+struct ExceptionCheck<QV4::ExecutionContext *(*)(QV4::ExecutionContext *)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A>
+struct ExceptionCheck<QV4::ExecutionContext *(*)(QV4::ExecutionContext *, A)> {
+ enum { NeedsCheck = 0 };
+};
+template <>
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowContext *)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A>
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowContext *, A)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A, typename B>
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowContext *, A, B)> {
+ enum { NeedsCheck = 0 };
+};
+template <typename A, typename B, typename C>
+struct ExceptionCheck<void (*)(QV4::NoThrowContext *, A, B, C)> {
+ enum { NeedsCheck = 0 };
+};
+
class Assembler : public JSC::MacroAssembler
{
public:
@@ -433,25 +466,7 @@ public:
V4IR::BasicBlock *block;
};
- void saveInstructionPointer(RegisterID freeScratchRegister) {
- Address ipAddr(ContextRegister, qOffsetOf(QV4::ExecutionContext, jitInstructionPointer));
- RegisterID sourceRegister = freeScratchRegister;
-
-#if CPU(X86_64) || CPU(X86)
- callToRetrieveIP();
- peek(sourceRegister);
- pop();
-#elif CPU(ARM)
- move(JSC::ARMRegisters::pc, sourceRegister);
-#else
-#error "Port me!"
-#endif
-
- storePtr(sourceRegister, ipAddr);
- }
-
void callAbsolute(const char* functionName, FunctionPtr function) {
- saveInstructionPointer(ScratchRegister);
CallToLink ctl;
ctl.call = call();
ctl.externalFunction = function;
@@ -460,13 +475,11 @@ public:
}
void callAbsolute(const char* /*functionName*/, Address addr) {
- saveInstructionPointer(ScratchRegister);
call(addr);
}
void callAbsolute(const char* /*functionName*/, const RelativeCall &relativeCall)
{
- saveInstructionPointer(ScratchRegister);
call(relativeCall.addr);
}
@@ -874,6 +887,23 @@ public:
void enterStandardStackFrame();
void leaveStandardStackFrame();
+ void checkException() {
+ loadPtr(Address(ContextRegister, qOffsetOf(QV4::ExecutionContext, engine)), ScratchRegister);
+ load32(Address(ScratchRegister, qOffsetOf(QV4::ExecutionEngine, hasException)), ScratchRegister);
+ Jump exceptionThrown = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
+ if (catchBlock)
+ addPatch(catchBlock, exceptionThrown);
+ else
+ exceptionPropagationJumps.append(exceptionThrown);
+ }
+ void jumpToExceptionHandler() {
+ Jump exceptionThrown = jump();
+ if (catchBlock)
+ addPatch(catchBlock, exceptionThrown);
+ else
+ exceptionPropagationJumps.append(exceptionThrown);
+ }
+
template <int argumentNumber, typename T>
void loadArgumentOnStackOrRegister(const T &value)
{
@@ -917,7 +947,6 @@ public:
enum { Size = 0 };
};
-
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6>
void generateFunctionCallImp(ArgRet r, const char* functionName, Callable function, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6)
{
@@ -954,10 +983,15 @@ public:
callAbsolute(functionName, function);
- storeReturnValue(r);
-
if (stackSpaceNeeded)
add32(TrustedImm32(stackSpaceNeeded), StackPointerRegister);
+
+ if (ExceptionCheck<Callable>::NeedsCheck) {
+ checkException();
+ }
+
+ storeReturnValue(r);
+
}
template <typename ArgRet, typename Callable, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
@@ -1346,11 +1380,12 @@ public:
JSC::MacroAssemblerCodeRef link(int *codeSize);
- void recordLineNumber(int lineNumber);
-
const StackLayout stackLayout() const { return _stackLayout; }
ConstantTable &constantTable() { return _constTable; }
+ Label exceptionReturnLabel;
+ V4IR::BasicBlock * catchBlock;
+ QVector<Jump> exceptionPropagationJumps;
private:
const StackLayout _stackLayout;
ConstantTable _constTable;
@@ -1370,13 +1405,6 @@ private:
QV4::ExecutableAllocator *_executableAllocator;
InstructionSelection *_isel;
-
- struct CodeLineNumerMapping
- {
- Assembler::Label location;
- int lineNumber;
- };
- QVector<CodeLineNumerMapping> codeLineNumberMappings;
};
template <typename T> inline void prepareRelativeCall(const T &, Assembler *){}
@@ -1391,7 +1419,7 @@ class Q_QML_EXPORT InstructionSelection:
public EvalInstructionSelection
{
public:
- InstructionSelection(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
+ InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator);
~InstructionSelection();
virtual void run(int functionIndex);
@@ -1410,7 +1438,9 @@ protected:
virtual void callBuiltinDeleteName(const QString &name, V4IR::Temp *result);
virtual void callBuiltinDeleteValue(V4IR::Temp *result);
virtual void callBuiltinThrow(V4IR::Expr *arg);
- virtual void callBuiltinFinishTry();
+ virtual void callBuiltinReThrow();
+ virtual void callBuiltinUnwindException(V4IR::Temp *);
+ virtual void callBuiltinPushCatchScope(const QString &exceptionName);
virtual void callBuiltinForeachIteratorObject(V4IR::Temp *arg, V4IR::Temp *result);
virtual void callBuiltinForeachNextPropertyname(V4IR::Temp *arg, V4IR::Temp *result);
virtual void callBuiltinPushWithScope(V4IR::Temp *arg);
@@ -1421,11 +1451,17 @@ protected:
virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args);
virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args);
virtual void callBuiltinSetupArgumentObject(V4IR::Temp *result);
+ virtual void callBuiltinConvertThisToObject();
virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
virtual void callProperty(V4IR::Expr *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
virtual void callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4IR::ExprList *args, V4IR::Temp *result);
virtual void convertType(V4IR::Temp *source, V4IR::Temp *target);
virtual void loadThisObject(V4IR::Temp *temp);
+ virtual void loadQmlIdArray(V4IR::Temp *temp);
+ virtual void loadQmlImportedScripts(V4IR::Temp *temp);
+ virtual void loadQmlContextObject(V4IR::Temp *temp);
+ virtual void loadQmlScopeObject(V4IR::Temp *temp);
+ virtual void loadQmlSingleton(const QString &name, V4IR::Temp *temp);
virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);
virtual void loadString(const QString &str, V4IR::Temp *targetTemp);
virtual void loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp);
@@ -1434,6 +1470,8 @@ protected:
virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target);
virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target);
virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName);
+ virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex);
+ virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target);
virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target);
virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex);
virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
@@ -1469,7 +1507,6 @@ protected:
virtual void visitJump(V4IR::Jump *);
virtual void visitCJump(V4IR::CJump *);
virtual void visitRet(V4IR::Ret *);
- virtual void visitTry(V4IR::Try *);
Assembler::Jump genTryDoubleConversion(V4IR::Expr *src, Assembler::FPRegisterID dest);
Assembler::Jump genInlineBinop(V4IR::AluOp oper, V4IR::Expr *leftSource,
@@ -1483,6 +1520,9 @@ protected:
bool visitCJumpStrictNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop,
V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
bool visitCJumpStrictBool(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
+ bool visitCJumpNullUndefined(V4IR::Type nullOrUndef, V4IR::Binop *binop,
+ V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
+ void visitCJumpEqual(V4IR::Binop *binop, V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
bool int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource,
V4IR::Temp *target);
@@ -1586,20 +1626,19 @@ private:
}
V4IR::BasicBlock *_block;
- V4IR::Function* _function;
QSet<V4IR::Jump *> _removableJumps;
Assembler* _as;
- QSet<V4IR::BasicBlock*> _reentryBlocks;
CompilationUnit *compilationUnit;
+ QQmlEnginePrivate *qmlEngine;
};
class Q_QML_EXPORT ISelFactory: public EvalISelFactory
{
public:
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
- { return new InstructionSelection(execAllocator, module, jsGenerator); }
+ virtual EvalInstructionSelection *create(QQmlEnginePrivate *qmlEngine, QV4::ExecutableAllocator *execAllocator, V4IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
+ { return new InstructionSelection(qmlEngine, execAllocator, module, jsGenerator); }
virtual bool jitCompileRegexps() const
{ return true; }
};