Skip to content

Commit

Permalink
Variables used in function/method calls weren't tracked properly, imp…
Browse files Browse the repository at this point in the history
…roving zephir_read_property_this implementation
  • Loading branch information
phalcon committed Mar 23, 2014
1 parent 0d3ddb4 commit b83d773
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 95 deletions.
2 changes: 1 addition & 1 deletion Library/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/
class Compiler
{
const VERSION = '0.3.10a';
const VERSION = '0.4.0a';

/**
* @var CompilerFile[]
Expand Down
5 changes: 5 additions & 0 deletions Library/FunctionCall.php
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ protected function _callNormal($expression, $compilationContext)
} else {
if ($this->mustInitSymbolVariable()) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}
$codePrinter->output('ZEPHIR_CALL_FUNCTION(&' . $symbolVariable->getName() . ', "' . $funcName . '", ' . $cachePointer . ');');
}
Expand All @@ -392,6 +393,7 @@ protected function _callNormal($expression, $compilationContext)
} else {
if ($this->mustInitSymbolVariable()) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}
$codePrinter->output('ZEPHIR_CALL_FUNCTION(&' . $symbolVariable->getName() . ', "' . $funcName . '", ' . $cachePointer . ', ' . join(', ', $params) . ');');
}
Expand Down Expand Up @@ -503,6 +505,7 @@ protected function _callDynamic($expression, $compilationContext)
} else {
if ($this->mustInitSymbolVariable()) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}
$codePrinter->output('ZEPHIR_CALL_ZVAL_FUNCTION(&' . $symbolVariable->getName() . ', ' . $variable->getName() . ', NULL);');
}
Expand All @@ -517,6 +520,7 @@ protected function _callDynamic($expression, $compilationContext)
} else {
if ($this->mustInitSymbolVariable()) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}
$codePrinter->output('ZEPHIR_CALL_ZVAL_FUNCTION(&' . $symbolVariable->getName() . ', ' . $variable->getName() . ', NULL, ' . join(', ', $params) . ');');
}
Expand All @@ -530,6 +534,7 @@ protected function _callDynamic($expression, $compilationContext)
} else {
if ($this->mustInitSymbolVariable()) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}
$codePrinter->output('ZEPHIR_CALL_ZVAL_FUNCTION(&' . $symbolVariable->getName() . ', ' . $variable->getName() . ', NULL);');
}
Expand Down
1 change: 1 addition & 0 deletions Library/MethodCall.php
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,7 @@ public function compile(Expression $expr, CompilationContext $compilationContext

if ($mustInit) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}

/**
Expand Down
3 changes: 3 additions & 0 deletions Library/StaticCall.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ protected function callSelf($methodName, array $expression, $symbolVariable, $mu

if ($mustInit) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}

/**
Expand Down Expand Up @@ -125,6 +126,7 @@ protected function callParent($methodName, array $expression, $symbolVariable, $

if ($mustInit) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}

/**
Expand Down Expand Up @@ -209,6 +211,7 @@ protected function callFromClass($methodName, array $expression, $symbolVariable

if ($mustInit) {
$symbolVariable->setMustInitNull(true);
$symbolVariable->trackVariant($compilationContext);
}

/**
Expand Down
44 changes: 44 additions & 0 deletions Library/Variable.php
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,50 @@ public function initVariant(CompilationContext $compilationContext)
}
}

/**
* Tells the compiler a generated code will track the variable
*
* @param CompilationContext $compilationContext
*/
public function trackVariant(CompilationContext $compilationContext)
{
if ($this->_numberSkips) {
$this->_numberSkips--;
return;
}

/**
* Variables are allocated for the first time using ZEPHIR_INIT_VAR
* the second, third, etc times are allocated using ZEPHIR_INIT_NVAR
* Variables initialized for the first time in a cycle are always initialized using ZEPHIR_INIT_NVAR
*/
if ($this->getName() != 'this_ptr' && $this->getName() != 'return_value') {

if ($this->_initBranch === false) {
$this->_initBranch = $compilationContext->currentBranch;
}

if (!$this->isLocalOnly()) {
$compilationContext->symbolTable->mustGrownStack(true);
if ($compilationContext->insideCycle) {
$this->_mustInitNull = true;
} else {
if ($this->_variantInits > 0) {
if ($this->_initBranch !== 1) {
$this->_mustInitNull = true;
}
}
}
} else {
if ($this->_variantInits > 0 || $compilationContext->insideCycle) {
$this->_mustInitNull = true;
}
}

$this->_variantInits++;
}
}

/**
* Initializes a variant variable that is intended to have the special
* behavior of only freed its body value instead of the full variable
Expand Down
90 changes: 2 additions & 88 deletions ext/kernel/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,93 +507,7 @@ int zephir_read_property(zval **result, zval *object, const char *property_name,
return SUCCESS;
}

/**
* Reads a property from this_ptr
* Variables must be defined in the class definition. This function ignores magic methods or dynamic properties
*/
int zephir_read_property_this(zval **result, zval *object, char *property_name, unsigned int property_length, int flags TSRMLS_DC) {

return zephir_read_property_this_quick(result, object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), flags TSRMLS_CC);
}

