diff options
Diffstat (limited to 'src/qml/compiler/qv4isel_masm_p.h')
-rw-r--r-- | src/qml/compiler/qv4isel_masm_p.h | 117 |
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; } }; |