diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sp.cc | 1 | ||||
-rw-r--r-- | sql/sp_head.cc | 161 | ||||
-rw-r--r-- | sql/sp_head.h | 102 |
3 files changed, 234 insertions, 30 deletions
diff --git a/sql/sp.cc b/sql/sp.cc index 4164a27ca5f..9d574c81545 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -292,6 +292,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) *sphp= thd->lex->sphead; (*sphp)->set_info((char *)definer, (uint)strlen(definer), created, modified, &chistics, sql_mode); + (*sphp)->optimize(); } thd->lex->sql_command= oldcmd; thd->variables.sql_mode= old_sql_mode; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 32c25c98425..5054b69cbd8 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -317,22 +317,26 @@ sp_head::create(THD *thd) DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s", m_type, m_name.str, m_params.str, m_body.str)); + #ifndef DBUG_OFF - String s; - sp_instr *i; - uint ip= 0; - while ((i = get_instr(ip))) + optimize(); { - char buf[8]; + String s; + sp_instr *i; + uint ip= 0; + while ((i = get_instr(ip))) + { + char buf[8]; - sprintf(buf, "%4u: ", ip); - s.append(buf); - i->print(&s); - s.append('\n'); - ip+= 1; + sprintf(buf, "%4u: ", ip); + s.append(buf); + i->print(&s); + s.append('\n'); + ip+= 1; + } + s.append('\0'); + DBUG_PRINT("info", ("Code %s\n%s", m_qname.str, s.ptr())); } - s.append('\0'); - DBUG_PRINT("info", ("Code %s\n%s", m_qname.str, s.ptr())); #endif if (m_type == TYPE_ENUM_FUNCTION) @@ -981,6 +985,58 @@ sp_head::show_create_function(THD *thd) thd->variables.sql_mode= old_sql_mode; DBUG_RETURN(res); } + +void +sp_head::optimize() +{ + List<sp_instr> bp; + sp_instr *i; + uint src, dst; + + opt_mark(0); + + bp.empty(); + src= dst= 0; + while ((i= get_instr(src))) + { + if (! i->marked) + { + delete i; + src+= 1; + } + else + { + if (src != dst) + { + sp_instr *ibp; + List_iterator_fast<sp_instr> li(bp); + + set_dynamic(&m_instr, (gptr)&i, dst); + while ((ibp= li++)) + { + sp_instr_jump *ji= static_cast<sp_instr_jump *>(ibp); + if (ji->m_dest == src) + ji->m_dest= dst; + } + } + i->opt_move(dst, &bp); + src+= 1; + dst+= 1; + } + } + m_instr.elements= dst; + bp.empty(); +} + +void +sp_head::opt_mark(uint ip) +{ + sp_instr *i; + + while ((i= get_instr(ip)) && !i->marked) + ip= i->opt_mark(this); +} + // ------------------------------------------------------------------ // @@ -1091,6 +1147,42 @@ sp_instr_jump::print(String *str) str->qs_append(m_dest); } +uint +sp_instr_jump::opt_mark(sp_head *sp) +{ + marked= 1; + m_dest= opt_shortcut_jump(sp); + m_optdest= sp->get_instr(m_dest); + return m_dest; +} + +uint +sp_instr_jump::opt_shortcut_jump(sp_head *sp) +{ + uint dest= m_dest; + sp_instr *i; + + while ((i= sp->get_instr(dest))) + { + uint ndest= i->opt_shortcut_jump(sp); + + if (ndest == dest) + break; + dest= ndest; + } + return dest; +} + +void +sp_instr_jump::opt_move(uint dst, List<sp_instr> *bp) +{ + if (m_dest > m_ip) + bp->push_back(this); // Forward + else if (m_optdest) + m_dest= m_optdest->m_ip; // Backward + m_ip= dst; +} + // // sp_instr_jump_if // @@ -1120,6 +1212,21 @@ sp_instr_jump_if::print(String *str) m_expr->print(str); } +uint +sp_instr_jump_if::opt_mark(sp_head *sp) +{ + sp_instr *i; + + marked= 1; + if ((i= sp->get_instr(m_dest))) + { + m_dest= i->opt_shortcut_jump(sp); + m_optdest= sp->get_instr(m_dest); + } + sp->opt_mark(m_dest); + return m_ip+1; +} + // // sp_instr_jump_if_not // @@ -1149,6 +1256,21 @@ sp_instr_jump_if_not::print(String *str) m_expr->print(str); } +uint +sp_instr_jump_if_not::opt_mark(sp_head *sp) +{ + sp_instr *i; + + marked= 1; + if ((i= sp->get_instr(m_dest))) + { + m_dest= i->opt_shortcut_jump(sp); + m_optdest= sp->get_instr(m_dest); + } + sp->opt_mark(m_dest); + return m_ip+1; +} + // // sp_instr_freturn // @@ -1206,6 +1328,21 @@ sp_instr_hpush_jump::print(String *str) str->qs_append(m_handler); } +uint +sp_instr_hpush_jump::opt_mark(sp_head *sp) +{ + sp_instr *i; + + marked= 1; + if ((i= sp->get_instr(m_dest))) + { + m_dest= i->opt_shortcut_jump(sp); + m_optdest= sp->get_instr(m_dest); + } + sp->opt_mark(m_dest); + return m_ip+1; +} + // // sp_instr_hpop // diff --git a/sql/sp_head.h b/sql/sp_head.h index fd6ecfd7320..165f83c58fd 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -201,6 +201,20 @@ public: void restore_thd_mem_root(THD *thd); + void optimize(); + void opt_mark(uint ip); + + inline sp_instr * + get_instr(uint i) + { + sp_instr *ip; + + if (i < m_instr.elements) + get_dynamic(&m_instr, (gptr)&ip, i); + else + ip= NULL; + return ip; + } private: @@ -218,18 +232,6 @@ private: } bp_t; List<bp_t> m_backpatch; // Instructions needing backpatching - inline sp_instr * - get_instr(uint i) - { - sp_instr *ip; - - if (i < m_instr.elements) - get_dynamic(&m_instr, (gptr)&ip, i); - else - ip= NULL; - return ip; - } - int execute(THD *thd); @@ -247,11 +249,13 @@ class sp_instr : public Sql_alloc public: + uint marked; Item *free_list; // My Items + uint m_ip; // My index // Should give each a name or type code for debugging purposes? sp_instr(uint ip) - :Sql_alloc(), free_list(0), m_ip(ip) + :Sql_alloc(), marked(0), free_list(0), m_ip(ip) {} virtual ~sp_instr() @@ -265,9 +269,24 @@ public: virtual void print(String *str) = 0; -protected: + virtual void set_destination(uint dest) + {} - uint m_ip; // My index + virtual uint opt_mark(sp_head *sp) + { + marked= 1; + return m_ip+1; + } + + virtual uint opt_shortcut_jump(sp_head *sp) + { + return m_ip; + } + + virtual void opt_move(uint dst, List<sp_instr> *ibp) + { + m_ip= dst; + } }; // class sp_instr : public Sql_alloc @@ -349,12 +368,14 @@ class sp_instr_jump : public sp_instr public: + uint m_dest; // Where we will go + sp_instr_jump(uint ip) - : sp_instr(ip), m_dest(0) + : sp_instr(ip), m_dest(0), m_optdest(0) {} sp_instr_jump(uint ip, uint dest) - : sp_instr(ip), m_dest(dest) + : sp_instr(ip), m_dest(dest), m_optdest(0) {} virtual ~sp_instr_jump() @@ -364,6 +385,12 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp); + + virtual uint opt_shortcut_jump(sp_head *sp); + + virtual void opt_move(uint dst, List<sp_instr> *ibp); + virtual void set_destination(uint dest) { @@ -373,7 +400,7 @@ public: protected: - int m_dest; // Where we will go + sp_instr *m_optdest; // Used during optimization }; // class sp_instr_jump : public sp_instr @@ -400,6 +427,13 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp); + + virtual uint opt_shortcut_jump(sp_head *sp) + { + return m_ip; + } + private: Item *m_expr; // The condition @@ -429,6 +463,13 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp); + + virtual uint opt_shortcut_jump(sp_head *sp) + { + return m_ip; + } + private: Item *m_expr; // The condition @@ -454,6 +495,12 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp) + { + marked= 1; + return UINT_MAX; + } + protected: Item *m_value; @@ -485,6 +532,13 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp); + + virtual uint opt_shortcut_jump(sp_head *sp) + { + return m_ip; + } + inline void add_condition(struct sp_cond_type *cond) { m_cond.push_front(cond); @@ -543,6 +597,12 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp) + { + marked= 1; + return UINT_MAX; + } + private: uint m_frame; @@ -700,6 +760,12 @@ public: virtual void print(String *str); + virtual uint opt_mark(sp_head *sp) + { + marked= 1; + return UINT_MAX; + } + private: int m_errcode; |