#include "src/compiler/add-type-assertions-reducer.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/schedule.h"
namespace v8 {
namespace internal {
namespace compiler {
namespace {
struct AddTypeAssertionsImpl {
JSGraph* jsgraph;
Schedule* schedule;
Zone* phase_zone;
SimplifiedOperatorBuilder* simplified = jsgraph->simplified();
TFGraph* graph = jsgraph->graph();
void Run();
void ProcessBlock(BasicBlock* block);
void InsertAssertion(Node* asserted, Node* effect_successor);
};
void AddTypeAssertionsImpl::Run() {
for (BasicBlock* block : *(schedule->rpo_order())) {
ProcessBlock(block);
}
}
void AddTypeAssertionsImpl::ProcessBlock(BasicBlock* block) {
std::vector<Node*> pending;
bool inside_of_region = false;
for (Node* node : *block) {
if (node->opcode() == IrOpcode::kBeginRegion) {
inside_of_region = true;
} else if (inside_of_region) {
if (node->opcode() == IrOpcode::kFinishRegion) {
inside_of_region = false;
}
continue;
}
if (node->op()->EffectOutputCount() == 1 &&
node->op()->EffectInputCount() == 1) {
for (Node* pending_node : pending) {
InsertAssertion(pending_node, node);
}
pending.clear();
}
if (node->opcode() == IrOpcode::kAssertType ||
node->opcode() == IrOpcode::kAllocate ||
node->opcode() == IrOpcode::kObjectState ||
node->opcode() == IrOpcode::kObjectId ||
node->opcode() == IrOpcode::kPhi || !NodeProperties::IsTyped(node) ||
node->opcode() == IrOpcode::kUnreachable) {
continue;
}
Type type = NodeProperties::GetType(node);
if (type.CanBeAsserted()) {
pending.push_back(node);
}
}
}
void AddTypeAssertionsImpl::InsertAssertion(Node* asserted,
Node* effect_successor) {
Node* assertion = graph->NewNode(
simplified->AssertType(NodeProperties::GetType(asserted)), asserted,
NodeProperties::GetEffectInput(effect_successor));
NodeProperties::ReplaceEffectInput(effect_successor, assertion);
}
}
void AddTypeAssertions(JSGraph* jsgraph, Schedule* schedule, Zone* phase_zone) {
AddTypeAssertionsImpl{jsgraph, schedule, phase_zone}.Run();
}
}
}
}