| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "Backend.h"
- IR::Instr *
- SimpleLayout::MoveHelperBlock(IR::Instr * lastOpHelperLabel, uint32 lastOpHelperStatementIndex, Func* lastOpHelperFunc, IR::LabelInstr * nextLabel,
- IR::Instr * instrAfter)
- {
- // Add pragma instructions around the moved code to track source mapping
- Func* pragmatInstrFunc = lastOpHelperFunc ? lastOpHelperFunc : this->func;
- if (instrAfter->IsPragmaInstr() && instrAfter->m_opcode == Js::OpCode::StatementBoundary)
- {
- IR::PragmaInstr* pragmaInstr = instrAfter->AsPragmaInstr();
- pragmaInstr->m_statementIndex = lastOpHelperStatementIndex;
- pragmaInstr->m_func = pragmatInstrFunc;
- }
- else
- {
- IR::PragmaInstr* pragmaInstr = IR::PragmaInstr::New(Js::OpCode::StatementBoundary, lastOpHelperStatementIndex, pragmatInstrFunc);
- instrAfter->InsertAfter(pragmaInstr);
- instrAfter = pragmaInstr;
- }
- // Move all the instruction between lastOpHelperLabel to lastOpHelperInstr
- // to the end of the function
- IR::Instr * lastOpHelperInstr = nextLabel->GetPrevRealInstrOrLabel();
- IR::Instr::MoveRangeAfter(lastOpHelperLabel, lastOpHelperInstr, instrAfter);
- instrAfter = lastOpHelperInstr;
- // Add the jmp back if the lastOpHelperInstr has fall through
- if (instrAfter->HasFallThrough())
- {
- IR::BranchInstr * branchInstr = IR::BranchInstr::New(
- LowererMD::MDUncondBranchOpcode, nextLabel, this->func);
- instrAfter->InsertAfter(branchInstr);
- instrAfter = branchInstr;
- }
- // Add pragma terminating this source mapping range
- IR::PragmaInstr* pragmaInstr = IR::PragmaInstr::New(Js::OpCode::StatementBoundary, Js::Constants::NoStatementIndex, this->func);
- instrAfter->InsertAfter(pragmaInstr);
- instrAfter = pragmaInstr;
- return instrAfter;
- }
- void
- SimpleLayout::Layout()
- {
- if (PHASE_OFF(Js::LayoutPhase, this->func) || CONFIG_ISENABLED(Js::DebugFlag))
- {
- return;
- }
- // Do simple layout of helper block. Push them to after FunctionExit.
- IR::Instr * lastInstr = func->m_tailInstr;
- IR::LabelInstr * lastOpHelperLabel = NULL;
- uint32 lastOpHelperStatementIndex = Js::Constants::NoStatementIndex;
- Func* lastOpHelperFunc = nullptr;
- FOREACH_INSTR_EDITING_IN_RANGE(instr, instrNext, func->m_headInstr, func->m_tailInstr->m_prev)
- {
- if (instr->IsPragmaInstr() && instr->m_opcode == Js::OpCode::StatementBoundary)
- {
- currentStatement = instr->AsPragmaInstr();
- }
- else if (instr->IsLabelInstr())
- {
- IR::LabelInstr * labelInstr = instr->AsLabelInstr();
- if (labelInstr->isOpHelper)
- {
- if (lastOpHelperLabel == NULL)
- {
- lastOpHelperLabel = labelInstr;
- lastOpHelperStatementIndex = currentStatement ? currentStatement->m_statementIndex : Js::Constants::NoStatementIndex;
- lastOpHelperFunc = currentStatement ? currentStatement->m_func : nullptr;
- }
- }
- else if (lastOpHelperLabel != NULL)
- {
- IR::Instr * prevInstr = lastOpHelperLabel->GetPrevRealInstrOrLabel();
- if (prevInstr->IsBranchInstr())
- {
- // If the previous instruction is to jump around this helper block
- // Then we move the helper block to the end of the function to
- // avoid the jmp in the fast path.
- // jxx $label <== prevInstr
- // $helper: <== lastOpHelperLabel
- // ...
- // ... <== lastOpHelperInstr
- // $label: <== labelInstr
- IR::BranchInstr * prevBranchInstr = prevInstr->AsBranchInstr();
- if (prevBranchInstr->GetTarget() == labelInstr)
- {
- lastInstr = this->MoveHelperBlock(lastOpHelperLabel, lastOpHelperStatementIndex, lastOpHelperFunc, labelInstr, lastInstr);
- if (prevBranchInstr->IsUnconditional())
- {
- // Remove the branch to next after the helper block is moved.
- prevBranchInstr->Remove();
- }
- else
- {
- // Reverse the condition
- LowererMD::InvertBranch(prevBranchInstr);
- prevBranchInstr->SetTarget(lastOpHelperLabel);
- }
- }
- else if (prevBranchInstr->IsUnconditional())
- {
- IR::Instr * prevPrevInstr = prevInstr->GetPrevRealInstrOrLabel();
- if (prevPrevInstr->IsBranchInstr()
- && prevPrevInstr->AsBranchInstr()->IsConditional()
- && prevPrevInstr->AsBranchInstr()->GetTarget() == labelInstr)
- {
- // jcc $label <== prevPrevInstr
- // jmp $blah <== prevInstr
- // $helper: <== lastOpHelperLabel
- // ...
- // ... <== lastOpHelperInstr
- // $label: <== labelInstr
- // Transform to
- // jncc $blah <== prevPrevInstr
- // $label: <== labelInstr
- // $helper: <== lastOpHelperLabel
- // ...
- // ... <== lastOpHelperInstr
- // jmp $label: <== labelInstr
- lastInstr = this->MoveHelperBlock(lastOpHelperLabel, lastOpHelperStatementIndex, lastOpHelperFunc, labelInstr, lastInstr);
- LowererMD::InvertBranch(prevPrevInstr->AsBranchInstr());
- prevPrevInstr->AsBranchInstr()->SetTarget(prevBranchInstr->GetTarget());
- prevBranchInstr->Remove();
- }
- else
- {
- IR::Instr *lastOpHelperInstr = labelInstr->GetPrevRealInstr();
- if (lastOpHelperInstr->IsBranchInstr())
- {
- IR::BranchInstr *lastOpHelperBranchInstr = lastOpHelperInstr->AsBranchInstr();
- // jmp $target <== prevInstr //this is unconditional jump
- // $helper: <== lastOpHelperLabel
- // ...
- // jmp $labeln <== lastOpHelperInstr //Conditional/Unconditional jump
- // $label: <== labelInstr
- lastInstr = this->MoveHelperBlock(lastOpHelperLabel, lastOpHelperStatementIndex, lastOpHelperFunc, labelInstr, lastInstr);
- //Compensation code if its not unconditional jump
- if (!lastOpHelperBranchInstr->IsUnconditional())
- {
- IR::BranchInstr *branchInstr = IR::BranchInstr::New(LowererMD::MDUncondBranchOpcode, labelInstr, this->func);
- lastOpHelperBranchInstr->InsertAfter(branchInstr);
- }
- }
- }
- }
- }
- lastOpHelperLabel = NULL;
- }
- }
- }
- NEXT_INSTR_EDITING_IN_RANGE;
- func->m_tailInstr = lastInstr;
- }
|