1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "block_builder.h"
18
19#include "bytecode_utils.h"
20
21namespace art {
22
23HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t dex_pc) {
24  return MaybeCreateBlockAt(dex_pc, dex_pc);
25}
26
27HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t semantic_dex_pc,
28                                                    uint32_t store_dex_pc) {
29  HBasicBlock* block = branch_targets_[store_dex_pc];
30  if (block == nullptr) {
31    block = new (arena_) HBasicBlock(graph_, semantic_dex_pc);
32    branch_targets_[store_dex_pc] = block;
33  }
34  DCHECK_EQ(block->GetDexPc(), semantic_dex_pc);
35  return block;
36}
37
38bool HBasicBlockBuilder::CreateBranchTargets() {
39  // Create the first block for the dex instructions, single successor of the entry block.
40  MaybeCreateBlockAt(0u);
41
42  if (code_item_.tries_size_ != 0) {
43    // Create branch targets at the start/end of the TryItem range. These are
44    // places where the program might fall through into/out of the a block and
45    // where TryBoundary instructions will be inserted later. Other edges which
46    // enter/exit the try blocks are a result of branches/switches.
47    for (size_t idx = 0; idx < code_item_.tries_size_; ++idx) {
48      const DexFile::TryItem* try_item = DexFile::GetTryItems(code_item_, idx);
49      uint32_t dex_pc_start = try_item->start_addr_;
50      uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
51      MaybeCreateBlockAt(dex_pc_start);
52      if (dex_pc_end < code_item_.insns_size_in_code_units_) {
53        // TODO: Do not create block if the last instruction cannot fall through.
54        MaybeCreateBlockAt(dex_pc_end);
55      } else if (dex_pc_end == code_item_.insns_size_in_code_units_) {
56        // The TryItem spans until the very end of the CodeItem and therefore
57        // cannot have any code afterwards.
58      } else {
59        // The TryItem spans beyond the end of the CodeItem. This is invalid code.
60        return false;
61      }
62    }
63
64    // Create branch targets for exception handlers.
65    const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item_, 0);
66    uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
67    for (uint32_t idx = 0; idx < handlers_size; ++idx) {
68      CatchHandlerIterator iterator(handlers_ptr);
69      for (; iterator.HasNext(); iterator.Next()) {
70        MaybeCreateBlockAt(iterator.GetHandlerAddress());
71      }
72      handlers_ptr = iterator.EndDataPointer();
73    }
74  }
75
76  // Iterate over all instructions and find branching instructions. Create blocks for
77  // the locations these instructions branch to.
78  for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
79    uint32_t dex_pc = it.CurrentDexPc();
80    const Instruction& instruction = it.CurrentInstruction();
81
82    if (instruction.IsBranch()) {
83      number_of_branches_++;
84      MaybeCreateBlockAt(dex_pc + instruction.GetTargetOffset());
85    } else if (instruction.IsSwitch()) {
86      DexSwitchTable table(instruction, dex_pc);
87      for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) {
88        MaybeCreateBlockAt(dex_pc + s_it.CurrentTargetOffset());
89
90        // Create N-1 blocks where we will insert comparisons of the input value
91        // against the Switch's case keys.
92        if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) {
93          // Store the block under dex_pc of the current key at the switch data
94          // instruction for uniqueness but give it the dex_pc of the SWITCH
95          // instruction which it semantically belongs to.
96          MaybeCreateBlockAt(dex_pc, s_it.GetDexPcForCurrentIndex());
97        }
98      }
99    } else if (instruction.Opcode() == Instruction::MOVE_EXCEPTION) {
100      // End the basic block after MOVE_EXCEPTION. This simplifies the later
101      // stage of TryBoundary-block insertion.
102    } else {
103      continue;
104    }
105
106    if (instruction.CanFlowThrough()) {
107      if (it.IsLast()) {
108        // In the normal case we should never hit this but someone can artificially forge a dex
109        // file to fall-through out the method code. In this case we bail out compilation.
110        return false;
111      } else {
112        MaybeCreateBlockAt(dex_pc + it.CurrentInstruction().SizeInCodeUnits());
113      }
114    }
115  }
116
117  return true;
118}
119
120void HBasicBlockBuilder::ConnectBasicBlocks() {
121  HBasicBlock* block = graph_->GetEntryBlock();
122  graph_->AddBlock(block);
123
124  bool is_throwing_block = false;
125  for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) {
126    uint32_t dex_pc = it.CurrentDexPc();
127
128    // Check if this dex_pc address starts a new basic block.
129    HBasicBlock* next_block = GetBlockAt(dex_pc);
130    if (next_block != nullptr) {
131      if (block != nullptr) {
132        // Last instruction did not end its basic block but a new one starts here.
133        // It must have been a block falling through into the next one.
134        block->AddSuccessor(next_block);
135      }
136      block = next_block;
137      is_throwing_block = false;
138      graph_->AddBlock(block);
139    }
140
141    if (block == nullptr) {
142      // Ignore dead code.
143      continue;
144    }
145
146    const Instruction& instruction = it.CurrentInstruction();
147
148    if (!is_throwing_block && IsThrowingDexInstruction(instruction)) {
149      DCHECK(!ContainsElement(throwing_blocks_, block));
150      is_throwing_block = true;
151      throwing_blocks_.push_back(block);
152    }
153
154    if (instruction.IsBranch()) {
155      uint32_t target_dex_pc = dex_pc + instruction.GetTargetOffset();
156      block->AddSuccessor(GetBlockAt(target_dex_pc));
157    } else if (instruction.IsReturn() || (instruction.Opcode() == Instruction::THROW)) {
158      block->AddSuccessor(graph_->GetExitBlock());
159    } else if (instruction.IsSwitch()) {
160      DexSwitchTable table(instruction, dex_pc);
161      for (DexSwitchTableIterator s_it(table); !s_it.Done(); s_it.Advance()) {
162        uint32_t target_dex_pc = dex_pc + s_it.CurrentTargetOffset();
163        block->AddSuccessor(GetBlockAt(target_dex_pc));
164
165        if (table.ShouldBuildDecisionTree() && !s_it.IsLast()) {
166          uint32_t next_case_dex_pc = s_it.GetDexPcForCurrentIndex();
167          HBasicBlock* next_case_block = GetBlockAt(next_case_dex_pc);
168          block->AddSuccessor(next_case_block);
169          block = next_case_block;
170          graph_->AddBlock(block);
171        }
172      }
173    } else {
174      // Remaining code only applies to instructions which end their basic block.
175      continue;
176    }
177
178    if (instruction.CanFlowThrough()) {
179      uint32_t next_dex_pc = dex_pc + instruction.SizeInCodeUnits();
180      block->AddSuccessor(GetBlockAt(next_dex_pc));
181    }
182
183    // The basic block ends here. Do not add any more instructions.
184    block = nullptr;
185  }
186
187  graph_->AddBlock(graph_->GetExitBlock());
188}
189
190// Returns the TryItem stored for `block` or nullptr if there is no info for it.
191static const DexFile::TryItem* GetTryItem(
192    HBasicBlock* block,
193    const ArenaSafeMap<uint32_t, const DexFile::TryItem*>& try_block_info) {
194  auto iterator = try_block_info.find(block->GetBlockId());
195  return (iterator == try_block_info.end()) ? nullptr : iterator->second;
196}
197
198// Iterates over the exception handlers of `try_item`, finds the corresponding
199// catch blocks and makes them successors of `try_boundary`. The order of
200// successors matches the order in which runtime exception delivery searches
201// for a handler.
202static void LinkToCatchBlocks(HTryBoundary* try_boundary,
203                              const DexFile::CodeItem& code_item,
204                              const DexFile::TryItem* try_item,
205                              const ArenaSafeMap<uint32_t, HBasicBlock*>& catch_blocks) {
206  for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
207    try_boundary->AddExceptionHandler(catch_blocks.Get(it.GetHandlerAddress()));
208  }
209}
210
211bool HBasicBlockBuilder::MightHaveLiveNormalPredecessors(HBasicBlock* catch_block) {
212  if (kIsDebugBuild) {
213    DCHECK_NE(catch_block->GetDexPc(), kNoDexPc) << "Should not be called on synthetic blocks";
214    DCHECK(!graph_->GetEntryBlock()->GetSuccessors().empty())
215        << "Basic blocks must have been created and connected";
216    for (HBasicBlock* predecessor : catch_block->GetPredecessors()) {
217      DCHECK(!predecessor->IsSingleTryBoundary())
218          << "TryBoundary blocks must not have not been created yet";
219    }
220  }
221
222  const Instruction& first = GetDexInstructionAt(code_item_, catch_block->GetDexPc());
223  if (first.Opcode() == Instruction::MOVE_EXCEPTION) {
224    // Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then
225    // it has no live normal predecessors.
226    return false;
227  } else if (catch_block->GetPredecessors().empty()) {
228    // Normal control-flow edges have already been created. Since block's list of
229    // predecessors is empty, it cannot have any live or dead normal predecessors.
230    return false;
231  }
232
233  // The catch block has normal predecessors but we do not know which are live
234  // and which will be removed during the initial DCE. Return `true` to signal
235  // that it may have live normal predecessors.
236  return true;
237}
238
239void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
240  if (code_item_.tries_size_ == 0) {
241    return;
242  }
243
244  // Keep a map of all try blocks and their respective TryItems. We do not use
245  // the block's pointer but rather its id to ensure deterministic iteration.
246  ArenaSafeMap<uint32_t, const DexFile::TryItem*> try_block_info(
247      std::less<uint32_t>(), arena_->Adapter(kArenaAllocGraphBuilder));
248
249  // Obtain TryItem information for blocks with throwing instructions, and split
250  // blocks which are both try & catch to simplify the graph.
251  for (HBasicBlock* block : graph_->GetBlocks()) {
252    if (block->GetDexPc() == kNoDexPc) {
253      continue;
254    }
255
256    // Do not bother creating exceptional edges for try blocks which have no
257    // throwing instructions. In that case we simply assume that the block is
258    // not covered by a TryItem. This prevents us from creating a throw-catch
259    // loop for synchronized blocks.
260    if (ContainsElement(throwing_blocks_, block)) {
261      // Try to find a TryItem covering the block.
262      const int32_t try_item_idx = DexFile::FindTryItem(code_item_, block->GetDexPc());
263      if (try_item_idx != -1) {
264        // Block throwing and in a TryItem. Store the try block information.
265        try_block_info.Put(block->GetBlockId(), DexFile::GetTryItems(code_item_, try_item_idx));
266      }
267    }
268  }
269
270  // Map from a handler dex_pc to the corresponding catch block.
271  ArenaSafeMap<uint32_t, HBasicBlock*> catch_blocks(
272      std::less<uint32_t>(), arena_->Adapter(kArenaAllocGraphBuilder));
273
274  // Iterate over catch blocks, create artifical landing pads if necessary to
275  // simplify the CFG, and set metadata.
276  const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(code_item_, 0);
277  uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
278  for (uint32_t idx = 0; idx < handlers_size; ++idx) {
279    CatchHandlerIterator iterator(handlers_ptr);
280    for (; iterator.HasNext(); iterator.Next()) {
281      uint32_t address = iterator.GetHandlerAddress();
282      if (catch_blocks.find(address) != catch_blocks.end()) {
283        // Catch block already processed.
284        continue;
285      }
286
287      // Check if we should create an artifical landing pad for the catch block.
288      // We create one if the catch block is also a try block because we do not
289      // have a strategy for inserting TryBoundaries on exceptional edges.
290      // We also create one if the block might have normal predecessors so as to
291      // simplify register allocation.
292      HBasicBlock* catch_block = GetBlockAt(address);
293      bool is_try_block = (try_block_info.find(catch_block->GetBlockId()) != try_block_info.end());
294      if (is_try_block || MightHaveLiveNormalPredecessors(catch_block)) {
295        HBasicBlock* new_catch_block = new (arena_) HBasicBlock(graph_, address);
296        new_catch_block->AddInstruction(new (arena_) HGoto(address));
297        new_catch_block->AddSuccessor(catch_block);
298        graph_->AddBlock(new_catch_block);
299        catch_block = new_catch_block;
300      }
301
302      catch_blocks.Put(address, catch_block);
303      catch_block->SetTryCatchInformation(
304        new (arena_) TryCatchInformation(iterator.GetHandlerTypeIndex(), *dex_file_));
305    }
306    handlers_ptr = iterator.EndDataPointer();
307  }
308
309  // Do a pass over the try blocks and insert entering TryBoundaries where at
310  // least one predecessor is not covered by the same TryItem as the try block.
311  // We do not split each edge separately, but rather create one boundary block
312  // that all predecessors are relinked to. This preserves loop headers (b/23895756).
313  for (auto entry : try_block_info) {
314    HBasicBlock* try_block = graph_->GetBlocks()[entry.first];
315    for (HBasicBlock* predecessor : try_block->GetPredecessors()) {
316      if (GetTryItem(predecessor, try_block_info) != entry.second) {
317        // Found a predecessor not covered by the same TryItem. Insert entering
318        // boundary block.
319        HTryBoundary* try_entry =
320            new (arena_) HTryBoundary(HTryBoundary::BoundaryKind::kEntry, try_block->GetDexPc());
321        try_block->CreateImmediateDominator()->AddInstruction(try_entry);
322        LinkToCatchBlocks(try_entry, code_item_, entry.second, catch_blocks);
323        break;
324      }
325    }
326  }
327
328  // Do a second pass over the try blocks and insert exit TryBoundaries where
329  // the successor is not in the same TryItem.
330  for (auto entry : try_block_info) {
331    HBasicBlock* try_block = graph_->GetBlocks()[entry.first];
332    // NOTE: Do not use iterators because SplitEdge would invalidate them.
333    for (size_t i = 0, e = try_block->GetSuccessors().size(); i < e; ++i) {
334      HBasicBlock* successor = try_block->GetSuccessors()[i];
335
336      // If the successor is a try block, all of its predecessors must be
337      // covered by the same TryItem. Otherwise the previous pass would have
338      // created a non-throwing boundary block.
339      if (GetTryItem(successor, try_block_info) != nullptr) {
340        DCHECK_EQ(entry.second, GetTryItem(successor, try_block_info));
341        continue;
342      }
343
344      // Insert TryBoundary and link to catch blocks.
345      HTryBoundary* try_exit =
346          new (arena_) HTryBoundary(HTryBoundary::BoundaryKind::kExit, successor->GetDexPc());
347      graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit);
348      LinkToCatchBlocks(try_exit, code_item_, entry.second, catch_blocks);
349    }
350  }
351}
352
353bool HBasicBlockBuilder::Build() {
354  DCHECK(graph_->GetBlocks().empty());
355
356  graph_->SetEntryBlock(new (arena_) HBasicBlock(graph_, kNoDexPc));
357  graph_->SetExitBlock(new (arena_) HBasicBlock(graph_, kNoDexPc));
358
359  // TODO(dbrazdil): Do CreateBranchTargets and ConnectBasicBlocks in one pass.
360  if (!CreateBranchTargets()) {
361    return false;
362  }
363
364  ConnectBasicBlocks();
365  InsertTryBoundaryBlocks();
366
367  return true;
368}
369
370}  // namespace art
371