Commit 51eb6440 authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

WL#2001: Optimize stored procedure code.

Added a simple optimizer that shortcuts jumps and skip unused instructions.
parent 7e6bade2
......@@ -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;
......
......@@ -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
//
......
......@@ -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;
......
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