From 6f1e2722b9eef73a4fe19951b47c4b172642a2ba Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 15 May 2018 13:15:43 +0200 Subject: Simplify Push and PopContext instructions There's no need for a temp register to store the old context in, as PopContext can simply retrieve the old context from the current one. Change-Id: Ife9cfdff7fa8e47fc71e844a7798de88dbc79e26 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4codegen.cpp | 2 +- src/qml/compiler/qv4compilercontext.cpp | 43 +++++++++++++---------------- src/qml/compiler/qv4compilercontext_p.h | 4 +-- src/qml/compiler/qv4compilercontrolflow_p.h | 21 ++++++-------- src/qml/compiler/qv4instr_moth.cpp | 6 ++-- src/qml/compiler/qv4instr_moth_p.h | 8 +++--- src/qml/jit/qv4assembler.cpp | 11 +++++--- src/qml/jit/qv4assembler_p.h | 4 +-- src/qml/jit/qv4jit.cpp | 22 ++++++--------- src/qml/jit/qv4jit_p.h | 8 +++--- src/qml/jsruntime/qv4vme_moth.cpp | 6 ++-- 11 files changed, 60 insertions(+), 75 deletions(-) (limited to 'src/qml') diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index b46891572e..860a1307f2 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -2482,7 +2482,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, statementList(body); - _context->emitBlockFooter(this, -1); + _context->emitBlockFooter(this); if (hasError || !endsWithReturn(_module, body)) { bytecodeGenerator->setLocation(ast->lastSourceLocation()); diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp index bfe0d4b131..c4f7e51f6c 100644 --- a/src/qml/compiler/qv4compilercontext.cpp +++ b/src/qml/compiler/qv4compilercontext.cpp @@ -159,36 +159,32 @@ Context::ResolvedName Context::resolveName(const QString &name) return result; } -int Context::emitBlockHeader(Codegen *codegen) +void Context::emitBlockHeader(Codegen *codegen) { using Instruction = Moth::Instruction; Moth::BytecodeGenerator *bytecodeGenerator = codegen->generator(); setupFunctionIndices(bytecodeGenerator); - int contextReg = -1; - if (requiresExecutionContext && blockIndex < 0) { - codegen->module()->blocks.append(this); - blockIndex = codegen->module()->blocks.count() - 1; - } + if (requiresExecutionContext) { + if (blockIndex < 0) { + codegen->module()->blocks.append(this); + blockIndex = codegen->module()->blocks.count() - 1; + } - if (requiresExecutionContext && contextType == ContextType::Global) { - Instruction::PushScriptContext scriptContext; - scriptContext.index = blockIndex; - bytecodeGenerator->addInstruction(scriptContext); - } else if (requiresExecutionContext || - contextType == ContextType::Binding) { // we don't really need this for bindings, but we do for signal handlers, and we don't know if the code is a signal handler or not. - if (contextType == ContextType::Block || (contextType == ContextType::Eval && !isStrict)) { + if (contextType == ContextType::Global) { + Instruction::PushScriptContext scriptContext; + scriptContext.index = blockIndex; + bytecodeGenerator->addInstruction(scriptContext); + } else if (contextType == ContextType::Block || (contextType == ContextType::Eval && !isStrict)) { if (isCatchBlock) { Instruction::PushCatchContext catchContext; catchContext.index = blockIndex; - catchContext.reg = contextReg = bytecodeGenerator->newRegister(); catchContext.name = codegen->registerString(caughtVariable); bytecodeGenerator->addInstruction(catchContext); } else { Instruction::PushBlockContext blockContext; blockContext.index = blockIndex; - blockContext.reg = contextReg = bytecodeGenerator->newRegister(); bytecodeGenerator->addInstruction(blockContext); } } else { @@ -196,6 +192,7 @@ int Context::emitBlockHeader(Codegen *codegen) bytecodeGenerator->addInstruction(createContext); } } + if (usesThis && !isStrict) { // make sure we convert this to an object Instruction::ConvertThisToObject convert; @@ -250,25 +247,23 @@ int Context::emitBlockHeader(Codegen *codegen) r.storeConsumeAccumulator(); } } - - return contextReg; } -void Context::emitBlockFooter(Codegen *codegen, int oldContextReg) +void Context::emitBlockFooter(Codegen *codegen) { using Instruction = Moth::Instruction; Moth::BytecodeGenerator *bytecodeGenerator = codegen->generator(); - if (requiresExecutionContext && contextType == ContextType::Global) { + if (!requiresExecutionContext) + return; + QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // the loads below are empty structs. + if (contextType == ContextType::Global) bytecodeGenerator->addInstruction(Instruction::PopScriptContext()); + else + bytecodeGenerator->addInstruction(Instruction::PopContext()); QT_WARNING_POP - } else if (oldContextReg != -1) { - Instruction::PopContext popContext; - popContext.reg = oldContextReg; - bytecodeGenerator->addInstruction(popContext); - } } void Context::setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator) diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 6838610d1c..95fca2c2c8 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -279,8 +279,8 @@ struct Context { bool isValid() const { return type != Unresolved; } }; ResolvedName resolveName(const QString &name); - int emitBlockHeader(Compiler::Codegen *codegen); - void emitBlockFooter(Compiler::Codegen *codegen, int oldContextReg); + void emitBlockHeader(Compiler::Codegen *codegen); + void emitBlockFooter(Compiler::Codegen *codegen); void setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator); }; diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h index 89791330f9..db109533eb 100644 --- a/src/qml/compiler/qv4compilercontrolflow_p.h +++ b/src/qml/compiler/qv4compilercontrolflow_p.h @@ -306,11 +306,9 @@ struct ControlFlowWith : public ControlFlowUnwind : ControlFlowUnwind(cg, With) { setupExceptionHandler(); - savedContextRegister = Moth::StackSlot::createRegister(generator()->newRegister()); // assumes the with object is in the accumulator Instruction::PushWithContext pushScope; - pushScope.reg = savedContextRegister; generator()->addInstruction(pushScope); generator()->setExceptionHandler(&unwindLabel); } @@ -321,12 +319,10 @@ struct ControlFlowWith : public ControlFlowUnwind generator()->setExceptionHandler(parentExceptionHandler()); Instruction::PopContext pop; - pop.reg = savedContextRegister; generator()->addInstruction(pop); emitUnwindHandler(); } - Moth::StackSlot savedContextRegister; }; struct ControlFlowBlock : public ControlFlowUnwind @@ -335,9 +331,9 @@ struct ControlFlowBlock : public ControlFlowUnwind : ControlFlowUnwind(cg, Block) { block = cg->enterBlock(ast); - savedContextRegister = block->emitBlockHeader(cg); + block->emitBlockHeader(cg); - if (savedContextRegister != -1) { + if (block->requiresExecutionContext) { setupExceptionHandler(); generator()->setExceptionHandler(&unwindLabel); } @@ -345,24 +341,23 @@ struct ControlFlowBlock : public ControlFlowUnwind virtual ~ControlFlowBlock() { // emit code for unwinding - if (savedContextRegister != -1) { + if (block->requiresExecutionContext ) { unwindLabel.link(); generator()->setExceptionHandler(parentExceptionHandler()); } - block->emitBlockFooter(cg, savedContextRegister); + block->emitBlockFooter(cg); - if (savedContextRegister != -1) + if (block->requiresExecutionContext ) emitUnwindHandler(); cg->leaveBlock(); } virtual Handler getHandler(HandlerType type, const QString &label = QString()) { - if (savedContextRegister == -1) + if (!block->requiresExecutionContext ) return getParentHandler(type, label); return ControlFlowUnwind::getHandler(type, label); } - int savedContextRegister = -1; Context *block; }; @@ -414,7 +409,7 @@ struct ControlFlowCatch : public ControlFlowUnwind Context *block = cg->enterBlock(catchExpression); - int savedContextReg = block->emitBlockHeader(cg); + block->emitBlockHeader(cg); // clear the unwind temp for exceptions, we want to resume normal code flow afterwards Reference::storeConstOnStack(cg, QV4::Encode::undefined(), controlFlowTemp); @@ -430,7 +425,7 @@ struct ControlFlowCatch : public ControlFlowUnwind // exceptions inside catch and break/return statements go here catchUnwindLabel.link(); - block->emitBlockFooter(cg, savedContextReg); + block->emitBlockFooter(cg); cg->leaveBlock(); diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 5e7fe816b2..95bc459df0 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -404,15 +404,14 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_END_INSTR(CreateCallContext) MOTH_BEGIN_INSTR(PushCatchContext) - d << dumpRegister(reg, nFormals) << ", " << index << ", " << name; + d << index << ", " << name; MOTH_END_INSTR(PushCatchContext) MOTH_BEGIN_INSTR(PushWithContext) - d << dumpRegister(reg, nFormals); MOTH_END_INSTR(PushWithContext) MOTH_BEGIN_INSTR(PushBlockContext) - d << dumpRegister(reg, nFormals) << ", " << index; + d << index; MOTH_END_INSTR(PushBlockContext) MOTH_BEGIN_INSTR(CloneBlockContext) @@ -426,7 +425,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_END_INSTR(PopScriptContext) MOTH_BEGIN_INSTR(PopContext) - d << dumpRegister(reg, nFormals); MOTH_END_INSTR(PopContext) MOTH_BEGIN_INSTR(GetIterator) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 83ff11a128..54a7f5f13e 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -114,13 +114,13 @@ QT_BEGIN_NAMESPACE #define INSTR_GetException(op) INSTRUCTION(op, GetException, 0) #define INSTR_SetException(op) INSTRUCTION(op, SetException, 0) #define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0) -#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 3, reg, index, name) -#define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 1, reg) -#define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 2, reg, index) +#define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, index, name) +#define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 0) +#define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 1, index) #define INSTR_CloneBlockContext(op) INSTRUCTION(op, CloneBlockContext, 0) #define INSTR_PushScriptContext(op) INSTRUCTION(op, PushScriptContext, 1, index) #define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0) -#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 1, reg) +#define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 0) #define INSTR_GetIterator(op) INSTRUCTION(op, GetIterator, 1, iterator) #define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 1, value) #define INSTR_IteratorClose(op) INSTRUCTION(op, IteratorClose, 1, done) diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp index 736dfd0908..45dc87db19 100644 --- a/src/qml/jit/qv4assembler.cpp +++ b/src/qml/jit/qv4assembler.cpp @@ -2241,9 +2241,8 @@ void Assembler::clearExceptionHandler() pasm()->storePtr(TrustedImmPtr(nullptr), pasm()->exceptionHandlerAddress()); } -void Assembler::pushCatchContext(int reg, int index, int name) +void Assembler::pushCatchContext(int index, int name) { - pasm()->copyReg(pasm()->contextAddress(), regAddr(reg)); prepareCallWithArgCount(3); passInt32AsArg(name, 2); passInt32AsArg(index, 1); @@ -2252,9 +2251,13 @@ void Assembler::pushCatchContext(int reg, int index, int name) pasm()->storeAccumulator(pasm()->contextAddress()); } -void Assembler::popContext(int reg) +void Assembler::popContext() { - pasm()->copyReg(regAddr(reg), pasm()->contextAddress()); + Heap::CallContext ctx; + Q_UNUSED(ctx) + pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister); + pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset)); + pasm()->storeAccumulator(regAddr(CallData::Context)); } void Assembler::ret() diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index 99ae48e5ed..a1596e1640 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -164,8 +164,8 @@ public: void setException(); void setExceptionHandler(int offset); void clearExceptionHandler(); - void pushCatchContext(int reg, int index, int name); - void popContext(int reg); + void pushCatchContext(int index, int name); + void popContext(); // other stuff void ret(); diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp index 15ece7e903..2bc60bff70 100644 --- a/src/qml/jit/qv4jit.cpp +++ b/src/qml/jit/qv4jit.cpp @@ -617,44 +617,40 @@ void BaselineJIT::generate_CreateCallContext() as->storeHeapObject(CallData::Context); } -void BaselineJIT::generate_PushCatchContext(int reg, int index, int name) { as->pushCatchContext(reg, index, name); } +void BaselineJIT::generate_PushCatchContext(int index, int name) { as->pushCatchContext(index, name); } -static void pushWithContextHelper(ExecutionEngine *engine, QV4::Value *stack, int reg) +static void pushWithContextHelper(ExecutionEngine *engine, QV4::Value *stack) { QV4::Value &accumulator = stack[CallData::Accumulator]; accumulator = accumulator.toObject(engine); if (engine->hasException) return; - stack[reg] = stack[CallData::Context]; ExecutionContext *c = static_cast(stack + CallData::Context); stack[CallData::Context] = Runtime::method_createWithContext(c, accumulator); } -void BaselineJIT::generate_PushWithContext(int reg) +void BaselineJIT::generate_PushWithContext() { STORE_IP(); as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(reg, 2); + as->prepareCallWithArgCount(2); as->passRegAsArg(0, 1); as->passEngineAsArg(0); JIT_GENERATE_RUNTIME_CALL(pushWithContextHelper, Assembler::IgnoreResult); as->checkException(); } -static void pushBlockContextHelper(QV4::Value *stack, int reg, int index) +static void pushBlockContextHelper(QV4::Value *stack, int index) { - stack[reg] = stack[CallData::Context]; ExecutionContext *c = static_cast(stack + CallData::Context); stack[CallData::Context] = Runtime::method_createBlockContext(c, index); } -void BaselineJIT::generate_PushBlockContext(int reg, int index) +void BaselineJIT::generate_PushBlockContext(int index) { as->saveAccumulatorInFrame(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(index, 2); - as->passInt32AsArg(reg, 1); + as->prepareCallWithArgCount(2); + as->passInt32AsArg(index, 1); as->passRegAsArg(0, 0); JIT_GENERATE_RUNTIME_CALL(pushBlockContextHelper, Assembler::IgnoreResult); } @@ -701,7 +697,7 @@ void BaselineJIT::generate_PopScriptContext() JIT_GENERATE_RUNTIME_CALL(popScriptContextHelper, Assembler::IgnoreResult); } -void BaselineJIT::generate_PopContext(int reg) { as->popContext(reg); } +void BaselineJIT::generate_PopContext() { as->popContext(); } void BaselineJIT::generate_GetIterator(int iterator) { diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h index d48041d954..8aa0cb430e 100644 --- a/src/qml/jit/qv4jit_p.h +++ b/src/qml/jit/qv4jit_p.h @@ -178,13 +178,13 @@ public: void generate_GetException() override; void generate_SetException() override; void generate_CreateCallContext() override; - void generate_PushCatchContext(int reg, int index, int name) override; - void generate_PushWithContext(int reg) override; - void generate_PushBlockContext(int reg, int index) override; + void generate_PushCatchContext(int index, int name) override; + void generate_PushWithContext() override; + void generate_PushBlockContext(int index) override; void generate_CloneBlockContext() override; void generate_PushScriptContext(int index) override; void generate_PopScriptContext() override; - void generate_PopContext(int reg) override; + void generate_PopContext() override; void generate_GetIterator(int iterator) override; void generate_IteratorNext(int value) override; void generate_IteratorClose(int done) override; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index f39fd39a98..84d5d6e6e4 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -909,7 +909,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const uchar *code) MOTH_END_INSTR(SetException) MOTH_BEGIN_INSTR(PushCatchContext) - STACK_VALUE(reg) = STACK_VALUE(CallData::Context); ExecutionContext *c = static_cast(stack + CallData::Context); STACK_VALUE(CallData::Context) = Runtime::method_createCatchContext(c, index, name); MOTH_END_INSTR(PushCatchContext) @@ -923,14 +922,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const uchar *code) STORE_ACC(); accumulator = accumulator.toObject(engine); CHECK_EXCEPTION; - STACK_VALUE(reg) = STACK_VALUE(CallData::Context); ExecutionContext *c = static_cast(stack + CallData::Context); STACK_VALUE(CallData::Context) = Runtime::method_createWithContext(c, accumulator); MOTH_END_INSTR(PushWithContext) MOTH_BEGIN_INSTR(PushBlockContext) STORE_ACC(); - STACK_VALUE(reg) = STACK_VALUE(CallData::Context); ExecutionContext *c = static_cast(stack + CallData::Context); STACK_VALUE(CallData::Context) = Runtime::method_createBlockContext(c, index); MOTH_END_INSTR(PushBlockContext) @@ -950,7 +947,8 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const uchar *code) MOTH_END_INSTR(PopScriptContext) MOTH_BEGIN_INSTR(PopContext) - STACK_VALUE(CallData::Context) = STACK_VALUE(reg); + ExecutionContext *c = static_cast(stack + CallData::Context); + STACK_VALUE(CallData::Context) = c->d()->outer; MOTH_END_INSTR(PopContext) MOTH_BEGIN_INSTR(GetIterator) -- cgit v1.2.3