void UpvalueMarker::reset_info(Proc *proc) { assert(NULL != proc); proc->thisclass_uprefer_pos = -1; proc->this_uprefer_pos = -1; SymbolTable *st = proc->symbol_table; assert(NULL != st); st->reset_upvalue_infos(); // 遍历 for (size_t i = 0, szi = proc->blocks.size(); i < szi; ++i) { BasicBlock *block = proc->blocks.at(i); assert(NULL != block); for (size_t j = 0, szj = block->codes().size(); j < szj; ++j) { ICode *c = block->codes().at(j); assert(NULL != c); if (IC_MAKE_LAMBDA == c->op) { MakeLambdaICode *mlc = SILK_DYNAMIC_CAST<MakeLambdaICode*>(c); assert(NULL != mlc); reset_info(mlc->proc); } else if (IC_MAKE_CLASS == c->op) { MakeClassICode *mcc = SILK_DYNAMIC_CAST<MakeClassICode*>(c); assert(NULL != mcc); for (size_t i = 0, sz = mcc->static_methods.size(); i < sz; ++i) { Proc *sub_proc = mcc->static_methods.at(i).proc; assert(NULL != sub_proc); reset_info(sub_proc); } reset_info(mcc->static_init_code.proc); for (size_t i = 0, sz = mcc->instance_methods.size(); i < sz; ++i) { Proc *sub_proc = mcc->instance_methods.at(i).proc; assert(NULL != sub_proc); reset_info(sub_proc); } reset_info(mcc->instance_init_code.proc); reset_info(mcc->constructor.proc); } } } }
void UpvalueMarker::run_on_proc(Proc *proc) { assert(NULL != proc); _proc_stack.push_back(proc); for (size_t i = 0, szi = proc->blocks.size(); i < szi; ++i) { BasicBlock *block = proc->blocks.at(i); assert(NULL != block); for (size_t j = 0, szj = block->codes().size(); j < szj; ++j) { ICode *c = block->codes().at(j); assert(NULL != c); run_on_icode(c); } } _proc_stack.pop_back(); }
bool ForwardDataFlowPass::recursive_traversal(Proc *proc) { assert(NULL != proc); // Push stack _proc_stack.push_back(proc); // Analyze and optimize clear_dirty_outputs(); analyze(); bool changed = optimize(); // Traversal const basic_blocks_t& blocks = proc->blocks; for (size_t i = 0, szi = blocks.size(); !changed && i < szi; ++i) { BasicBlock *block = blocks.at(i); assert(NULL != block); icodes_t& codes = block->codes(); for (size_t j = 0, szj = codes.size(); !changed && j < szj; ++j) { ICode *c = codes.at(j); assert(NULL != c); if (IC_MAKE_LAMBDA == c->op) { MakeLambdaICode *mlc = dynamic_cast<MakeLambdaICode*>(c); assert(NULL != mlc); changed |= recursive_traversal(mlc->proc); } else if (IC_MAKE_CLASS == c->op) { MakeClassICode *mcc = dynamic_cast<MakeClassICode*>(c); assert(NULL != mcc); for (size_t k = 0, szk = mcc->static_methods.size(); k < szk; ++k) { changed |= recursive_traversal(mcc->static_methods.at(k).proc); } changed |= recursive_traversal(mcc->static_init_code.proc); for (size_t k = 0, szk = mcc->instance_methods.size(); k < szk; ++k) { changed |= recursive_traversal(mcc->instance_methods.at(k).proc); } changed |= recursive_traversal(mcc->instance_init_code.proc); changed |= recursive_traversal(mcc->constructor.proc); } } } // Pop stack _proc_stack.pop_back(); return changed; }
bool BackwardDataFlowPass::optimize() { assert(!_proc_stack.empty()); Proc *proc = _proc_stack.at(_proc_stack.size() - 1); assert(NULL != proc); const basic_blocks_t& blocks = proc->blocks; if (_optimizer->run_on_proc(proc, _outputs)) { _stage->notify_proc_changed(proc); return true; } if (!_optimizer->need_run_on_icode()) return false; bool dirty = false; for (ssize_t i = ((ssize_t) blocks.size()) - 1; i >= 0; --i) { BasicBlock *block = blocks.at(i); assert(NULL != block); if (!block->is_dirty(_code_dirty_id)) continue; // Merge all inputs into one nut::rc_ptr<FlowSet> flow_set = new_flow_set(); for (size_t j = 0, szj = block->get_exit_count(); j < szj; ++j) { const Edge *e = block->get_exit(j); assert(NULL != e && e->from == block); flowset_map_t::const_iterator iter = _outputs.find(e->to); assert(iter != _outputs.end()); FlowSet *const another_input = iter->second; assert(NULL != another_input); flow_set->merge_with(another_input); } icodes_t& codes = block->codes(); ssize_t reverse_index = 0; bool dirty_reported = false; while (reverse_index < (ssize_t) codes.size()) { // Run optimizer const ssize_t old_size = codes.size(); ssize_t index = old_size - reverse_index - 1; ICodeStepper stepper(proc, block, index, flow_set); _optimizer->run_on_icode(&stepper); if (stepper.dirty) { if (!dirty_reported) { _stage->notify_basic_block_changed(proc, block); dirty_reported = true; } } else { block->set_dirty(_code_dirty_id, false); } dirty |= stepper.dirty; // 强制中断处理 if (stepper.force_break) return dirty; // 如果代码发生更改,需要重新定位 if (stepper.change_begin <= stepper.change_end) { const ssize_t reverse_begin = old_size - stepper.change_end; if (reverse_begin < reverse_index) { // 数据流上游发生更改,无法处理. NOTE 这里强制设置脏标记 assert(false); return dirty; } else if (reverse_begin == reverse_index) { // 需要对当前 reverse_index 重新运行优化器 continue; } else if (reverse_index >= (ssize_t) codes.size()) { // codes.size() 可能发生了改变 break; } // else, 更改不影响数据流的有效性,继续执行 } // Kill and gen index = codes.size() - reverse_index - 1; kill_and_gen(proc, block, index, flow_set); ++reverse_index; } } return dirty; }
void BackwardDataFlowPass::analyze() { assert(!_proc_stack.empty()); Proc *proc = _proc_stack.at(_proc_stack.size() - 1); assert(NULL != proc); // Queue every block const basic_blocks_t& blocks = proc->blocks; std::queue<BasicBlock*> process_queue; for (ssize_t i = ((ssize_t) blocks.size()) - 1; i >= 0; --i) { BasicBlock *block = blocks.at(i); assert(NULL != block); if (block->is_dirty(_flow_dirty_id)) process_queue.push(block); } // Loop until every block is processed #if !defined(NDEBUG) && 0 int process_count = 0; #endif while (!process_queue.empty()) { BasicBlock *block = process_queue.front(); assert(NULL != block); process_queue.pop(); block->set_dirty(_flow_dirty_id, false); #if !defined(NDEBUG) && 0 ++process_count; #endif // Merge all inputs into one nut::rc_ptr<FlowSet> flow_set = new_flow_set(); for (size_t i = 0, sz = block->get_exit_count(); i < sz; ++i) { const Edge *e = block->get_exit(i); assert(NULL != e && e->from == block); flowset_map_t::const_iterator iter = _outputs.find(e->to); if (iter == _outputs.end()) continue; FlowSet *const another_input = iter->second; assert(NULL != another_input); flow_set->merge_with(another_input); } // Process the codes icodes_t& codes = block->codes(); for (ssize_t i = ((ssize_t) codes.size()) - 1; i >= 0; --i) { // Kill and gen kill_and_gen(proc, block, i, flow_set); } // Check if output is changed flowset_map_t::const_iterator iter = _outputs.find(block); FlowSet *ori_output = NULL; if (iter != _outputs.end()) ori_output = iter->second; if (NULL == ori_output || !ori_output->equals(flow_set)) { for (size_t i = 0, sz = block->get_entry_count(); i < sz; ++i) { const Edge *e = block->get_entry(i); assert(NULL != e && e->to == block); BasicBlock *affected = e->from; if (NULL == affected) continue; if (affected->is_dirty(_flow_dirty_id)) continue; affected->set_dirty(_flow_dirty_id, true); process_queue.push(affected); } } // Commit the output _outputs[block] = flow_set; } #if !defined(NDEBUG) && 0 std::cout << " process count " << process_count << " / " << blocks.size() << std::endl; #endif }