Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jit/ScalarReplacement.h"
#include "jit/IonAnalysis.h"
#include "jit/JitSpewer.h"
#include "jit/MIR-wasm.h"
#include "jit/MIR.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
#include "jit/WarpBuilderShared.h"
#include "js/Vector.h"
#include "vm/ArgumentsObject.h"
#include "gc/ObjectKind-inl.h"
namespace js {
namespace jit {
template <typename MemoryView>
class EmulateStateOf {
private:
using BlockState = typename MemoryView::BlockState;
const MIRGenerator* mir_;
MIRGraph& graph_;
// Block state at the entrance of all basic blocks.
Vector<BlockState*, 8, SystemAllocPolicy> states_;
public:
EmulateStateOf(const MIRGenerator* mir, MIRGraph& graph)
: mir_(mir), graph_(graph) {}
bool run(MemoryView& view);
};
template <typename MemoryView>
bool EmulateStateOf<MemoryView>::run(MemoryView& view) {
// Initialize the current block state of each block to an unknown state.
if (!states_.appendN(nullptr, graph_.numBlocks())) {
return false;
}
// Initialize the first block which needs to be traversed in RPO.
MBasicBlock* startBlock = view.startingBlock();
if (!view.initStartingState(&states_[startBlock->id()])) {
return false;
}
// Iterate over each basic block which has a valid entry state, and merge
// the state in the successor blocks.
for (ReversePostorderIterator block = graph_.rpoBegin(startBlock);
block != graph_.rpoEnd(); block++) {
if (mir_->shouldCancel(MemoryView::phaseName)) {
return false;
}
// Get the block state as the result of the merge of all predecessors
// which have already been visited in RPO. This means that backedges
// are not yet merged into the loop.
BlockState* state = states_[block->id()];
if (!state) {
continue;
}
view.setEntryBlockState(state);
// Iterates over resume points, phi and instructions.
for (MNodeIterator iter(*block); iter;) {
// Increment the iterator before visiting the instruction, as the
// visit function might discard itself from the basic block.
MNode* ins = *iter++;
if (ins->isDefinition()) {
MDefinition* def = ins->toDefinition();
switch (def->op()) {
#define MIR_OP(op) \
case MDefinition::Opcode::op: \
view.visit##op(def->to##op()); \
break;