/**
* Reads a property from this_ptr (with pre-calculated key)
* Variables must be defined in the class definition. This function ignores magic methods or dynamic properties
*/
int zephir_read_property_this_quick(zval **result, zval *object, char *property_name, unsigned int property_length, unsigned long key, int flags TSRMLS_DC) {

zval *property;
zend_class_entry *ce, *old_scope;

if (Z_TYPE_P(object) != IS_OBJECT) {

if ((flags & PH_NOISY) == PH_NOISY) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Trying to get property of non-object");
}

*result = ZEPHIR_GLOBAL(global_null);
Z_ADDREF_P(*result);
return FAILURE;
}

ce = Z_OBJCE_P(object);
if (ce->parent) {
ce = zephir_lookup_class_ce(ce, property_name, property_length TSRMLS_CC);
}

old_scope = EG(scope);
EG(scope) = ce;

if (!Z_OBJ_HT_P(object)->read_property) {
#if PHP_VERSION_ID < 50400
char *class_name;
#else
const char *class_name;
#endif
zend_uint class_name_len;

zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", property_name, class_name);
}

MAKE_STD_ZVAL(property);
ZVAL_STRINGL(property, property_name, property_length, 0);

#if PHP_VERSION_ID < 50400
*result = Z_OBJ_HT_P(object)->read_property(object, property, (flags & PH_NOISY) == PH_NOISY ? BP_VAR_IS : BP_VAR_R TSRMLS_CC);
#else
*result = Z_OBJ_HT_P(object)->read_property(object, property, (flags & PH_NOISY) == PH_NOISY ? BP_VAR_IS : BP_VAR_R, 0 TSRMLS_CC);
#endif

Z_ADDREF_PP(result);

if (Z_REFCOUNT_P(property) > 1) {
ZVAL_STRINGL(property, property_name, property_length, 1);
} else {
ZVAL_NULL(property);
}

zval_ptr_dtor(&property);

EG(scope) = old_scope;
return SUCCESS;
}

zval* zephir_fetch_nproperty_this(zval *object, char *property_name, unsigned int property_length, int flags TSRMLS_DC) {
return zephir_fetch_nproperty_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), flags TSRMLS_CC);
}

zval* zephir_fetch_nproperty_this_quick(zval *object, char *property_name, unsigned int property_length, unsigned long key, int flags TSRMLS_DC) {
zval *result = zephir_fetch_property_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), flags TSRMLS_CC);
return result ? result : ZEPHIR_GLOBAL(global_null);
}


zval* zephir_fetch_property_this(zval *object, char *property_name, unsigned int property_length, int flags TSRMLS_DC) {
return zephir_fetch_property_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), flags TSRMLS_CC);
}

