LCOV - code coverage report
Current view: top level - lib - optimizer_tables.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 37 37 100.0 %
Date: 2014-11-22 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* optimizer_tables.cpp -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2014 */
       2             : 
       3             : /*
       4             : 
       5             : Copyright (c) 2005-2014 Made to Order Software Corp.
       6             : 
       7             : http://snapwebsites.org/project/as2js
       8             : 
       9             : Permission is hereby granted, free of charge, to any
      10             : person obtaining a copy of this software and
      11             : associated documentation files (the "Software"), to
      12             : deal in the Software without restriction, including
      13             : without limitation the rights to use, copy, modify,
      14             : merge, publish, distribute, sublicense, and/or sell
      15             : copies of the Software, and to permit persons to whom
      16             : the Software is furnished to do so, subject to the
      17             : following conditions:
      18             : 
      19             : The above copyright notice and this permission notice
      20             : shall be included in all copies or substantial
      21             : portions of the Software.
      22             : 
      23             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      24             : ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      25             : LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      26             : FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      27             : EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      28             : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      29             : WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      30             : ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      31             : SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      32             : SOFTWARE.
      33             : 
      34             : */
      35             : 
      36             : #include    "optimizer_tables.h"
      37             : 
      38             : #include    "as2js/exceptions.h"
      39             : 
      40             : // Low level matching tables
      41             : #include    "optimizer_matches.ci"
      42             : #include    "optimizer_values.ci"
      43             : 
      44             : // Optimization tables 
      45             : #include    "optimizer_optimize.ci"
      46             : 
      47             : // Actual optimization entries
      48             : #include    "optimizer_additive.ci"
      49             : #include    "optimizer_assignments.ci"
      50             : #include    "optimizer_bitwise.ci"
      51             : #include    "optimizer_compare.ci"
      52             : #include    "optimizer_conditional.ci"
      53             : #include    "optimizer_equality.ci"
      54             : #include    "optimizer_logical.ci"
      55             : #include    "optimizer_match.ci"
      56             : #include    "optimizer_multiplicative.ci"
      57             : #include    "optimizer_relational.ci"
      58             : #include    "optimizer_statements.ci"
      59             : 
      60             : namespace as2js
      61             : {
      62             : 
      63             : /** \brief The optimizer sub-namespace.
      64             :  *
      65             :  * This namespace is used to define all the optimizer internal
      66             :  * tables, functions, and classes.
      67             :  *
      68             :  * We have a separate namespace because the number of tables
      69             :  * in the optimizer is really large and could clash with other
      70             :  * parts of the libraries.
      71             :  */
      72             : namespace optimizer_details
      73             : {
      74             : 
      75             : 
      76             : 
      77             : /** \brief Hide all optimizer tables implementation details.
      78             :  *
      79             :  * This unnamed namespace is used to further hide all the optimizer
      80             :  * details.
      81             :  */
      82             : namespace
      83             : {
      84             : 
      85             : /** \brief Table holding all the optimization tables.
      86             :  *
      87             :  * We have one additional level for no technical reason other
      88             :  * than it makes it a bit cleaner to definie one table per
      89             :  * category of optimization and conglomerate them in one
      90             :  * larger table here.
      91             :  *
      92             :  * The table size is known and defined below. It is not
      93             :  * otherwise terminated with a null entry or anything like
      94             :  * that.
      95             :  *
      96             :  * The table is only defined locally and used in the optimize_tree()
      97             :  * function below.
      98             :  */
      99             : optimization_tables_t const g_optimizer_tables[] =
     100             : {
     101             :     {
     102             :         POINTER_AND_COUNT(g_optimizer_additive_table)
     103             :     },
     104             :     {
     105             :         POINTER_AND_COUNT(g_optimizer_assignments_table)
     106             :     },
     107             :     {
     108             :         POINTER_AND_COUNT(g_optimizer_bitwise_table)
     109             :     },
     110             :     {
     111             :         POINTER_AND_COUNT(g_optimizer_compare_table)
     112             :     },
     113             :     {
     114             :         POINTER_AND_COUNT(g_optimizer_conditional_table)
     115             :     },
     116             :     {
     117             :         POINTER_AND_COUNT(g_optimizer_equality_table)
     118             :     },
     119             :     {
     120             :         POINTER_AND_COUNT(g_optimizer_logical_table)
     121             :     },
     122             : // regex is not well supported before 4.9.0
     123             : #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
     124             :     {
     125             :         POINTER_AND_COUNT(g_optimizer_match_table)
     126             :     },
     127             : #endif
     128             :     {
     129             :         POINTER_AND_COUNT(g_optimizer_multiplicative_table)
     130             :     },
     131             :     {
     132             :         POINTER_AND_COUNT(g_optimizer_relational_table)
     133             :     },
     134             :     {
     135             :         POINTER_AND_COUNT(g_optimizer_statements_table)
     136             :     }
     137             : };
     138             : 
     139             : 
     140             : /** \brief The size of the table of tables.
     141             :  *
     142             :  * This variable holds the number of tables defined in the
     143             :  * g_optimizer_tables. It is always larger than zero.
     144             :  */
     145             : size_t g_optimizer_tables_count = sizeof(g_optimizer_tables) / sizeof(g_optimizer_tables[0]);
     146             : 
     147             : 
     148             : /** \brief Attempt to apply one optimization against this node.
     149             :  *
     150             :  * This function applies the optimization entry defined in \p entry to
     151             :  * the specified node tree. If the node tree matches that entry, then
     152             :  * the function proceeds and optimizes the node tree and returns true.
     153             :  *
     154             :  * Note that the root node (the input node) may itself be changed.
     155             :  *
     156             :  * \internal
     157             :  *
     158             :  * \param[in] node  The tree of nodes being optimized.
     159             :  * \param[in] entry  The entry definining one optimization.
     160             :  *
     161             :  * \return If this optimization was applied, true, otherwise false.
     162             :  */
     163      204769 : bool apply_optimization(Node::pointer_t& node, optimization_entry_t const *entry)
     164             : {
     165      204769 :     if((entry->f_flags & OPTIMIZATION_ENTRY_FLAG_UNSAFE_MATH) != 0)
     166             :     {
     167             :         // TODO: test whether the Unsafe Math option is turned on, if not
     168             :         //       skip this optimization
     169             :     }
     170             : 
     171      204769 :     node_pointer_vector_t node_array;
     172      204769 :     if(match_tree(node_array, node, entry->f_match, entry->f_match_count, 0))
     173             :     {
     174             : #if defined(_DEBUG) || defined(DEBUG)
     175         525 :         std::cout << "Optimize with: " << entry->f_name << "\n";
     176             : #endif
     177         525 :         Node::pointer_t parent(node->get_parent());
     178         525 :         if(!parent)
     179             :         {
     180             :             // if you create your own tree of node, it is possible to
     181             :             // reach this statement... otherwise, the top should always
     182             :             // have a NODE_PROGRAM which cannot be optimized
     183           1 :             throw exception_internal_error("INTERNAL ERROR: somehow the optimizer is optimizing a node without a parent.");
     184             :         }
     185         524 :         size_t index(node->get_offset());
     186             : 
     187         524 :         apply_functions(node_array, entry->f_optimize, entry->f_optimize_count);
     188             : 
     189             :         // in case the node pointer changed (which is nearly always)
     190         524 :         node = parent->get_child(index);
     191         525 :         return true;
     192             :     }
     193             : 
     194      204245 :     return false;
     195             : }
     196             : 
     197             : 
     198             : }
     199             : // noname namespace
     200             : 
     201             : 
     202             : /** \brief Optimize a tree of nodes as much as possible.
     203             :  *
     204             :  * This function checks the specified node against all the available
     205             :  * optimizations defined in the optimizer.
     206             :  *
     207             :  * \todo
     208             :  * Look into losing the recusirve aspect of this function (so the
     209             :  * entire tree of nodes gets checked.)
     210             :  *
     211             :  * \param[in] node  The node being checked.
     212             :  *
     213             :  * \return true if any optimization was applied
     214             :  */
     215        2284 : bool optimize_tree(Node::pointer_t node)
     216             : {
     217        2284 :     bool result(false);
     218             : 
     219             :     // accept empty nodes, just ignore them
     220        2284 :     if(!node || node->get_type() == Node::node_t::NODE_UNKNOWN)
     221             :     {
     222           2 :         return result;
     223             :     }
     224             : 
     225             :     // we need to optimize the child most nodes first
     226        2282 :     size_t const max_children(node->get_children_size());
     227        4141 :     for(size_t idx(0); idx < max_children; ++idx)
     228             :     {
     229             :         // Note: although the child at index 'idx' may change
     230             :         //       the number of children in 'node' cannot change
     231        1859 :         if(optimize_tree(node->get_child(idx))) // recursive
     232             :         {
     233         932 :             result = true;
     234             :         }
     235             :     }
     236             : 
     237             :     for(;;)
     238             :     {
     239        2806 :         bool repeat(false);
     240       30856 :         for(size_t i(0); i < g_optimizer_tables_count; ++i)
     241             :         {
     242       28051 :             optimization_table_t const *table(g_optimizer_tables[i].f_table);
     243       28051 :             size_t const table_max(g_optimizer_tables[i].f_table_count);
     244      232819 :             for(size_t j(0); j < table_max; ++j)
     245             :             {
     246      204769 :                 optimization_entry_t const *entry(table[j].f_entry);
     247      204769 :                 size_t const entry_max(table[j].f_entry_count);
     248      409537 :                 for(size_t k(0); k < entry_max; ++k)
     249             :                 {
     250      204769 :                     if(apply_optimization(node, entry + k))
     251             :                     {
     252         524 :                         repeat = true;
     253             : 
     254             :                         // at least one optimization was applied
     255         524 :                         result = true;
     256             : 
     257             :                         // TBD: would it be faster to immediately
     258             :                         //      repeat from the start?
     259             :                     }
     260             :                 }
     261             :             }
     262             :         }
     263             : 
     264             :         // anything was optimized?
     265        2805 :         if(!repeat)
     266             :         {
     267             :             // we are done
     268        2281 :             break;
     269             :         }
     270         524 :     }
     271             : 
     272        2281 :     return result;
     273             : }
     274             : 
     275             : }
     276             : // namespace optimizer_details
     277          63 : }
     278             : // namespace as2js
     279             : 
     280             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10