summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/sp.cc1
-rw-r--r--sql/sp_head.cc161
-rw-r--r--sql/sp_head.h102
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;