zval* zephir_fetch_property_this_quick(zval *object, char *property_name, unsigned int property_length, unsigned long key, int flags TSRMLS_DC) {
zval* zephir_fetch_property_this_quick(zval *object, const char *property_name, zend_uint property_length, ulong key, int silent TSRMLS_DC) {

zval **zv = NULL;
zend_object *zobj;
Expand Down Expand Up @@ -661,7 +575,7 @@ zval* zephir_fetch_property_this_quick(zval *object, char *property_name, unsign
EG(scope) = old_scope;

} else {
if ((flags & PH_NOISY) == PH_NOISY) {
if (silent == PH_NOISY) {
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Trying to get property of non-object");
}
}
Expand Down
74 changes: 68 additions & 6 deletions ext/kernel/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,7 @@ int zephir_isset_property_quick(zval *object, const char *property_name, unsigne
int zephir_isset_property_zval(zval *object, const zval *property TSRMLS_DC);

/** Reading properties */
int zephir_read_property_this(zval **result, zval *object, char *property_name, unsigned int property_length, int silent TSRMLS_DC);
int zephir_read_property_this_quick(zval **result, zval *object, char *property_name, unsigned int property_length, unsigned long key, int silent TSRMLS_DC);
zval* zephir_fetch_nproperty_this(zval *object, char *property_name, unsigned int property_length, int silent TSRMLS_DC);
zval* zephir_fetch_nproperty_this_quick(zval *object, char *property_name, unsigned int property_length, unsigned long key, int silent TSRMLS_DC);
zval* zephir_fetch_property_this(zval *object, char *property_name, unsigned int property_length, int silent TSRMLS_DC);
zval* zephir_fetch_property_this_quick(zval *object, char *property_name, unsigned int property_length, unsigned long key, int silent TSRMLS_DC);
zval* zephir_fetch_property_this_quick(zval *object, const char *property_name, zend_uint property_length, ulong key, int silent TSRMLS_DC);
int zephir_read_property(zval **result, zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC);
int zephir_read_property_zval(zval **result, zval *object, zval *property, int silent TSRMLS_DC);
int zephir_return_property(zval *return_value, zval **return_value_ptr, zval *object, char *property_name, unsigned int property_length TSRMLS_DC);
Expand Down Expand Up @@ -107,4 +102,71 @@ zval* zephir_fetch_static_property_ce(zend_class_entry *ce, char *property, int
int zephir_create_instance(zval *return_value, const zval *class_name TSRMLS_DC);
int zephir_create_instance_params(zval *return_value, const zval *class_name, zval *params TSRMLS_DC);

/**
* Reads a property from this_ptr (with pre-calculated key)
* Variables must be defined in the class definition. This function ignores magic methods or dynamic properties
*/
ZEPHIR_ATTR_NONNULL static inline int zephir_read_property_this_quick(zval **result, zval *object, const char *property_name, zend_uint property_length, ulong key, int silent TSRMLS_DC)
{
zval *tmp = zephir_fetch_property_this_quick(object, property_name, property_length, key, silent TSRMLS_CC);
if (EXPECTED(tmp != NULL)) {
*result = tmp;
Z_ADDREF_PP(result);
return SUCCESS;
}

ALLOC_INIT_ZVAL(*result);
return FAILURE;
}

/**
* Reads a property from this_ptr
* Variables must be defined in the class definition. This function ignores magic methods or dynamic properties
*/
ZEPHIR_ATTR_NONNULL static inline int zephir_read_property_this(zval **result, zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC)
{
#ifdef __GNUC__
if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
return zephir_read_property_this_quick(result, object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
}
#endif

return zephir_read_property_this_quick(result, object, property_name, property_length, zend_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
}

ZEPHIR_ATTR_NONNULL static inline zval* zephir_fetch_nproperty_this_quick(zval *object, const char *property_name, zend_uint property_length, ulong key, int silent TSRMLS_DC)
{
#ifdef __GNUC__
if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
zval *result = zephir_fetch_property_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
return result ? result : EG(uninitialized_zval_ptr);
}
#endif

zval *result = zephir_fetch_property_this_quick(object, property_name, property_length, zend_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
return result ? result : EG(uninitialized_zval_ptr);
}

ZEPHIR_ATTR_NONNULL static inline zval* zephir_fetch_nproperty_this(zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC)
{
#ifdef __GNUC__
if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
return zephir_fetch_nproperty_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
}
#endif

return zephir_fetch_nproperty_this_quick(object, property_name, property_length, zend_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
}

ZEPHIR_ATTR_NONNULL static inline zval* zephir_fetch_property_this(zval *object, const char *property_name, zend_uint property_length, int silent TSRMLS_DC)
{
#ifdef __GNUC__
if (__builtin_constant_p(property_name) && __builtin_constant_p(property_length)) {
return zephir_fetch_property_this_quick(object, property_name, property_length, zend_inline_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
}
#endif

return zephir_fetch_property_this_quick(object, property_name, property_length, zend_hash_func(property_name, property_length + 1), silent TSRMLS_CC);
}

#endif

0 comments on commit b83d773

Please sign in to comment.