From c60cdb3e64c5508dc837b63e3e683eebc96d94c3 Mon Sep 17 00:00:00 2001 From: uwetews Date: Thu, 31 Dec 2015 02:20:47 +0100 Subject: [PATCH] - optimization of {assign}, {if} and {while} compiled code --- change_log.txt | 3 + libs/Smarty.class.php | 2 +- .../smarty_internal_compile_assign.php | 65 ++++++++++--------- .../sysplugins/smarty_internal_compile_if.php | 6 +- .../smarty_internal_compile_while.php | 2 +- .../smarty_internal_extension_handler.php | 1 - .../smarty_internal_runtime_updatescope.php | 41 +++++++----- .../smarty_internal_runtime_var.php | 33 ---------- libs/sysplugins/smarty_internal_template.php | 45 +++++++++++++ .../smarty_internal_testinstall.php | 1 - 10 files changed, 113 insertions(+), 86 deletions(-) delete mode 100644 libs/sysplugins/smarty_internal_runtime_var.php diff --git a/change_log.txt b/change_log.txt index 20d2be1c..22d7231c 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,7 @@  ===== 3.1.30-dev ===== (xx.xx.xx) + 31.12.2015 + - optimization of {assign}, {if} and {while} compiled code + 30.12.2015 - bugfix plugin names starting with "php" did not compile https://github.com/smarty-php/smarty/issues/147 diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 3d4170d2..437afe14 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -121,7 +121,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.30-dev/13'; + const SMARTY_VERSION = '3.1.30-dev/14'; /** * define variable scopes diff --git a/libs/sysplugins/smarty_internal_compile_assign.php b/libs/sysplugins/smarty_internal_compile_assign.php index 5e3fce3c..3b2eb614 100644 --- a/libs/sysplugins/smarty_internal_compile_assign.php +++ b/libs/sysplugins/smarty_internal_compile_assign.php @@ -21,8 +21,8 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase * * @var array */ - public $valid_scopes = array('local' => true, 'parent' => true, 'root' => true, 'global' => true, - 'smarty' => true, 'tpl_root' => true); + public $valid_scopes = array('local' => true, 'parent' => true, 'root' => true, 'global' => true, + 'smarty' => true, 'tpl_root' => true); /** * Compiles code for the {assign} tag @@ -47,52 +47,55 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase if ($compiler->tag_nocache || $compiler->nocache) { $_nocache = 'true'; // create nocache var to make it know for further compiling - if (isset($compiler->template->tpl_vars[trim($_attr['var'], "'")])) { - $compiler->template->tpl_vars[trim($_attr['var'], "'")]->nocache = true; + if (isset($compiler->template->tpl_vars[ trim($_attr[ 'var' ], "'") ])) { + $compiler->template->tpl_vars[ trim($_attr[ 'var' ], "'") ]->nocache = true; } else { - $compiler->template->tpl_vars[trim($_attr['var'], "'")] = new Smarty_Variable(null, true); + $compiler->template->tpl_vars[ trim($_attr[ 'var' ], "'") ] = new Smarty_Variable(null, true); } } // scope setup $_scope = Smarty::SCOPE_LOCAL; - if (isset($_attr['scope'])) { - $_attr['scope'] = trim($_attr['scope'], "'\""); - if (!isset($this->valid_scopes[$_attr['scope']])) { - $compiler->trigger_template_error("illegal value '{$_attr['scope']}' for \"scope\" attribute", null, true); + if (isset($_attr[ 'scope' ])) { + $_attr[ 'scope' ] = trim($_attr[ 'scope' ], "'\""); + if (!isset($this->valid_scopes[ $_attr[ 'scope' ] ])) { + $compiler->trigger_template_error("illegal value '{$_attr['scope']}' for \"scope\" attribute", null, + true); } - if ($_attr['scope'] != 'local') { - if ($_attr['scope'] == 'parent') { + if ($_attr[ 'scope' ] != 'local') { + if ($_attr[ 'scope' ] == 'parent') { $_scope = Smarty::SCOPE_PARENT; - } elseif ($_attr['scope'] == 'root') { + } elseif ($_attr[ 'scope' ] == 'root') { $_scope = Smarty::SCOPE_ROOT; - } elseif ($_attr['scope'] == 'global') { + } elseif ($_attr[ 'scope' ] == 'global') { $_scope = Smarty::SCOPE_GLOBAL; - } elseif ($_attr['scope'] == 'smarty') { + } elseif ($_attr[ 'scope' ] == 'smarty') { $_scope = Smarty::SCOPE_SMARTY; - } elseif ($_attr['scope'] == 'tpl_root') { + } elseif ($_attr[ 'scope' ] == 'tpl_root') { $_scope = Smarty::SCOPE_TPL_ROOT; } - $_scope += (isset($_attr['bubble_up']) && $_attr['bubble_up'] == 'false') ? 0 : Smarty::SCOPE_BUBBLE_UP; + $_scope += (isset($_attr[ 'bubble_up' ]) && $_attr[ 'bubble_up' ] == 'false') ? 0 : + Smarty::SCOPE_BUBBLE_UP; } } - // compiled output - if (isset($parameter['smarty_internal_index'])) { - $output = - "smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, $_attr[var], $_nocache);\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value$parameter[smarty_internal_index] = $_attr[value];"; - } else { - // implement Smarty2's behaviour of variables assigned by reference - if ($compiler->template->smarty instanceof SmartyBC) { - $output = - "tpl_vars[$_attr[var]])) {\$_smarty_tpl->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];"; - $output .= "\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value = $_attr[value]; \$_smarty_tpl->tpl_vars[$_attr[var]]->nocache = $_nocache;"; - $output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache);"; + if (isset($parameter[ 'smarty_internal_index' ])) { + $output = "_createLocalArrayVariable({$_attr['var']}, {$_nocache});\n"; + $output .= "\$_smarty_tpl->tpl_vars[{$_attr['var']}]->value{$parameter['smarty_internal_index']} = {$_attr['value']};\n"; + if ($_scope != Smarty::SCOPE_LOCAL) { + $output .= "\$_smarty_tpl->ext->_updateScope->updateScope(\$_smarty_tpl, {$_attr['var']}, {$_scope});\n"; } else { - $output = "tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache);"; + $output .= "if (\$_smarty_tpl->scope & Smarty::SCOPE_BUBBLE_UP) {\n"; + $output .= "\$_smarty_tpl->ext->_updateScope->updateScope(\$_smarty_tpl, {$_attr['var']});\n}\n"; } + $output .= '?>'; + } else { + if ($compiler->template->smarty instanceof SmartyBC) { + $_smartyBC = 'true'; + } else { + $_smartyBC = 'false'; + } + $output = + "_assignInScope({$_attr['var']}, {$_attr['value']}, {$_nocache}, {$_scope}, {$_smartyBC});\n?>"; } - $output .= "\n\$_smarty_tpl->ext->_updateScope->updateScope(\$_smarty_tpl, $_attr[var], $_scope);"; - $output .= '?>'; - return $output; } } diff --git a/libs/sysplugins/smarty_internal_compile_if.php b/libs/sysplugins/smarty_internal_compile_if.php index 541e2181..84bafc5d 100644 --- a/libs/sysplugins/smarty_internal_compile_if.php +++ b/libs/sysplugins/smarty_internal_compile_if.php @@ -58,7 +58,7 @@ class Smarty_Internal_Compile_If extends Smarty_Internal_CompileBase if (is_array($parameter['if condition']['var'])) { $_output = "tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . - "]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " . $parameter['if condition']['var']['var'] . + "]->value)) \$_smarty_tpl->_createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"; $_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . @@ -162,7 +162,7 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase $_output = "tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . - "]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " . + "]->value)) \$_smarty_tpl->_createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"; $_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . @@ -195,7 +195,7 @@ class Smarty_Internal_Compile_Elseif extends Smarty_Internal_CompileBase $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . - "]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " . + "]->value)) \$_smarty_tpl->_createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"); $_output .= "if (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . diff --git a/libs/sysplugins/smarty_internal_compile_while.php b/libs/sysplugins/smarty_internal_compile_while.php index bd31f667..9678ede5 100644 --- a/libs/sysplugins/smarty_internal_compile_while.php +++ b/libs/sysplugins/smarty_internal_compile_while.php @@ -60,7 +60,7 @@ class Smarty_Internal_Compile_While extends Smarty_Internal_CompileBase if (is_array($parameter['if condition']['var'])) { $_output .= "if (!isset(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]) || !is_array(\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . - "]->value)) \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, " . $parameter['if condition']['var']['var'] . + "]->value)) \$_smarty_tpl->_createLocalArrayVariable(" . $parameter['if condition']['var']['var'] . "$_nocache);\n"; $_output .= "while (\$_smarty_tpl->tpl_vars[" . $parameter['if condition']['var']['var'] . "]->value" . $parameter['if condition']['var']['smarty_internal_index'] . " = " . diff --git a/libs/sysplugins/smarty_internal_extension_handler.php b/libs/sysplugins/smarty_internal_extension_handler.php index e4d771bd..94fc81a6 100644 --- a/libs/sysplugins/smarty_internal_extension_handler.php +++ b/libs/sysplugins/smarty_internal_extension_handler.php @@ -12,7 +12,6 @@ * * @property Smarty_Internal_Runtime_Inheritance $_inheritance * @property Smarty_Internal_Runtime_TplFunction $_tplFunction - * @property Smarty_Internal_Runtime_Var $_var * @property Smarty_Internal_Runtime_Foreach $_foreach * @property Smarty_Internal_Runtime_WriteFile $_writeFile * @property Smarty_Internal_Runtime_CodeFrame $_codeFrame diff --git a/libs/sysplugins/smarty_internal_runtime_updatescope.php b/libs/sysplugins/smarty_internal_runtime_updatescope.php index 5a125a4a..b99acf42 100644 --- a/libs/sysplugins/smarty_internal_runtime_updatescope.php +++ b/libs/sysplugins/smarty_internal_runtime_updatescope.php @@ -1,7 +1,7 @@ scope) { + $scopes = array(); + if ($scope) { + $scopes[] = $scope; + } + if ($tpl->scope) { + $scopes[] = $tpl->scope; + } + if (empty($scopes)) { return; } - foreach (array($scope, $tpl->scope) as $s) { + /* @var Smarty_Internal_Data $ptr */ + $ptr = null; + foreach ($scopes as $s) { $s = ($bubble_up = $s >= Smarty::SCOPE_BUBBLE_UP) ? $s - Smarty::SCOPE_BUBBLE_UP : $s; if ($bubble_up && $s) { - $ptr = $tpl->parent; - if (isset($ptr)) { - $ptr->tpl_vars[$varName] = $tpl->tpl_vars[$varName]; - $ptr = $ptr->parent; + if (isset($tpl->parent)) { + $ptr = $tpl->parent; + $ptr->tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ]; + if (isset($ptr->parent)) { + $ptr = $ptr->parent; + } } if ($s == Smarty::SCOPE_PARENT) { continue; } while (isset($ptr) && $ptr->_objType == 2) { - $ptr->tpl_vars[$varName] = $tpl->tpl_vars[$varName]; + $ptr->tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ]; $ptr = $ptr->parent; } if ($s == Smarty::SCOPE_TPL_ROOT) { continue; } elseif ($s == Smarty::SCOPE_SMARTY) { - $tpl->smarty->tpl_vars[$varName] = $tpl->tpl_vars[$varName]; + $tpl->smarty->tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ]; } elseif ($s == Smarty::SCOPE_GLOBAL) { - Smarty::$global_tpl_vars[$varName] = $tpl->tpl_vars[$varName]; + Smarty::$global_tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ]; } elseif ($s == Smarty::SCOPE_ROOT) { while (isset($ptr->parent)) { $ptr = $ptr->parent; } - $ptr->tpl_vars[$varName] = $tpl->tpl_vars[$varName]; + $ptr->tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ]; } } } diff --git a/libs/sysplugins/smarty_internal_runtime_var.php b/libs/sysplugins/smarty_internal_runtime_var.php deleted file mode 100644 index 8e09108f..00000000 --- a/libs/sysplugins/smarty_internal_runtime_var.php +++ /dev/null @@ -1,33 +0,0 @@ -tpl_vars[$varName])) { - $tpl->tpl_vars[$varName] = new Smarty_Variable(array(), $nocache); - } else { - $tpl->tpl_vars[$varName] = clone $tpl->tpl_vars[$varName]; - if (!(is_array($tpl->tpl_vars[$varName]->value) || - $tpl->tpl_vars[$varName]->value instanceof ArrayAccess) - ) { - settype($tpl->tpl_vars[$varName]->value, 'array'); - } - } - } -} diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index d135f74b..fea9012e 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -393,6 +393,51 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase return isset($this->parent) && $this->parent->_objType == 2; } + /** + * Assign variable in scope + * + * @param string $varName variable name + * @param mixed $value value + * @param bool $nocache nocache flag + * @param int $scope scope into which variable shall be assigned + * @param bool $smartyBC true if called in Smarty bc class + * + * @throws \SmartyException + */ + public function _assignInScope($varName, $value, $nocache, $scope, $smartyBC) + { + if ($smartyBC && isset($this->tpl_vars[ $varName ])) { + $this->tpl_vars[ $varName ] = clone $this->tpl_vars[ $varName ]; + $this->tpl_vars[ $varName ]->value = $value; + $this->tpl_vars[ $varName ]->nocache = $nocache; + } else { + $this->tpl_vars[ $varName ] = new Smarty_Variable($value, $nocache); + } + if ($scope || $this->scope & Smarty::SCOPE_BUBBLE_UP) { + $this->ext->_updateScope->updateScope($this, $varName, $scope); + } + } + + /** + * Template code runtime function to create a local Smarty variable for array assignments + * + * @param string $varName template variable name + * @param bool $nocache cache mode of variable + */ + public function _createLocalArrayVariable($varName, $nocache = false) + { + if (!isset($this->tpl_vars[ $varName ])) { + $this->tpl_vars[ $varName ] = new Smarty_Variable(array(), $nocache); + } else { + $this->tpl_vars[ $varName ] = clone $this->tpl_vars[ $varName ]; + if (!(is_array($this->tpl_vars[ $varName ]->value) || + $this->tpl_vars[ $varName ]->value instanceof ArrayAccess) + ) { + settype($this->tpl_vars[ $varName ]->value, 'array'); + } + } + } + /** * This function is executed automatically when a compiled or cached template file is included * - Decode saved properties from compiled template and cache files diff --git a/libs/sysplugins/smarty_internal_testinstall.php b/libs/sysplugins/smarty_internal_testinstall.php index c75fe87b..e91f2338 100644 --- a/libs/sysplugins/smarty_internal_testinstall.php +++ b/libs/sysplugins/smarty_internal_testinstall.php @@ -481,7 +481,6 @@ class Smarty_Internal_TestInstall 'smarty_internal_runtime_tplfunction.php' => true, 'smarty_internal_runtime_updatecache.php' => true, 'smarty_internal_runtime_updatescope.php' => true, - 'smarty_internal_runtime_var.php' => true, 'smarty_internal_runtime_writefile.php' => true, 'smarty_internal_smartytemplatecompiler.php' => true, 'smarty_internal_template.php' => true,