block->GetBlockId()));
}
- // Ensure that the only Return(Void) and Throw jump to Exit. An exiting
+ // Ensure that only Return(Void) and Throw jump to Exit. An exiting
// TryBoundary may be between a Throw and the Exit if the Throw is in a try.
if (block->IsExitBlock()) {
for (size_t i = 0, e = block->GetPredecessors().Size(); i < e; ++i) {
void SSAChecker::VisitBasicBlock(HBasicBlock* block) {
super_type::VisitBasicBlock(block);
- // Ensure that only catch blocks have exceptional predecessors, and if they do
- // these are instructions which throw into them.
- if (block->IsCatchBlock()) {
- for (size_t i = 0, e = block->GetExceptionalPredecessors().Size(); i < e; ++i) {
- HInstruction* thrower = block->GetExceptionalPredecessors().Get(i);
- HBasicBlock* try_block = thrower->GetBlock();
- if (!thrower->CanThrow()) {
- AddError(StringPrintf("Exceptional predecessor %s:%d of catch block %d does not throw.",
- thrower->DebugName(),
- thrower->GetId(),
- block->GetBlockId()));
- } else if (!try_block->IsInTry()) {
- AddError(StringPrintf("Exceptional predecessor %s:%d of catch block %d "
- "is not in a try block.",
- thrower->DebugName(),
- thrower->GetId(),
- block->GetBlockId()));
- } else if (!try_block->GetTryEntry()->HasExceptionHandler(*block)) {
- AddError(StringPrintf("Catch block %d is not an exception handler of "
- "its exceptional predecessor %s:%d.",
- block->GetBlockId(),
- thrower->DebugName(),
- thrower->GetId()));
- }
- }
- } else {
- if (!block->GetExceptionalPredecessors().IsEmpty()) {
- AddError(StringPrintf("Normal block %d has %zu exceptional predecessors.",
- block->GetBlockId(),
- block->GetExceptionalPredecessors().Size()));
- }
- }
-
// Ensure that catch blocks are not normal successors, and normal blocks are
// never exceptional successors.
const size_t num_normal_successors = block->NumberOfNormalSuccessors();
void SSAChecker::VisitInstruction(HInstruction* instruction) {
super_type::VisitInstruction(instruction);
- HBasicBlock* block = instruction->GetBlock();
// Ensure an instruction dominates all its uses.
for (HUseIterator<HInstruction*> use_it(instruction->GetUses());
}
}
}
-
- // Ensure that throwing instructions in try blocks are listed as exceptional
- // predecessors in their exception handlers.
- if (instruction->CanThrow() && block->IsInTry()) {
- for (HExceptionHandlerIterator handler_it(*block->GetTryEntry());
- !handler_it.Done();
- handler_it.Advance()) {
- if (!handler_it.Current()->GetExceptionalPredecessors().Contains(instruction)) {
- AddError(StringPrintf("Instruction %s:%d is in try block %d and can throw "
- "but its exception handler %d does not list it in "
- "its exceptional predecessors.",
- instruction->DebugName(),
- instruction->GetId(),
- block->GetBlockId(),
- handler_it.Current()->GetBlockId()));
- }
- }
- }
}
static Primitive::Type PrimitiveKind(Primitive::Type type) {
if (phi->IsCatchPhi()) {
// The number of inputs of a catch phi corresponds to the total number of
// throwing instructions caught by this catch block.
- const GrowableArray<HInstruction*>& predecessors =
- phi->GetBlock()->GetExceptionalPredecessors();
- if (phi->InputCount() != predecessors.Size()) {
- AddError(StringPrintf(
- "Phi %d in catch block %d has %zu inputs, "
- "but catch block %d has %zu exceptional predecessors.",
- phi->GetId(), phi->GetBlock()->GetBlockId(), phi->InputCount(),
- phi->GetBlock()->GetBlockId(), predecessors.Size()));
- } else {
- for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
- HInstruction* input = phi->InputAt(i);
- HInstruction* thrower = predecessors.Get(i);
- if (!input->StrictlyDominates(thrower)) {
- AddError(StringPrintf(
- "Input %d at index %zu of phi %d from catch block %d does not "
- "dominate the throwing instruction %s:%d.",
- input->GetId(), i, phi->GetId(), phi->GetBlock()->GetBlockId(),
- thrower->DebugName(), thrower->GetId()));
- }
- }
- }
} else {
// Ensure the number of inputs of a non-catch phi is the same as the number
// of its predecessors.
explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
: graph_(graph),
predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
- exceptional_predecessors_(graph->GetArena(), kDefaultNumberOfExceptionalPredecessors),
successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
loop_information_(nullptr),
dominator_(nullptr),
return predecessors_;
}
- const GrowableArray<HInstruction*>& GetExceptionalPredecessors() const {
- return exceptional_predecessors_;
- }
-
const GrowableArray<HBasicBlock*>& GetSuccessors() const {
return successors_;
}
HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
const HInstructionList& GetPhis() const { return phis_; }
- void AddExceptionalPredecessor(HInstruction* exceptional_predecessor);
-
void AddSuccessor(HBasicBlock* block) {
successors_.Add(block);
block->predecessors_.Add(this);
predecessors_.Delete(block);
}
- void RemoveExceptionalPredecessor(HInstruction* instruction) {
- exceptional_predecessors_.Delete(instruction);
- }
-
void RemoveSuccessor(HBasicBlock* block) {
successors_.Delete(block);
}
return -1;
}
- size_t GetExceptionalPredecessorIndexOf(HInstruction* exceptional_predecessor) const {
- for (size_t i = 0, e = exceptional_predecessors_.Size(); i < e; ++i) {
- if (exceptional_predecessors_.Get(i) == exceptional_predecessor) {
- return i;
- }
- }
- return -1;
- }
-
size_t GetSuccessorIndexOf(HBasicBlock* successor) const {
for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
if (successors_.Get(i) == successor) {
private:
HGraph* graph_;
GrowableArray<HBasicBlock*> predecessors_;
- GrowableArray<HInstruction*> exceptional_predecessors_;
GrowableArray<HBasicBlock*> successors_;
HInstructionList instructions_;
HInstructionList phis_;