Exemplo n.º 1
0
    void build() {
      find_backward_gotos();

      // Construct the root block specially.
      if(blocks_[0]) {
        root_ = blocks_[0];
      } else {
        root_ = new CFGBlock(0);
        blocks_[0] = root_;
      }

      current_ = root_;

      VMMethod::Iterator iter(stream_, stream_size_);
      for(;;) {
        if(CFGBlock* next_block = find_block(iter.position())) {
          if(next_block->loop_p()) {
            // The handler wasn't setup originally, so we have to set it now.
            next_block->set_exception_handler(current_->exception_handler());

            close_current(iter, next_block);
          } else {
            current_ = next_block;
          }
        }

        switch(iter.op()) {
        case InstructionSequence::insn_goto:
        case InstructionSequence::insn_goto_if_true:
        case InstructionSequence::insn_goto_if_false:
          if(iter.operand1() > iter.position()) {
            current_->add_child(add_block(iter.operand1()));
            start_new_block(iter);
          } else {
#ifndef NDEBUG
            CFGBlock* loop_header = find_block(iter.operand1());
            assert(loop_header);
            assert(loop_header->exception_handler() == current_->exception_handler());
#endif
          }
          break;

        case InstructionSequence::insn_setup_unwind: {
          assert(iter.operand1() > iter.position());
          CFGBlock* handler = add_block(iter.operand1());
          handler->set_exception_type(iter.operand2());

          current_->add_child(handler);

          CFGBlock* body = start_new_block(iter);
          assert(body); // make sure it's not at the end.

          body->set_exception_handler(handler);
          break;
        }
        case InstructionSequence::insn_pop_unwind: {
          assert(current_->exception_handler());
          CFGBlock* cont = start_new_block(iter);
          CFGBlock* current_handler = cont->exception_handler();
          assert(current_handler);

          // Effectively pop the current handler by setting the
          // blocks handler (and thus all blocks after it) to the current
          // handlers handler.
          cont->set_exception_handler(current_handler->exception_handler());
          break;
        }

        case InstructionSequence::insn_ensure_return:
        case InstructionSequence::insn_raise_exc:
        case InstructionSequence::insn_raise_return:
        case InstructionSequence::insn_raise_break:
        case InstructionSequence::insn_reraise:
        case InstructionSequence::insn_ret:
          start_new_block(iter);
          break;
        }

        if(!iter.advance()) break;
      }

      current_->set_end_ip(iter.position());
    }
Exemplo n.º 2
0
 void close_current(VMMethod::Iterator& iter, CFGBlock* next) {
   current_->set_end_ip(iter.position());
   current_->add_child(next);
   current_ = next;
 }