From 0913fd1aac820637d8f28790124cf908300cedba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Wed, 26 Feb 2020 20:47:11 +0100 Subject: [PATCH] [yul-phaser] Extract ProgramBasedMetric base class from ProgramSize --- test/yulPhaser/FitnessMetrics.cpp | 29 +++++++++++++++++++++++++---- tools/yulPhaser/FitnessMetrics.cpp | 9 +++++++-- tools/yulPhaser/FitnessMetrics.h | 30 +++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/test/yulPhaser/FitnessMetrics.cpp b/test/yulPhaser/FitnessMetrics.cpp index e7a389be7..293fac426 100644 --- a/test/yulPhaser/FitnessMetrics.cpp +++ b/test/yulPhaser/FitnessMetrics.cpp @@ -22,16 +22,26 @@ #include +#include + #include using namespace std; using namespace solidity::langutil; +using namespace solidity::util; using namespace solidity::yul; namespace solidity::phaser::test { -class FitnessMetricFixture +class DummyProgramBasedMetric: public ProgramBasedMetric +{ +public: + using ProgramBasedMetric::ProgramBasedMetric; + size_t evaluate(Chromosome const&) const override { return 0; } +}; + +class ProgramBasedMetricFixture { protected: static constexpr char SampleSourceCode[] = @@ -68,9 +78,20 @@ protected: BOOST_AUTO_TEST_SUITE(Phaser) BOOST_AUTO_TEST_SUITE(FitnessMetricsTest) +BOOST_AUTO_TEST_SUITE(ProgramBasedMetricTest) + +BOOST_FIXTURE_TEST_CASE(optimisedProgram_should_return_optimised_program, ProgramBasedMetricFixture) +{ + string code = toString(DummyProgramBasedMetric(m_program).optimisedProgram(m_chromosome)); + + BOOST_TEST(code != toString(m_program)); + BOOST_TEST(code == toString(m_optimisedProgram)); +} + +BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(ProgramSizeTest) -BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_size_of_the_optimised_program, FitnessMetricFixture) +BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_size_of_the_optimised_program, ProgramBasedMetricFixture) { size_t fitness = ProgramSize(m_program).evaluate(m_chromosome); @@ -78,7 +99,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_compute_size_of_the_optimised_program, F BOOST_TEST(fitness == m_optimisedProgram.codeSize()); } -BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number_of_times, FitnessMetricFixture) +BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number_of_times, ProgramBasedMetricFixture) { Program const& programOptimisedOnce = m_optimisedProgram; Program programOptimisedTwice = optimisedProgram(programOptimisedOnce); @@ -91,7 +112,7 @@ BOOST_FIXTURE_TEST_CASE(evaluate_should_repeat_the_optimisation_specified_number BOOST_TEST(fitness == programOptimisedTwice.codeSize()); } -BOOST_FIXTURE_TEST_CASE(evaluate_should_not_optimise_if_number_of_repetitions_is_zero, FitnessMetricFixture) +BOOST_FIXTURE_TEST_CASE(evaluate_should_not_optimise_if_number_of_repetitions_is_zero, ProgramBasedMetricFixture) { ProgramSize metric(m_program, 0); size_t fitness = metric.evaluate(m_chromosome); diff --git a/tools/yulPhaser/FitnessMetrics.cpp b/tools/yulPhaser/FitnessMetrics.cpp index be7ea5497..a3a344eb9 100644 --- a/tools/yulPhaser/FitnessMetrics.cpp +++ b/tools/yulPhaser/FitnessMetrics.cpp @@ -20,11 +20,16 @@ using namespace std; using namespace solidity::phaser; -size_t ProgramSize::evaluate(Chromosome const& _chromosome) const +Program ProgramBasedMetric::optimisedProgram(Chromosome const& _chromosome) const { Program programCopy = m_program; for (size_t i = 0; i < m_repetitionCount; ++i) programCopy.optimise(_chromosome.optimisationSteps()); - return programCopy.codeSize(); + return programCopy; +} + +size_t ProgramSize::evaluate(Chromosome const& _chromosome) const +{ + return optimisedProgram(_chromosome).codeSize(); } diff --git a/tools/yulPhaser/FitnessMetrics.h b/tools/yulPhaser/FitnessMetrics.h index 95608e89b..180fa322c 100644 --- a/tools/yulPhaser/FitnessMetrics.h +++ b/tools/yulPhaser/FitnessMetrics.h @@ -47,24 +47,44 @@ public: }; /** - * Fitness metric based on the size of a specific program after applying the optimisations from the - * chromosome to it. + * Abstract base class for fitness metrics that return values based on program size. + * + * The class provides utilities for optimising programs according to the information stored in + * chromosomes. + * + * It can also store weights for the @a CodeSize metric. It does not do anything with + * them because it does not actually compute the code size but they are readily available for use + * by derived classes. */ -class ProgramSize: public FitnessMetric +class ProgramBasedMetric: public FitnessMetric { public: - explicit ProgramSize(Program _program, size_t _repetitionCount = 1): + explicit ProgramBasedMetric( + Program _program, + size_t _repetitionCount = 1 + ): m_program(std::move(_program)), m_repetitionCount(_repetitionCount) {} Program const& program() const { return m_program; } size_t repetitionCount() const { return m_repetitionCount; } - size_t evaluate(Chromosome const& _chromosome) const override; + Program optimisedProgram(Chromosome const& _chromosome) const; private: Program m_program; size_t m_repetitionCount; }; +/** + * Fitness metric based on the size of a specific program after applying the optimisations from the + * chromosome to it. + */ +class ProgramSize: public ProgramBasedMetric +{ +public: + using ProgramBasedMetric::ProgramBasedMetric; + size_t evaluate(Chromosome const& _chromosome) const override; +}; + }