diff options
Diffstat (limited to 'Userland/Libraries/LibJS/Bytecode/PassManager.h')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/PassManager.h | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/PassManager.h b/Userland/Libraries/LibJS/Bytecode/PassManager.h new file mode 100644 index 0000000000..b4a44da5c5 --- /dev/null +++ b/Userland/Libraries/LibJS/Bytecode/PassManager.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibJS/Bytecode/BasicBlock.h> +#include <LibJS/Bytecode/Generator.h> +#include <sys/time.h> +#include <time.h> + +namespace JS::Bytecode { + +struct PassPipelineExecutable { + Executable& executable; + Optional<HashMap<BasicBlock const*, HashTable<BasicBlock const*>>> cfg {}; + Optional<HashMap<BasicBlock const*, HashTable<BasicBlock const*>>> inverted_cfg {}; + Optional<HashTable<BasicBlock const*>> exported_blocks {}; +}; + +class Pass { +public: + Pass() = default; + virtual ~Pass() = default; + + virtual void perform(PassPipelineExecutable&) = 0; + void started() + { + gettimeofday(&m_start_time, nullptr); + } + void finished() + { + struct timeval end_time { + 0, 0 + }; + gettimeofday(&end_time, nullptr); + time_t interval_s = end_time.tv_sec - m_start_time.tv_sec; + suseconds_t interval_us = end_time.tv_usec; + if (interval_us < m_start_time.tv_usec) { + interval_s -= 1; + interval_us += 1000000; + } + interval_us -= m_start_time.tv_usec; + m_time_difference = interval_s * 1000000 + interval_us; + } + + u64 elapsed() const { return m_time_difference; } + +protected: + struct timeval m_start_time { + 0, 0 + }; + u64 m_time_difference { 0 }; +}; + +class PassManager : public Pass { +public: + PassManager() = default; + ~PassManager() override = default; + + void add(NonnullOwnPtr<Pass> pass) { m_passes.append(move(pass)); } + + template<typename PassT, typename... Args> + void add(Args&&... args) { m_passes.append(make<PassT>(forward<Args>(args)...)); } + + void perform(Executable& executable) + { + PassPipelineExecutable pipeline_executable { executable }; + perform(pipeline_executable); + } + + virtual void perform(PassPipelineExecutable& executable) override + { + started(); + for (auto& pass : m_passes) + pass.perform(executable); + finished(); + } + +private: + NonnullOwnPtrVector<Pass> m_passes; +}; + +namespace Passes { + +class GenerateCFG : public Pass { +public: + GenerateCFG() = default; + ~GenerateCFG() override = default; + +private: + virtual void perform(PassPipelineExecutable&) override; +}; + +class MergeBlocks : public Pass { +public: + MergeBlocks() = default; + ~MergeBlocks() override = default; + +private: + virtual void perform(PassPipelineExecutable&) override; +}; + +class PlaceBlocks : public Pass { +public: + PlaceBlocks() = default; + ~PlaceBlocks() override = default; + +private: + virtual void perform(PassPipelineExecutable&) override; +}; + +class UnifySameBlocks : public Pass { +public: + UnifySameBlocks() = default; + ~UnifySameBlocks() override = default; + +private: + virtual void perform(PassPipelineExecutable&) override; +}; + +class DumpCFG : public Pass { +public: + DumpCFG(FILE* file) + : m_file(file) + { + } + + ~DumpCFG() override = default; + +private: + virtual void perform(PassPipelineExecutable&) override; + + FILE* m_file { nullptr }; +}; + +} + +} |