Ejemplo n.º 1
0
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);
            }
        }
    }
}
Ejemplo n.º 2
0
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();
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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
}