mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
WL#2001: Optimize stored procedure code.
Added a simple optimizer that shortcuts jumps and skip unused instructions.
This commit is contained in:
@@ -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;
|
||||
|
||||
165
sql/sp_head.cc
165
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)))
|
||||
{
|
||||
char buf[8];
|
||||
|
||||
sprintf(buf, "%4u: ", ip);
|
||||
s.append(buf);
|
||||
i->print(&s);
|
||||
s.append('\n');
|
||||
ip+= 1;
|
||||
#ifndef DBUG_OFF
|
||||
optimize();
|
||||
{
|
||||
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;
|
||||
}
|
||||
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
|
||||
//
|
||||
|
||||
102
sql/sp_head.h
102
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;
|
||||
|
||||
Reference in New Issue
Block a user