Commit 81aad353 authored by unknown's avatar unknown

WL#2001: Optimize stored procedure code.

Added a simple optimizer that shortcuts jumps and skip unused instructions.


sql/sp.cc:
  Optimize the code after parsing.
sql/sp_head.cc:
  Added a simple optimizer that shortcuts jumps and skip unused instructions.
sql/sp_head.h:
  Added a simple optimizer that shortcuts jumps and skip unused instructions.
parent 4467bcf2
...@@ -292,6 +292,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ...@@ -292,6 +292,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
*sphp= thd->lex->sphead; *sphp= thd->lex->sphead;
(*sphp)->set_info((char *)definer, (uint)strlen(definer), (*sphp)->set_info((char *)definer, (uint)strlen(definer),
created, modified, &chistics, sql_mode); created, modified, &chistics, sql_mode);
(*sphp)->optimize();
} }
thd->lex->sql_command= oldcmd; thd->lex->sql_command= oldcmd;
thd->variables.sql_mode= old_sql_mode; thd->variables.sql_mode= old_sql_mode;
......
...@@ -317,22 +317,26 @@ sp_head::create(THD *thd) ...@@ -317,22 +317,26 @@ sp_head::create(THD *thd)
DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s", DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s",
m_type, m_name.str, m_params.str, m_body.str)); m_type, m_name.str, m_params.str, m_body.str));
#ifndef DBUG_OFF #ifndef DBUG_OFF
String s; optimize();
sp_instr *i;
uint ip= 0;
while ((i = get_instr(ip)))
{ {
char buf[8]; String s;
sp_instr *i;
uint ip= 0;
while ((i = get_instr(ip)))
{
char buf[8];
sprintf(buf, "%4u: ", ip); sprintf(buf, "%4u: ", ip);
s.append(buf); s.append(buf);
i->print(&s); i->print(&s);
s.append('\n'); s.append('\n');
ip+= 1; 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 #endif
if (m_type == TYPE_ENUM_FUNCTION) if (m_type == TYPE_ENUM_FUNCTION)
...@@ -981,6 +985,58 @@ sp_head::show_create_function(THD *thd) ...@@ -981,6 +985,58 @@ sp_head::show_create_function(THD *thd)
thd->variables.sql_mode= old_sql_mode; thd->variables.sql_mode= old_sql_mode;
DBUG_RETURN(res); 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) ...@@ -1091,6 +1147,42 @@ sp_instr_jump::print(String *str)
str->qs_append(m_dest); 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 // sp_instr_jump_if
// //
...@@ -1120,6 +1212,21 @@ sp_instr_jump_if::print(String *str) ...@@ -1120,6 +1212,21 @@ sp_instr_jump_if::print(String *str)
m_expr->print(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 // sp_instr_jump_if_not
// //
...@@ -1149,6 +1256,21 @@ sp_instr_jump_if_not::print(String *str) ...@@ -1149,6 +1256,21 @@ sp_instr_jump_if_not::print(String *str)
m_expr->print(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 // sp_instr_freturn
// //
...@@ -1206,6 +1328,21 @@ sp_instr_hpush_jump::print(String *str) ...@@ -1206,6 +1328,21 @@ sp_instr_hpush_jump::print(String *str)
str->qs_append(m_handler); 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 // sp_instr_hpop
// //
......
...@@ -201,6 +201,20 @@ class sp_head :private Item_arena ...@@ -201,6 +201,20 @@ class sp_head :private Item_arena
void restore_thd_mem_root(THD *thd); 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: private:
...@@ -218,18 +232,6 @@ class sp_head :private Item_arena ...@@ -218,18 +232,6 @@ class sp_head :private Item_arena
} bp_t; } bp_t;
List<bp_t> m_backpatch; // Instructions needing backpatching 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 int
execute(THD *thd); execute(THD *thd);
...@@ -247,11 +249,13 @@ class sp_instr : public Sql_alloc ...@@ -247,11 +249,13 @@ class sp_instr : public Sql_alloc
public: public:
uint marked;
Item *free_list; // My Items Item *free_list; // My Items
uint m_ip; // My index
// Should give each a name or type code for debugging purposes? // Should give each a name or type code for debugging purposes?
sp_instr(uint ip) 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() virtual ~sp_instr()
...@@ -265,9 +269,24 @@ class sp_instr : public Sql_alloc ...@@ -265,9 +269,24 @@ class sp_instr : public Sql_alloc
virtual void print(String *str) = 0; 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 }; // class sp_instr : public Sql_alloc
...@@ -349,12 +368,14 @@ class sp_instr_jump : public sp_instr ...@@ -349,12 +368,14 @@ class sp_instr_jump : public sp_instr
public: public:
uint m_dest; // Where we will go
sp_instr_jump(uint ip) 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_jump(uint ip, uint dest)
: sp_instr(ip), m_dest(dest) : sp_instr(ip), m_dest(dest), m_optdest(0)
{} {}
virtual ~sp_instr_jump() virtual ~sp_instr_jump()
...@@ -364,6 +385,12 @@ class sp_instr_jump : public sp_instr ...@@ -364,6 +385,12 @@ class sp_instr_jump : public sp_instr
virtual void print(String *str); 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 virtual void
set_destination(uint dest) set_destination(uint dest)
{ {
...@@ -373,7 +400,7 @@ class sp_instr_jump : public sp_instr ...@@ -373,7 +400,7 @@ class sp_instr_jump : public sp_instr
protected: protected:
int m_dest; // Where we will go sp_instr *m_optdest; // Used during optimization
}; // class sp_instr_jump : public sp_instr }; // class sp_instr_jump : public sp_instr
...@@ -400,6 +427,13 @@ class sp_instr_jump_if : public sp_instr_jump ...@@ -400,6 +427,13 @@ class sp_instr_jump_if : public sp_instr_jump
virtual void print(String *str); virtual void print(String *str);
virtual uint opt_mark(sp_head *sp);
virtual uint opt_shortcut_jump(sp_head *sp)
{
return m_ip;
}
private: private:
Item *m_expr; // The condition Item *m_expr; // The condition
...@@ -429,6 +463,13 @@ class sp_instr_jump_if_not : public sp_instr_jump ...@@ -429,6 +463,13 @@ class sp_instr_jump_if_not : public sp_instr_jump
virtual void print(String *str); virtual void print(String *str);
virtual uint opt_mark(sp_head *sp);
virtual uint opt_shortcut_jump(sp_head *sp)
{
return m_ip;
}
private: private:
Item *m_expr; // The condition Item *m_expr; // The condition
...@@ -454,6 +495,12 @@ class sp_instr_freturn : public sp_instr ...@@ -454,6 +495,12 @@ class sp_instr_freturn : public sp_instr
virtual void print(String *str); virtual void print(String *str);
virtual uint opt_mark(sp_head *sp)
{
marked= 1;
return UINT_MAX;
}
protected: protected:
Item *m_value; Item *m_value;
...@@ -485,6 +532,13 @@ class sp_instr_hpush_jump : public sp_instr_jump ...@@ -485,6 +532,13 @@ class sp_instr_hpush_jump : public sp_instr_jump
virtual void print(String *str); 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) inline void add_condition(struct sp_cond_type *cond)
{ {
m_cond.push_front(cond); m_cond.push_front(cond);
...@@ -543,6 +597,12 @@ class sp_instr_hreturn : public sp_instr ...@@ -543,6 +597,12 @@ class sp_instr_hreturn : public sp_instr
virtual void print(String *str); virtual void print(String *str);
virtual uint opt_mark(sp_head *sp)
{
marked= 1;
return UINT_MAX;
}
private: private:
uint m_frame; uint m_frame;
...@@ -700,6 +760,12 @@ class sp_instr_error : public sp_instr ...@@ -700,6 +760,12 @@ class sp_instr_error : public sp_instr
virtual void print(String *str); virtual void print(String *str);
virtual uint opt_mark(sp_head *sp)
{
marked= 1;
return UINT_MAX;
}
private: private:
int m_errcode; int m_errcode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment