Skip to content

Commit

Permalink
Adding array_keys optimizer, allow using isset with parentheses, othe…
Browse files Browse the repository at this point in the history
…r fixes
  • Loading branch information
andresgutierrez committed Jan 18, 2014
1 parent b5b4aed commit 15b4412
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Library/ClassMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ public function compile(CompilationContext $compilationContext)
*/
$initCode .= "\t" . 'if (!' . $name . ') {' . PHP_EOL;
$initCode .= $this->assignDefaultValue($parameter, $compilationContext);
if ($dataType == 'variable' || $dataType == 'string') {
if ($dataType == 'variable' || $dataType == 'string') {
if (isset($parametersToSeparate[$name])) {
$initCode .= "\t" . '} else {' . PHP_EOL;
$initCode .= "\t\t" . "ZEPHIR_SEPARATE_PARAM(" . $name . ");" . PHP_EOL;
Expand Down
4 changes: 2 additions & 2 deletions Library/MethodCall.php
Original file line number Diff line number Diff line change
Expand Up @@ -465,15 +465,15 @@ public function compile(Expression $expr, CompilationContext $compilationContext
if ($isExpecting) {
$codePrinter->output('zephir_call_internal_method(' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', "' . $methodName . '", ZEND_MN(' . $classDefinition->getNCNamespace() . '_' . $classDefinition->getName() . '_' . $methodName . '));');
} else {
$codePrinter->output('zephir_call_internal_method_noret(' . $variableVariable->getName() . ', "' . $methodName . '");');
$codePrinter->output('zephir_call_internal_method_noret(' . $variableVariable->getName() . ', "' . $methodName . '", ZEND_MN(' . $classDefinition->getNCNamespace() . '_' . $classDefinition->getName() . '_' . $methodName . '));');
}

} else {

if ($isExpecting) {
$codePrinter->output('zephir_call_internal_method_p' . count($params) . '(' . $symbolVariable->getName() . ', ' . $variableVariable->getName() . ', "' . $methodName . '", ZEND_MN(' . $classDefinition->getNCNamespace() . '_' . $classDefinition->getName() . '_' . $methodName . '), ' . join(', ', $params) . ');');
} else {
$codePrinter->output('zephir_call_internal_method_p' . count($params) . '_noret(' . $variableVariable->getName() . ', "' . $methodName . '", ' . join(', ', $params) . ');');
$codePrinter->output('zephir_call_internal_method_p' . count($params) . '_noret(' . $variableVariable->getName() . ', "' . $methodName . '", ZEND_MN(' . $classDefinition->getNCNamespace() . '_' . $classDefinition->getName() . '_' . $methodName . '), ' . join(', ', $params) . ');');
}

}
Expand Down
19 changes: 19 additions & 0 deletions Library/Operators/Comparison/BaseOperator.php
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,25 @@ public function compile($expression, CompilationContext $compilationContext)
return new CompiledExpression('bool', '(\'\\0\' ' . $this->_operator . ' \'' . $right->getCode() . '\')', $expression);
case 'double':
return new CompiledExpression('bool', '(0 ' . $this->_operator . ' (int) ' . $right->getCode() . ')', $expression);
case 'variable':
$variableRight = $compilationContext->symbolTable->getVariableForRead($right->getCode(), $compilationContext, $expression['left']);
switch ($variableRight->getType()) {
case 'int':
case 'uint':
case 'long':
case 'ulong':
$compilationContext->headersManager->add('kernel/operators');
return new CompiledExpression('bool', '(0 ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
case 'double':
$compilationContext->headersManager->add('kernel/operators');
return new CompiledExpression('bool', '(0 ' . $this->_operator . ' ' . $variableRight->getName() . ')', $expression);
case 'variable':
$compilationContext->headersManager->add('kernel/operators');
return new CompiledExpression('bool', 'ZEPHIR_IS_NULL(' . $variableRight->getName() . ')', $expression);
default:
throw new CompilerException("Unknown type: " . $variableRight->getType(), $expression['right']);
}
break;
default:
throw new CompilerException("Unknown type: " . $right->getType(), $expression);
}
Expand Down
34 changes: 20 additions & 14 deletions Library/Operators/Other/IssetOperator.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,58 +37,64 @@ public function compile($expression, CompilationContext $compilationContext)

$compilationContext->headersManager->add('kernel/array');

switch ($expression['left']['type']) {
if ($expression['left']['type'] == 'list') {
$left = $expression['left']['left'];
} else {
$left = $expression['left'];
}

switch ($left['type']) {
case 'array-access':

$exprVariable = new Expression($expression['left']['left']);
$exprVariable = new Expression($left['left']);
$exprVariable->setReadOnly(true);

$exprCompiledVariable = $exprVariable->compile($compilationContext);
if ($exprCompiledVariable->getType() != 'variable') {
throw new CompilerException("Expression type: " . $exprCompiledVariable->getType() . " cannot be used as array", $expression['left']['left']);
throw new CompilerException("Expression type: " . $exprCompiledVariable->getType() . " cannot be used as array", $left['left']);
}

$variable = $compilationContext->symbolTable->getVariableForRead($exprCompiledVariable->getCode(), $compilationContext, $expression['left']['left']);
$variable = $compilationContext->symbolTable->getVariableForRead($exprCompiledVariable->getCode(), $compilationContext, $left['left']);
if ($variable->getType() != 'variable') {
throw new CompilerException("Variable type: " . $variable->getType() . " cannot be used as array", $expression['left']['left']);
throw new CompilerException("Variable type: " . $variable->getType() . " cannot be used as array", $left['left']);
}

if ($variable->hasDifferentDynamicType(array('undefined', 'array', 'object', 'null'))) {
$compilationContext->logger->warning('Possible attempt to use non array/object in isset operator', 'non-valid-isset', $expression);
}

$expr = new Expression($expression['left']['right']);
$expr = new Expression($left['right']);
$expr->setReadOnly(true);
$resolvedExpr = $expr->compile($compilationContext);
switch ($resolvedExpr->getType()) {
case 'int':
case 'long':
return new CompiledExpression('bool', 'zephir_array_isset_long(' . $variable->getName() . ', ' . $resolvedExpr->getCode() . ')', $expression['left']['right']);
return new CompiledExpression('bool', 'zephir_array_isset_long(' . $variable->getName() . ', ' . $resolvedExpr->getCode() . ')', $left['right']);
case 'string':
return new CompiledExpression('bool', 'zephir_array_isset_string(' . $variable->getName() . ', SS("' . $resolvedExpr->getCode() . '"))', $expression['left']['right']);
return new CompiledExpression('bool', 'zephir_array_isset_string(' . $variable->getName() . ', SS("' . $resolvedExpr->getCode() . '"))', $left['right']);
case 'variable':
$indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $expression['left']['right']);
$indexVariable = $compilationContext->symbolTable->getVariableForRead($resolvedExpr->getCode(), $compilationContext, $left['right']);
switch ($indexVariable->getType()) {
case 'int':
case 'long':
return new CompiledExpression('bool', 'zephir_array_isset_long(' . $variable->getName() . ', ' . $indexVariable->getName() . ')', $expression['left']['right']);
return new CompiledExpression('bool', 'zephir_array_isset_long(' . $variable->getName() . ', ' . $indexVariable->getName() . ')', $left['right']);
case 'variable':
case 'string':
return new CompiledExpression('bool', 'zephir_array_isset(' . $variable->getName() . ', ' . $indexVariable->getName() . ')', $expression['left']['right']);
return new CompiledExpression('bool', 'zephir_array_isset(' . $variable->getName() . ', ' . $indexVariable->getName() . ')', $left['right']);
default:
throw new CompilerException('[' . $indexVariable->getType() . ']', $expression);
}
break;
default:
throw new CompilerException('[' . $expression['left']['right']['type'] . ']', $expression);
throw new CompilerException('[' . $left['right']['type'] . ']', $expression);
}
break;
case 'property-access':
return new CompiledExpression('bool', '0 == 0', $expression['left']['right']);
return new CompiledExpression('bool', '0 == 0', $left['right']);
//return new CompiledExpression('bool', 'zephir_isset_property(' . $variable->getName() . ', SS("' . $expression['left']['right']['value'] . '") TSRMLS_CC)', $expression['left']['right']);
break;
case 'property-dynamic-access':
return new CompiledExpression('bool', '0 == 0', $expression['left']['right']);
return new CompiledExpression('bool', '0 == 0', $left['right']);
/*$expr = new Expression($expression['left']['right']);
$expr->setReadOnly(true);
$resolvedExpr = $expr->compile($compilationContext);
Expand Down
68 changes: 68 additions & 0 deletions Library/Optimizers/FunctionCall/ArrayKeysOptimizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

/*
+--------------------------------------------------------------------------+
| Zephir Language |
+--------------------------------------------------------------------------+
| Copyright (c) 2013-2014 Zephir Team and contributors |
+--------------------------------------------------------------------------+
| This source file is subject the MIT license, that is bundled with |
| this package in the file LICENSE, and is available through the |
| world-wide-web at the following url: |
| http://zephir-lang.com/license.html |
| |
| If you did not receive a copy of the MIT license and are unable |
| to obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+--------------------------------------------------------------------------+
*/

/**
* ArrayKeysOptimizer
*
* Optimizes calls to 'array_keys' using internal function
*/
class ArrayKeysOptimizer
extends OptimizerAbstract
{
/**
* @param array $expression
* @param Call $call
* @param CompilationContext $context
* @return bool|CompiledExpression|mixed
* @throws CompilerException
*/
public function optimize(array $expression, Call $call, CompilationContext $context)
{
if (!isset($expression['parameters'])) {
return false;
}

if (count($expression['parameters']) != 1) {
return false;
}

/**
* Process the expected symbol to be returned
*/
$call->processExpectedReturn($context);

$symbolVariable = $call->getSymbolVariable();
if ($symbolVariable->getType() != 'variable') {
throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression);
}

if ($call->mustInitSymbolVariable()) {
$symbolVariable->initVariant($context);
}

$context->headersManager->add('kernel/extended/array');

$symbolVariable->setDynamicTypes('array');

$resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
$context->codePrinter->output('zephir_array_keys(' . $symbolVariable->getName() . ', ' . $resolvedParams[0] . ' TSRMLS_CC);');
return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression);
}

}
102 changes: 102 additions & 0 deletions ext/kernel/extended/array.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@

/*
+------------------------------------------------------------------------+
| Zephir Language |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2014 Zephir Team (http://www.zephir-lang.com) |
+------------------------------------------------------------------------+
| This source file is subject to the New BSD License that is bundled |
| with this package in the file docs/LICENSE.txt. |
| |
| If you did not receive a copy of the license and are unable to |
| obtain it through the world-wide-web, please send an email |
| to [email protected] so we can send you a copy immediately. |
+------------------------------------------------------------------------+
| Authors: Andres Gutierrez <[email protected]> |
| Eduar Carvajal <[email protected]> |
+------------------------------------------------------------------------+
*/

/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <[email protected]> |
| Zeev Suraski <[email protected]> |
| Rasmus Lerdorf <[email protected]> |
| Andrei Zmievski <[email protected]> |
| Stig Venaas <[email protected]> |
| Jason Greene <[email protected]> |
+----------------------------------------------------------------------+
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "php.h"
#include "php_ext.h"

#include "Zend/zend_API.h"
#include "Zend/zend_exceptions.h"
#include "Zend/zend_execute.h"

#include "kernel/main.h"

#include "kernel/extended/array.h"

void zephir_array_keys(zval *input TSRMLS_DC) {

zval *search_value = NULL, /* Value to search for */
**entry, /* An entry in the input array */
res, /* Result of comparison */
*new_val; /* New value */
int add_key; /* Flag to indicate whether a key should be added */
zend_bool strict = 0; /* do strict comparison */
HashPosition pos;
int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;

//if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zb", &input, &search_value, &strict) == FAILURE) {
// return;
//}

if (strict) {
is_equal_func = is_identical_function;
}

/* Initialize return array */
if (search_value != NULL) {
array_init(return_value);
} else {
array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
}
add_key = 1;

/* Go through input array and add keys to the return array */
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {
if (search_value != NULL) {
is_equal_func(&res, search_value, *entry TSRMLS_CC);
add_key = zval_is_true(&res);
}
}

if (add_key) {
MAKE_STD_ZVAL(new_val);
zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(input), new_val, &pos);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);
}

zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);

}
43 changes: 43 additions & 0 deletions ext/kernel/extended/array.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

/*
+------------------------------------------------------------------------+
| Zephir Language |
+------------------------------------------------------------------------+
| Copyright (c) 2011-2014 Zephir Team (http://www.zephir-lang.com) |
+------------------------------------------------------------------------+
| This source file is subject to the New BSD License that is bundled |
| with this package in the file docs/LICENSE.txt. |
| |
| If you did not receive a copy of the license and are unable to |
| obtain it through the world-wide-web, please send an email |
| to [email protected] so we can send you a copy immediately. |
+------------------------------------------------------------------------+
| Authors: Andres Gutierrez <[email protected]> |
| Eduar Carvajal <[email protected]> |
+------------------------------------------------------------------------+
*/

/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| [email protected] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Andi Gutmans <[email protected]> |
| Zeev Suraski <[email protected]> |
| Rasmus Lerdorf <[email protected]> |
| Andrei Zmievski <[email protected]> |
| Stig Venaas <[email protected]> |
| Jason Greene <[email protected]> |
+----------------------------------------------------------------------+
*/

void zephir_array_keys(zval *input TSRMLS_DC);
2 changes: 1 addition & 1 deletion templates/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PHP_ARG_ENABLE(%PROJECT_LOWER%, whether to enable %PROJECT_LOWER%, [ --enable-%P

if test "$PHP_%PROJECT_UPPER%" = "yes"; then
AC_DEFINE(HAVE_%PROJECT_UPPER%, 1, [Whether you have %PROJECT_CAMELIZE%])
%PROJECT_LOWER%_sources="%PROJECT_LOWER%.c kernel/main.c kernel/memory.c kernel/exception.c kernel/hash.c kernel/debug.c kernel/backtrace.c kernel/object.c kernel/array.c kernel/string.c kernel/fcall.c kernel/require.c kernel/alternative/fcall.c kernel/file.c kernel/operators.c kernel/concat.c kernel/variables.c %FILES_COMPILED% %EXTRA_FILES_COMPILED%"
%PROJECT_LOWER%_sources="%PROJECT_LOWER%.c kernel/main.c kernel/memory.c kernel/exception.c kernel/hash.c kernel/debug.c kernel/backtrace.c kernel/object.c kernel/array.c kernel/extended/array.c kernel/string.c kernel/fcall.c kernel/require.c kernel/alternative/fcall.c kernel/file.c kernel/operators.c kernel/concat.c kernel/variables.c %FILES_COMPILED% %EXTRA_FILES_COMPILED%"
PHP_NEW_EXTENSION(%PROJECT_LOWER%, $%PROJECT_LOWER%_sources, $ext_shared)

old_CPPFLAGS=$CPPFLAGS
Expand Down

0 comments on commit 15b4412

Please sign in to comment.