mirror of
https://github.com/php/php-src.git
synced 2026-04-28 18:53:33 +02:00
Merge branch 'master' of git.php.net:php-src
This commit is contained in:
@@ -245,10 +245,6 @@ ext/reflection/spl.chm
|
||||
ext/simplexml/examples/security.new.xml
|
||||
ext/spl/examples/.htaccess
|
||||
ext/spl/examples/*.phps
|
||||
ext/sqlite/weztest.sqlite
|
||||
ext/sqlite/libsqlite/src/sqlite.h
|
||||
ext/sqlite/libsqlite/src/parse.out
|
||||
ext/sqlite/libsqlite/src/libsqlite.dsw
|
||||
ext/sqlite3/tests/phpsql*
|
||||
ext/sqlite3/tests/*.db
|
||||
ext/sqlite3/tests/*.tmp
|
||||
|
||||
@@ -2,19 +2,30 @@ PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 2016, PHP 7.1.0
|
||||
|
||||
Core:
|
||||
- Core:
|
||||
. Fixed bug #62210 (Exceptions can leak temporary variables). (Dmitry, Bob)
|
||||
. Implemented the RFC `Support Class Constant Visibility`. (Sean DuBois,
|
||||
Reeze Xia, Dmitry)
|
||||
. Added void return type. (Andrea)
|
||||
|
||||
Hash:
|
||||
- FTP:
|
||||
. Implemented FR #55651 (Option to ignore the returned FTP PASV address).
|
||||
(abrender at elitehosts dot com)
|
||||
|
||||
- Hash:
|
||||
. Added SHA3 fixed mode algorithms (224, 256, 384, and 512 bit). (Sara)
|
||||
|
||||
PDO_Firebird:
|
||||
- PDO_Firebird:
|
||||
. Fixed bug #60052 (Integer returned as a 64bit integer on X64_86). (Mariuz)
|
||||
|
||||
Standard:
|
||||
- Pgsql:
|
||||
. Implemented FR #31021 (pg_result_notice() is needed to get all notice
|
||||
messages). (Yasuo)
|
||||
. Implemented FR #48532 (Allow pg_fetch_all() to index numerically). (Yasuo)
|
||||
|
||||
- Standard:
|
||||
. Fixed bug #71100 (long2ip() doesn't accept integers in strict mode).
|
||||
(Laruence)
|
||||
. Implemented FR #55716 (Add an option to pass a custom stream context to
|
||||
get_headers()). (Ferenc)
|
||||
. Implemented FR #69359 (Provide a way to fetch the current environment
|
||||
|
||||
@@ -45,6 +45,13 @@ PHP 7.1 UPGRADE NOTES
|
||||
- The first $varname argument for getenv() is no longer mandatory, the
|
||||
current environment variables will be returned as an associative array
|
||||
when omitted.
|
||||
- long2ip() accepts integer as parameter now
|
||||
- pg_last_notice() accepts optional 2nd bool parameter to get all notices and
|
||||
returns empty string or array on successful calls. It returned FALSE for
|
||||
empty notice previously.
|
||||
- pg_fetch_all() accepts optional 2nd bool parameter to get numerically indexed
|
||||
rows.
|
||||
- pg_select() accepts PGSQL_FETCH_NUM option to get numerically indexed rows.
|
||||
|
||||
========================================
|
||||
6. New Functions
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Array addition is not commutative -- do not swap operands
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$array = [1, 2, 3];
|
||||
$array = [4, 5, 6] + $array;
|
||||
var_dump($array);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(4)
|
||||
[1]=>
|
||||
int(5)
|
||||
[2]=>
|
||||
int(6)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ var_dump(parse_ini_file($ini_file));
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
unlink(__DIR__ . "bug70748.ini");
|
||||
unlink(__DIR__ . "/bug70748.ini");
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: syntax error, unexpected $end, expecting '}' in %sbug70748.ini on line %d
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
--TEST--
|
||||
Bug #71067 (Local object in class method stays in memory for each call)
|
||||
--INI--
|
||||
opcache.enable=0
|
||||
error_reporting=0
|
||||
--FILE--
|
||||
<?php
|
||||
class Test {
|
||||
public function test(){
|
||||
$arr = (object) [
|
||||
'children' => []
|
||||
];
|
||||
$arr->children[] = 1;
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
|
||||
$o = new Test();
|
||||
$o->test();
|
||||
|
||||
print_r($o->test());
|
||||
?>
|
||||
--EXPECT--
|
||||
stdClass Object
|
||||
(
|
||||
[children] => Array
|
||||
(
|
||||
[0] => 1
|
||||
)
|
||||
|
||||
)
|
||||
@@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
Bug #71086: Invalid numeric literal parse error within highlight_string() function
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$highlightedString = highlight_string("<?php \n 09 09 09;", true);
|
||||
var_dump($highlightedString);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(169) "<code><span style="color: #000000">
|
||||
<span style="color: #0000BB"><?php <br /> </span><span style="color: #007700">09 09 09;</span>
|
||||
</span>
|
||||
</code>"
|
||||
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Global variable import using a name with side effects
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function sf($arg) {
|
||||
echo "called\n";
|
||||
return $arg;
|
||||
}
|
||||
|
||||
function test() {
|
||||
global ${sf("a")};
|
||||
var_dump($a);
|
||||
}
|
||||
|
||||
$a = 42;
|
||||
test();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
called
|
||||
int(42)
|
||||
@@ -0,0 +1,43 @@
|
||||
--TEST--
|
||||
Using an integer as a static property name
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Foo {
|
||||
public static $bar = 42;
|
||||
}
|
||||
|
||||
$n = 42;
|
||||
|
||||
${42} = 24;
|
||||
var_dump(${42});
|
||||
var_dump(${(int) 42});
|
||||
var_dump(${(int) $n});
|
||||
|
||||
try {
|
||||
var_dump(Foo::${42});
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(Foo::${(int) 42});
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(Foo::${(int) $n});
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(24)
|
||||
int(24)
|
||||
int(24)
|
||||
Access to undeclared static property: Foo::$42
|
||||
Access to undeclared static property: Foo::$42
|
||||
Access to undeclared static property: Foo::$42
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
return type with finally
|
||||
--INI--
|
||||
opcache.enable=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function foo() : array {
|
||||
try {
|
||||
throw new Exception("xxxx");
|
||||
} finally {
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
||||
foo();
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught TypeError: Return value of foo() must be of the type array, none returned in %s29.php:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): foo()
|
||||
#1 {main}
|
||||
thrown in %s029.php on line %d
|
||||
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
Bug #71092 (Segmentation fault with return type hinting)
|
||||
--INI--
|
||||
opcache.enable=0
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function boom(): array {
|
||||
$data = [['id']];
|
||||
switch ($data[0]) {
|
||||
case ['id']:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boom();
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught TypeError: Return value of boom() must be of the type array, none returned in %sbug71092.php:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): boom()
|
||||
#1 {main}
|
||||
thrown in %sbug71092.php on line %d
|
||||
@@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
instanceof self outside a class
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$fn = function() {
|
||||
try {
|
||||
new stdClass instanceof self;
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
};
|
||||
$fn();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Cannot access self:: when no class scope is active
|
||||
@@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
Accessing self:: properties or methods outside a class
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$fn = function() {
|
||||
$str = "foo";
|
||||
try {
|
||||
self::${$str . "bar"};
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
unset(self::${$str . "bar"});
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
isset(self::${$str . "bar"});
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
try {
|
||||
self::{$str . "bar"}();
|
||||
} catch (Error $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
};
|
||||
$fn();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Cannot access self:: when no class scope is active
|
||||
Cannot access self:: when no class scope is active
|
||||
Cannot access self:: when no class scope is active
|
||||
Cannot access self:: when no class scope is active
|
||||
+1
-1
@@ -622,7 +622,7 @@ static zend_bool php_auto_globals_create_globals(zend_string *name) /* {{{ */
|
||||
zval globals;
|
||||
|
||||
ZVAL_ARR(&globals, &EG(symbol_table));
|
||||
Z_TYPE_INFO_P(&globals) = IS_ARRAY | (IS_TYPE_SYMBOLTABLE << Z_TYPE_FLAGS_SHIFT);
|
||||
Z_TYPE_INFO_P(&globals) = IS_ARRAY;
|
||||
ZVAL_NEW_REF(&globals, &globals);
|
||||
zend_hash_update(&EG(symbol_table), name, &globals);
|
||||
return 0;
|
||||
|
||||
+10
-4
@@ -25,6 +25,7 @@
|
||||
#include "zend_execute.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_modules.h"
|
||||
#include "zend_extensions.h"
|
||||
#include "zend_constants.h"
|
||||
#include "zend_exceptions.h"
|
||||
#include "zend_closures.h"
|
||||
@@ -2004,7 +2005,7 @@ ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /
|
||||
lcname = zend_string_alloc(name_len, 0);
|
||||
zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
|
||||
|
||||
if (zend_hash_exists(&module_registry, lcname)) {
|
||||
if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
|
||||
zend_string_free(lcname);
|
||||
/* TODO: Check version relationship */
|
||||
zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
|
||||
@@ -3749,7 +3750,7 @@ ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *n
|
||||
}
|
||||
|
||||
if (zend_string_equals_literal_ci(name, "class")) {
|
||||
zend_error((ce->type == ZEND_INTERNAL_CLASS) ? E_CORE_ERROR : E_COMPILE_ERROR,
|
||||
zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
|
||||
"A class constant must not be called 'class'; it is reserved for class name fetching");
|
||||
}
|
||||
|
||||
@@ -3765,8 +3766,13 @@ ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *n
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
return zend_hash_add_ptr(&ce->constants_table, name, c) ?
|
||||
SUCCESS : FAILURE;
|
||||
|
||||
if (!zend_hash_add_ptr(&ce->constants_table, name, c)) {
|
||||
zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
|
||||
"Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -2028,14 +2028,14 @@ ZEND_FUNCTION(zend_test_func)
|
||||
{
|
||||
zval *arg1, *arg2;
|
||||
|
||||
zend_get_parameters(ZEND_NUM_ARGS(), 2, &arg1, &arg2);
|
||||
zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
|
||||
}
|
||||
|
||||
ZEND_FUNCTION(zend_test_func2)
|
||||
{
|
||||
zval *arg1, *arg2;
|
||||
|
||||
zend_get_parameters(ZEND_NUM_ARGS(), 2, &arg1, &arg2);
|
||||
zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+24
-24
@@ -1860,7 +1860,6 @@ static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
|
||||
case BP_VAR_R:
|
||||
return;
|
||||
case BP_VAR_W:
|
||||
case BP_VAR_REF:
|
||||
opline->opcode += 1 * factor;
|
||||
return;
|
||||
case BP_VAR_RW:
|
||||
@@ -2616,6 +2615,7 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t
|
||||
opline = zend_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
|
||||
}
|
||||
if (opline->op1_type == IS_CONST) {
|
||||
convert_to_string(CT_CONSTANT(opline->op1));
|
||||
zend_alloc_polymorphic_cache_slot(opline->op1.constant);
|
||||
}
|
||||
if (class_node.op_type == IS_CONST) {
|
||||
@@ -2625,7 +2625,6 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t
|
||||
} else {
|
||||
SET_NODE(opline->op2, &class_node);
|
||||
}
|
||||
opline->extended_value |= ZEND_FETCH_STATIC_MEMBER;
|
||||
|
||||
return opline;
|
||||
}
|
||||
@@ -2830,7 +2829,7 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
|
||||
zend_ensure_writable_variable(target_ast);
|
||||
|
||||
zend_compile_var(&target_node, target_ast, BP_VAR_W);
|
||||
zend_compile_var(&source_node, source_ast, BP_VAR_REF);
|
||||
zend_compile_var(&source_node, source_ast, BP_VAR_W);
|
||||
|
||||
if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
|
||||
@@ -2903,7 +2902,6 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
|
||||
|
||||
uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
|
||||
{
|
||||
/* TODO.AST &var error */
|
||||
zend_ast_list *args = zend_ast_get_list(ast);
|
||||
uint32_t i;
|
||||
zend_bool uses_arg_unpack = 0;
|
||||
@@ -3361,7 +3359,9 @@ static int zend_compile_assert(znode *result, zend_ast_list *args, zend_string *
|
||||
|
||||
zend_compile_call_common(result, (zend_ast*)args, fbc);
|
||||
|
||||
CG(active_op_array)->opcodes[check_op_number].op2.opline_num = get_next_op_number(CG(active_op_array));
|
||||
opline = &CG(active_op_array)->opcodes[check_op_number];
|
||||
opline->op2.opline_num = get_next_op_number(CG(active_op_array));
|
||||
SET_NODE(opline->result, result);
|
||||
} else {
|
||||
if (!fbc) {
|
||||
zend_string_release(name);
|
||||
@@ -3622,7 +3622,7 @@ void zend_compile_clone(znode *result, zend_ast *ast) /* {{{ */
|
||||
znode obj_node;
|
||||
zend_compile_expr(&obj_node, obj_ast);
|
||||
|
||||
zend_emit_op(result, ZEND_CLONE, &obj_node, NULL);
|
||||
zend_emit_op_tmp(result, ZEND_CLONE, &obj_node, NULL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -3642,12 +3642,16 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
|
||||
zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
|
||||
zend_alloc_cache_slot(opline->op2.constant);
|
||||
} else {
|
||||
zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
|
||||
/* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
|
||||
* to not free the name_node operand, so it can be reused in the following
|
||||
* ASSIGN_REF, which then frees it. */
|
||||
zend_op *opline = zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
|
||||
opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
|
||||
|
||||
// TODO.AST Avoid double fetch
|
||||
//opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
|
||||
|
||||
zend_emit_assign_ref_znode(var_ast, &result);
|
||||
zend_emit_assign_ref_znode(
|
||||
zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
|
||||
&result
|
||||
);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -3802,13 +3806,11 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
|
||||
expr_node.op_type = IS_CONST;
|
||||
ZVAL_NULL(&expr_node.u.constant);
|
||||
} else if (by_ref && zend_is_variable(expr_ast) && !zend_is_call(expr_ast)) {
|
||||
zend_compile_var(&expr_node, expr_ast, BP_VAR_REF);
|
||||
zend_compile_var(&expr_node, expr_ast, BP_VAR_W);
|
||||
} else {
|
||||
zend_compile_expr(&expr_node, expr_ast);
|
||||
}
|
||||
|
||||
zend_handle_loops_and_finally();
|
||||
|
||||
if (CG(context).in_finally) {
|
||||
opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL);
|
||||
opline->op1_type = IS_TMP_VAR;
|
||||
@@ -3819,6 +3821,9 @@ void zend_compile_return(zend_ast *ast) /* {{{ */
|
||||
if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
|
||||
zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
|
||||
}
|
||||
|
||||
zend_handle_loops_and_finally();
|
||||
|
||||
opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
|
||||
&expr_node, NULL);
|
||||
|
||||
@@ -5228,10 +5233,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
|
||||
zend_const_expr_to_zval(&value_zv, value_ast);
|
||||
|
||||
name = zend_new_interned_string_safe(name);
|
||||
if (zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment) != SUCCESS) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s",
|
||||
ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -5488,7 +5490,6 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
|
||||
opline = get_next_op(CG(active_op_array));
|
||||
zend_make_var_result(&declare_node, opline);
|
||||
|
||||
// TODO.AST drop this
|
||||
GET_NODE(&FC(implementing_class), opline->result);
|
||||
|
||||
opline->op2_type = IS_CONST;
|
||||
@@ -6503,7 +6504,7 @@ void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
|
||||
|
||||
if (value_ast) {
|
||||
if (returns_by_ref && zend_is_variable(value_ast) && !zend_is_call(value_ast)) {
|
||||
zend_compile_var(&value_node, value_ast, BP_VAR_REF);
|
||||
zend_compile_var(&value_node, value_ast, BP_VAR_W);
|
||||
} else {
|
||||
zend_compile_expr(&value_node, value_ast);
|
||||
}
|
||||
@@ -6544,7 +6545,8 @@ void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
|
||||
"instanceof expects an object instance, constant given");
|
||||
}
|
||||
|
||||
zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
||||
zend_compile_class_ref_ex(&class_node, class_ast,
|
||||
ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
|
||||
opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
|
||||
|
||||
@@ -7468,9 +7470,7 @@ void zend_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
|
||||
*result = *zend_ast_get_znode(ast);
|
||||
return;
|
||||
default:
|
||||
if (type == BP_VAR_W || type == BP_VAR_REF
|
||||
|| type == BP_VAR_RW || type == BP_VAR_UNSET
|
||||
) {
|
||||
if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Cannot use temporary expression in write context");
|
||||
}
|
||||
|
||||
@@ -860,7 +860,6 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
|
||||
#define BP_VAR_IS 3
|
||||
#define BP_VAR_FUNC_ARG 4
|
||||
#define BP_VAR_UNSET 5
|
||||
#define BP_VAR_REF 6 /* right-hand side of by-ref assignment */
|
||||
|
||||
/* Bottom 3 bits are the type, top bits are arg num for BP_VAR_FUNC_ARG */
|
||||
#define BP_VAR_SHIFT 3
|
||||
@@ -892,7 +891,6 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
|
||||
#define ZEND_FETCH_GLOBAL 0x00000000
|
||||
#define ZEND_FETCH_LOCAL 0x10000000
|
||||
#define ZEND_FETCH_STATIC 0x20000000
|
||||
#define ZEND_FETCH_STATIC_MEMBER 0x30000000
|
||||
#define ZEND_FETCH_GLOBAL_LOCK 0x40000000
|
||||
#define ZEND_FETCH_LEXICAL 0x50000000
|
||||
|
||||
|
||||
+8
-2
@@ -150,7 +150,7 @@ static const zend_internal_function zend_pass_function = {
|
||||
static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
|
||||
zend_vm_stack page = (zend_vm_stack)emalloc(size);
|
||||
|
||||
page->top = ZEND_VM_STACK_ELEMETS(page);
|
||||
page->top = ZEND_VM_STACK_ELEMENTS(page);
|
||||
page->end = (zval*)((char*)page + size);
|
||||
page->prev = prev;
|
||||
return page;
|
||||
@@ -1980,6 +1980,12 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
|
||||
return;
|
||||
}
|
||||
} else if (EXPECTED(zobj->properties != NULL)) {
|
||||
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
|
||||
if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
|
||||
GC_REFCOUNT(zobj->properties)--;
|
||||
}
|
||||
zobj->properties = zend_array_dup(zobj->properties);
|
||||
}
|
||||
retval = zend_hash_find(zobj->properties, Z_STR_P(prop_ptr));
|
||||
if (EXPECTED(retval)) {
|
||||
ZVAL_INDIRECT(result, retval);
|
||||
@@ -2413,7 +2419,7 @@ static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call,
|
||||
EG(vm_stack)->prev->top = (zval*)call;
|
||||
|
||||
/* delete previous stack segment if it becames empty */
|
||||
if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) {
|
||||
if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMENTS(EG(vm_stack)->prev))) {
|
||||
zend_vm_stack r = EG(vm_stack)->prev;
|
||||
|
||||
EG(vm_stack)->prev = r->prev;
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ struct _zend_vm_stack {
|
||||
#define ZEND_VM_STACK_HEADER_SLOTS \
|
||||
((ZEND_MM_ALIGNED_SIZE(sizeof(struct _zend_vm_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval)))
|
||||
|
||||
#define ZEND_VM_STACK_ELEMETS(stack) \
|
||||
#define ZEND_VM_STACK_ELEMENTS(stack) \
|
||||
(((zval*)(stack)) + ZEND_VM_STACK_HEADER_SLOTS)
|
||||
|
||||
/*
|
||||
|
||||
@@ -218,7 +218,7 @@ static void zend_throw_or_error(int fetch_type, zend_class_entry *exception_ce,
|
||||
zend_vspprintf(&message, 0, format, va);
|
||||
|
||||
if (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) {
|
||||
zend_throw_error(exception_ce, message);
|
||||
zend_throw_error(exception_ce, "%s", message);
|
||||
} else {
|
||||
zend_error(E_ERROR, "%s", message);
|
||||
}
|
||||
|
||||
@@ -109,6 +109,14 @@ int zend_load_extension(const char *path)
|
||||
/* See http://support.microsoft.com/kb/190351 */
|
||||
#ifdef ZEND_WIN32
|
||||
fflush(stderr);
|
||||
#endif
|
||||
DL_UNLOAD(handle);
|
||||
return FAILURE;
|
||||
} else if (zend_get_extension(new_extension->name)) {
|
||||
fprintf(stderr, "Cannot load %s - extension already loaded\n", new_extension->name);
|
||||
/* See http://support.microsoft.com/kb/190351 */
|
||||
#ifdef PHP_WIN32
|
||||
fflush(stderr);
|
||||
#endif
|
||||
DL_UNLOAD(handle);
|
||||
return FAILURE;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "zend_highlight.h"
|
||||
#include "zend_ptr_stack.h"
|
||||
#include "zend_globals.h"
|
||||
#include "zend_exceptions.h"
|
||||
|
||||
ZEND_API void zend_html_putc(char c)
|
||||
{
|
||||
@@ -168,6 +169,9 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
}
|
||||
zend_printf("</span>\n");
|
||||
zend_printf("</code>");
|
||||
|
||||
/* Discard parse errors thrown during tokenization */
|
||||
zend_clear_exception();
|
||||
}
|
||||
|
||||
ZEND_API void zend_strip(void)
|
||||
|
||||
@@ -687,7 +687,13 @@ ZEND_API int pass_two(zend_op_array *op_array)
|
||||
case ZEND_NEW:
|
||||
case ZEND_FE_RESET_R:
|
||||
case ZEND_FE_RESET_RW:
|
||||
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
|
||||
break;
|
||||
case ZEND_ASSERT_CHECK:
|
||||
/* If result of assert is unused, result of check is unused as well */
|
||||
if (op_array->opcodes[opline->op2.opline_num - 1].result_type & EXT_TYPE_UNUSED) {
|
||||
opline->result_type |= EXT_TYPE_UNUSED;
|
||||
}
|
||||
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
|
||||
break;
|
||||
case ZEND_FE_FETCH_R:
|
||||
|
||||
+1
-5
@@ -397,7 +397,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
|
||||
#define IS_TYPE_REFCOUNTED (1<<2)
|
||||
#define IS_TYPE_COLLECTABLE (1<<3)
|
||||
#define IS_TYPE_COPYABLE (1<<4)
|
||||
#define IS_TYPE_SYMBOLTABLE (1<<5)
|
||||
|
||||
/* extended types */
|
||||
#define IS_INTERNED_STRING_EX IS_STRING
|
||||
@@ -474,9 +473,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
|
||||
#define Z_IMMUTABLE(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_IMMUTABLE) != 0)
|
||||
#define Z_IMMUTABLE_P(zval_p) Z_IMMUTABLE(*(zval_p))
|
||||
|
||||
#define Z_SYMBOLTABLE(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_SYMBOLTABLE) != 0)
|
||||
#define Z_SYMBOLTABLE_P(zval_p) Z_SYMBOLTABLE(*(zval_p))
|
||||
|
||||
/* the following Z_OPT_* macros make better code when Z_TYPE_INFO accessed before */
|
||||
#define Z_OPT_TYPE(zval) (Z_TYPE_INFO(zval) & Z_TYPE_MASK)
|
||||
#define Z_OPT_TYPE_P(zval_p) Z_OPT_TYPE(*(zval_p))
|
||||
@@ -813,7 +809,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
|
||||
#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z))
|
||||
|
||||
static zend_always_inline uint32_t zval_refcount_p(zval* pz) {
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_IMMUTABLE_P(pz) || Z_SYMBOLTABLE_P(pz));
|
||||
ZEND_ASSERT(Z_REFCOUNTED_P(pz) || Z_IMMUTABLE_P(pz));
|
||||
return GC_REFCOUNT(Z_COUNTED_P(pz));
|
||||
}
|
||||
|
||||
|
||||
+157
-148
@@ -685,7 +685,7 @@ ZEND_VM_HANDLER(13, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -699,7 +699,7 @@ ZEND_VM_HANDLER(13, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, binary_op_type binary_op)
|
||||
ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, binary_op_type binary_op)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2, free_op_data1;
|
||||
@@ -764,7 +764,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
|
||||
ZEND_VM_NEXT_OPCODE_EX(1, 2);
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, binary_op_type binary_op)
|
||||
ZEND_VM_HELPER(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, binary_op_type binary_op)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2, free_op_data1;
|
||||
@@ -835,7 +835,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|
|
||||
ZEND_VM_NEXT_OPCODE_EX(1, 2);
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, binary_op_type binary_op)
|
||||
ZEND_VM_HELPER(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, binary_op_type binary_op)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -872,247 +872,247 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, binary_
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(23, ZEND_ASSIGN_ADD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(23, ZEND_ASSIGN_ADD, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, add_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, add_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, add_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, add_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, add_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, add_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, add_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, add_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(24, ZEND_ASSIGN_SUB, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(24, ZEND_ASSIGN_SUB, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, sub_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, sub_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, sub_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, sub_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, sub_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, sub_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, sub_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, sub_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(25, ZEND_ASSIGN_MUL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(25, ZEND_ASSIGN_MUL, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, mul_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, mul_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mul_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, mul_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, mul_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, mul_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mul_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, mul_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(26, ZEND_ASSIGN_DIV, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(26, ZEND_ASSIGN_DIV, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, div_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, div_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, div_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, div_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, div_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, div_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, div_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, div_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(27, ZEND_ASSIGN_MOD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(27, ZEND_ASSIGN_MOD, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, mod_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, mod_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mod_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, mod_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, mod_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, mod_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mod_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, mod_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(28, ZEND_ASSIGN_SL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(28, ZEND_ASSIGN_SL, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, shift_left_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, shift_left_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_left_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, shift_left_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, shift_left_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, shift_left_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_left_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, shift_left_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(29, ZEND_ASSIGN_SR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(29, ZEND_ASSIGN_SR, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, shift_right_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, shift_right_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_right_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, shift_right_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, shift_right_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, shift_right_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_right_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, shift_right_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(30, ZEND_ASSIGN_CONCAT, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(30, ZEND_ASSIGN_CONCAT, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, concat_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, concat_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, concat_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, concat_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, concat_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, concat_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, concat_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, concat_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(31, ZEND_ASSIGN_BW_OR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(31, ZEND_ASSIGN_BW_OR, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, bitwise_or_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, bitwise_or_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_or_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, bitwise_or_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, bitwise_or_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, bitwise_or_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_or_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, bitwise_or_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(32, ZEND_ASSIGN_BW_AND, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(32, ZEND_ASSIGN_BW_AND, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, bitwise_and_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, bitwise_and_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_and_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, bitwise_and_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, bitwise_and_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, bitwise_and_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_and_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, bitwise_and_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, bitwise_xor_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, bitwise_xor_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_xor_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, bitwise_xor_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, bitwise_xor_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, bitwise_xor_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_xor_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, bitwise_xor_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(167, ZEND_ASSIGN_POW, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
|
||||
ZEND_VM_HANDLER(167, ZEND_ASSIGN_POW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ)
|
||||
{
|
||||
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
|
||||
USE_OPLINE
|
||||
|
||||
# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
|
||||
if (EXPECTED(opline->extended_value == 0)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, pow_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, pow_function);
|
||||
}
|
||||
# endif
|
||||
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, pow_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, pow_function);
|
||||
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, pow_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, pow_function);
|
||||
}
|
||||
#else
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, pow_function);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, pow_function);
|
||||
#endif
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
|
||||
ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -1183,17 +1183,17 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, inc, 1);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_pre_incdec_property_helper, inc, 1);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, inc, 0);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_pre_incdec_property_helper, inc, 0);
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
|
||||
ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -1260,14 +1260,14 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, inc, 1);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_post_incdec_property_helper, inc, 1);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, inc, 0);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_post_incdec_property_helper, inc, 0);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
|
||||
@@ -1470,7 +1470,7 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
|
||||
ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -1566,41 +1566,41 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int ty
|
||||
|
||||
ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_R);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_W);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_RW);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_RW);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ARG_NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_W);
|
||||
} else {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_R);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_IS);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_IS);
|
||||
}
|
||||
|
||||
ZEND_VM_HELPER_EX(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
|
||||
ZEND_VM_HELPER(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -1652,6 +1652,10 @@ ZEND_VM_HELPER_EX(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (OP1_TYPE != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -1672,6 +1676,9 @@ ZEND_VM_HELPER_EX(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (OP1_TYPE != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -1698,40 +1705,40 @@ ZEND_VM_C_LABEL(fetch_static_prop_return):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_R);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_R);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_W);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_RW);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_RW);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_W);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W);
|
||||
} else {
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_R);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_R);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_UNSET);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_UNSET);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
|
||||
{
|
||||
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_IS);
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_IS);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
@@ -1748,7 +1755,7 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|CV)
|
||||
ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -1770,7 +1777,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|CV)
|
||||
ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -1806,7 +1813,7 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|CV)
|
||||
ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *container;
|
||||
@@ -1871,7 +1878,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -1944,7 +1951,7 @@ ZEND_VM_C_LABEL(fetch_obj_r_no_object):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -1975,7 +1982,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -2005,7 +2012,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -2078,7 +2085,7 @@ ZEND_VM_C_LABEL(fetch_obj_is_no_object):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *container;
|
||||
@@ -2120,7 +2127,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPV
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -2195,7 +2202,7 @@ ZEND_VM_C_LABEL(try_fetch_list):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -2225,7 +2232,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_EX(1, 2);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|CV)
|
||||
ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -2359,7 +2366,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
|
||||
ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -2461,7 +2468,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
const zend_op *old_opline = EX(opline);
|
||||
zend_throw_exception_internal(NULL);
|
||||
if (RETURN_VALUE_USED(old_opline)) {
|
||||
if (old_opline->opcode != ZEND_HANDLE_EXCEPTION && RETURN_VALUE_USED(old_opline)) {
|
||||
zval_ptr_dtor(EX_VAR(old_opline->result.var));
|
||||
}
|
||||
HANDLE_EXCEPTION_LEAVE();
|
||||
@@ -2967,7 +2974,7 @@ ZEND_VM_C_LABEL(try_class_name):
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV, NUM)
|
||||
ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *function_name;
|
||||
@@ -3088,7 +3095,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CONST|VAR, CONST|TMPVAR|UNUSED|CV, NUM)
|
||||
ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, CONST|TMPVAR|UNUSED|CONSTRUCTOR|CV, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *function_name;
|
||||
@@ -3117,6 +3124,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CONST|VAR, CONST|TMPVA
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
FREE_UNFETCHED_OP2();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -4064,7 +4072,7 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
|
||||
ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
@@ -4348,7 +4356,7 @@ ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, NUM)
|
||||
ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, NUM, SEND)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -4897,7 +4905,7 @@ ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -4977,7 +4985,7 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CONST|VAR, JMP_ADDR, NUM)
|
||||
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, JMP_ADDR, NUM)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval object_zval;
|
||||
@@ -5035,7 +5043,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CONST|VAR, JMP_ADDR, NUM)
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
|
||||
ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -5074,19 +5082,15 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
|
||||
} while (0);
|
||||
|
||||
ce = Z_OBJCE_P(obj);
|
||||
clone = ce ? ce->clone : NULL;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
clone = ce->clone;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
if (UNEXPECTED(clone_call == NULL)) {
|
||||
if (ce) {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
} else {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object");
|
||||
}
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
if (ce && clone) {
|
||||
if (clone) {
|
||||
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
/* Ensure that if we're calling a private function, we're allowed to do so.
|
||||
*/
|
||||
@@ -5106,12 +5110,11 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(EG(exception) == NULL)) {
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
|
||||
FREE_OP1();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
@@ -5160,7 +5163,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED, CONST, CONST_FETCH)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CONST)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zend_class_constant *c;
|
||||
@@ -5242,7 +5245,7 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|CV, NUM)
|
||||
ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, REF)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -5341,7 +5344,7 @@ ZEND_VM_C_LABEL(num_index):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, ARRAY_INIT)
|
||||
ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
|
||||
{
|
||||
zval *array;
|
||||
uint32_t size;
|
||||
@@ -5603,7 +5606,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ISSET)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval tmp, *varname;
|
||||
@@ -5658,7 +5661,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval tmp, *varname;
|
||||
@@ -5698,6 +5701,10 @@ ZEND_VM_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -5712,7 +5719,7 @@ ZEND_VM_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -5811,7 +5818,7 @@ ZEND_VM_C_LABEL(num_index_dim):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -6552,7 +6559,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR, ISSET)
|
||||
ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, ISSET)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *value;
|
||||
@@ -6591,6 +6598,10 @@ ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CON
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -6632,7 +6643,7 @@ ZEND_VM_C_LABEL(is_static_prop_return):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV, ISSET)
|
||||
ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, ISSET)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -6769,7 +6780,7 @@ ZEND_VM_C_LABEL(isset_dim_obj_exit):
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV, ISSET)
|
||||
ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, ISSET)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1, free_op2;
|
||||
@@ -7133,7 +7144,7 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CONST|VAR)
|
||||
ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
@@ -7162,6 +7173,7 @@ ZEND_VM_C_LABEL(try_instanceof):
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
FREE_OP1();
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -7452,7 +7464,7 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSED)
|
||||
ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSED, SRC)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
@@ -7908,7 +7920,7 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY, TYPE)
|
||||
if (OP1_TYPE != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(value);
|
||||
|
||||
if (UNEXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
if (EXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
EXPECTED(memcmp(ZSTR_VAL(ce->name), "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) {
|
||||
result = 1;
|
||||
}
|
||||
@@ -7941,7 +7953,6 @@ ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY)
|
||||
result = 1;
|
||||
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op1), 0)) == NULL) {
|
||||
result = 0;
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), c);
|
||||
result = 1;
|
||||
@@ -7957,10 +7968,8 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
|
||||
|
||||
if (EG(assertions) <= 0) {
|
||||
zend_op *target = OP_JMP_ADDR(opline, opline->op2);
|
||||
zend_op *result = target - 1;
|
||||
SKIP_EXT_OPLINE(result);
|
||||
if (RETURN_VALUE_USED(result)) {
|
||||
ZVAL_TRUE(EX_VAR(result->result.var));
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
}
|
||||
ZEND_VM_JMP(target);
|
||||
} else {
|
||||
|
||||
+195
-68
@@ -501,7 +501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
const zend_op *old_opline = EX(opline);
|
||||
zend_throw_exception_internal(NULL);
|
||||
if (RETURN_VALUE_USED(old_opline)) {
|
||||
if (old_opline->opcode != ZEND_HANDLE_EXCEPTION && RETURN_VALUE_USED(old_opline)) {
|
||||
zval_ptr_dtor(EX_VAR(old_opline->result.var));
|
||||
}
|
||||
HANDLE_EXCEPTION_LEAVE();
|
||||
@@ -1675,10 +1675,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSERT_CHECK_SPEC_HANDLER(ZEND
|
||||
|
||||
if (EG(assertions) <= 0) {
|
||||
zend_op *target = OP_JMP_ADDR(opline, opline->op2);
|
||||
zend_op *result = target - 1;
|
||||
SKIP_EXT_OPLINE(result);
|
||||
if (RETURN_VALUE_USED(result)) {
|
||||
ZVAL_TRUE(EX_VAR(result->result.var));
|
||||
if (RETURN_VALUE_USED(opline)) {
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
}
|
||||
ZEND_VM_JMP(target);
|
||||
} else {
|
||||
@@ -2843,7 +2841,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZE
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -3330,7 +3328,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_O
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -3441,19 +3439,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_
|
||||
} while (0);
|
||||
|
||||
ce = Z_OBJCE_P(obj);
|
||||
clone = ce ? ce->clone : NULL;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
clone = ce->clone;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
if (UNEXPECTED(clone_call == NULL)) {
|
||||
if (ce) {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
} else {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object");
|
||||
}
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
if (ce && clone) {
|
||||
if (clone) {
|
||||
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
/* Ensure that if we're calling a private function, we're allowed to do so.
|
||||
*/
|
||||
@@ -3473,11 +3467,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(EG(exception) == NULL)) {
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -4259,7 +4251,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(
|
||||
if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(value);
|
||||
|
||||
if (UNEXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
if (EXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
EXPECTED(memcmp(ZSTR_VAL(ce->name), "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) {
|
||||
result = 1;
|
||||
}
|
||||
@@ -4292,7 +4284,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEN
|
||||
result = 1;
|
||||
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op1), 0)) == NULL) {
|
||||
result = 0;
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), c);
|
||||
result = 1;
|
||||
@@ -4991,6 +4982,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -5011,6 +5006,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (IS_CONST != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -5586,6 +5584,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -6073,6 +6072,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CONST_C
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -6126,6 +6129,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -6791,6 +6798,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -6811,6 +6822,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (IS_CONST != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -6911,6 +6925,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CONST_V
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -6964,6 +6982,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -7327,6 +7349,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -7347,6 +7373,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (IS_CONST != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -7478,6 +7507,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -7869,6 +7899,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CONST_U
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -7979,6 +8013,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -9290,6 +9328,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -11104,6 +11143,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -12488,7 +12528,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZE
|
||||
if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(value);
|
||||
|
||||
if (UNEXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
if (EXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
EXPECTED(memcmp(ZSTR_VAL(ce->name), "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) {
|
||||
result = 1;
|
||||
}
|
||||
@@ -16301,7 +16341,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZE
|
||||
if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(value);
|
||||
|
||||
if (UNEXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
if (EXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
EXPECTED(memcmp(ZSTR_VAL(ce->name), "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) {
|
||||
result = 1;
|
||||
}
|
||||
@@ -17435,6 +17475,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -19044,6 +19085,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -20669,6 +20711,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -22245,6 +22288,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -22726,19 +22770,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND
|
||||
} while (0);
|
||||
|
||||
ce = Z_OBJCE_P(obj);
|
||||
clone = ce ? ce->clone : NULL;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
clone = ce->clone;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
if (UNEXPECTED(clone_call == NULL)) {
|
||||
if (ce) {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
} else {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object");
|
||||
}
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
if (ce && clone) {
|
||||
if (clone) {
|
||||
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
/* Ensure that if we're calling a private function, we're allowed to do so.
|
||||
*/
|
||||
@@ -22758,11 +22798,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(EG(exception) == NULL)) {
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -23817,6 +23855,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -25171,6 +25210,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -26529,6 +26569,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -28162,6 +28203,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
ce = zend_fetch_class(NULL, opline->op1.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -28654,7 +28696,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -29434,7 +29476,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCO
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -29487,19 +29529,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC
|
||||
} while (0);
|
||||
|
||||
ce = Z_OBJCE_P(obj);
|
||||
clone = ce ? ce->clone : NULL;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
clone = ce->clone;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
if (UNEXPECTED(clone_call == NULL)) {
|
||||
if (ce) {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
} else {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object");
|
||||
}
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
if (ce && clone) {
|
||||
if (clone) {
|
||||
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
/* Ensure that if we're calling a private function, we're allowed to do so.
|
||||
*/
|
||||
@@ -29519,11 +29557,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(EG(exception) == NULL)) {
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -30305,7 +30341,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEN
|
||||
if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
||||
zend_class_entry *ce = Z_OBJCE_P(value);
|
||||
|
||||
if (UNEXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
if (EXPECTED(ZSTR_LEN(ce->name) != sizeof("__PHP_Incomplete_Class") - 1) ||
|
||||
EXPECTED(memcmp(ZSTR_VAL(ce->name), "__PHP_Incomplete_Class", sizeof("__PHP_Incomplete_Class") - 1) != 0)) {
|
||||
result = 1;
|
||||
}
|
||||
@@ -31584,6 +31620,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -31604,6 +31644,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (IS_CV != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -32709,6 +32752,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_CONS
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -32903,6 +32950,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -33155,6 +33206,7 @@ try_instanceof:
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -33701,6 +33753,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -33721,6 +33777,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (IS_CV != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -33908,6 +33967,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_VAR_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -33961,6 +34024,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -34030,6 +34097,7 @@ try_instanceof:
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -34684,6 +34752,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -34704,6 +34776,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if (IS_CV != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -35236,6 +35311,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_UNUS
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -35346,6 +35425,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -35415,6 +35498,7 @@ try_instanceof:
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -40723,7 +40807,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -40990,7 +41074,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_
|
||||
ZVAL_TRUE(EX_VAR(opline->result.var));
|
||||
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
|
||||
ZVAL_FALSE(EX_VAR(opline->result.var));
|
||||
if (UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
|
||||
SAVE_OPLINE();
|
||||
GET_OP1_UNDEF_CV(val, BP_VAR_R);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
@@ -41043,19 +41127,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND
|
||||
} while (0);
|
||||
|
||||
ce = Z_OBJCE_P(obj);
|
||||
clone = ce ? ce->clone : NULL;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
clone = ce->clone;
|
||||
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
||||
if (UNEXPECTED(clone_call == NULL)) {
|
||||
if (ce) {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
} else {
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object");
|
||||
}
|
||||
zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
if (ce && clone) {
|
||||
if (clone) {
|
||||
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
||||
/* Ensure that if we're calling a private function, we're allowed to do so.
|
||||
*/
|
||||
@@ -41075,12 +41155,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED(EG(exception) == NULL)) {
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
||||
}
|
||||
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
@@ -41939,6 +42018,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -41959,6 +42042,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -42458,6 +42544,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -42511,6 +42601,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -42764,6 +42858,7 @@ try_instanceof:
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -42837,6 +42932,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -42857,6 +42956,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -42959,6 +43061,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -43012,6 +43118,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -43082,6 +43192,7 @@ try_instanceof:
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -43285,6 +43396,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -43305,6 +43420,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_
|
||||
}
|
||||
retval = zend_std_get_static_property(ce, name, 0);
|
||||
if (UNEXPECTED(EG(exception))) {
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
||||
zend_string_release(name);
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
@@ -43462,6 +43580,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -43573,6 +43695,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
||||
zend_string_release(Z_STR(tmp));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
@@ -43643,6 +43769,7 @@ try_instanceof:
|
||||
ce = zend_fetch_class(NULL, opline->op2.num);
|
||||
if (UNEXPECTED(ce == NULL)) {
|
||||
ZEND_ASSERT(EG(exception));
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
} else {
|
||||
|
||||
+114
-67
@@ -58,32 +58,47 @@ $vm_op_flags = array(
|
||||
"ZEND_VM_OP1_SPEC" => 1<<0,
|
||||
"ZEND_VM_OP1_CONST" => 1<<1,
|
||||
"ZEND_VM_OP1_TMPVAR" => 1<<2,
|
||||
"ZEND_VM_OP1_NUM" => 1<<3,
|
||||
"ZEND_VM_OP1_JMP_ADDR" => 1<<4,
|
||||
"ZEND_VM_OP1_TRY_CATCH" => 1<<5,
|
||||
"ZEND_VM_OP1_LIVE_RANGE" => 1<<6,
|
||||
"ZEND_VM_OP1_MASK" => 0xf0,
|
||||
"ZEND_VM_OP1_NUM" => 0x10,
|
||||
"ZEND_VM_OP1_JMP_ADDR" => 0x20,
|
||||
"ZEND_VM_OP1_TRY_CATCH" => 0x30,
|
||||
"ZEND_VM_OP1_LIVE_RANGE" => 0x40,
|
||||
"ZEND_VM_OP1_THIS" => 0x50,
|
||||
"ZEND_VM_OP1_NEXT" => 0x60,
|
||||
"ZEND_VM_OP1_CLASS_FETCH" => 0x70,
|
||||
"ZEND_VM_OP1_CONSTRUCTOR" => 0x80,
|
||||
|
||||
"ZEND_VM_OP2_SPEC" => 1<<8,
|
||||
"ZEND_VM_OP2_CONST" => 1<<9,
|
||||
"ZEND_VM_OP2_TMPVAR" => 1<<10,
|
||||
"ZEND_VM_OP2_NUM" => 1<<11,
|
||||
"ZEND_VM_OP2_JMP_ADDR" => 1<<12,
|
||||
"ZEND_VM_OP2_TRY_CATCH" => 1<<13,
|
||||
"ZEND_VM_OP2_LIVE_RANGE" => 1<<14,
|
||||
"ZEND_VM_OP2_MASK" => 0xf000,
|
||||
"ZEND_VM_OP2_NUM" => 0x1000,
|
||||
"ZEND_VM_OP2_JMP_ADDR" => 0x2000,
|
||||
"ZEND_VM_OP2_TRY_CATCH" => 0x3000,
|
||||
"ZEND_VM_OP2_LIVE_RANGE" => 0x4000,
|
||||
"ZEND_VM_OP2_THIS" => 0x5000,
|
||||
"ZEND_VM_OP2_NEXT" => 0x6000,
|
||||
"ZEND_VM_OP2_CLASS_FETCH" => 0x7000,
|
||||
"ZEND_VM_OP2_CONSTRUCTOR" => 0x8000,
|
||||
|
||||
"ZEND_VM_EXT_NUM" => 1<<16,
|
||||
"ZEND_VM_EXT_VAR" => 1<<17,
|
||||
"ZEND_VM_EXT_JMP_ADDR" => 1<<18,
|
||||
"ZEND_VM_EXT_DIM_OBJ" => 1<<19,
|
||||
"ZEND_VM_EXT_CLASS_FETCH" => 1<<20,
|
||||
"ZEND_VM_EXT_CONST_FETCH" => 1<<21,
|
||||
"ZEND_VM_EXT_VAR_FETCH" => 1<<22,
|
||||
"ZEND_VM_EXT_ARRAY_INIT" => 1<<23,
|
||||
"ZEND_VM_EXT_TYPE" => 1<<24,
|
||||
"ZEND_VM_EXT_EVAL" => 1<<25,
|
||||
"ZEND_VM_EXT_FAST_CALL" => 1<<26,
|
||||
"ZEND_VM_EXT_FAST_RET" => 1<<27,
|
||||
"ZEND_VM_EXT_ISSET" => 1<<28,
|
||||
"ZEND_VM_EXT_VAR_FETCH" => 1<<16,
|
||||
"ZEND_VM_EXT_ISSET" => 1<<17,
|
||||
"ZEND_VM_EXT_ARG_NUM" => 1<<18,
|
||||
"ZEND_VM_EXT_ARRAY_INIT" => 1<<19,
|
||||
"ZEND_VM_EXT_REF" => 1<<20,
|
||||
"ZEND_VM_EXT_MASK" => 0xff000000,
|
||||
"ZEND_VM_EXT_NUM" => 0x01000000,
|
||||
"ZEND_VM_EXT_VAR" => 0x02000000,
|
||||
"ZEND_VM_EXT_JMP_ADDR" => 0x03000000,
|
||||
"ZEND_VM_EXT_DIM_OBJ" => 0x04000000,
|
||||
"ZEND_VM_EXT_CLASS_FETCH" => 0x05000000,
|
||||
"ZEND_VM_EXT_CONST_FETCH" => 0x06000000,
|
||||
"ZEND_VM_EXT_TYPE" => 0x07000000,
|
||||
"ZEND_VM_EXT_EVAL" => 0x08000000,
|
||||
"ZEND_VM_EXT_FAST_CALL" => 0x09000000,
|
||||
"ZEND_VM_EXT_FAST_RET" => 0x0a000000,
|
||||
"ZEND_VM_EXT_SRC" => 0x0b000000,
|
||||
"ZEND_VM_EXT_SEND" => 0x0c000000,
|
||||
);
|
||||
|
||||
foreach ($vm_op_flags as $name => $val) {
|
||||
@@ -102,6 +117,10 @@ $vm_op_decode = array(
|
||||
"JMP_ADDR" => ZEND_VM_OP1_JMP_ADDR,
|
||||
"TRY_CATCH" => ZEND_VM_OP1_TRY_CATCH,
|
||||
"LIVE_RANGE" => ZEND_VM_OP1_LIVE_RANGE,
|
||||
"THIS" => ZEND_VM_OP1_THIS,
|
||||
"NEXT" => ZEND_VM_OP1_NEXT,
|
||||
"CLASS_FETCH" => ZEND_VM_OP1_CLASS_FETCH,
|
||||
"CONSTRUCTOR" => ZEND_VM_OP1_CONSTRUCTOR,
|
||||
);
|
||||
|
||||
$vm_ext_decode = array(
|
||||
@@ -118,6 +137,10 @@ $vm_ext_decode = array(
|
||||
"FAST_CALL" => ZEND_VM_EXT_FAST_CALL,
|
||||
"FAST_RET" => ZEND_VM_EXT_FAST_RET,
|
||||
"ISSET" => ZEND_VM_EXT_ISSET,
|
||||
"ARG_NUM" => ZEND_VM_EXT_ARG_NUM,
|
||||
"REF" => ZEND_VM_EXT_REF,
|
||||
"SRC" => ZEND_VM_EXT_SRC,
|
||||
"SEND" => ZEND_VM_EXT_SEND,
|
||||
);
|
||||
|
||||
$vm_kind_name = array(
|
||||
@@ -527,6 +550,25 @@ function helper_name($name, $spec, $op1, $op2) {
|
||||
return $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2];
|
||||
}
|
||||
|
||||
function opcode_name($name, $spec, $op1, $op2) {
|
||||
global $prefix, $opnames, $opcodes;
|
||||
|
||||
if (isset($opnames[$name])) {
|
||||
$opcode = $opcodes[$opnames[$name]];
|
||||
// If we haven't helper with specified spicialized operands then
|
||||
// using unspecialized helper
|
||||
if (!isset($opcode["op1"][$op1]) &&
|
||||
isset($opcode["op1"]["ANY"])) {
|
||||
$op1 = "ANY";
|
||||
}
|
||||
if (!isset($opcode["op2"][$op2]) &&
|
||||
isset($opcode["op2"]["ANY"])) {
|
||||
$op2 = "ANY";
|
||||
}
|
||||
}
|
||||
return $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2];
|
||||
}
|
||||
|
||||
// Generates code for opcode handler or helper
|
||||
function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
|
||||
global $op1_type, $op2_type, $op1_get_zval_ptr, $op2_get_zval_ptr,
|
||||
@@ -645,17 +687,20 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
|
||||
array(
|
||||
"/EXECUTE_DATA/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*[A-Za-z_]*\s*,\s*(.*)\s*\);/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
|
||||
),
|
||||
function($matches) use ($spec, $prefix, $op1, $op2) {
|
||||
if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
|
||||
return "execute_data";
|
||||
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
|
||||
return "ZEND_VM_TAIL_CALL(" . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
|
||||
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) {
|
||||
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2) . "(" . $matches[2]. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));";
|
||||
return "ZEND_VM_TAIL_CALL(" . opcode_name($matches[1], $spec, $op1, $op2) . "_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
|
||||
} else {
|
||||
// ZEND_VM_DISPATCH_TO_HELPER
|
||||
if (isset($matches[2])) {
|
||||
// extra args
|
||||
$args = substr(preg_replace("/,\s*[A-Za-z_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2);
|
||||
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2) . "(" . $args. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))";
|
||||
}
|
||||
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
|
||||
}
|
||||
},
|
||||
@@ -666,17 +711,20 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
|
||||
array(
|
||||
"/EXECUTE_DATA/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
|
||||
),
|
||||
function($matches) use ($spec, $prefix, $op1, $op2) {
|
||||
if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
|
||||
return "execute_data";
|
||||
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
|
||||
return "goto " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_LABEL";
|
||||
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) {
|
||||
return $matches[2] . " = " . $matches[3] . "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";";
|
||||
return "goto " . opcode_name($matches[1], $spec, $op1, $op2) . "_LABEL";
|
||||
} else {
|
||||
// ZEND_VM_DISPATCH_TO_HELPER
|
||||
if (isset($matches[2])) {
|
||||
// extra args
|
||||
$args = preg_replace("/,\s*([A-Za-z_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]);
|
||||
return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2);
|
||||
}
|
||||
return "goto " . helper_name($matches[1], $spec, $op1, $op2);
|
||||
}
|
||||
},
|
||||
@@ -687,17 +735,20 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
|
||||
array(
|
||||
"/EXECUTE_DATA/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m",
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*(,[^)]*)?\)/m",
|
||||
),
|
||||
function($matches) use ($spec, $prefix, $op1, $op2) {
|
||||
if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) {
|
||||
return "execute_data";
|
||||
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) {
|
||||
return "goto " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_HANDLER";
|
||||
} else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) {
|
||||
return $matches[2] . " = " . $matches[3] . "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";";
|
||||
return "goto " . opcode_name($matches[1], $spec, $op1, $op2) . "_HANDLER";
|
||||
} else {
|
||||
// ZEND_VM_DISPATCH_TO_HELPER
|
||||
if (isset($matches[2])) {
|
||||
// extra args
|
||||
$args = preg_replace("/,\s*([A-Za-z_]*)\s*,\s*([^,)\s]*)\s*/", "$1 = $2; ", $matches[2]);
|
||||
return $args . "goto " . helper_name($matches[1], $spec, $op1, $op2);
|
||||
}
|
||||
return "goto " . helper_name($matches[1], $spec, $op1, $op2);
|
||||
}
|
||||
},
|
||||
@@ -782,7 +833,7 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno)
|
||||
}
|
||||
|
||||
// Generates helper
|
||||
function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno) {
|
||||
function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, $inline) {
|
||||
global $definition_file, $prefix;
|
||||
|
||||
if (ZEND_VM_LINES) {
|
||||
@@ -792,12 +843,19 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno)
|
||||
// Generate helper's entry point according to selected threading model
|
||||
switch($kind) {
|
||||
case ZEND_VM_KIND_CALL:
|
||||
if ($inline) {
|
||||
$zend_always_inline = " zend_always_inline";
|
||||
$zend_fastcall = "";
|
||||
} else {
|
||||
$zend_always_inline = "";
|
||||
$zend_fastcall = " ZEND_FASTCALL";
|
||||
}
|
||||
if ($param == null) {
|
||||
// Helper without parameters
|
||||
out($f, "static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(ZEND_OPCODE_HANDLER_ARGS)\n");
|
||||
out($f, "static$zend_always_inline ZEND_OPCODE_HANDLER_RET$zend_fastcall ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(ZEND_OPCODE_HANDLER_ARGS)\n");
|
||||
} else {
|
||||
// Helper with parameter
|
||||
out($f, "static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(".$param." ZEND_OPCODE_HANDLER_ARGS_DC)\n");
|
||||
out($f, "static$zend_always_inline ZEND_OPCODE_HANDLER_RET$zend_fastcall ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."(".$param." ZEND_OPCODE_HANDLER_ARGS_DC)\n");
|
||||
}
|
||||
break;
|
||||
case ZEND_VM_KIND_SWITCH:
|
||||
@@ -1023,7 +1081,7 @@ function gen_executor_code($f, $spec, $kind, $prolog) {
|
||||
if (isset($helpers[$num]["op1"][$op1]) &&
|
||||
isset($helpers[$num]["op2"][$op2])) {
|
||||
// Generate helper code
|
||||
gen_helper($f, 1, $kind, $num, $op1, $op2, $helpers[$num]["param"], $helpers[$num]["code"], $lineno);
|
||||
gen_helper($f, 1, $kind, $num, $op1, $op2, $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"]);
|
||||
}
|
||||
} else {
|
||||
var_dump($dsc);
|
||||
@@ -1044,7 +1102,7 @@ function gen_executor_code($f, $spec, $kind, $prolog) {
|
||||
} else if (isset($dsc["helper"])) {
|
||||
$num = $dsc["helper"];
|
||||
// Generate helper code
|
||||
gen_helper($f, 0, $kind, $num, "ANY", "ANY", $helpers[$num]["param"], $helpers[$num]["code"], $lineno);
|
||||
gen_helper($f, 0, $kind, $num, "ANY", "ANY", $helpers[$num]["param"], $helpers[$num]["code"], $lineno, $helpers[$num]["inline"]);
|
||||
} else {
|
||||
var_dump($dsc);
|
||||
die("??? $kind:$num\n");
|
||||
@@ -1477,43 +1535,32 @@ function gen_vm($def, $skel) {
|
||||
$handler = $code;
|
||||
$helper = null;
|
||||
$list[$lineno] = array("handler"=>$handler);
|
||||
} else if (strpos($line,"ZEND_VM_HELPER(") === 0) {
|
||||
} else if (strpos($line,"ZEND_VM_HELPER(") === 0 || strpos($line,"ZEND_VM_INLINE_HELPER(") === 0) {
|
||||
// Parsing helper's definition
|
||||
if (preg_match(
|
||||
"/^ZEND_VM_HELPER\(\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*\)/",
|
||||
"/^ZEND_VM(_INLINE)?_HELPER\(\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(?:,\s*([^)]*))?\s*\)/",
|
||||
$line,
|
||||
$m) == 0) {
|
||||
die("ERROR ($def:$lineno): Invalid ZEND_VM_HELPER definition.\n");
|
||||
}
|
||||
$helper = $m[1];
|
||||
$op1 = parse_operand_spec($def, $lineno, $m[2], $flags1);
|
||||
$op2 = parse_operand_spec($def, $lineno, $m[3], $flags2);
|
||||
if (isset($helpers[$helper])) {
|
||||
die("ERROR ($def:$lineno): Helper with name '$helper' is already defined.\n");
|
||||
}
|
||||
$helpers[$helper] = array("op1"=>$op1,"op2"=>$op2,"param"=>null,"code"=>"");
|
||||
$handler = null;
|
||||
$list[$lineno] = array("helper"=>$helper);
|
||||
} else if (strpos($line,"ZEND_VM_HELPER_EX(") === 0) {
|
||||
// Parsing helper with parameter definition
|
||||
if (preg_match(
|
||||
"/^ZEND_VM_HELPER_EX\(\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*,\s*(.*)\s*\)/",
|
||||
$line,
|
||||
$m) == 0) {
|
||||
die("ERROR ($def:$lineno): Invalid ZEND_VM_HELPER definition.\n");
|
||||
}
|
||||
$helper = $m[1];
|
||||
$op1 = parse_operand_spec($def, $lineno, $m[2], $flags1);
|
||||
$op2 = parse_operand_spec($def, $lineno, $m[3], $flags2);
|
||||
$param = $m[4];
|
||||
$inline = !empty($m[1]);
|
||||
$helper = $m[2];
|
||||
$op1 = parse_operand_spec($def, $lineno, $m[3], $flags1);
|
||||
$op2 = parse_operand_spec($def, $lineno, $m[4], $flags2);
|
||||
$param = isset($m[5]) ? $m[5] : null;
|
||||
if (isset($helpers[$helper])) {
|
||||
die("ERROR ($def:$lineno): Helper with name '$helper' is already defined.\n");
|
||||
}
|
||||
|
||||
// Store parameter
|
||||
$params[$param] = 1;
|
||||
// Store parameters
|
||||
foreach (explode(",", $param) as $p) {
|
||||
$p = trim($p);
|
||||
if ($p !== "") {
|
||||
$params[$p] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$helpers[$helper] = array("op1"=>$op1,"op2"=>$op2,"param"=>$param,"code"=>"");
|
||||
$helpers[$helper] = array("op1"=>$op1,"op2"=>$op2,"param"=>$param,"code"=>"","inline"=>$inline);
|
||||
$handler = null;
|
||||
$list[$lineno] = array("helper"=>$helper);
|
||||
} else if (strpos($line,"ZEND_VM_EXPORT_HANDLER(") === 0) {
|
||||
|
||||
+106
-106
@@ -228,167 +228,167 @@ static uint32_t zend_vm_opcodes_flags[182] = {
|
||||
0x00000707,
|
||||
0x00000707,
|
||||
0x00000707,
|
||||
0x01000003,
|
||||
0x07000003,
|
||||
0x00000003,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x00080701,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x04006751,
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
0x00000001,
|
||||
0x00000301,
|
||||
0x00000101,
|
||||
0x0b000101,
|
||||
0x00000007,
|
||||
0x00000000,
|
||||
0x00000010,
|
||||
0x00001007,
|
||||
0x00001007,
|
||||
0x00041007,
|
||||
0x00001007,
|
||||
0x00001007,
|
||||
0x00000020,
|
||||
0x00002007,
|
||||
0x00002007,
|
||||
0x03002007,
|
||||
0x00002007,
|
||||
0x00002007,
|
||||
0x00000707,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000007,
|
||||
0x00000707,
|
||||
0x00010701,
|
||||
0x00010701,
|
||||
0x00010701,
|
||||
0x01000701,
|
||||
0x01000701,
|
||||
0x01000701,
|
||||
0x00000000,
|
||||
0x00000001,
|
||||
0x00010300,
|
||||
0x01000300,
|
||||
0x00000000,
|
||||
0x00010300,
|
||||
0x01000300,
|
||||
0x00000003,
|
||||
0x00000008,
|
||||
0x00000308,
|
||||
0x00000803,
|
||||
0x00000801,
|
||||
0x00000801,
|
||||
0x00011003,
|
||||
0x00010300,
|
||||
0x00004005,
|
||||
0x00800703,
|
||||
0x00010703,
|
||||
0x02000007,
|
||||
0x00400107,
|
||||
0x00000701,
|
||||
0x00000701,
|
||||
0x00000010,
|
||||
0x00000310,
|
||||
0x00001003,
|
||||
0x00040001,
|
||||
0x00001001,
|
||||
0x00001001,
|
||||
0x01002073,
|
||||
0x01000300,
|
||||
0x00004005,
|
||||
0x00186703,
|
||||
0x00106703,
|
||||
0x08000007,
|
||||
0x00030107,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00002003,
|
||||
0x03000001,
|
||||
0x00000007,
|
||||
0x00400107,
|
||||
0x00010107,
|
||||
0x00000707,
|
||||
0x00000703,
|
||||
0x00400107,
|
||||
0x00000701,
|
||||
0x00000701,
|
||||
0x00400107,
|
||||
0x00000701,
|
||||
0x00000701,
|
||||
0x00400107,
|
||||
0x00000753,
|
||||
0x00010107,
|
||||
0x00006701,
|
||||
0x00000751,
|
||||
0x00010107,
|
||||
0x00006701,
|
||||
0x00000751,
|
||||
0x00010107,
|
||||
0x00000707,
|
||||
0x00000707,
|
||||
0x00400107,
|
||||
0x00000703,
|
||||
0x00000703,
|
||||
0x00400107,
|
||||
0x00000701,
|
||||
0x00000757,
|
||||
0x00050107,
|
||||
0x01006703,
|
||||
0x01000753,
|
||||
0x00010107,
|
||||
0x00000701,
|
||||
0x00000751,
|
||||
0x00000307,
|
||||
0x00200301,
|
||||
0x06000301,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00010000,
|
||||
0x00000801,
|
||||
0x00040103,
|
||||
0x01000000,
|
||||
0x0c001001,
|
||||
0x03000103,
|
||||
0x00000003,
|
||||
0x00100700,
|
||||
0x00000007,
|
||||
0x00000003,
|
||||
0x00010707,
|
||||
0x00010703,
|
||||
0x10400107,
|
||||
0x10000707,
|
||||
0x00000803,
|
||||
0x00000801,
|
||||
0x00010703,
|
||||
0x00000000,
|
||||
0x00000801,
|
||||
0x00000007,
|
||||
0x00000003,
|
||||
0x01000003,
|
||||
0x00000103,
|
||||
0x05000700,
|
||||
0x00000057,
|
||||
0x0b000003,
|
||||
0x01000757,
|
||||
0x01008773,
|
||||
0x00030107,
|
||||
0x00020757,
|
||||
0x00001003,
|
||||
0x00040001,
|
||||
0x00001001,
|
||||
0x01000703,
|
||||
0x00000000,
|
||||
0x00001001,
|
||||
0x00000007,
|
||||
0x00000003,
|
||||
0x07000003,
|
||||
0x00000103,
|
||||
0x00002003,
|
||||
0x03000001,
|
||||
0x00004005,
|
||||
0x00010700,
|
||||
0x01000700,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000701,
|
||||
0x00000701,
|
||||
0x00000701,
|
||||
0x00000701,
|
||||
0x00000701,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00000751,
|
||||
0x00000000,
|
||||
0x00000305,
|
||||
0x00007305,
|
||||
0x00000000,
|
||||
0x00020000,
|
||||
0x02000000,
|
||||
0x00000000,
|
||||
0x00000003,
|
||||
0x00000303,
|
||||
0x00000300,
|
||||
0x00020000,
|
||||
0x02000000,
|
||||
0x00000000,
|
||||
0x00000701,
|
||||
0x10000707,
|
||||
0x00006701,
|
||||
0x00020757,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00001000,
|
||||
0x00001003,
|
||||
0x00002000,
|
||||
0x00002003,
|
||||
0x00000103,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000101,
|
||||
0x00100000,
|
||||
0x05000000,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x00000303,
|
||||
0x0b000303,
|
||||
0x00000003,
|
||||
0x04002010,
|
||||
0x08002000,
|
||||
0x00000008,
|
||||
0x09003020,
|
||||
0x0a003000,
|
||||
0x00000010,
|
||||
0x00000000,
|
||||
0x00000707,
|
||||
0x00080701,
|
||||
0x04006751,
|
||||
0x00000301,
|
||||
0x00001003,
|
||||
0x00002003,
|
||||
0x00000707,
|
||||
0x00000010,
|
||||
0x00020010,
|
||||
0x00000307,
|
||||
0x00000307,
|
||||
0x00000307,
|
||||
0x00000307,
|
||||
0x00000307,
|
||||
0x00000307,
|
||||
0x00000307,
|
||||
0x10000307,
|
||||
0x00000303,
|
||||
0x00000020,
|
||||
0x02000020,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x01007307,
|
||||
0x00007307,
|
||||
0x00007307,
|
||||
0x00027307,
|
||||
0x00000373,
|
||||
};
|
||||
|
||||
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
|
||||
|
||||
+34
-19
@@ -31,30 +31,45 @@
|
||||
#define ZEND_VM_OP1_SPEC 0x00000001
|
||||
#define ZEND_VM_OP1_CONST 0x00000002
|
||||
#define ZEND_VM_OP1_TMPVAR 0x00000004
|
||||
#define ZEND_VM_OP1_NUM 0x00000008
|
||||
#define ZEND_VM_OP1_JMP_ADDR 0x00000010
|
||||
#define ZEND_VM_OP1_TRY_CATCH 0x00000020
|
||||
#define ZEND_VM_OP1_MASK 0x000000f0
|
||||
#define ZEND_VM_OP1_NUM 0x00000010
|
||||
#define ZEND_VM_OP1_JMP_ADDR 0x00000020
|
||||
#define ZEND_VM_OP1_TRY_CATCH 0x00000030
|
||||
#define ZEND_VM_OP1_LIVE_RANGE 0x00000040
|
||||
#define ZEND_VM_OP1_THIS 0x00000050
|
||||
#define ZEND_VM_OP1_NEXT 0x00000060
|
||||
#define ZEND_VM_OP1_CLASS_FETCH 0x00000070
|
||||
#define ZEND_VM_OP1_CONSTRUCTOR 0x00000080
|
||||
#define ZEND_VM_OP2_SPEC 0x00000100
|
||||
#define ZEND_VM_OP2_CONST 0x00000200
|
||||
#define ZEND_VM_OP2_TMPVAR 0x00000400
|
||||
#define ZEND_VM_OP2_NUM 0x00000800
|
||||
#define ZEND_VM_OP2_JMP_ADDR 0x00001000
|
||||
#define ZEND_VM_OP2_TRY_CATCH 0x00002000
|
||||
#define ZEND_VM_OP2_MASK 0x0000f000
|
||||
#define ZEND_VM_OP2_NUM 0x00001000
|
||||
#define ZEND_VM_OP2_JMP_ADDR 0x00002000
|
||||
#define ZEND_VM_OP2_TRY_CATCH 0x00003000
|
||||
#define ZEND_VM_OP2_LIVE_RANGE 0x00004000
|
||||
#define ZEND_VM_EXT_NUM 0x00010000
|
||||
#define ZEND_VM_EXT_VAR 0x00020000
|
||||
#define ZEND_VM_EXT_JMP_ADDR 0x00040000
|
||||
#define ZEND_VM_EXT_DIM_OBJ 0x00080000
|
||||
#define ZEND_VM_EXT_CLASS_FETCH 0x00100000
|
||||
#define ZEND_VM_EXT_CONST_FETCH 0x00200000
|
||||
#define ZEND_VM_EXT_VAR_FETCH 0x00400000
|
||||
#define ZEND_VM_EXT_ARRAY_INIT 0x00800000
|
||||
#define ZEND_VM_EXT_TYPE 0x01000000
|
||||
#define ZEND_VM_EXT_EVAL 0x02000000
|
||||
#define ZEND_VM_EXT_FAST_CALL 0x04000000
|
||||
#define ZEND_VM_EXT_FAST_RET 0x08000000
|
||||
#define ZEND_VM_EXT_ISSET 0x10000000
|
||||
#define ZEND_VM_OP2_THIS 0x00005000
|
||||
#define ZEND_VM_OP2_NEXT 0x00006000
|
||||
#define ZEND_VM_OP2_CLASS_FETCH 0x00007000
|
||||
#define ZEND_VM_OP2_CONSTRUCTOR 0x00008000
|
||||
#define ZEND_VM_EXT_VAR_FETCH 0x00010000
|
||||
#define ZEND_VM_EXT_ISSET 0x00020000
|
||||
#define ZEND_VM_EXT_ARG_NUM 0x00040000
|
||||
#define ZEND_VM_EXT_ARRAY_INIT 0x00080000
|
||||
#define ZEND_VM_EXT_REF 0x00100000
|
||||
#define ZEND_VM_EXT_MASK 0xff000000
|
||||
#define ZEND_VM_EXT_NUM 0x01000000
|
||||
#define ZEND_VM_EXT_VAR 0x02000000
|
||||
#define ZEND_VM_EXT_JMP_ADDR 0x03000000
|
||||
#define ZEND_VM_EXT_DIM_OBJ 0x04000000
|
||||
#define ZEND_VM_EXT_CLASS_FETCH 0x05000000
|
||||
#define ZEND_VM_EXT_CONST_FETCH 0x06000000
|
||||
#define ZEND_VM_EXT_TYPE 0x07000000
|
||||
#define ZEND_VM_EXT_EVAL 0x08000000
|
||||
#define ZEND_VM_EXT_FAST_CALL 0x09000000
|
||||
#define ZEND_VM_EXT_FAST_RET 0x0a000000
|
||||
#define ZEND_VM_EXT_SRC 0x0b000000
|
||||
#define ZEND_VM_EXT_SEND 0x0c000000
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
|
||||
@@ -810,7 +810,7 @@ PHP_FUNCTION(com_message_pump)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool com_load_typelib(string typelib_name [, int case_insensitive])
|
||||
/* {{{ proto bool com_load_typelib(string typelib_name [, bool case_insensitive])
|
||||
Loads a Typelibrary and registers its constants */
|
||||
PHP_FUNCTION(com_load_typelib)
|
||||
{
|
||||
|
||||
+2
-2
@@ -3579,9 +3579,9 @@ PHP_FUNCTION(date_diff)
|
||||
zval *object1, *object2;
|
||||
php_date_obj *dateobj1, *dateobj2;
|
||||
php_interval_obj *interval;
|
||||
zend_long absolute = 0;
|
||||
zend_bool absolute = 0;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO|l", &object1, date_ce_interface, &object2, date_ce_interface, &absolute) == FAILURE) {
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO|b", &object1, date_ce_interface, &object2, date_ce_interface, &absolute) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
dateobj1 = Z_PHPDATE_P(object1);
|
||||
|
||||
+5
-1
@@ -320,6 +320,10 @@ if test "$PHP_DB4" != "no"; then
|
||||
THIS_PREFIX=$i
|
||||
THIS_INCLUDE=$i/db4/db.h
|
||||
break
|
||||
elif test -f "$i/include/db5.3/db.h"; then
|
||||
THIS_PREFIX=$i
|
||||
THIS_INCLUDE=$i/include/db5.3/db.h
|
||||
break
|
||||
elif test -f "$i/include/db5.1/db.h"; then
|
||||
THIS_PREFIX=$i
|
||||
THIS_INCLUDE=$i/include/db5.1/db.h
|
||||
@@ -362,7 +366,7 @@ if test "$PHP_DB4" != "no"; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
PHP_DBA_DB_CHECK(4, db-5.1 db-5.0 db-4.8 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)])
|
||||
PHP_DBA_DB_CHECK(4, db-5.3 db-5.1 db-5.0 db-4.8 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)])
|
||||
fi
|
||||
PHP_DBA_STD_RESULT(db4,Berkeley DB4)
|
||||
|
||||
|
||||
+13
-6
@@ -209,7 +209,7 @@ static size_t php_dba_make_key(zval *key, char **key_str, char **key_free)
|
||||
|
||||
if (zend_hash_num_elements(Z_ARRVAL_P(key)) != 2) {
|
||||
php_error_docref(NULL, E_RECOVERABLE_ERROR, "Key does not have exactly two elements: (key, name)");
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(key), &pos);
|
||||
group = zend_hash_get_current_data_ex(Z_ARRVAL_P(key), &pos);
|
||||
@@ -232,9 +232,10 @@ static size_t php_dba_make_key(zval *key, char **key_str, char **key_free)
|
||||
ZVAL_COPY(&tmp, key);
|
||||
convert_to_string(&tmp);
|
||||
|
||||
*key_free = *key_str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
|
||||
len = Z_STRLEN(tmp);
|
||||
|
||||
if (len) {
|
||||
*key_free = *key_str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
|
||||
}
|
||||
zval_ptr_dtor(&tmp);
|
||||
return len;
|
||||
}
|
||||
@@ -281,8 +282,14 @@ static size_t php_dba_make_key(zval *key, char **key_str, char **key_free)
|
||||
RETURN_FALSE; \
|
||||
}
|
||||
|
||||
#define DBA_ID_GET2 DBA_ID_PARS; DBA_GET2; DBA_FETCH_RESOURCE(info, id)
|
||||
#define DBA_ID_GET2_3 DBA_ID_PARS; DBA_GET2_3; DBA_FETCH_RESOURCE(info, id)
|
||||
#define DBA_FETCH_RESOURCE_WITH_ID(info, id) \
|
||||
if ((info = (dba_info *)zend_fetch_resource2(Z_RES_P(id), "DBA identifier", le_db, le_pdb)) == NULL) { \
|
||||
DBA_ID_DONE; \
|
||||
RETURN_FALSE; \
|
||||
}
|
||||
|
||||
#define DBA_ID_GET2 DBA_ID_PARS; DBA_GET2; DBA_FETCH_RESOURCE_WITH_ID(info, id)
|
||||
#define DBA_ID_GET2_3 DBA_ID_PARS; DBA_GET2_3; DBA_FETCH_RESOURCE_WITH_ID(info, id)
|
||||
|
||||
#define DBA_ID_DONE \
|
||||
if (key_free) efree(key_free)
|
||||
@@ -578,7 +585,7 @@ static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
DBA_FETCH_RESOURCE(info, id);
|
||||
DBA_FETCH_RESOURCE_WITH_ID(info, id);
|
||||
|
||||
DBA_WRITE_CHECK_WITH_ID;
|
||||
|
||||
|
||||
+2
-2
@@ -1348,9 +1348,9 @@ PHP_FUNCTION(dom_node_clone_node)
|
||||
xmlNode *n, *node;
|
||||
int ret;
|
||||
dom_object *intern;
|
||||
zend_long recursive = 0;
|
||||
zend_bool recursive = 0;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &id, dom_node_class_entry, &recursive) == FAILURE) {
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|b", &id, dom_node_class_entry, &recursive) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -299,12 +299,12 @@ if test -n "$proto"; then
|
||||
warning="
|
||||
NOTE! Because some arguments to functions were resources, the code generated
|
||||
cannot yet be compiled without editing. Please consider this to be step 4.5
|
||||
in the instructions above.
|
||||
in the instructions above.
|
||||
"
|
||||
fi
|
||||
fi
|
||||
|
||||
find . -type f | xargs chmod 644
|
||||
find . -type f | xargs chmod 644
|
||||
find . -type d | xargs chmod 755
|
||||
fi
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ Bug #71063 (filter_input(INPUT_ENV, ..) does not work)
|
||||
<?php if (!extension_loaded("filter")) die("skip"); ?>
|
||||
--ENV--
|
||||
PATH=/
|
||||
--INI--
|
||||
variables_order=E
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(count($_ENV['PATH']) > 0);
|
||||
|
||||
+5
-3
@@ -754,10 +754,11 @@ ftp_pasv(ftpbuf_t *ftp, int pasv)
|
||||
memset(&ftp->pasvaddr, 0, n);
|
||||
sa = (struct sockaddr *) &ftp->pasvaddr;
|
||||
|
||||
#if HAVE_IPV6
|
||||
if (getpeername(ftp->fd, sa, &n) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_IPV6
|
||||
if (sa->sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
|
||||
char *endptr, delimiter;
|
||||
@@ -810,8 +811,9 @@ ftp_pasv(ftpbuf_t *ftp, int pasv)
|
||||
ipbox.c[n] = (unsigned char) b[n];
|
||||
}
|
||||
sin = (struct sockaddr_in *) sa;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_addr = ipbox.ia[0];
|
||||
if (ftp->usepasvaddress) {
|
||||
sin->sin_addr = ipbox.ia[0];
|
||||
}
|
||||
sin->sin_port = ipbox.s[2];
|
||||
|
||||
ftp->pasv = 2;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#define FTP_DEFAULT_TIMEOUT 90
|
||||
#define FTP_DEFAULT_AUTOSEEK 1
|
||||
#define FTP_DEFAULT_USEPASVADDRESS 1
|
||||
#define PHP_FTP_FAILED 0
|
||||
#define PHP_FTP_FINISHED 1
|
||||
#define PHP_FTP_MOREDATA 2
|
||||
@@ -71,6 +72,7 @@ typedef struct ftpbuf
|
||||
php_sockaddr_storage pasvaddr; /* passive mode address */
|
||||
zend_long timeout_sec; /* User configurable timeout (seconds) */
|
||||
int autoseek; /* User configurable autoseek flag */
|
||||
int usepasvaddress; /* Use the address returned by the pasv command */
|
||||
|
||||
int nb; /* "nonblocking" transfer in progress */
|
||||
databuf_t *data; /* Data connection for "nonblocking" transfers */
|
||||
|
||||
@@ -326,6 +326,7 @@ PHP_MINIT_FUNCTION(ftp)
|
||||
REGISTER_LONG_CONSTANT("FTP_AUTORESUME", PHP_FTP_AUTORESUME, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_TIMEOUT_SEC", PHP_FTP_OPT_TIMEOUT_SEC, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_AUTOSEEK", PHP_FTP_OPT_AUTOSEEK, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_USEPASVADDRESS", PHP_FTP_OPT_USEPASVADDRESS, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_FAILED", PHP_FTP_FAILED, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_FINISHED", PHP_FTP_FINISHED, CONST_PERSISTENT | CONST_CS);
|
||||
REGISTER_LONG_CONSTANT("FTP_MOREDATA", PHP_FTP_MOREDATA, CONST_PERSISTENT | CONST_CS);
|
||||
@@ -379,6 +380,7 @@ PHP_FUNCTION(ftp_connect)
|
||||
|
||||
/* autoseek for resuming */
|
||||
ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
|
||||
ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS;
|
||||
#ifdef HAVE_FTP_SSL
|
||||
/* disable ssl */
|
||||
ftp->use_ssl = 0;
|
||||
@@ -415,6 +417,7 @@ PHP_FUNCTION(ftp_ssl_connect)
|
||||
|
||||
/* autoseek for resuming */
|
||||
ftp->autoseek = FTP_DEFAULT_AUTOSEEK;
|
||||
ftp->usepasvaddress = FTP_DEFAULT_USEPASVADDRESS;
|
||||
/* enable ssl */
|
||||
ftp->use_ssl = 1;
|
||||
|
||||
@@ -1478,6 +1481,15 @@ PHP_FUNCTION(ftp_set_option)
|
||||
ftp->autoseek = Z_TYPE_P(z_value) == IS_TRUE ? 1 : 0;
|
||||
RETURN_TRUE;
|
||||
break;
|
||||
case PHP_FTP_OPT_USEPASVADDRESS:
|
||||
if (Z_TYPE_P(z_value) != IS_TRUE && Z_TYPE_P(z_value) != IS_FALSE) {
|
||||
php_error_docref(NULL, E_WARNING, "Option USEPASVADDRESS expects value of type boolean, %s given",
|
||||
zend_zval_type_name(z_value));
|
||||
RETURN_FALSE;
|
||||
}
|
||||
ftp->usepasvaddress = Z_TYPE_P(z_value) == IS_TRUE ? 1 : 0;
|
||||
RETURN_TRUE;
|
||||
break;
|
||||
default:
|
||||
php_error_docref(NULL, E_WARNING, "Unknown option '%pd'", option);
|
||||
RETURN_FALSE;
|
||||
@@ -1509,6 +1521,9 @@ PHP_FUNCTION(ftp_get_option)
|
||||
case PHP_FTP_OPT_AUTOSEEK:
|
||||
RETURN_BOOL(ftp->autoseek);
|
||||
break;
|
||||
case PHP_FTP_OPT_USEPASVADDRESS:
|
||||
RETURN_BOOL(ftp->usepasvaddress);
|
||||
break;
|
||||
default:
|
||||
php_error_docref(NULL, E_WARNING, "Unknown option '%pd'", option);
|
||||
RETURN_FALSE;
|
||||
|
||||
@@ -32,6 +32,7 @@ extern zend_module_entry php_ftp_module_entry;
|
||||
|
||||
#define PHP_FTP_OPT_TIMEOUT_SEC 0
|
||||
#define PHP_FTP_OPT_AUTOSEEK 1
|
||||
#define PHP_FTP_OPT_USEPASVADDRESS 2
|
||||
#define PHP_FTP_AUTORESUME -1
|
||||
|
||||
PHP_MINIT_FUNCTION(ftp);
|
||||
|
||||
+10
-5
@@ -20,9 +20,9 @@ AC_DEFUN([IMAP_LIB_CHK],[
|
||||
done
|
||||
])
|
||||
|
||||
dnl PHP_IMAP_TEST_BUILD(function, action-if-ok, action-if-not-ok, extra-libs)
|
||||
dnl PHP_IMAP_TEST_BUILD(function, action-if-ok, action-if-not-ok, extra-libs, extra-source)
|
||||
AC_DEFUN([PHP_IMAP_TEST_BUILD], [
|
||||
PHP_TEST_BUILD([$1], [$2], [$3], [$4],
|
||||
PHP_TEST_BUILD([$1], [$2], [$3], [$4], [$5]
|
||||
[
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define PHP_IMAP_EXPORT __attribute__ ((visibility("default")))
|
||||
@@ -228,10 +228,15 @@ if test "$PHP_IMAP" != "no"; then
|
||||
AC_DEFINE(HAVE_IMAP_AUTH_GSS, 1, [ ])
|
||||
], [], $TST_LIBS)
|
||||
|
||||
dnl Check if utf8_to_mutf7 exists
|
||||
PHP_IMAP_TEST_BUILD(utf8_to_mutf7, [
|
||||
dnl Check if utf8_to_mutf7 exists. We need to do some gymnastics because
|
||||
dnl utf8_to_mutf7 takes an argument and will segfault without it. We
|
||||
dnl therefore test another function utf8_to_mutf7_php() which calls
|
||||
dnl the utf8_to_mutf7() function with the empty string as an argument.
|
||||
PHP_IMAP_TEST_BUILD(utf8_to_mutf7_php, [
|
||||
AC_DEFINE(HAVE_IMAP_MUTF7, 1, [ ])
|
||||
], [], $TST_LIBS)
|
||||
], [], $TST_LIBS, [
|
||||
char utf8_to_mutf7_php(){ return utf8_to_mutf7(""); }
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING(whether rfc822_output_address_list function present)
|
||||
PHP_TEST_BUILD(foobar, [
|
||||
|
||||
@@ -143,17 +143,14 @@ PHP_FUNCTION(ibase_wait_event)
|
||||
|
||||
if (Z_TYPE(args[0]) == IS_RESOURCE) {
|
||||
if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(&args[0], "InterBase link", le_link, le_plink)) == NULL) {
|
||||
efree(args);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
i = 1;
|
||||
} else {
|
||||
if (ZEND_NUM_ARGS() > 15) {
|
||||
efree(args);
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) {
|
||||
efree(args);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -170,7 +167,6 @@ PHP_FUNCTION(ibase_wait_event)
|
||||
if (isc_wait_for_event(IB_STATUS, &ib_link->handle, buffer_size, event_buffer, result_buffer)) {
|
||||
_php_ibase_error();
|
||||
_php_ibase_event_free(event_buffer,result_buffer);
|
||||
efree(args);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
@@ -180,7 +176,6 @@ PHP_FUNCTION(ibase_wait_event)
|
||||
if (occurred_event[i]) {
|
||||
zend_string *result = zend_string_init(events[i], strlen(events[i]), 0);
|
||||
_php_ibase_event_free(event_buffer,result_buffer);
|
||||
efree(args);
|
||||
RETURN_STR(result);
|
||||
}
|
||||
}
|
||||
@@ -188,7 +183,6 @@ PHP_FUNCTION(ibase_wait_event)
|
||||
/* If we reach this line, isc_wait_for_event() did return, but we don't know
|
||||
which event fired. */
|
||||
_php_ibase_event_free(event_buffer,result_buffer);
|
||||
efree(args);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -505,8 +505,6 @@ void calendar_register_IntlCalendar_class(void)
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_AM_PM", UCAL_AM_PM);
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_HOUR", UCAL_HOUR);
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_HOUR_OF_DAY", UCAL_HOUR_OF_DAY);
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_HOUR", UCAL_HOUR);
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_HOUR_OF_DAY", UCAL_HOUR_OF_DAY);
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_MINUTE", UCAL_MINUTE);
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_SECOND", UCAL_SECOND);
|
||||
CALENDAR_DECL_LONG_CONST("FIELD_MILLISECOND", UCAL_MILLISECOND);
|
||||
|
||||
+14
-8
@@ -5,16 +5,22 @@ Use the OCI8 extension to access Oracle Database.
|
||||
|
||||
Documentation is at http://php.net/oci8
|
||||
|
||||
The extension can be linked with Oracle client libraries from Oracle
|
||||
Database 10.2, 11, or 12.1. These libraries are found in the database
|
||||
installation, or in the free Oracle Instant Client available from
|
||||
Oracle.
|
||||
PHP OCI8 2.1 builds with PHP 7.
|
||||
|
||||
Use 'pecl install oci8' to install OCI8 for PHP 7.
|
||||
|
||||
Use 'pecl install oci8-2.0.10' to install OCI8 for PHP 5.2 - PHP 5.6.
|
||||
|
||||
Use 'pecl install oci8-1.4.10' to install OCI8 for PHP 4.3.9 - PHP 5.1.
|
||||
|
||||
The OCI8 extension needs to be linked with Oracle 12.1, 11, or 10.2
|
||||
client libraries. These libraries are found in your database
|
||||
installation, or in the free Oracle Instant Client from
|
||||
http://www.oracle.com/technetwork/database/features/instant-client/
|
||||
Install the 'Basic' or 'Basic Lite' Instant Client package. If
|
||||
building from source, then also install the SDK package.
|
||||
|
||||
Oracle's standard cross-version connectivity applies. For example,
|
||||
PHP OCI8 linked with Instant Client 11.2 can connect to Oracle
|
||||
Database 9.2 onward. See Oracle's note "Oracle Client / Server
|
||||
Interoperability Support" (ID 207303.1) for details.
|
||||
|
||||
PHP OCI8 2.0 can be built with PHP 5.2 onward. Use the older PHP OCI8
|
||||
1.4.10 when using PHP 4.3.9 through to PHP 5.1.x, or when only Oracle
|
||||
Database 9.2 client libraries are available.
|
||||
|
||||
+1
-3
@@ -40,10 +40,8 @@
|
||||
/* PHP 5.2 is the minimum supported version for OCI8 2.0 */
|
||||
#if PHP_MAJOR_VERSION < 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION <= 1)
|
||||
#error Use PHP OCI8 1.4 for your version of PHP
|
||||
#endif
|
||||
|
||||
#elif PHP_MAJOR_VERSION < 7
|
||||
/* PHP 7 is the minimum supported version for OCI8 2.1 */
|
||||
#if PHP_MAJOR_VERSION < 7
|
||||
#error Use PHP OCI8 2.0 for your version of PHP
|
||||
#endif
|
||||
|
||||
|
||||
+71
-67
@@ -8,17 +8,18 @@ http://pear.php.net/dtd/package-2.0.xsd">
|
||||
<summary>Extension for Oracle Database</summary>
|
||||
|
||||
<description>
|
||||
Use the OCI8 extension to access Oracle Database. The extension can
|
||||
be linked with Oracle client libraries from Oracle Database 10.2, 11,
|
||||
or 12.1. These libraries are found in the database installation, or
|
||||
in the free Oracle Instant Client available from Oracle. Oracle's
|
||||
standard cross-version connectivity applies. For example, PHP OCI8
|
||||
linked with Instant Client 11.2 can connect to Oracle Database 9.2
|
||||
onward. See Oracle's note "Oracle Client / Server Interoperability
|
||||
Support" (ID 207303.1) for details. PHP OCI8 2.1.0 can be built with
|
||||
PHP 7. PHP OCI8 2.0.9 can be built with PHP 5.2 onward. Use the older
|
||||
PHP OCI8 1.4.10 when using PHP 4.3.9 through to PHP 5.1.x, or when
|
||||
only Oracle Database 9.2 client libraries are available.
|
||||
Use the OCI8 extension to access Oracle Database. PHP OCI8 2.1 builds
|
||||
with PHP 7. Use 'pecl install oci8-2.0.10' to install OCI8 for PHP
|
||||
5.2 - PHP 5.6. Use 'pecl install oci8-1.4.10' to install PHP OCI8 1.4
|
||||
for PHP 4.3.9 - PHP 5.1. The OCI8 extension can be linked with Oracle
|
||||
client libraries from Oracle Database 12.1, 11, or 10.2. These
|
||||
libraries are found in your database installation, or in the free
|
||||
Oracle Instant Client from
|
||||
http://www.oracle.com/technetwork/database/features/instant-client/.
|
||||
Oracle's standard cross-version connectivity applies. For example,
|
||||
PHP OCI8 linked with Instant Client 11.2 can connect to Oracle
|
||||
Database 9.2 onward. See Oracle's note "Oracle Client / Server
|
||||
Interoperability Support" (ID 207303.1) for details.
|
||||
</description>
|
||||
<lead>
|
||||
<name>Christopher Jones</name>
|
||||
@@ -45,7 +46,7 @@ only Oracle Database 9.2 client libraries are available.
|
||||
<active>no</active>
|
||||
</lead>
|
||||
|
||||
<date>2015-01-01</date>
|
||||
<date>2015-12-12</date>
|
||||
<time>12:00:00</time>
|
||||
|
||||
<version>
|
||||
@@ -80,53 +81,54 @@ Updated driver name format.
|
||||
<file name="array_bind_014.phpt" role="test" />
|
||||
<file name="array_bind_bdouble.phpt" role="test" />
|
||||
<file name="array_bind_bfloat.phpt" role="test" />
|
||||
<file name="array_bind_date1.phpt" role="test" />
|
||||
<file name="array_bind_date.phpt" role="test" />
|
||||
<file name="array_bind_float1.phpt" role="test" />
|
||||
<file name="array_bind_date1.phpt" role="test" />
|
||||
<file name="array_bind_float.phpt" role="test" />
|
||||
<file name="array_bind_int1.phpt" role="test" />
|
||||
<file name="array_bind_float1.phpt" role="test" />
|
||||
<file name="array_bind_int.phpt" role="test" />
|
||||
<file name="array_bind_str1.phpt" role="test" />
|
||||
<file name="array_bind_int1.phpt" role="test" />
|
||||
<file name="array_bind_str.phpt" role="test" />
|
||||
<file name="array_bind_str1.phpt" role="test" />
|
||||
<file name="array_bind_uin.phpt" role="test" />
|
||||
<file name="b47243_1.phpt" role="test" />
|
||||
<file name="b47243_2.phpt" role="test" />
|
||||
<file name="b47243_3.phpt" role="test" />
|
||||
<file name="bind_boolean_1.phpt" role="test" />
|
||||
<file name="bind_char_1_11gR1.phpt" role="test" />
|
||||
<file name="bind_char_1.phpt" role="test" />
|
||||
<file name="bind_char_2_11gR1.phpt" role="test" />
|
||||
<file name="bind_char_1_11gR1.phpt" role="test" />
|
||||
<file name="bind_char_2.phpt" role="test" />
|
||||
<file name="bind_char_3_11gR1.phpt" role="test" />
|
||||
<file name="bind_char_2_11gR1.phpt" role="test" />
|
||||
<file name="bind_char_3.phpt" role="test" />
|
||||
<file name="bind_char_4_11gR1.phpt" role="test" />
|
||||
<file name="bind_char_3_11gR1.phpt" role="test" />
|
||||
<file name="bind_char_4.phpt" role="test" />
|
||||
<file name="bind_char_4_11gR1.phpt" role="test" />
|
||||
<file name="bind_empty.phpt" role="test" />
|
||||
<file name="bind_long.phpt" role="test" />
|
||||
<file name="bind_long_raw.phpt" role="test" />
|
||||
<file name="bind_misccoltypes_errs.phpt" role="test" />
|
||||
<file name="bind_misccoltypes.phpt" role="test" />
|
||||
<file name="bind_misccoltypes_errs.phpt" role="test" />
|
||||
<file name="bind_number.phpt" role="test" />
|
||||
<file name="bind_query.phpt" role="test" />
|
||||
<file name="bind_raw_2.phpt" role="test" />
|
||||
<file name="bind_raw.phpt" role="test" />
|
||||
<file name="bind_raw_2.phpt" role="test" />
|
||||
<file name="bind_rowid.phpt" role="test" />
|
||||
<file name="bind_sqltafc.phpt" role="test" />
|
||||
<file name="bind_sqltchr_1.phpt" role="test" />
|
||||
<file name="bind_sqltchr_2.phpt" role="test" />
|
||||
<file name="bind_sqltint.phpt" role="test" />
|
||||
<file name="bind_sqltnum.phpt" role="test" />
|
||||
<file name="bind_sqltnum_11g.phpt" role="test" />
|
||||
<file name="bind_unsupported_1.phpt" role="test" />
|
||||
<file name="bind_unsupported_2.phpt" role="test" />
|
||||
<file name="bind_unsupported_3.phpt" role="test" />
|
||||
<file name="bug26133.phpt" role="test" />
|
||||
<file name="bug27303_1_11gR1.phpt" role="test" />
|
||||
<file name="bug27303_1.phpt" role="test" />
|
||||
<file name="bug27303_2_11gR1.phpt" role="test" />
|
||||
<file name="bug27303_1_11gR1.phpt" role="test" />
|
||||
<file name="bug27303_2.phpt" role="test" />
|
||||
<file name="bug27303_2_11gR1.phpt" role="test" />
|
||||
<file name="bug27303_3.phpt" role="test" />
|
||||
<file name="bug27303_4_11gR1.phpt" role="test" />
|
||||
<file name="bug27303_4.phpt" role="test" />
|
||||
<file name="bug27303_4_11gR1.phpt" role="test" />
|
||||
<file name="bug32325.phpt" role="test" />
|
||||
<file name="bug35973.phpt" role="test" />
|
||||
<file name="bug36010.phpt" role="test" />
|
||||
@@ -144,8 +146,8 @@ Updated driver name format.
|
||||
<file name="bug42496_1.phpt" role="test" />
|
||||
<file name="bug42496_2.phpt" role="test" />
|
||||
<file name="bug42841.phpt" role="test" />
|
||||
<file name="bug43492_2.phpt" role="test" />
|
||||
<file name="bug43492.phpt" role="test" />
|
||||
<file name="bug43492_2.phpt" role="test" />
|
||||
<file name="bug43497.phpt" role="test" />
|
||||
<file name="bug44008.phpt" role="test" />
|
||||
<file name="bug44113.phpt" role="test" />
|
||||
@@ -158,54 +160,55 @@ Updated driver name format.
|
||||
<file name="bug51253.phpt" role="test" />
|
||||
<file name="bug51291_1.phpt" role="test" />
|
||||
<file name="bug51291_2.phpt" role="test" />
|
||||
<file name="bug68298.phpt" role="test" />
|
||||
<file name="clientversion.phpt" role="test" />
|
||||
<file name="close.phpt" role="test" />
|
||||
<file name="coll_001.phpt" role="test" />
|
||||
<file name="coll_002_func.phpt" role="test" />
|
||||
<file name="coll_002.phpt" role="test" />
|
||||
<file name="coll_003_func.phpt" role="test" />
|
||||
<file name="coll_002_func.phpt" role="test" />
|
||||
<file name="coll_003.phpt" role="test" />
|
||||
<file name="coll_004_func.phpt" role="test" />
|
||||
<file name="coll_003_func.phpt" role="test" />
|
||||
<file name="coll_004.phpt" role="test" />
|
||||
<file name="coll_004_func.phpt" role="test" />
|
||||
<file name="coll_005.phpt" role="test" />
|
||||
<file name="coll_006_func.phpt" role="test" />
|
||||
<file name="coll_006.phpt" role="test" />
|
||||
<file name="coll_006_func.phpt" role="test" />
|
||||
<file name="coll_007.phpt" role="test" />
|
||||
<file name="coll_008.phpt" role="test" />
|
||||
<file name="coll_009_func.phpt" role="test" />
|
||||
<file name="coll_009.phpt" role="test" />
|
||||
<file name="coll_010_func.phpt" role="test" />
|
||||
<file name="coll_009_func.phpt" role="test" />
|
||||
<file name="coll_010.phpt" role="test" />
|
||||
<file name="coll_011_func.phpt" role="test" />
|
||||
<file name="coll_010_func.phpt" role="test" />
|
||||
<file name="coll_011.phpt" role="test" />
|
||||
<file name="coll_012_func.phpt" role="test" />
|
||||
<file name="coll_011_func.phpt" role="test" />
|
||||
<file name="coll_012.phpt" role="test" />
|
||||
<file name="coll_013_func.phpt" role="test" />
|
||||
<file name="coll_012_func.phpt" role="test" />
|
||||
<file name="coll_013.phpt" role="test" />
|
||||
<file name="coll_014_func.phpt" role="test" />
|
||||
<file name="coll_013_func.phpt" role="test" />
|
||||
<file name="coll_014.phpt" role="test" />
|
||||
<file name="coll_015_func.phpt" role="test" />
|
||||
<file name="coll_014_func.phpt" role="test" />
|
||||
<file name="coll_015.phpt" role="test" />
|
||||
<file name="coll_016_func.phpt" role="test" />
|
||||
<file name="coll_015_func.phpt" role="test" />
|
||||
<file name="coll_016.phpt" role="test" />
|
||||
<file name="coll_017_func.phpt" role="test" />
|
||||
<file name="coll_016_func.phpt" role="test" />
|
||||
<file name="coll_017.phpt" role="test" />
|
||||
<file name="coll_017_func.phpt" role="test" />
|
||||
<file name="coll_018.phpt" role="test" />
|
||||
<file name="coll_019.phpt" role="test" />
|
||||
<file name="commit_001.phpt" role="test" />
|
||||
<file name="commit_002.phpt" role="test" />
|
||||
<file name="commit_old.phpt" role="test" />
|
||||
<file name="conn_attr.inc" role="test" />
|
||||
<file name="conn_attr_1.phpt" role="test" />
|
||||
<file name="conn_attr_2.phpt" role="test" />
|
||||
<file name="conn_attr_3.phpt" role="test" />
|
||||
<file name="conn_attr_4.phpt" role="test" />
|
||||
<file name="conn_attr_5.phpt" role="test" />
|
||||
<file name="conn_attr.inc" role="test" />
|
||||
<file name="connect_1_old.phpt" role="test" />
|
||||
<file name="connect_1.phpt" role="test" />
|
||||
<file name="connect.inc" role="test" />
|
||||
<file name="connect_old.phpt" role="test" />
|
||||
<file name="connect.phpt" role="test" />
|
||||
<file name="connect_1.phpt" role="test" />
|
||||
<file name="connect_1_old.phpt" role="test" />
|
||||
<file name="connect_old.phpt" role="test" />
|
||||
<file name="connect_scope1.phpt" role="test" />
|
||||
<file name="connect_scope2.phpt" role="test" />
|
||||
<file name="connect_scope_try1.phpt" role="test" />
|
||||
@@ -215,24 +218,25 @@ Updated driver name format.
|
||||
<file name="connect_scope_try5.phpt" role="test" />
|
||||
<file name="connect_scope_try6.phpt" role="test" />
|
||||
<file name="connect_with_charset_001.phpt" role="test" />
|
||||
<file name="connect_without_oracle_home_11.phpt" role="test" />
|
||||
<file name="connect_without_oracle_home_old_11.phpt" role="test" />
|
||||
<file name="connect_without_oracle_home_old.phpt" role="test" />
|
||||
<file name="connect_without_oracle_home.phpt" role="test" />
|
||||
<file name="connect_without_oracle_home_11.phpt" role="test" />
|
||||
<file name="connect_without_oracle_home_old.phpt" role="test" />
|
||||
<file name="connect_without_oracle_home_old_11.phpt" role="test" />
|
||||
<file name="create_table.inc" role="test" />
|
||||
<file name="create_type.inc" role="test" />
|
||||
<file name="cursor_bind_err.phpt" role="test" />
|
||||
<file name="cursor_bind.phpt" role="test" />
|
||||
<file name="cursors_old.phpt" role="test" />
|
||||
<file name="cursor_bind_err.phpt" role="test" />
|
||||
<file name="cursors.phpt" role="test" />
|
||||
<file name="dbmsoutput.phpt" role="test" />
|
||||
<file name="cursors_old.phpt" role="test" />
|
||||
<file name="db_op_1.phpt" role="test" />
|
||||
<file name="db_op_2.phpt" role="test" />
|
||||
<file name="dbmsoutput.phpt" role="test" />
|
||||
<file name="debug.phpt" role="test" />
|
||||
<file name="default_prefetch.phpt" role="test" />
|
||||
<file name="default_prefetch0.phpt" role="test" />
|
||||
<file name="default_prefetch1.phpt" role="test" />
|
||||
<file name="default_prefetch2.phpt" role="test" />
|
||||
<file name="default_prefetch.phpt" role="test" />
|
||||
<file name="define.phpt" role="test" />
|
||||
<file name="define0.phpt" role="test" />
|
||||
<file name="define1.phpt" role="test" />
|
||||
<file name="define2.phpt" role="test" />
|
||||
@@ -241,7 +245,6 @@ Updated driver name format.
|
||||
<file name="define5.phpt" role="test" />
|
||||
<file name="define6.phpt" role="test" />
|
||||
<file name="define_old.phpt" role="test" />
|
||||
<file name="define.phpt" role="test" />
|
||||
<file name="descriptors.phpt" role="test" />
|
||||
<file name="details.inc" role="test" />
|
||||
<file name="drcp_cclass1.phpt" role="test" />
|
||||
@@ -261,11 +264,13 @@ Updated driver name format.
|
||||
<file name="drcp_scope4.phpt" role="test" />
|
||||
<file name="drcp_scope5.phpt" role="test" />
|
||||
<file name="driver_name.phpt" role="test" />
|
||||
<file name="driver_name_11gR2.phpt" role="test" />
|
||||
<file name="drop_table.inc" role="test" />
|
||||
<file name="drop_type.inc" role="test" />
|
||||
<file name="dupcolnames.phpt" role="test" />
|
||||
<file name="edition_1.phpt" role="test" />
|
||||
<file name="edition_2.phpt" role="test" />
|
||||
<file name="error.phpt" role="test" />
|
||||
<file name="error1.phpt" role="test" />
|
||||
<file name="error2.phpt" role="test" />
|
||||
<file name="error3.phpt" role="test" />
|
||||
@@ -274,7 +279,6 @@ Updated driver name format.
|
||||
<file name="error_bind_3.phpt" role="test" />
|
||||
<file name="error_old.phpt" role="test" />
|
||||
<file name="error_parse.phpt" role="test" />
|
||||
<file name="error.phpt" role="test" />
|
||||
<file name="error_set.phpt" role="test" />
|
||||
<file name="exec_fetch.phpt" role="test" />
|
||||
<file name="execute_mode.phpt" role="test" />
|
||||
@@ -282,28 +286,28 @@ Updated driver name format.
|
||||
<file name="extauth_02.phpt" role="test" />
|
||||
<file name="extauth_03.phpt" role="test" />
|
||||
<file name="extauth_04.phpt" role="test" />
|
||||
<file name="fetch.phpt" role="test" />
|
||||
<file name="fetch_all.phpt" role="test" />
|
||||
<file name="fetch_all1.phpt" role="test" />
|
||||
<file name="fetch_all2.phpt" role="test" />
|
||||
<file name="fetch_all3.phpt" role="test" />
|
||||
<file name="fetch_all4.phpt" role="test" />
|
||||
<file name="fetch_all5.phpt" role="test" />
|
||||
<file name="fetch_all.phpt" role="test" />
|
||||
<file name="fetch_array.phpt" role="test" />
|
||||
<file name="fetch_assoc.phpt" role="test" />
|
||||
<file name="fetch_into.phpt" role="test" />
|
||||
<file name="fetch_into1.phpt" role="test" />
|
||||
<file name="fetch_into2.phpt" role="test" />
|
||||
<file name="fetch_into.phpt" role="test" />
|
||||
<file name="fetch_object.phpt" role="test" />
|
||||
<file name="fetch_object_1.phpt" role="test" />
|
||||
<file name="fetch_object_2.phpt" role="test" />
|
||||
<file name="fetch_object.phpt" role="test" />
|
||||
<file name="fetch.phpt" role="test" />
|
||||
<file name="fetch_row.phpt" role="test" />
|
||||
<file name="field_funcs.phpt" role="test" />
|
||||
<file name="field_funcs0.phpt" role="test" />
|
||||
<file name="field_funcs1.phpt" role="test" />
|
||||
<file name="field_funcs2.phpt" role="test" />
|
||||
<file name="field_funcs3.phpt" role="test" />
|
||||
<file name="field_funcs_old.phpt" role="test" />
|
||||
<file name="field_funcs.phpt" role="test" />
|
||||
<file name="function_aliases.phpt" role="test" />
|
||||
<file name="imp_res_1.phpt" role="test" />
|
||||
<file name="imp_res_2.phpt" role="test" />
|
||||
@@ -384,33 +388,33 @@ Updated driver name format.
|
||||
<file name="lob_044.phpt" role="test" />
|
||||
<file name="lob_aliases.phpt" role="test" />
|
||||
<file name="lob_null.phpt" role="test" />
|
||||
<file name="lob_temp.phpt" role="test" />
|
||||
<file name="lob_temp1.phpt" role="test" />
|
||||
<file name="lob_temp2.phpt" role="test" />
|
||||
<file name="lob_temp.phpt" role="test" />
|
||||
<file name="minfo.phpt" role="test" />
|
||||
<file name="null_byte_1.phpt" role="test" />
|
||||
<file name="null_byte_2.phpt" role="test" />
|
||||
<file name="null_byte_3.phpt" role="test" />
|
||||
<file name="num.phpt" role="test" />
|
||||
<file name="oci_execute_segfault.phpt" role="test" />
|
||||
<file name="old_oci_close1.phpt" role="test" />
|
||||
<file name="old_oci_close.phpt" role="test" />
|
||||
<file name="old_oci_close1.phpt" role="test" />
|
||||
<file name="password.phpt" role="test" />
|
||||
<file name="password_2.phpt" role="test" />
|
||||
<file name="password_new.phpt" role="test" />
|
||||
<file name="password_old.phpt" role="test" />
|
||||
<file name="password.phpt" role="test" />
|
||||
<file name="pecl_bug10194_blob_64.phpt" role="test" />
|
||||
<file name="pecl_bug10194_blob.phpt" role="test" />
|
||||
<file name="pecl_bug10194.phpt" role="test" />
|
||||
<file name="pecl_bug10194_blob.phpt" role="test" />
|
||||
<file name="pecl_bug10194_blob_64.phpt" role="test" />
|
||||
<file name="pecl_bug16035.phpt" role="test" />
|
||||
<file name="pecl_bug16842.phpt" role="test" />
|
||||
<file name="pecl_bug6109.phpt" role="test" />
|
||||
<file name="pecl_bug8816.phpt" role="test" />
|
||||
<file name="persistent.phpt" role="test" />
|
||||
<file name="prefetch_old.phpt" role="test" />
|
||||
<file name="prefetch.phpt" role="test" />
|
||||
<file name="privileged_connect1.phpt" role="test" />
|
||||
<file name="prefetch_old.phpt" role="test" />
|
||||
<file name="privileged_connect.phpt" role="test" />
|
||||
<file name="privileged_connect1.phpt" role="test" />
|
||||
<file name="refcur_prefetch_1.phpt" role="test" />
|
||||
<file name="refcur_prefetch_2.phpt" role="test" />
|
||||
<file name="refcur_prefetch_3.phpt" role="test" />
|
||||
@@ -421,11 +425,11 @@ Updated driver name format.
|
||||
<file name="serverversion.phpt" role="test" />
|
||||
<file name="skipif.inc" role="test" />
|
||||
<file name="statement_cache.phpt" role="test" />
|
||||
<file name="statement_type_old.phpt" role="test" />
|
||||
<file name="statement_type.phpt" role="test" />
|
||||
<file name="statement_type_old.phpt" role="test" />
|
||||
<file name="test.gif" role="test" />
|
||||
<file name="testping.phpt" role="test" />
|
||||
<file name="test.txt" role="test" />
|
||||
<file name="testping.phpt" role="test" />
|
||||
<file name="uncommitted.phpt" role="test" />
|
||||
<file name="xmltype_01.phpt" role="test" />
|
||||
<file name="xmltype_02.phpt" role="test" />
|
||||
@@ -448,7 +452,7 @@ Updated driver name format.
|
||||
<dependencies>
|
||||
<required>
|
||||
<php>
|
||||
<min>5.2.0</min>
|
||||
<min>7.0.0</min>
|
||||
</php>
|
||||
<pearinstaller>
|
||||
<min>1.4.0b1</min>
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
#include "zend_cfg.h"
|
||||
#include "zend_dump.h"
|
||||
|
||||
#define DEBUG_BLOCKPASS 0
|
||||
|
||||
/* Checks if a constant (like "true") may be replaced by its value */
|
||||
int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy)
|
||||
{
|
||||
@@ -129,8 +127,6 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
/* remove leading NOPs */
|
||||
strip_leading_nops(op_array, block);
|
||||
|
||||
/* we track data dependencies only insight a single basic block */
|
||||
memset(Tsource, 0, (op_array->last_var + op_array->T) * sizeof(zend_op *));
|
||||
opline = op_array->opcodes + block->start;
|
||||
end = op_array->opcodes + block->end + 1;
|
||||
while (opline < end) {
|
||||
@@ -326,9 +322,17 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
|
||||
}
|
||||
#endif
|
||||
|
||||
case ZEND_FETCH_LIST:
|
||||
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
|
||||
/* LIST variable will be deleted later by FREE */
|
||||
Tsource[VAR_NUM(opline->op1.var)] = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZEND_CASE:
|
||||
if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
|
||||
/* CASE variable will be deleted later by FREE, so we can't optimize it */
|
||||
Tsource[VAR_NUM(opline->op1.var)] = NULL;
|
||||
break;
|
||||
}
|
||||
if (opline->op1_type == IS_CONST &&
|
||||
@@ -759,9 +763,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
|
||||
zend_op *new_opcodes;
|
||||
zend_op *opline;
|
||||
uint32_t len = 0;
|
||||
#if DEBUG_BLOCKPASS
|
||||
int n;
|
||||
#endif
|
||||
|
||||
for (b = blocks; b < end; b++) {
|
||||
if (b->flags & ZEND_BB_REACHABLE) {
|
||||
@@ -776,7 +778,11 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
|
||||
if (next < end && next == blocks + b->successors[0]) {
|
||||
/* JMP to the next block - strip it */
|
||||
MAKE_NOP(opline);
|
||||
b->end--;
|
||||
if (b->end == 0) {
|
||||
b->start++;
|
||||
} else {
|
||||
b->end--;
|
||||
}
|
||||
}
|
||||
} else if (b->start == b->end && opline->opcode == ZEND_NOP) {
|
||||
/* skip empty block */
|
||||
@@ -811,6 +817,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
|
||||
b->end = opline - new_opcodes + n - 1;
|
||||
opline += n;
|
||||
} else {
|
||||
b->flags |= ZEND_BB_EMPTY;
|
||||
b->start = b->end = opline - new_opcodes;
|
||||
}
|
||||
}
|
||||
@@ -822,7 +829,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
|
||||
op_array->last = len;
|
||||
|
||||
for (b = blocks; b < end; b++) {
|
||||
if (!(b->flags & ZEND_BB_REACHABLE)) {
|
||||
if (!(b->flags & ZEND_BB_REACHABLE) || b->start > b->end) {
|
||||
continue;
|
||||
}
|
||||
opline = op_array->opcodes + b->end;
|
||||
@@ -948,8 +955,8 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
|
||||
op_array->last_live_range = j;
|
||||
while (opline != end) {
|
||||
if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) &&
|
||||
opline->extended_value == ZEND_FREE_ON_RETURN &&
|
||||
opline->op2.num < (uint32_t)j) {
|
||||
opline->extended_value == ZEND_FREE_ON_RETURN) {
|
||||
ZEND_ASSERT(opline->op2.num < (uint32_t) i);
|
||||
opline->op2.num = map[opline->op2.num];
|
||||
}
|
||||
opline++;
|
||||
@@ -975,15 +982,13 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
|
||||
*opline_num = -1;
|
||||
}
|
||||
|
||||
#if DEBUG_BLOCKPASS
|
||||
/* rebild map (judt for printing) */
|
||||
/* rebuild map (just for printing) */
|
||||
memset(cfg->map, -1, sizeof(int) * op_array->last);
|
||||
for (n = 0; n < cfg->blocks_count; n++) {
|
||||
if (cfg->blocks[n].flags & ZEND_BB_REACHABLE) {
|
||||
cfg->map[cfg->blocks[n].start] = n;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_array, zend_cfg *cfg, zend_uchar *same_t)
|
||||
@@ -1460,7 +1465,7 @@ next_target_znz:
|
||||
static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset used_ext, zend_optimizer_ctx *ctx)
|
||||
{
|
||||
int n;
|
||||
zend_basic_block *block;
|
||||
zend_basic_block *block, *next_block;
|
||||
uint32_t var_num;
|
||||
uint32_t bitset_len;
|
||||
zend_bitset usage;
|
||||
@@ -1476,9 +1481,9 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
|
||||
|
||||
checkpoint = zend_arena_checkpoint(ctx->arena);
|
||||
bitset_len = zend_bitset_len(op_array->last_var + op_array->T);
|
||||
usage = zend_arena_calloc(&ctx->arena, bitset_len, ZEND_BITSET_ELM_SIZE);
|
||||
defined_here = zend_arena_alloc(&ctx->arena, bitset_len * ZEND_BITSET_ELM_SIZE);
|
||||
|
||||
zend_bitset_clear(defined_here, bitset_len);
|
||||
for (n = 1; n < cfg->blocks_count; n++) {
|
||||
block = cfg->blocks + n;
|
||||
|
||||
@@ -1488,7 +1493,11 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
|
||||
|
||||
opline = op_array->opcodes + block->start;
|
||||
end = op_array->opcodes + block->end + 1;
|
||||
zend_bitset_clear(defined_here, bitset_len);
|
||||
if (!(block->flags & ZEND_BB_FOLLOW) ||
|
||||
(block->flags & ZEND_BB_TARGET)) {
|
||||
/* Skip continuation of "extended" BB */
|
||||
zend_bitset_clear(defined_here, bitset_len);
|
||||
}
|
||||
|
||||
while (opline<end) {
|
||||
if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
|
||||
@@ -1534,15 +1543,14 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_BLOCKPASS > 2
|
||||
{
|
||||
if (ctx->debug_level & ZEND_DUMP_BLOCK_PASS_VARS) {
|
||||
int printed = 0;
|
||||
uint32_t i;
|
||||
|
||||
for (i = op_array->last_var; i< op_array->T; i++) {
|
||||
if (zend_bitset_in(used_ext, i)) {
|
||||
if (!printed) {
|
||||
fprintf(stderr, "NON-LOCAL-VARS: %s: %d", op_array->function_name ? op_array->function_name->val : "(null)", i);
|
||||
fprintf(stderr, "NON-LOCAL-VARS: %d", i);
|
||||
printed = 1;
|
||||
} else {
|
||||
fprintf(stderr, ", %d", i);
|
||||
@@ -1551,13 +1559,13 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
|
||||
}
|
||||
if (printed) {
|
||||
fprintf(stderr, "\n");
|
||||
zend_dump_op_array(op_array, cfg, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (n = 0; n < cfg->blocks_count; n++) {
|
||||
block = cfg->blocks + n;
|
||||
usage = defined_here;
|
||||
next_block = NULL;
|
||||
for (n = cfg->blocks_count; n > 0;) {
|
||||
block = cfg->blocks + (--n);
|
||||
|
||||
if (!(block->flags & ZEND_BB_REACHABLE)) {
|
||||
continue;
|
||||
@@ -1565,7 +1573,15 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use
|
||||
|
||||
opline = op_array->opcodes + block->end;
|
||||
end = op_array->opcodes + block->start;
|
||||
zend_bitset_copy(usage, used_ext, bitset_len);
|
||||
if (!next_block ||
|
||||
!(next_block->flags & ZEND_BB_FOLLOW) ||
|
||||
(next_block->flags & ZEND_BB_TARGET)) {
|
||||
/* Skip continuation of "extended" BB */
|
||||
zend_bitset_copy(usage, used_ext, bitset_len);
|
||||
} else if (block->successors[1] != -1) {
|
||||
zend_bitset_union(usage, used_ext, bitset_len);
|
||||
}
|
||||
next_block = block;
|
||||
|
||||
while (opline >= end) {
|
||||
/* usage checks */
|
||||
@@ -1727,22 +1743,16 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
zend_op **Tsource;
|
||||
zend_uchar *same_t;
|
||||
|
||||
#if DEBUG_BLOCKPASS
|
||||
fprintf(stderr, "File %s func %s\n", op_array->filename->val, op_array->function_name ? op_array->function_name->val : "main");
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
/* Build CFG */
|
||||
checkpoint = zend_arena_checkpoint(ctx->arena);
|
||||
if (zend_build_cfg(&ctx->arena, op_array, 0, 0, &cfg, NULL) != SUCCESS) {
|
||||
if (zend_build_cfg(&ctx->arena, op_array, 0, &cfg, NULL) != SUCCESS) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
#if DEBUG_BLOCKPASS
|
||||
fprintf(stderr, "\nBEFORE-BLOCK-PASS: %s:\n", op_array->function_name ? op_array->function_name->val : "(null)");
|
||||
zend_dump_op_array(op_array, &cfg, 1);
|
||||
#endif
|
||||
if (ctx->debug_level & ZEND_DUMP_BEFORE_BLOCK_PASS) {
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_CFG, "before block pass", &cfg);
|
||||
}
|
||||
|
||||
if (op_array->last_var || op_array->T) {
|
||||
bitset_len = zend_bitset_len(op_array->last_var + op_array->T);
|
||||
@@ -1764,9 +1774,16 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
|
||||
/* optimize each basic block separately */
|
||||
for (b = blocks; b < end; b++) {
|
||||
if (b->flags & ZEND_BB_REACHABLE) {
|
||||
zend_optimize_block(b, op_array, usage, &cfg, Tsource);
|
||||
if (!(b->flags & ZEND_BB_REACHABLE)) {
|
||||
continue;
|
||||
}
|
||||
/* we track data dependencies only insight a single basic block */
|
||||
if (!(b->flags & ZEND_BB_FOLLOW) ||
|
||||
(b->flags & ZEND_BB_TARGET)) {
|
||||
/* Skip continuation of "extended" BB */
|
||||
memset(Tsource, 0, (op_array->last_var + op_array->T) * sizeof(zend_op *));
|
||||
}
|
||||
zend_optimize_block(b, op_array, usage, &cfg, Tsource);
|
||||
}
|
||||
|
||||
/* Jump optimization for each block */
|
||||
@@ -1777,7 +1794,7 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
}
|
||||
|
||||
/* Eliminate unreachable basic blocks */
|
||||
zend_remark_reachable_blocks(op_array, &cfg);
|
||||
zend_cfg_remark_reachable_blocks(op_array, &cfg);
|
||||
|
||||
/* Merge Blocks */
|
||||
zend_merge_blocks(op_array, &cfg);
|
||||
@@ -1787,10 +1804,9 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
zend_t_usage(&cfg, op_array, usage, ctx);
|
||||
assemble_code_blocks(&cfg, op_array);
|
||||
|
||||
#if DEBUG_BLOCKPASS
|
||||
fprintf(stderr, "\nAFTER-BLOCK-PASS: %s:\n", op_array->function_name ? op_array->function_name->val : "(null)");
|
||||
zend_dump_op_array(op_array, &cfg, 0);
|
||||
#endif
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_BLOCK_PASS) {
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_CFG | ZEND_DUMP_HIDE_UNREACHABLE, "after block pass", &cfg);
|
||||
}
|
||||
|
||||
/* Destroy CFG */
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend OPcache |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
#include "Optimizer/zend_optimizer.h"
|
||||
#include "Optimizer/zend_optimizer_internal.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_constants.h"
|
||||
#include "zend_execute.h"
|
||||
#include "zend_vm.h"
|
||||
#include "zend_bitset.h"
|
||||
#include "zend_cfg.h"
|
||||
#include "zend_ssa.h"
|
||||
#include "zend_func_info.h"
|
||||
#include "zend_inference.h"
|
||||
#include "zend_dump.h"
|
||||
|
||||
#ifndef HAVE_DFA_PASS
|
||||
# define HAVE_DFA_PASS 0
|
||||
#endif
|
||||
|
||||
void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
{
|
||||
void *checkpoint;
|
||||
uint32_t build_flags;
|
||||
uint32_t flags = 0;
|
||||
zend_ssa ssa;
|
||||
|
||||
#if !HAVE_DFA_PASS
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Build SSA */
|
||||
memset(&ssa, 0, sizeof(ssa));
|
||||
checkpoint = zend_arena_checkpoint(ctx->arena);
|
||||
|
||||
if (zend_build_cfg(&ctx->arena, op_array, 0, &ssa.cfg, &flags) != SUCCESS) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & ZEND_FUNC_TOO_DYNAMIC) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (zend_cfg_build_predecessors(&ctx->arena, &ssa.cfg) != SUCCESS) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_DFA_CFG) {
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_CFG | ZEND_DUMP_HIDE_UNUSED_VARS, "dfa cfg", &ssa.cfg);
|
||||
}
|
||||
|
||||
/* Compute Dominators Tree */
|
||||
if (zend_cfg_compute_dominators_tree(op_array, &ssa.cfg) != SUCCESS) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Identify reducible and irreducible loops */
|
||||
if (zend_cfg_identify_loops(op_array, &ssa.cfg, &flags) != SUCCESS) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_DFA_DOMINATORS) {
|
||||
zend_dump_dominators(op_array, &ssa.cfg);
|
||||
}
|
||||
|
||||
build_flags = 0;
|
||||
if (ctx->debug_level & ZEND_DUMP_DFA_LIVENESS) {
|
||||
build_flags |= ZEND_SSA_DEBUG_LIVENESS;
|
||||
}
|
||||
if (ctx->debug_level & ZEND_DUMP_DFA_PHI) {
|
||||
build_flags |= ZEND_SSA_DEBUG_PHI_PLACEMENT;
|
||||
}
|
||||
if (zend_build_ssa(&ctx->arena, op_array, build_flags, &ssa, &flags) != SUCCESS) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_DFA_SSA) {
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", &ssa);
|
||||
}
|
||||
|
||||
|
||||
if (zend_ssa_compute_use_def_chains(&ctx->arena, op_array, &ssa) != SUCCESS){
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (zend_ssa_find_false_dependencies(op_array, &ssa) != SUCCESS) {
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (zend_ssa_find_sccs(op_array, &ssa) != SUCCESS){
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
return;
|
||||
}
|
||||
|
||||
if (zend_ssa_inference(&ctx->arena, op_array, ctx->script, &ssa) != SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_DFA_SSA_VARS) {
|
||||
zend_dump_ssa_variables(op_array, &ssa);
|
||||
}
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_BEFORE_DFA_PASS) {
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", &ssa);
|
||||
}
|
||||
|
||||
//TODO: Add optimization patterns ???
|
||||
if (ssa.var_info) {
|
||||
int i;
|
||||
// 1: #1.T = OP_Y | #3.CV = OP_Y
|
||||
// 2: ASSIGN #2.CV [undef,null,bool] -> #3.cv, #1.T | NOP
|
||||
for (i = 0; i < ssa.vars_count; i++) {
|
||||
int op2 = ssa.vars[i].definition;
|
||||
|
||||
if (op2 >= 0
|
||||
&& op_array->opcodes[op2].opcode == ZEND_ASSIGN
|
||||
&& op_array->opcodes[op2].op1_type == IS_CV
|
||||
&& (op_array->opcodes[op2].op2_type & (IS_TMP_VAR|IS_VAR))
|
||||
&& !RETURN_VALUE_USED(&op_array->opcodes[op2])
|
||||
) {
|
||||
|
||||
int var1 = ssa.ops[op2].op2_use;
|
||||
int var2 = ssa.ops[op2].op1_use;
|
||||
|
||||
if (var1 >= 0
|
||||
&& var2 >= 0
|
||||
&& !(ssa.var_info[var2].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
|
||||
&& !(ssa.var_info[var1].type & MAY_BE_REF)
|
||||
&& ssa.vars[var1].definition >= 0
|
||||
&& ssa.ops[ssa.vars[var1].definition].result_def == var1
|
||||
&& ssa.ops[ssa.vars[var1].definition].result_use < 0
|
||||
&& ssa.vars[var1].use_chain == op2
|
||||
&& ssa.ops[op2].op2_use_chain < 0
|
||||
&& !ssa.vars[var1].phi_use_chain
|
||||
&& !ssa.vars[var1].sym_use_chain
|
||||
) {
|
||||
int op1 = ssa.vars[var1].definition;
|
||||
int var3 = i;
|
||||
|
||||
if (zend_ssa_unlink_use_chain(&ssa, op2, var2)) {
|
||||
/* Reconstruct SSA */
|
||||
ssa.vars[var3].definition = op1;
|
||||
ssa.ops[op1].result_def = var3;
|
||||
|
||||
ssa.vars[var1].definition = -1;
|
||||
ssa.vars[var1].use_chain = -1;
|
||||
|
||||
ssa.ops[op2].op1_use = -1;
|
||||
ssa.ops[op2].op2_use = -1;
|
||||
ssa.ops[op2].op1_def = -1;
|
||||
ssa.ops[op2].op1_use_chain = -1;
|
||||
|
||||
/* Update opcodes */
|
||||
op_array->opcodes[op1].result_type = op_array->opcodes[op2].op1_type;
|
||||
op_array->opcodes[op1].result.var = op_array->opcodes[op2].op1.var;
|
||||
MAKE_NOP(&op_array->opcodes[op2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_DFA_PASS) {
|
||||
zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "after dfa pass", &ssa);
|
||||
}
|
||||
|
||||
/* Destroy SSA */
|
||||
zend_arena_release(&ctx->arena, checkpoint);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -42,7 +42,9 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
int i = 0;
|
||||
zend_op *opline = op_array->opcodes;
|
||||
zend_op *end = opline + op_array->last;
|
||||
zend_bool collect_constants = (op_array == &ctx->script->main_op_array);
|
||||
/* bug #71127*
|
||||
zend_bool collect_constants = (op_array == &ctx->script->main_op_array); */
|
||||
zend_bool collect_constants = 0;
|
||||
|
||||
while (opline < end) {
|
||||
switch (opline->opcode) {
|
||||
|
||||
@@ -114,14 +114,21 @@ void zend_optimizer_pass2(zend_op_array *op_array)
|
||||
case ZEND_JMPZ_EX:
|
||||
case ZEND_JMPNZ_EX:
|
||||
/* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */
|
||||
if (0 && /* FIXME: temporary disable unsafe pattern */
|
||||
ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
|
||||
#if 0
|
||||
/* Disabled unsafe pattern: in conjunction with
|
||||
* ZEND_VM_SMART_BRANCH() this may improperly eliminate
|
||||
* assignment to Ti.
|
||||
*/
|
||||
if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
|
||||
ZEND_RESULT_TYPE(opline) == IS_TMP_VAR &&
|
||||
ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
|
||||
opline->opcode -= 3;
|
||||
SET_UNUSED(opline->result);
|
||||
} else
|
||||
#endif
|
||||
/* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C)
|
||||
in case we know it wouldn't jump */
|
||||
} else if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
|
||||
if (opline->opcode == ZEND_JMPZ_EX) {
|
||||
should_jmp = !should_jmp;
|
||||
|
||||
@@ -106,7 +106,9 @@ void zend_optimizer_pass3(zend_op_array *op_array)
|
||||
zend_uchar tmp_type = opline->op1_type;
|
||||
znode_op tmp = opline->op1;
|
||||
|
||||
if (opline->opcode != ZEND_ADD || ZEND_OP1_TYPE(opline) == IS_CONST) {
|
||||
if (opline->opcode != ZEND_ADD
|
||||
|| (ZEND_OP1_TYPE(opline) == IS_CONST
|
||||
&& Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_ARRAY)) {
|
||||
/* protection from array add: $a = array + $a is not commutative! */
|
||||
COPY_NODE(opline->op1, opline->op2);
|
||||
COPY_NODE(opline->op2, tmp);
|
||||
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine, Call Graph |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id:$ */
|
||||
|
||||
#include "php.h"
|
||||
#include "zend_compile.h"
|
||||
#include "zend_extensions.h"
|
||||
#include "zend_inference.h"
|
||||
#include "zend_call_graph.h"
|
||||
#include "zend_func_info.h"
|
||||
#include "zend_inference.h"
|
||||
#include "zend_call_graph.h"
|
||||
|
||||
typedef int (*zend_op_array_func_t)(zend_call_graph *call_graph, zend_op_array *op_array);
|
||||
|
||||
static int zend_op_array_calc(zend_call_graph *call_graph, zend_op_array *op_array)
|
||||
{
|
||||
(void) op_array;
|
||||
|
||||
call_graph->op_arrays_count++;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int zend_op_array_collect(zend_call_graph *call_graph, zend_op_array *op_array)
|
||||
{
|
||||
zend_func_info *func_info = call_graph->func_infos + call_graph->op_arrays_count;
|
||||
|
||||
ZEND_SET_FUNC_INFO(op_array, func_info);
|
||||
call_graph->op_arrays[call_graph->op_arrays_count] = op_array;
|
||||
func_info->num = call_graph->op_arrays_count;
|
||||
func_info->num_args = -1;
|
||||
func_info->return_value_used = -1;
|
||||
call_graph->op_arrays_count++;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int zend_foreach_op_array(zend_call_graph *call_graph, zend_script *script, zend_op_array_func_t func)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zend_op_array *op_array;
|
||||
|
||||
if (func(call_graph, &script->main_op_array) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
ZEND_HASH_FOREACH_PTR(&script->function_table, op_array) {
|
||||
if (func(call_graph, op_array) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
|
||||
ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
|
||||
if (op_array->scope == ce) {
|
||||
if (func(call_graph, op_array) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static void zend_collect_args_info(zend_call_info *call_info)
|
||||
{
|
||||
zend_op *opline = call_info->caller_init_opline;
|
||||
zend_op *end = call_info->caller_call_opline;
|
||||
uint32_t i;
|
||||
int num;
|
||||
int level = 0;
|
||||
|
||||
ZEND_ASSERT(opline && end);
|
||||
if (!opline->extended_value) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < opline->extended_value; i++) {
|
||||
call_info->arg_info[i].opline = NULL;
|
||||
}
|
||||
while (opline < end) {
|
||||
opline++;
|
||||
switch (opline->opcode) {
|
||||
case ZEND_SEND_VAL:
|
||||
case ZEND_SEND_VAR:
|
||||
case ZEND_SEND_VAL_EX:
|
||||
case ZEND_SEND_VAR_EX:
|
||||
case ZEND_SEND_REF:
|
||||
case ZEND_SEND_VAR_NO_REF:
|
||||
num = opline->op2.num;
|
||||
if (num > 0) {
|
||||
num--;
|
||||
}
|
||||
if (!level) {
|
||||
call_info->arg_info[num].opline = opline;
|
||||
}
|
||||
break;
|
||||
case ZEND_SEND_ARRAY:
|
||||
case ZEND_SEND_USER:
|
||||
case ZEND_SEND_UNPACK:
|
||||
// ???
|
||||
break;
|
||||
case ZEND_INIT_FCALL:
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
case ZEND_INIT_NS_FCALL_BY_NAME:
|
||||
case ZEND_INIT_DYNAMIC_CALL:
|
||||
case ZEND_NEW:
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_INIT_USER_CALL:
|
||||
level++;
|
||||
break;
|
||||
case ZEND_DO_FCALL:
|
||||
case ZEND_DO_ICALL:
|
||||
case ZEND_DO_UCALL:
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
level--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_op_array *op_array, zend_func_info *func_info)
|
||||
{
|
||||
zend_op *opline = op_array->opcodes;
|
||||
zend_op *end = opline + op_array->last;
|
||||
zend_function *func;
|
||||
zend_call_info *call_info;
|
||||
int call = 0;
|
||||
zend_call_info **call_stack;
|
||||
ALLOCA_FLAG(use_heap);
|
||||
|
||||
call_stack = do_alloca((op_array->last / 2) * sizeof(zend_call_info*), use_heap);
|
||||
while (opline != end) {
|
||||
call_info = NULL;
|
||||
switch (opline->opcode) {
|
||||
case ZEND_INIT_FCALL:
|
||||
if ((func = zend_hash_find_ptr(&script->function_table, Z_STR_P(CRT_CONSTANT(opline->op2)))) != NULL) {
|
||||
zend_func_info *callee_func_info = ZEND_FUNC_INFO(&func->op_array);
|
||||
if (callee_func_info) {
|
||||
call_info = zend_arena_calloc(arena, 1, sizeof(zend_call_info) + (sizeof(zend_send_arg_info) * ((int)opline->extended_value - 1)));
|
||||
call_info->caller_op_array = op_array;
|
||||
call_info->caller_init_opline = opline;
|
||||
call_info->caller_call_opline = NULL;
|
||||
call_info->callee_func = func;
|
||||
call_info->num_args = opline->extended_value;
|
||||
call_info->next_caller = callee_func_info->caller_info;
|
||||
callee_func_info->caller_info = call_info;
|
||||
call_info->next_callee = func_info->callee_info;
|
||||
func_info->callee_info = call_info;
|
||||
}
|
||||
} else if ((func = zend_hash_find_ptr(EG(function_table), Z_STR_P(CRT_CONSTANT(opline->op2)))) != NULL &&
|
||||
func->type == ZEND_INTERNAL_FUNCTION) {
|
||||
call_info = zend_arena_calloc(arena, 1, sizeof(zend_call_info) + (sizeof(zend_send_arg_info) * ((int)opline->extended_value - 1)));
|
||||
call_info->caller_op_array = op_array;
|
||||
call_info->caller_init_opline = opline;
|
||||
call_info->caller_call_opline = NULL;
|
||||
call_info->callee_func = func;
|
||||
call_info->num_args = opline->extended_value;
|
||||
call_info->next_caller = NULL;
|
||||
call_info->next_callee = func_info->callee_info;
|
||||
func_info->callee_info = call_info;
|
||||
}
|
||||
/* break missing intentionally */
|
||||
case ZEND_INIT_FCALL_BY_NAME:
|
||||
case ZEND_INIT_NS_FCALL_BY_NAME:
|
||||
case ZEND_INIT_DYNAMIC_CALL:
|
||||
case ZEND_NEW:
|
||||
case ZEND_INIT_METHOD_CALL:
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_INIT_USER_CALL:
|
||||
call_stack[call] = call_info;
|
||||
call++;
|
||||
break;
|
||||
case ZEND_DO_FCALL:
|
||||
case ZEND_DO_ICALL:
|
||||
case ZEND_DO_UCALL:
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
func_info->flags |= ZEND_FUNC_HAS_CALLS;
|
||||
call--;
|
||||
if (call_stack[call]) {
|
||||
call_stack[call]->caller_call_opline = opline;
|
||||
zend_collect_args_info(call_stack[call]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
opline++;
|
||||
}
|
||||
free_alloca(call_stack, use_heap);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int zend_is_indirectly_recursive(zend_op_array *root, zend_op_array *op_array, zend_bitset visited)
|
||||
{
|
||||
zend_func_info *func_info;
|
||||
zend_call_info *call_info;
|
||||
int ret = 0;
|
||||
|
||||
if (op_array == root) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
func_info = ZEND_FUNC_INFO(op_array);
|
||||
if (zend_bitset_in(visited, func_info->num)) {
|
||||
return 0;
|
||||
}
|
||||
zend_bitset_incl(visited, func_info->num);
|
||||
call_info = func_info->caller_info;
|
||||
while (call_info) {
|
||||
if (zend_is_indirectly_recursive(root, call_info->caller_op_array, visited)) {
|
||||
call_info->recursive = 1;
|
||||
ret = 1;
|
||||
}
|
||||
call_info = call_info->next_caller;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void zend_analyze_recursion(zend_call_graph *call_graph)
|
||||
{
|
||||
zend_op_array *op_array;
|
||||
zend_func_info *func_info;
|
||||
zend_call_info *call_info;
|
||||
int i;
|
||||
int set_len = zend_bitset_len(call_graph->op_arrays_count);
|
||||
zend_bitset visited;
|
||||
ALLOCA_FLAG(use_heap);
|
||||
|
||||
visited = ZEND_BITSET_ALLOCA(set_len, use_heap);
|
||||
for (i = 0; i < call_graph->op_arrays_count; i++) {
|
||||
op_array = call_graph->op_arrays[i];
|
||||
func_info = call_graph->func_infos + i;
|
||||
call_info = func_info->caller_info;
|
||||
while (call_info) {
|
||||
if (call_info->caller_op_array == op_array) {
|
||||
call_info->recursive = 1;
|
||||
func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_DIRECTLY;
|
||||
} else {
|
||||
memset(visited, 0, sizeof(uint32_t) * set_len);
|
||||
if (zend_is_indirectly_recursive(op_array, call_info->caller_op_array, visited)) {
|
||||
call_info->recursive = 1;
|
||||
func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_INDIRECTLY;
|
||||
}
|
||||
}
|
||||
call_info = call_info->next_caller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_sort_op_arrays(zend_call_graph *call_graph)
|
||||
{
|
||||
(void) call_graph;
|
||||
|
||||
// TODO: perform topological sort of cyclic call graph
|
||||
}
|
||||
|
||||
int zend_build_call_graph(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_call_graph *call_graph) /* {{{ */
|
||||
{
|
||||
int i;
|
||||
|
||||
call_graph->op_arrays_count = 0;
|
||||
if (zend_foreach_op_array(call_graph, script, zend_op_array_calc) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
call_graph->op_arrays = (zend_op_array**)zend_arena_calloc(arena, call_graph->op_arrays_count, sizeof(zend_op_array*));
|
||||
call_graph->func_infos = (zend_func_info*)zend_arena_calloc(arena, call_graph->op_arrays_count, sizeof(zend_func_info));
|
||||
if (!call_graph->op_arrays || !call_graph->func_infos) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
call_graph->op_arrays_count = 0;
|
||||
if (zend_foreach_op_array(call_graph, script, zend_op_array_collect) != SUCCESS) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
for (i = 0; i < call_graph->op_arrays_count; i++) {
|
||||
zend_analyze_calls(arena, script, build_flags, call_graph->op_arrays[i], call_graph->func_infos + i);
|
||||
}
|
||||
zend_analyze_recursion(call_graph);
|
||||
zend_sort_op_arrays(call_graph);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine, Call Graph |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef ZEND_CALL_GRAPH_H
|
||||
#define ZEND_CALL_GRAPH_H
|
||||
|
||||
#include "zend_ssa.h"
|
||||
#include "zend_func_info.h"
|
||||
#include "zend_optimizer.h"
|
||||
|
||||
typedef struct _zend_send_arg_info {
|
||||
zend_op *opline;
|
||||
} zend_send_arg_info;
|
||||
|
||||
typedef struct _zend_recv_arg_info {
|
||||
int ssa_var;
|
||||
zend_ssa_var_info info;
|
||||
} zend_recv_arg_info;
|
||||
|
||||
struct _zend_call_info {
|
||||
zend_op_array *caller_op_array;
|
||||
zend_op *caller_init_opline;
|
||||
zend_op *caller_call_opline;
|
||||
zend_function *callee_func;
|
||||
zend_call_info *next_caller;
|
||||
zend_call_info *next_callee;
|
||||
zend_func_info *clone;
|
||||
int recursive;
|
||||
int num_args;
|
||||
zend_send_arg_info arg_info[1];
|
||||
};
|
||||
|
||||
struct _zend_func_info {
|
||||
int num;
|
||||
uint32_t flags;
|
||||
zend_ssa ssa; /* Static Single Assignmnt Form */
|
||||
zend_call_info *caller_info; /* where this function is called from */
|
||||
zend_call_info *callee_info; /* which functions are called from this one */
|
||||
int num_args; /* (-1 - unknown) */
|
||||
zend_recv_arg_info *arg_info;
|
||||
zend_ssa_var_info return_info;
|
||||
zend_func_info *clone;
|
||||
int clone_num;
|
||||
int return_value_used; /* -1 unknown, 0 no, 1 yes */
|
||||
void *codegen_data;
|
||||
};
|
||||
|
||||
typedef struct _zend_call_graph {
|
||||
int op_arrays_count;
|
||||
zend_op_array **op_arrays;
|
||||
zend_func_info *func_infos;
|
||||
} zend_call_graph;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
int zend_build_call_graph(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_call_graph *call_graph);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif /* ZEND_CALL_GRAPH_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -19,8 +19,10 @@
|
||||
#include "php.h"
|
||||
#include "zend_compile.h"
|
||||
#include "zend_cfg.h"
|
||||
#include "zend_func_info.h"
|
||||
#include "zend_worklist.h"
|
||||
|
||||
static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend_basic_block *b)
|
||||
static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend_basic_block *b) /* {{{ */
|
||||
{
|
||||
zend_uchar opcode;
|
||||
zend_basic_block *b0;
|
||||
@@ -72,8 +74,9 @@ static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_mark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg, int start)
|
||||
static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg, int start) /* {{{ */
|
||||
{
|
||||
zend_basic_block *blocks = cfg->blocks;
|
||||
|
||||
@@ -195,8 +198,9 @@ static void zend_mark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg, i
|
||||
} while (changed);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void zend_remark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg)
|
||||
void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg) /* {{{ */
|
||||
{
|
||||
zend_basic_block *blocks = cfg->blocks;
|
||||
int i;
|
||||
@@ -217,6 +221,7 @@ void zend_remark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg)
|
||||
|
||||
zend_mark_reachable_blocks(op_array, cfg, start);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void record_successor(zend_basic_block *blocks, int pred, int n, int succ)
|
||||
{
|
||||
@@ -228,7 +233,7 @@ static void record_successor(zend_basic_block *blocks, int pred, int n, int succ
|
||||
block_map[i] = 1; \
|
||||
} while (0)
|
||||
|
||||
int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants, int stackless, zend_cfg *cfg, uint32_t *func_flags) /* {{{ */
|
||||
int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg, uint32_t *func_flags) /* {{{ */
|
||||
{
|
||||
uint32_t flags = 0;
|
||||
uint32_t i;
|
||||
@@ -266,7 +271,7 @@ int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants
|
||||
case ZEND_YIELD:
|
||||
case ZEND_YIELD_FROM:
|
||||
flags |= ZEND_FUNC_TOO_DYNAMIC;
|
||||
if (stackless) {
|
||||
if (build_flags & ZEND_CFG_STACKLESS) {
|
||||
BB_START(i + 1);
|
||||
}
|
||||
break;
|
||||
@@ -274,7 +279,7 @@ int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants
|
||||
case ZEND_DO_UCALL:
|
||||
case ZEND_DO_FCALL_BY_NAME:
|
||||
flags |= ZEND_FUNC_HAS_CALLS;
|
||||
if (stackless) {
|
||||
if (build_flags & ZEND_CFG_STACKLESS) {
|
||||
BB_START(i + 1);
|
||||
}
|
||||
break;
|
||||
@@ -282,11 +287,7 @@ int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants
|
||||
flags |= ZEND_FUNC_HAS_CALLS;
|
||||
break;
|
||||
case ZEND_INIT_FCALL:
|
||||
if (rt_constants) {
|
||||
zv = RT_CONSTANT(op_array, opline->op2);
|
||||
} else {
|
||||
zv = CT_CONSTANT_EX(op_array, opline->op2.constant);
|
||||
}
|
||||
zv = CRT_CONSTANT(opline->op2);
|
||||
if ((fn = zend_hash_find_ptr(EG(function_table), Z_STR_P(zv))) != NULL) {
|
||||
if (fn->type == ZEND_INTERNAL_FUNCTION) {
|
||||
if (Z_STRLEN_P(zv) == sizeof("extract")-1 &&
|
||||
@@ -377,11 +378,7 @@ int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants
|
||||
case ZEND_DECLARE_LAMBDA_FUNCTION: {
|
||||
//??? zend_op_array *lambda_op_array;
|
||||
//???
|
||||
//??? if (rt_constants) {
|
||||
//??? zv = RT_CONSTANT(op_array, opline->op1);
|
||||
//??? } else {
|
||||
//??? zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
|
||||
//??? }
|
||||
//??? zv = CRT_CONSTANT(opline->op1);
|
||||
//??? if (ctx->main_script &&
|
||||
//??? (lambda_op_array = zend_hash_find_ptr(&ctx->main_script->function_table, Z_STR_P(zv))) != NULL) {
|
||||
//??? if (lambda_op_array->type == ZEND_USER_FUNCTION &&
|
||||
@@ -536,7 +533,7 @@ int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants
|
||||
zend_mark_reachable_blocks(op_array, cfg, 0);
|
||||
|
||||
if (func_flags) {
|
||||
*func_flags = flags;
|
||||
*func_flags |= flags;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@@ -606,6 +603,207 @@ int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg) /* {{{ */
|
||||
{
|
||||
zend_basic_block *blocks = cfg->blocks;
|
||||
int blocks_count = cfg->blocks_count;
|
||||
int j, k, changed;
|
||||
|
||||
/* FIXME: move declarations */
|
||||
blocks[0].idom = 0;
|
||||
do {
|
||||
changed = 0;
|
||||
for (j = 1; j < blocks_count; j++) {
|
||||
int idom = -1;
|
||||
|
||||
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
|
||||
continue;
|
||||
}
|
||||
for (k = 0; k < blocks[j].predecessors_count; k++) {
|
||||
int pred = cfg->predecessors[blocks[j].predecessor_offset + k];
|
||||
|
||||
if (idom < 0) {
|
||||
if (blocks[pred].idom >= 0)
|
||||
idom = pred;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (blocks[pred].idom >= 0) {
|
||||
while (idom != pred) {
|
||||
while (pred > idom) pred = blocks[pred].idom;
|
||||
while (idom > pred) idom = blocks[idom].idom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (idom >= 0 && blocks[j].idom != idom) {
|
||||
blocks[j].idom = idom;
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
} while (changed);
|
||||
blocks[0].idom = -1;
|
||||
|
||||
for (j = 1; j < blocks_count; j++) {
|
||||
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (blocks[j].idom >= 0) {
|
||||
/* Sort by block number to traverse children in pre-order */
|
||||
if (blocks[blocks[j].idom].children < 0 ||
|
||||
j < blocks[blocks[j].idom].children) {
|
||||
blocks[j].next_child = blocks[blocks[j].idom].children;
|
||||
blocks[blocks[j].idom].children = j;
|
||||
} else {
|
||||
int k = blocks[blocks[j].idom].children;
|
||||
while (blocks[k].next_child >=0 && j > blocks[k].next_child) {
|
||||
k = blocks[k].next_child;
|
||||
}
|
||||
blocks[j].next_child = blocks[k].next_child;
|
||||
blocks[k].next_child = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < blocks_count; j++) {
|
||||
int idom = blocks[j].idom, level = 0;
|
||||
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
|
||||
continue;
|
||||
}
|
||||
while (idom >= 0) {
|
||||
level++;
|
||||
if (blocks[idom].level >= 0) {
|
||||
level += blocks[idom].level;
|
||||
break;
|
||||
} else {
|
||||
idom = blocks[idom].idom;
|
||||
}
|
||||
}
|
||||
blocks[j].level = level;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static int dominates(zend_basic_block *blocks, int a, int b) /* {{{ */
|
||||
{
|
||||
while (blocks[b].level > blocks[a].level) {
|
||||
b = blocks[b].idom;
|
||||
}
|
||||
return a == b;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
int zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg, uint32_t *flags) /* {{{ */
|
||||
{
|
||||
int i, j, k;
|
||||
int depth;
|
||||
zend_basic_block *blocks = cfg->blocks;
|
||||
int *dj_spanning_tree;
|
||||
zend_worklist work;
|
||||
int flag = ZEND_FUNC_NO_LOOPS;
|
||||
ALLOCA_FLAG(list_use_heap);
|
||||
ALLOCA_FLAG(tree_use_heap);
|
||||
|
||||
ZEND_WORKLIST_ALLOCA(&work, cfg->blocks_count, list_use_heap);
|
||||
dj_spanning_tree = do_alloca(sizeof(int) * cfg->blocks_count, tree_use_heap);
|
||||
|
||||
for (i = 0; i < cfg->blocks_count; i++) {
|
||||
dj_spanning_tree[i] = -1;
|
||||
}
|
||||
zend_worklist_push(&work, 0);
|
||||
while (zend_worklist_len(&work)) {
|
||||
next:
|
||||
i = zend_worklist_peek(&work);
|
||||
/* Visit blocks immediately dominated by i. */
|
||||
for (j = blocks[i].children; j >= 0; j = blocks[j].next_child) {
|
||||
if (zend_worklist_push(&work, j)) {
|
||||
dj_spanning_tree[j] = i;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
/* Visit join edges. */
|
||||
for (j = 0; j < 2; j++) {
|
||||
int succ = blocks[i].successors[j];
|
||||
if (succ < 0) {
|
||||
continue;
|
||||
} else if (blocks[succ].idom == i) {
|
||||
continue;
|
||||
} else if (zend_worklist_push(&work, succ)) {
|
||||
dj_spanning_tree[succ] = i;
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
zend_worklist_pop(&work);
|
||||
}
|
||||
|
||||
/* Identify loops. See Sreedhar et al, "Identifying Loops Using DJ
|
||||
Graphs". */
|
||||
|
||||
for (i = 0, depth = 0; i < cfg->blocks_count; i++) {
|
||||
if (blocks[i].level > depth) {
|
||||
depth = blocks[i].level;
|
||||
}
|
||||
}
|
||||
for (; depth >= 0; depth--) {
|
||||
for (i = 0; i < cfg->blocks_count; i++) {
|
||||
if (blocks[i].level != depth) {
|
||||
continue;
|
||||
}
|
||||
zend_bitset_clear(work.visited, zend_bitset_len(cfg->blocks_count));
|
||||
for (j = 0; j < blocks[i].predecessors_count; j++) {
|
||||
int pred = cfg->predecessors[blocks[i].predecessor_offset + j];
|
||||
|
||||
/* A join edge is one for which the predecessor does not
|
||||
immediately dominate the successor. */
|
||||
if (blocks[i].idom == pred) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* In a loop back-edge (back-join edge), the successor dominates
|
||||
the predecessor. */
|
||||
if (dominates(blocks, i, pred)) {
|
||||
blocks[i].flags |= ZEND_BB_LOOP_HEADER;
|
||||
flag &= ~ZEND_FUNC_NO_LOOPS;
|
||||
zend_worklist_push(&work, pred);
|
||||
} else {
|
||||
/* Otherwise it's a cross-join edge. See if it's a branch
|
||||
to an ancestor on the dominator spanning tree. */
|
||||
int dj_parent = pred;
|
||||
while (dj_parent >= 0) {
|
||||
if (dj_parent == i) {
|
||||
/* An sp-back edge: mark as irreducible. */
|
||||
blocks[i].flags |= ZEND_BB_IRREDUCIBLE_LOOP;
|
||||
flag |= ZEND_FUNC_IRREDUCIBLE;
|
||||
flag &= ~ZEND_FUNC_NO_LOOPS;
|
||||
break;
|
||||
} else {
|
||||
dj_parent = dj_spanning_tree[dj_parent];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (zend_worklist_len(&work)) {
|
||||
j = zend_worklist_pop(&work);
|
||||
if (blocks[j].loop_header < 0 && j != i) {
|
||||
blocks[j].loop_header = i;
|
||||
for (k = 0; k < blocks[j].predecessors_count; k++) {
|
||||
zend_worklist_push(&work, cfg->predecessors[blocks[j].predecessor_offset + k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_alloca(dj_spanning_tree, tree_use_heap);
|
||||
ZEND_WORKLIST_FREE_ALLOCA(&work, list_use_heap);
|
||||
*flags |= flag;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
#ifndef ZEND_CFG_H
|
||||
#define ZEND_CFG_H
|
||||
|
||||
/* func flags */
|
||||
#define ZEND_FUNC_TOO_DYNAMIC (1<<0)
|
||||
#define ZEND_FUNC_HAS_CALLS (1<<1)
|
||||
#define ZEND_FUNC_VARARG (1<<2)
|
||||
|
||||
/* zend_basic_bloc.flags */
|
||||
#define ZEND_BB_START (1<<0) /* fist block */
|
||||
#define ZEND_BB_FOLLOW (1<<1) /* follows the next block */
|
||||
@@ -36,6 +31,7 @@
|
||||
#define ZEND_BB_FINALLY_END (1<<8) /* end of finally block */
|
||||
#define ZEND_BB_GEN_VAR (1<<9) /* start of live range */
|
||||
#define ZEND_BB_KILL_VAR (1<<10) /* end of live range */
|
||||
#define ZEND_BB_EMPTY (1<<11)
|
||||
|
||||
#define ZEND_BB_LOOP_HEADER (1<<16)
|
||||
#define ZEND_BB_IRREDUCIBLE_LOOP (1<<17)
|
||||
@@ -92,11 +88,32 @@ typedef struct _zend_cfg {
|
||||
uint32_t *map;
|
||||
} zend_cfg;
|
||||
|
||||
/* Build Flags */
|
||||
#define ZEND_RT_CONSTANTS (1<<31)
|
||||
#define ZEND_CFG_STACKLESS (1<<30)
|
||||
#define ZEND_SSA_DEBUG_LIVENESS (1<<29)
|
||||
#define ZEND_SSA_DEBUG_PHI_PLACEMENT (1<<28)
|
||||
|
||||
#define CRT_CONSTANT_EX(op_array, node, rt_constants) \
|
||||
((rt_constants) ? \
|
||||
RT_CONSTANT(op_array, (node)) \
|
||||
: \
|
||||
CT_CONSTANT_EX(op_array, (node).constant) \
|
||||
)
|
||||
|
||||
#define CRT_CONSTANT(node) \
|
||||
CRT_CONSTANT_EX(op_array, node, (build_flags & ZEND_RT_CONSTANTS))
|
||||
|
||||
#define RETURN_VALUE_USED(opline) \
|
||||
(!((opline)->result_type & EXT_TYPE_UNUSED))
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants, int stackless, zend_cfg *cfg, uint32_t *func_flags);
|
||||
void zend_remark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg);
|
||||
int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg);
|
||||
int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg, uint32_t *func_flags);
|
||||
void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg);
|
||||
int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg);
|
||||
int zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg);
|
||||
int zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg, uint32_t *flags);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine, DFG - Data Flow Graph |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "php.h"
|
||||
#include "zend_compile.h"
|
||||
#include "zend_dfg.h"
|
||||
|
||||
int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg) /* {{{ */
|
||||
{
|
||||
int set_size;
|
||||
zend_basic_block *blocks = cfg->blocks;
|
||||
int blocks_count = cfg->blocks_count;
|
||||
zend_bitset tmp, gen, def, use, in, out;
|
||||
zend_op *opline;
|
||||
uint32_t k;
|
||||
int j, changed;
|
||||
|
||||
/* FIXME: can we use "gen" instead of "def" for flow analyzing? */
|
||||
set_size = dfg->size;
|
||||
tmp = dfg->tmp;
|
||||
gen = dfg->gen;
|
||||
def = dfg->def;
|
||||
use = dfg->use;
|
||||
in = dfg->in;
|
||||
out = dfg->out;
|
||||
|
||||
/* Collect "gen", "def" and "use" sets */
|
||||
for (j = 0; j < blocks_count; j++) {
|
||||
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
|
||||
continue;
|
||||
}
|
||||
for (k = blocks[j].start; k <= blocks[j].end; k++) {
|
||||
opline = op_array->opcodes + k;
|
||||
if (opline->opcode != ZEND_OP_DATA) {
|
||||
zend_op *next = opline + 1;
|
||||
if (k < blocks[j].end &&
|
||||
next->opcode == ZEND_OP_DATA) {
|
||||
if (next->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
|
||||
if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(next->op1.var))) {
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op1.var));
|
||||
}
|
||||
}
|
||||
if (next->op2_type == IS_CV) {
|
||||
if (!DFG_ISSET(def, set_size, j,EX_VAR_TO_NUM(next->op2.var))) {
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op2.var));
|
||||
}
|
||||
} else if (next->op2_type == IS_VAR ||
|
||||
next->op2_type == IS_TMP_VAR) {
|
||||
/* ZEND_ASSIGN_??? use the second operand
|
||||
of the following OP_DATA instruction as
|
||||
a temporary variable */
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
case ZEND_ASSIGN_ADD:
|
||||
case ZEND_ASSIGN_SUB:
|
||||
case ZEND_ASSIGN_MUL:
|
||||
case ZEND_ASSIGN_DIV:
|
||||
case ZEND_ASSIGN_MOD:
|
||||
case ZEND_ASSIGN_SL:
|
||||
case ZEND_ASSIGN_SR:
|
||||
case ZEND_ASSIGN_CONCAT:
|
||||
case ZEND_ASSIGN_BW_OR:
|
||||
case ZEND_ASSIGN_BW_AND:
|
||||
case ZEND_ASSIGN_BW_XOR:
|
||||
case ZEND_ASSIGN_POW:
|
||||
break;
|
||||
default:
|
||||
if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(next->op2.var))) {
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op2.var));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opline->op1_type == IS_CV) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN:
|
||||
case ZEND_ASSIGN_REF:
|
||||
case ZEND_BIND_GLOBAL:
|
||||
case ZEND_SEND_VAR_EX:
|
||||
case ZEND_SEND_REF:
|
||||
case ZEND_SEND_VAR_NO_REF:
|
||||
case ZEND_FE_RESET_R:
|
||||
case ZEND_FE_RESET_RW:
|
||||
case ZEND_ADD_ARRAY_ELEMENT:
|
||||
case ZEND_INIT_ARRAY:
|
||||
if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) {
|
||||
// FIXME: include into "use" to ...?
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
|
||||
DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
|
||||
}
|
||||
DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
|
||||
break;
|
||||
case ZEND_ASSIGN_ADD:
|
||||
case ZEND_ASSIGN_SUB:
|
||||
case ZEND_ASSIGN_MUL:
|
||||
case ZEND_ASSIGN_DIV:
|
||||
case ZEND_ASSIGN_MOD:
|
||||
case ZEND_ASSIGN_SL:
|
||||
case ZEND_ASSIGN_SR:
|
||||
case ZEND_ASSIGN_CONCAT:
|
||||
case ZEND_ASSIGN_BW_OR:
|
||||
case ZEND_ASSIGN_BW_AND:
|
||||
case ZEND_ASSIGN_BW_XOR:
|
||||
case ZEND_ASSIGN_POW:
|
||||
case ZEND_PRE_INC:
|
||||
case ZEND_PRE_DEC:
|
||||
case ZEND_POST_INC:
|
||||
case ZEND_POST_DEC:
|
||||
case ZEND_ASSIGN_DIM:
|
||||
case ZEND_ASSIGN_OBJ:
|
||||
case ZEND_UNSET_DIM:
|
||||
case ZEND_UNSET_OBJ:
|
||||
case ZEND_FETCH_DIM_W:
|
||||
case ZEND_FETCH_DIM_RW:
|
||||
case ZEND_FETCH_DIM_FUNC_ARG:
|
||||
case ZEND_FETCH_DIM_UNSET:
|
||||
case ZEND_FETCH_OBJ_W:
|
||||
case ZEND_FETCH_OBJ_RW:
|
||||
case ZEND_FETCH_OBJ_FUNC_ARG:
|
||||
case ZEND_FETCH_OBJ_UNSET:
|
||||
DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
|
||||
default:
|
||||
if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) {
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
|
||||
}
|
||||
}
|
||||
} else if (opline->op1_type == IS_VAR ||
|
||||
opline->op1_type == IS_TMP_VAR) {
|
||||
if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) {
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
|
||||
}
|
||||
}
|
||||
if (opline->op2_type == IS_CV) {
|
||||
switch (opline->opcode) {
|
||||
case ZEND_ASSIGN:
|
||||
case ZEND_ASSIGN_REF:
|
||||
case ZEND_FE_FETCH_R:
|
||||
case ZEND_FE_FETCH_RW:
|
||||
if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) {
|
||||
// FIXME: include into "use" to ...?
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
|
||||
DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
|
||||
}
|
||||
DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
|
||||
break;
|
||||
default:
|
||||
if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) {
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (opline->op2_type == IS_VAR ||
|
||||
opline->op2_type == IS_TMP_VAR) {
|
||||
if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) {
|
||||
if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) {
|
||||
DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
|
||||
}
|
||||
DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
|
||||
} else {
|
||||
if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) {
|
||||
DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opline->result_type == IS_CV) {
|
||||
if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->result.var))) {
|
||||
DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->result.var));
|
||||
}
|
||||
DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->result.var));
|
||||
} else if (opline->result_type == IS_VAR ||
|
||||
opline->result_type == IS_TMP_VAR) {
|
||||
if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->result.var))) {
|
||||
DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->result.var));
|
||||
}
|
||||
DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->result.var));
|
||||
}
|
||||
if ((opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) && opline->result_type == IS_TMP_VAR) {
|
||||
if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(next->result.var))) {
|
||||
DFG_SET(def, set_size, j, EX_VAR_TO_NUM(next->result.var));
|
||||
}
|
||||
DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(next->result.var));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate "in" and "out" sets */
|
||||
do {
|
||||
changed = 0;
|
||||
for (j = 0; j < blocks_count; j++) {
|
||||
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (blocks[j].successors[0] >= 0) {
|
||||
zend_bitset_copy(DFG_BITSET(out, set_size, j), DFG_BITSET(in, set_size, blocks[j].successors[0]), set_size);
|
||||
if (blocks[j].successors[1] >= 0) {
|
||||
zend_bitset_union(DFG_BITSET(out, set_size, j), DFG_BITSET(in, set_size, blocks[j].successors[1]), set_size);
|
||||
}
|
||||
} else {
|
||||
zend_bitset_clear(DFG_BITSET(out, set_size, j), set_size);
|
||||
}
|
||||
zend_bitset_union_with_difference(tmp, DFG_BITSET(use, set_size, j), DFG_BITSET(out, set_size, j), DFG_BITSET(def, set_size, j), set_size);
|
||||
if (!zend_bitset_equal(DFG_BITSET(in, set_size, j), tmp, set_size)) {
|
||||
zend_bitset_copy(DFG_BITSET(in, set_size, j), tmp, set_size);
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
} while (changed);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine, DFG - Data Flow Graph |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef ZEND_DFG_H
|
||||
#define ZEND_DFG_H
|
||||
|
||||
#include "zend_bitset.h"
|
||||
#include "zend_cfg.h"
|
||||
|
||||
typedef struct _zend_dfg {
|
||||
int vars;
|
||||
uint32_t size;
|
||||
zend_bitset tmp;
|
||||
zend_bitset gen;
|
||||
zend_bitset def;
|
||||
zend_bitset use;
|
||||
zend_bitset in;
|
||||
zend_bitset out;
|
||||
} zend_dfg;
|
||||
|
||||
#define DFG_BITSET(set, set_size, block_num) \
|
||||
((set) + ((block_num) * (set_size)))
|
||||
|
||||
#define DFG_SET(set, set_size, block_num, var_num) \
|
||||
zend_bitset_incl(DFG_BITSET(set, set_size, block_num), (var_num))
|
||||
|
||||
#define DFG_ISSET(set, set_size, block_num, var_num) \
|
||||
zend_bitset_in(DFG_BITSET(set, set_size, block_num), (var_num))
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif /* ZEND_DFG_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
+1002
-106
File diff suppressed because it is too large
Load Diff
@@ -19,9 +19,24 @@
|
||||
#ifndef ZEND_DUMP_H
|
||||
#define ZEND_DUMP_H
|
||||
|
||||
#include "zend_ssa.h"
|
||||
#include "zend_dfg.h"
|
||||
|
||||
#define ZEND_DUMP_HIDE_UNREACHABLE (1<<0)
|
||||
#define ZEND_DUMP_HIDE_UNUSED_VARS (1<<1)
|
||||
#define ZEND_DUMP_CFG (1<<2)
|
||||
#define ZEND_DUMP_SSA (1<<3)
|
||||
#define ZEND_DUMP_RT_CONSTANTS ZEND_RT_CONSTANTS
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, int all);
|
||||
void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, const char *msg, const void *data);
|
||||
void zend_dump_dominators(const zend_op_array *op_array, const zend_cfg *cfg);
|
||||
void zend_dump_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg);
|
||||
void zend_dump_phi_placement(const zend_op_array *op_array, const zend_ssa *ssa);
|
||||
void zend_dump_variables(const zend_op_array *op_array);
|
||||
void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa);
|
||||
void zend_dump_var(const zend_op_array *op_array, zend_uchar var_type, int var_num);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine, Func Info |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef ZEND_FUNC_INFO_H
|
||||
#define ZEND_FUNC_INFO_H
|
||||
|
||||
#include "zend_ssa.h"
|
||||
|
||||
/* func flags */
|
||||
#define ZEND_FUNC_TOO_DYNAMIC (1<<0)
|
||||
#define ZEND_FUNC_HAS_CALLS (1<<1)
|
||||
#define ZEND_FUNC_VARARG (1<<2)
|
||||
#define ZEND_FUNC_NO_LOOPS (1<<3)
|
||||
#define ZEND_FUNC_IRREDUCIBLE (1<<4)
|
||||
#define ZEND_FUNC_RECURSIVE (1<<7)
|
||||
#define ZEND_FUNC_RECURSIVE_DIRECTLY (1<<8)
|
||||
#define ZEND_FUNC_RECURSIVE_INDIRECTLY (1<<9)
|
||||
|
||||
/* The following flags are valid only for return values of internal functions
|
||||
* returned by zend_get_func_info()
|
||||
*/
|
||||
#define FUNC_MAY_WARN (1<<30)
|
||||
#define FUNC_MAY_INLINE (1<<31)
|
||||
|
||||
typedef struct _zend_func_info zend_func_info;
|
||||
typedef struct _zend_call_info zend_call_info;
|
||||
|
||||
#define ZEND_FUNC_INFO(op_array) \
|
||||
((zend_func_info*)((op_array)->reserved[zend_func_info_rid]))
|
||||
|
||||
#define ZEND_SET_FUNC_INFO(op_array, info) do { \
|
||||
zend_func_info** pinfo = (zend_func_info**)&(op_array)->reserved[zend_func_info_rid]; \
|
||||
*pinfo = info; \
|
||||
} while (0)
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
extern int zend_func_info_rid;
|
||||
|
||||
uint32_t zend_get_func_info(const zend_call_info *call_info, const zend_ssa *ssa);
|
||||
|
||||
int zend_func_info_startup(void);
|
||||
int zend_func_info_shutdown(void);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif /* ZEND_FUNC_INFO_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine, e-SSA based Type & Range Inference |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef ZEND_INFERENCE_H
|
||||
#define ZEND_INFERENCE_H
|
||||
|
||||
#include "zend_optimizer.h"
|
||||
#include "zend_ssa.h"
|
||||
#include "zend_bitset.h"
|
||||
|
||||
/* Bitmask for type inference (zend_ssa_var_info.type) */
|
||||
#define MAY_BE_UNDEF (1 << IS_UNDEF)
|
||||
#define MAY_BE_NULL (1 << IS_NULL)
|
||||
#define MAY_BE_FALSE (1 << IS_FALSE)
|
||||
#define MAY_BE_TRUE (1 << IS_TRUE)
|
||||
#define MAY_BE_LONG (1 << IS_LONG)
|
||||
#define MAY_BE_DOUBLE (1 << IS_DOUBLE)
|
||||
#define MAY_BE_STRING (1 << IS_STRING)
|
||||
#define MAY_BE_ARRAY (1 << IS_ARRAY)
|
||||
#define MAY_BE_OBJECT (1 << IS_OBJECT)
|
||||
#define MAY_BE_RESOURCE (1 << IS_RESOURCE)
|
||||
#define MAY_BE_ANY (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)
|
||||
#define MAY_BE_REF (1 << IS_REFERENCE) /* may be reference */
|
||||
|
||||
#define MAY_BE_ARRAY_SHIFT (IS_REFERENCE)
|
||||
|
||||
#define MAY_BE_ARRAY_OF_NULL (MAY_BE_NULL << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_FALSE (MAY_BE_FALSE << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_TRUE (MAY_BE_TRUE << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_LONG (MAY_BE_LONG << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_DOUBLE (MAY_BE_DOUBLE << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_STRING (MAY_BE_STRING << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_ARRAY (MAY_BE_ARRAY << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_OBJECT (MAY_BE_OBJECT << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_RESOURCE (MAY_BE_RESOURCE << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_ANY (MAY_BE_ANY << MAY_BE_ARRAY_SHIFT)
|
||||
#define MAY_BE_ARRAY_OF_REF (MAY_BE_REF << MAY_BE_ARRAY_SHIFT)
|
||||
|
||||
#define MAY_BE_ARRAY_KEY_LONG (1<<21)
|
||||
#define MAY_BE_ARRAY_KEY_STRING (1<<22)
|
||||
#define MAY_BE_ARRAY_KEY_ANY (MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_KEY_STRING)
|
||||
|
||||
#define MAY_BE_ERROR (1<<23)
|
||||
#define MAY_BE_CLASS (1<<24)
|
||||
|
||||
#define MAY_BE_IN_REG (1<<25) /* value allocated in CPU register */
|
||||
|
||||
//TODO: remome MAY_BE_DEF, MAY_BE_RC1, MAY_BE_RCN???
|
||||
#define MAY_BE_DEF (1<<26)
|
||||
#define MAY_BE_RC1 (1<<27) /* may be non-reference with refcount == 1 */
|
||||
#define MAY_BE_RCN (1<<28) /* may be non-reference with refcount > 1 */
|
||||
|
||||
|
||||
#define DEFINE_SSA_OP_HAS_RANGE(opN) \
|
||||
static zend_always_inline long _ssa_##opN##_has_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline) \
|
||||
{ \
|
||||
if (opline->opN##_type == IS_CONST) { \
|
||||
zval *zv = CRT_CONSTANT_EX(op_array, opline->opN, ssa->rt_constants); \
|
||||
return (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE || Z_TYPE_P(zv) == IS_NULL); \
|
||||
} else { \
|
||||
return (opline->opN##_type != IS_UNUSED && \
|
||||
ssa->ops && \
|
||||
ssa->var_info && \
|
||||
ssa->ops[opline - op_array->opcodes].opN##_use >= 0 && \
|
||||
ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].has_range); \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define DEFINE_SSA_OP_MIN_RANGE(opN) \
|
||||
static zend_always_inline long _ssa_##opN##_min_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline) \
|
||||
{ \
|
||||
if (opline->opN##_type == IS_CONST) { \
|
||||
zval *zv = CRT_CONSTANT_EX(op_array, opline->opN, ssa->rt_constants); \
|
||||
if (Z_TYPE_P(zv) == IS_LONG) { \
|
||||
return Z_LVAL_P(zv); \
|
||||
} else if (Z_TYPE_P(zv) == IS_TRUE) { \
|
||||
return 1; \
|
||||
} else if (Z_TYPE_P(zv) == IS_FALSE) { \
|
||||
return 0; \
|
||||
} else if (Z_TYPE_P(zv) == IS_NULL) { \
|
||||
return 0; \
|
||||
} \
|
||||
} else if (opline->opN##_type != IS_UNUSED && \
|
||||
ssa->ops && \
|
||||
ssa->var_info && \
|
||||
ssa->ops[opline - op_array->opcodes].opN##_use >= 0 && \
|
||||
ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].has_range) { \
|
||||
return ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].range.min; \
|
||||
} \
|
||||
return LONG_MIN; \
|
||||
}
|
||||
|
||||
#define DEFINE_SSA_OP_MAX_RANGE(opN) \
|
||||
static zend_always_inline long _ssa_##opN##_max_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline) \
|
||||
{ \
|
||||
if (opline->opN##_type == IS_CONST) { \
|
||||
zval *zv = CRT_CONSTANT_EX(op_array, opline->opN, ssa->rt_constants); \
|
||||
if (Z_TYPE_P(zv) == IS_LONG) { \
|
||||
return Z_LVAL_P(zv); \
|
||||
} else if (Z_TYPE_P(zv) == IS_TRUE) { \
|
||||
return 1; \
|
||||
} else if (Z_TYPE_P(zv) == IS_FALSE) { \
|
||||
return 0; \
|
||||
} else if (Z_TYPE_P(zv) == IS_NULL) { \
|
||||
return 0; \
|
||||
} \
|
||||
} else if (opline->opN##_type != IS_UNUSED && \
|
||||
ssa->ops && \
|
||||
ssa->var_info && \
|
||||
ssa->ops[opline - op_array->opcodes].opN##_use >= 0 && \
|
||||
ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].has_range) { \
|
||||
return ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].range.max; \
|
||||
} \
|
||||
return LONG_MAX; \
|
||||
}
|
||||
|
||||
#define DEFINE_SSA_OP_RANGE_UNDERFLOW(opN) \
|
||||
static zend_always_inline char _ssa_##opN##_range_underflow(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline) \
|
||||
{ \
|
||||
if (opline->opN##_type == IS_CONST) { \
|
||||
zval *zv = CRT_CONSTANT_EX(op_array, opline->opN, ssa->rt_constants); \
|
||||
if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE || Z_TYPE_P(zv) == IS_NULL) { \
|
||||
return 0; \
|
||||
} \
|
||||
} else if (opline->opN##_type != IS_UNUSED && \
|
||||
ssa->ops && \
|
||||
ssa->var_info && \
|
||||
ssa->ops[opline - op_array->opcodes].opN##_use >= 0 && \
|
||||
ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].has_range) { \
|
||||
return ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].range.underflow; \
|
||||
} \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define DEFINE_SSA_OP_RANGE_OVERFLOW(opN) \
|
||||
static zend_always_inline char _ssa_##opN##_range_overflow(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline) \
|
||||
{ \
|
||||
if (opline->opN##_type == IS_CONST) { \
|
||||
zval *zv = CRT_CONSTANT_EX(op_array, opline->opN, ssa->rt_constants); \
|
||||
if (Z_TYPE_P(zv) == IS_LONG || Z_TYPE_P(zv) == IS_TRUE || Z_TYPE_P(zv) == IS_FALSE || Z_TYPE_P(zv) == IS_NULL) { \
|
||||
return 0; \
|
||||
} \
|
||||
} else if (opline->opN##_type != IS_UNUSED && \
|
||||
ssa->ops && \
|
||||
ssa->var_info && \
|
||||
ssa->ops[opline - op_array->opcodes].opN##_use >= 0 && \
|
||||
ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].has_range) { \
|
||||
return ssa->var_info[ssa->ops[opline - op_array->opcodes].opN##_use].range.overflow; \
|
||||
} \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
DEFINE_SSA_OP_HAS_RANGE(op1)
|
||||
DEFINE_SSA_OP_MIN_RANGE(op1)
|
||||
DEFINE_SSA_OP_MAX_RANGE(op1)
|
||||
DEFINE_SSA_OP_RANGE_UNDERFLOW(op1)
|
||||
DEFINE_SSA_OP_RANGE_OVERFLOW(op1)
|
||||
DEFINE_SSA_OP_HAS_RANGE(op2)
|
||||
DEFINE_SSA_OP_MIN_RANGE(op2)
|
||||
DEFINE_SSA_OP_MAX_RANGE(op2)
|
||||
DEFINE_SSA_OP_RANGE_UNDERFLOW(op2)
|
||||
DEFINE_SSA_OP_RANGE_OVERFLOW(op2)
|
||||
|
||||
#define OP1_HAS_RANGE() (_ssa_op1_has_range (op_array, ssa, opline))
|
||||
#define OP1_MIN_RANGE() (_ssa_op1_min_range (op_array, ssa, opline))
|
||||
#define OP1_MAX_RANGE() (_ssa_op1_max_range (op_array, ssa, opline))
|
||||
#define OP1_RANGE_UNDERFLOW() (_ssa_op1_range_underflow (op_array, ssa, opline))
|
||||
#define OP1_RANGE_OVERFLOW() (_ssa_op1_range_overflow (op_array, ssa, opline))
|
||||
#define OP2_HAS_RANGE() (_ssa_op2_has_range (op_array, ssa, opline))
|
||||
#define OP2_MIN_RANGE() (_ssa_op2_min_range (op_array, ssa, opline))
|
||||
#define OP2_MAX_RANGE() (_ssa_op2_max_range (op_array, ssa, opline))
|
||||
#define OP2_RANGE_UNDERFLOW() (_ssa_op2_range_underflow (op_array, ssa, opline))
|
||||
#define OP2_RANGE_OVERFLOW() (_ssa_op2_range_overflow (op_array, ssa, opline))
|
||||
|
||||
static zend_always_inline uint32_t _const_op_type(const zval *zv) {
|
||||
if (Z_TYPE_P(zv) == IS_CONSTANT) {
|
||||
return MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY;
|
||||
} else if (Z_TYPE_P(zv) == IS_CONSTANT_AST) {
|
||||
return MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY;
|
||||
} else if (Z_TYPE_P(zv) == IS_ARRAY) {
|
||||
HashTable *ht = Z_ARRVAL_P(zv);
|
||||
uint32_t tmp = MAY_BE_ARRAY | MAY_BE_DEF | MAY_BE_RC1;
|
||||
|
||||
zend_string *str;
|
||||
zval *val;
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, str, val) {
|
||||
if (str) {
|
||||
tmp |= MAY_BE_ARRAY_KEY_STRING;
|
||||
} else {
|
||||
tmp |= MAY_BE_ARRAY_KEY_LONG;
|
||||
}
|
||||
tmp |= 1 << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
return tmp;
|
||||
} else {
|
||||
return (1 << Z_TYPE_P(zv)) | MAY_BE_DEF | MAY_BE_RC1;
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline uint32_t get_ssa_var_info(const zend_ssa *ssa, int ssa_var_num)
|
||||
{
|
||||
if (ssa->var_info && ssa_var_num >= 0) {
|
||||
return ssa->var_info[ssa_var_num].type;
|
||||
} else {
|
||||
return MAY_BE_DEF | MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | MAY_BE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_SSA_OP_INFO(opN) \
|
||||
static zend_always_inline uint32_t _ssa_##opN##_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline) \
|
||||
{ \
|
||||
if (opline->opN##_type == IS_CONST) { \
|
||||
return _const_op_type(CRT_CONSTANT_EX(op_array, opline->opN, ssa->rt_constants)); \
|
||||
} else { \
|
||||
return get_ssa_var_info(ssa, ssa->ops ? ssa->ops[opline - op_array->opcodes].opN##_use : -1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_SSA_OP_DEF_INFO(opN) \
|
||||
static zend_always_inline uint32_t _ssa_##opN##_def_info(const zend_op_array *op_array, const zend_ssa *ssa, const zend_op *opline) \
|
||||
{ \
|
||||
return get_ssa_var_info(ssa, ssa->ops ? ssa->ops[opline - op_array->opcodes].opN##_def : -1); \
|
||||
}
|
||||
|
||||
|
||||
DEFINE_SSA_OP_INFO(op1)
|
||||
DEFINE_SSA_OP_INFO(op2)
|
||||
DEFINE_SSA_OP_INFO(result)
|
||||
DEFINE_SSA_OP_DEF_INFO(op1)
|
||||
DEFINE_SSA_OP_DEF_INFO(op2)
|
||||
DEFINE_SSA_OP_DEF_INFO(result)
|
||||
|
||||
#define OP1_INFO() (_ssa_op1_info(op_array, ssa, opline))
|
||||
#define OP2_INFO() (_ssa_op2_info(op_array, ssa, opline))
|
||||
#define OP1_DATA_INFO() (_ssa_op1_info(op_array, ssa, (opline+1)))
|
||||
#define OP2_DATA_INFO() (_ssa_op2_info(op_array, ssa, (opline+1)))
|
||||
#define RES_USE_INFO() (_ssa_result_info(op_array, ssa, opline))
|
||||
#define OP1_DEF_INFO() (_ssa_op1_def_info(op_array, ssa, opline))
|
||||
#define OP2_DEF_INFO() (_ssa_op2_def_info(op_array, ssa, opline))
|
||||
#define OP1_DATA_DEF_INFO() (_ssa_op1_def_info(op_array, ssa, (opline+1)))
|
||||
#define OP2_DATA_DEF_INFO() (_ssa_op2_def_info(op_array, ssa, (opline+1)))
|
||||
#define RES_INFO() (_ssa_result_def_info(op_array, ssa, opline))
|
||||
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa);
|
||||
int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa);
|
||||
int zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa);
|
||||
|
||||
uint32_t zend_array_element_type(uint32_t t1, int write, int insert);
|
||||
|
||||
int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int var, int widening, int narrowing, zend_ssa_range *tmp);
|
||||
void zend_inference_init_range(const zend_op_array *op_array, zend_ssa *ssa, int var, zend_bool underflow, long min, long max, zend_bool overflow);
|
||||
int zend_inference_narrowing_meet(zend_ssa_var_info *var_info, zend_ssa_range *r);
|
||||
int zend_inference_widening_meet(zend_ssa_var_info *var_info, zend_ssa_range *r);
|
||||
void zend_inference_check_recursive_dependencies(zend_op_array *op_array);
|
||||
|
||||
int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_bitset worklist);
|
||||
|
||||
void zend_func_return_info(const zend_op_array *op_array,
|
||||
int recursive,
|
||||
int widening,
|
||||
zend_ssa_var_info *ret);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif /* ZEND_INFERENCE_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -26,6 +26,9 @@
|
||||
#include "zend_constants.h"
|
||||
#include "zend_execute.h"
|
||||
#include "zend_vm.h"
|
||||
#include "zend_cfg.h"
|
||||
#include "zend_func_info.h"
|
||||
#include "zend_dump.h"
|
||||
|
||||
static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
|
||||
{
|
||||
@@ -132,6 +135,10 @@ static inline void drop_leading_backslash(zval *val) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void alloc_cache_slots_op1(zend_op_array *op_array, zend_op *opline, uint32_t num) {
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size;
|
||||
op_array->cache_size += num * sizeof(void *);
|
||||
}
|
||||
static inline void alloc_cache_slots_op2(zend_op_array *op_array, zend_op *opline, uint32_t num) {
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
|
||||
op_array->cache_size += num * sizeof(void *);
|
||||
@@ -160,7 +167,7 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
||||
case ZEND_FREE:
|
||||
MAKE_NOP(opline);
|
||||
zval_dtor(val);
|
||||
break;
|
||||
return 1;
|
||||
case ZEND_INIT_STATIC_METHOD_CALL:
|
||||
case ZEND_CATCH:
|
||||
case ZEND_FETCH_CONSTANT:
|
||||
@@ -168,27 +175,40 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
|
||||
case ZEND_DEFINED:
|
||||
case ZEND_NEW:
|
||||
REQUIRES_STRING(val);
|
||||
ZEND_OP1_TYPE(opline) = IS_CONST;
|
||||
drop_leading_backslash(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
|
||||
Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size;
|
||||
op_array->cache_size += sizeof(void*);
|
||||
alloc_cache_slots_op1(op_array, opline, 1);
|
||||
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
|
||||
break;
|
||||
case ZEND_FETCH_STATIC_PROP_R:
|
||||
case ZEND_FETCH_STATIC_PROP_W:
|
||||
case ZEND_FETCH_STATIC_PROP_RW:
|
||||
case ZEND_FETCH_STATIC_PROP_IS:
|
||||
case ZEND_FETCH_STATIC_PROP_UNSET:
|
||||
case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
|
||||
TO_STRING_NOWARN(val);
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
alloc_cache_slots_op1(op_array, opline, 2);
|
||||
break;
|
||||
case ZEND_CONCAT:
|
||||
case ZEND_FAST_CONCAT:
|
||||
case ZEND_FETCH_R:
|
||||
case ZEND_FETCH_W:
|
||||
case ZEND_FETCH_RW:
|
||||
case ZEND_FETCH_IS:
|
||||
case ZEND_FETCH_UNSET:
|
||||
case ZEND_FETCH_FUNC_ARG:
|
||||
TO_STRING_NOWARN(val);
|
||||
/* break missing intentionally */
|
||||
default:
|
||||
ZEND_OP1_TYPE(opline) = IS_CONST;
|
||||
opline->op1.constant = zend_optimizer_add_literal(op_array, val);
|
||||
if (Z_TYPE_P(val) == IS_STRING) {
|
||||
zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ZEND_OP1_TYPE(opline) = IS_CONST;
|
||||
if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
|
||||
zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -529,6 +549,10 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_BEFORE_OPTIMIZER) {
|
||||
zend_dump_op_array(op_array, 0, "before optimizer", NULL);
|
||||
}
|
||||
|
||||
/* pass 1
|
||||
* - substitute persistent constants (true, false, null, etc)
|
||||
* - perform compile-time evaluation of constant binary and unary operations
|
||||
@@ -537,6 +561,9 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_1 & ctx->optimization_level) {
|
||||
zend_optimizer_pass1(op_array, ctx);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_1) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 1", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 2:
|
||||
@@ -547,6 +574,9 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_2 & ctx->optimization_level) {
|
||||
zend_optimizer_pass2(op_array);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_2) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 2", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 3:
|
||||
@@ -556,6 +586,9 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_3 & ctx->optimization_level) {
|
||||
zend_optimizer_pass3(op_array);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_3) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 1", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 4:
|
||||
@@ -563,6 +596,9 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_4 & ctx->optimization_level) {
|
||||
optimize_func_calls(op_array, ctx);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_4) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 1", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 5:
|
||||
@@ -570,6 +606,19 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_5 & ctx->optimization_level) {
|
||||
optimize_cfg(op_array, ctx);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_5) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 5", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 6:
|
||||
* - DFA optimization
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) {
|
||||
optimize_dfa(op_array, ctx);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_6) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 6", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 9:
|
||||
@@ -577,6 +626,9 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_9 & ctx->optimization_level) {
|
||||
optimize_temporary_variables(op_array, ctx);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_9) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 9", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 10:
|
||||
@@ -584,6 +636,9 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & ctx->optimization_level) == ZEND_OPTIMIZER_PASS_10) {
|
||||
zend_optimizer_nop_removal(op_array);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_10) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 10", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* pass 11:
|
||||
@@ -591,6 +646,13 @@ static void zend_optimize(zend_op_array *op_array,
|
||||
*/
|
||||
if (ZEND_OPTIMIZER_PASS_11 & ctx->optimization_level) {
|
||||
zend_optimizer_compact_literals(op_array, ctx);
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_11) {
|
||||
zend_dump_op_array(op_array, 0, "after pass 11", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->debug_level & ZEND_DUMP_AFTER_OPTIMIZER) {
|
||||
zend_dump_op_array(op_array, 0, "after optimizer", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,7 +712,7 @@ static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer
|
||||
}
|
||||
}
|
||||
|
||||
int zend_optimize_script(zend_script *script, zend_long optimization_level)
|
||||
int zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level)
|
||||
{
|
||||
uint idx, j;
|
||||
Bucket *p, *q;
|
||||
@@ -662,6 +724,7 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level)
|
||||
ctx.script = script;
|
||||
ctx.constants = NULL;
|
||||
ctx.optimization_level = optimization_level;
|
||||
ctx.debug_level = debug_level;
|
||||
|
||||
zend_optimize_op_array(&script->main_op_array, &ctx);
|
||||
|
||||
@@ -732,3 +795,21 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zend_optimizer_startup(void)
|
||||
{
|
||||
return zend_func_info_startup();
|
||||
}
|
||||
|
||||
int zend_optimizer_shutdown(void)
|
||||
{
|
||||
return zend_func_info_shutdown();
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define ZEND_OPTIMIZER_PASS_3 (1<<2) /* ++, +=, series of jumps */
|
||||
#define ZEND_OPTIMIZER_PASS_4 (1<<3) /* INIT_FCALL_BY_NAME -> DO_FCALL */
|
||||
#define ZEND_OPTIMIZER_PASS_5 (1<<4) /* CFG based optimization */
|
||||
#define ZEND_OPTIMIZER_PASS_6 (1<<5)
|
||||
#define ZEND_OPTIMIZER_PASS_6 (1<<5) /* DFA based optimization */
|
||||
#define ZEND_OPTIMIZER_PASS_7 (1<<6)
|
||||
#define ZEND_OPTIMIZER_PASS_8 (1<<7)
|
||||
#define ZEND_OPTIMIZER_PASS_9 (1<<8) /* TMP VAR usage */
|
||||
@@ -44,6 +44,38 @@
|
||||
|
||||
#define DEFAULT_OPTIMIZATION_LEVEL "0xFFFFFFFF"
|
||||
|
||||
|
||||
#define ZEND_DUMP_AFTER_PASS_1 ZEND_OPTIMIZER_PASS_1
|
||||
#define ZEND_DUMP_AFTER_PASS_2 ZEND_OPTIMIZER_PASS_2
|
||||
#define ZEND_DUMP_AFTER_PASS_3 ZEND_OPTIMIZER_PASS_3
|
||||
#define ZEND_DUMP_AFTER_PASS_4 ZEND_OPTIMIZER_PASS_4
|
||||
#define ZEND_DUMP_AFTER_PASS_5 ZEND_OPTIMIZER_PASS_5
|
||||
#define ZEND_DUMP_AFTER_PASS_6 ZEND_OPTIMIZER_PASS_6
|
||||
#define ZEND_DUMP_AFTER_PASS_7 ZEND_OPTIMIZER_PASS_7
|
||||
#define ZEND_DUMP_AFTER_PASS_8 ZEND_OPTIMIZER_PASS_8
|
||||
#define ZEND_DUMP_AFTER_PASS_9 ZEND_OPTIMIZER_PASS_9
|
||||
#define ZEND_DUMP_AFTER_PASS_10 ZEND_OPTIMIZER_PASS_10
|
||||
#define ZEND_DUMP_AFTER_PASS_11 ZEND_OPTIMIZER_PASS_11
|
||||
#define ZEND_DUMP_AFTER_PASS_12 ZEND_OPTIMIZER_PASS_12
|
||||
#define ZEND_DUMP_AFTER_PASS_13 ZEND_OPTIMIZER_PASS_13
|
||||
#define ZEND_DUMP_AFTER_PASS_14 ZEND_OPTIMIZER_PASS_14
|
||||
|
||||
#define ZEND_DUMP_BEFORE_OPTIMIZER (1<<16)
|
||||
#define ZEND_DUMP_AFTER_OPTIMIZER (1<<17)
|
||||
|
||||
#define ZEND_DUMP_BEFORE_BLOCK_PASS (1<<18)
|
||||
#define ZEND_DUMP_AFTER_BLOCK_PASS (1<<19)
|
||||
#define ZEND_DUMP_BLOCK_PASS_VARS (1<<20)
|
||||
|
||||
#define ZEND_DUMP_BEFORE_DFA_PASS (1<<21)
|
||||
#define ZEND_DUMP_AFTER_DFA_PASS (1<<22)
|
||||
#define ZEND_DUMP_DFA_CFG (1<<23)
|
||||
#define ZEND_DUMP_DFA_DOMINATORS (1<<24)
|
||||
#define ZEND_DUMP_DFA_LIVENESS (1<<25)
|
||||
#define ZEND_DUMP_DFA_PHI (1<<26)
|
||||
#define ZEND_DUMP_DFA_SSA (1<<27)
|
||||
#define ZEND_DUMP_DFA_SSA_VARS (1<<28)
|
||||
|
||||
typedef struct _zend_script {
|
||||
zend_string *filename;
|
||||
zend_op_array main_op_array;
|
||||
@@ -51,6 +83,8 @@ typedef struct _zend_script {
|
||||
HashTable class_table;
|
||||
} zend_script;
|
||||
|
||||
int zend_optimize_script(zend_script *script, zend_long optimization_level);
|
||||
int zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level);
|
||||
int zend_optimizer_startup(void);
|
||||
int zend_optimizer_shutdown(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,7 @@ typedef struct _zend_optimizer_ctx {
|
||||
zend_script *script;
|
||||
HashTable *constants;
|
||||
zend_long optimization_level;
|
||||
zend_long debug_level;
|
||||
} zend_optimizer_ctx;
|
||||
|
||||
#define LITERAL_LONG(op, val) do { \
|
||||
@@ -96,6 +97,7 @@ void zend_optimizer_pass2(zend_op_array *op_array);
|
||||
void zend_optimizer_pass3(zend_op_array *op_array);
|
||||
void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
void zend_optimizer_nop_removal(zend_op_array *op_array);
|
||||
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine, SSA - Static Single Assignment Form |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Dmitry Stogov <dmitry@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef ZEND_SSA_H
|
||||
#define ZEND_SSA_H
|
||||
|
||||
#include "zend_cfg.h"
|
||||
|
||||
typedef struct _zend_ssa_range {
|
||||
zend_long min;
|
||||
zend_long max;
|
||||
zend_bool underflow;
|
||||
zend_bool overflow;
|
||||
} zend_ssa_range;
|
||||
|
||||
typedef enum _zend_ssa_negative_lat {
|
||||
NEG_NONE = 0,
|
||||
NEG_INIT = 1,
|
||||
NEG_INVARIANT = 2,
|
||||
NEG_USE_LT = 3,
|
||||
NEG_USE_GT = 4,
|
||||
NEG_UNKNOWN = 5
|
||||
} zend_ssa_negative_lat;
|
||||
|
||||
/* Special kind of SSA Phi function used in eSSA */
|
||||
typedef struct _zend_ssa_pi_range {
|
||||
zend_ssa_range range; /* simple range constraint */
|
||||
int min_var;
|
||||
int max_var;
|
||||
int min_ssa_var; /* ((min_var>0) ? MIN(ssa_var) : 0) + range.min */
|
||||
int max_ssa_var; /* ((man_var>0) ? MAX(ssa_var) : 0) + range.man */
|
||||
zend_ssa_negative_lat negative;
|
||||
} zend_ssa_pi_range;
|
||||
|
||||
/* SSA Phi - ssa_var = Phi(source0, source1, ...sourceN) */
|
||||
typedef struct _zend_ssa_phi zend_ssa_phi;
|
||||
struct _zend_ssa_phi {
|
||||
zend_ssa_phi *next; /* next Phi in the same BB */
|
||||
int pi; /* if >= 0 this is actually a e-SSA Pi */
|
||||
zend_ssa_pi_range constraint; /* e-SSA Pi constraint */
|
||||
int var; /* Original CV, VAR or TMP variable index */
|
||||
int ssa_var; /* SSA variable index */
|
||||
int block; /* current BB index */
|
||||
int visited; /* flag to avoid recursive processing */
|
||||
zend_ssa_phi **use_chains;
|
||||
zend_ssa_phi *sym_use_chain;
|
||||
int *sources; /* Array of SSA IDs that produce this var.
|
||||
As many as this block has
|
||||
predecessors. */
|
||||
};
|
||||
|
||||
typedef struct _zend_ssa_block {
|
||||
zend_ssa_phi *phis;
|
||||
} zend_ssa_block;
|
||||
|
||||
typedef struct _zend_ssa_op {
|
||||
int op1_use;
|
||||
int op2_use;
|
||||
int result_use;
|
||||
int op1_def;
|
||||
int op2_def;
|
||||
int result_def;
|
||||
int op1_use_chain;
|
||||
int op2_use_chain;
|
||||
int res_use_chain;
|
||||
} zend_ssa_op;
|
||||
|
||||
typedef struct _zend_ssa_var {
|
||||
int var; /* original var number; op.var for CVs and following numbers for VARs and TMP_VARs */
|
||||
int scc; /* strongly connected component */
|
||||
int definition; /* opcode that defines this value */
|
||||
zend_ssa_phi *definition_phi; /* phi that defines this value */
|
||||
int use_chain; /* uses of this value, linked through opN_use_chain */
|
||||
zend_ssa_phi *phi_use_chain; /* uses of this value in Phi, linked through use_chain */
|
||||
zend_ssa_phi *sym_use_chain; /* uses of this value in Pi constaints */
|
||||
unsigned int no_val : 1; /* value doesn't mater (used as op1 in ZEND_ASSIGN) */
|
||||
unsigned int scc_entry : 1;
|
||||
} zend_ssa_var;
|
||||
|
||||
typedef struct _zend_ssa_var_info {
|
||||
uint32_t type; /* inferred type (see zend_inference.h) */
|
||||
zend_ssa_range range;
|
||||
zend_class_entry *ce;
|
||||
unsigned int has_range : 1;
|
||||
unsigned int is_instanceof : 1; /* 0 - class == "ce", 1 - may be child of "ce" */
|
||||
unsigned int recursive : 1;
|
||||
unsigned int use_as_double : 1;
|
||||
} zend_ssa_var_info;
|
||||
|
||||
typedef struct _zend_ssa {
|
||||
zend_cfg cfg; /* control flow graph */
|
||||
int rt_constants; /* run-time or compile-time */
|
||||
int vars_count; /* number of SSA variables */
|
||||
zend_ssa_block *blocks; /* array of SSA blocks */
|
||||
zend_ssa_op *ops; /* array of SSA instructions */
|
||||
zend_ssa_var *vars; /* use/def chain of SSA variables */
|
||||
int sccs; /* number of SCCs */
|
||||
zend_ssa_var_info *var_info;
|
||||
} zend_ssa;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, uint32_t *func_flags);
|
||||
int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa);
|
||||
int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, int use)
|
||||
{
|
||||
ssa_op += use;
|
||||
if (ssa_op->result_use == var) {
|
||||
return ssa_op->res_use_chain;
|
||||
}
|
||||
return (ssa_op->op1_use == var) ? ssa_op->op1_use_chain : ssa_op->op2_use_chain;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(zend_ssa *ssa, int var, zend_ssa_phi *p)
|
||||
{
|
||||
if (p->pi >= 0) {
|
||||
return p->use_chains[0];
|
||||
} else {
|
||||
int j;
|
||||
for (j = 0; j < ssa->cfg.blocks[p->block].predecessors_count; j++) {
|
||||
if (p->sources[j] == var) {
|
||||
return p->use_chains[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* ZEND_SSA_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Zend Engine |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1998-2015 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 |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Andy Wingo <wingo@igalia.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id:$ */
|
||||
|
||||
#ifndef _ZEND_WORKLIST_H_
|
||||
#define _ZEND_WORKLIST_H_
|
||||
|
||||
#include "zend_arena.h"
|
||||
#include "zend_bitset.h"
|
||||
|
||||
typedef struct _zend_worklist_stack {
|
||||
int *buf;
|
||||
int len;
|
||||
int capacity;
|
||||
} zend_worklist_stack;
|
||||
|
||||
#define ZEND_WORKLIST_STACK_ALLOCA(s, _len, use_heap) do { \
|
||||
(s)->buf = (int*)do_alloca(sizeof(int) * _len, use_heap); \
|
||||
(s)->len = 0; \
|
||||
(s)->capacity = _len; \
|
||||
} while (0)
|
||||
|
||||
#define ZEND_WORKLIST_STACK_FREE_ALLOCA(s, use_heap) \
|
||||
free_alloca((s)->buf, use_heap)
|
||||
|
||||
static inline int zend_worklist_stack_prepare(zend_arena **arena, zend_worklist_stack *stack, int len)
|
||||
{
|
||||
ZEND_ASSERT(len >= 0);
|
||||
|
||||
stack->buf = (int*)zend_arena_calloc(arena, sizeof(*stack->buf), len);
|
||||
if (!stack->buf) {
|
||||
return FAILURE;
|
||||
}
|
||||
stack->len = 0;
|
||||
stack->capacity = len;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static inline void zend_worklist_stack_push(zend_worklist_stack *stack, int i)
|
||||
{
|
||||
ZEND_ASSERT(stack->len < stack->capacity);
|
||||
stack->buf[stack->len++] = i;
|
||||
}
|
||||
|
||||
static inline int zend_worklist_stack_peek(zend_worklist_stack *stack)
|
||||
{
|
||||
ZEND_ASSERT(stack->len);
|
||||
return stack->buf[stack->len - 1];
|
||||
}
|
||||
|
||||
static inline int zend_worklist_stack_pop(zend_worklist_stack *stack)
|
||||
{
|
||||
ZEND_ASSERT(stack->len);
|
||||
return stack->buf[--stack->len];
|
||||
}
|
||||
|
||||
typedef struct _zend_worklist {
|
||||
zend_bitset visited;
|
||||
zend_worklist_stack stack;
|
||||
} zend_worklist;
|
||||
|
||||
#define ZEND_WORKLIST_ALLOCA(w, _len, use_heap) do { \
|
||||
(w)->stack.buf = (int*)do_alloca(sizeof(int) * _len + sizeof(zend_ulong) * zend_bitset_len(_len), use_heap); \
|
||||
(w)->stack.len = 0; \
|
||||
(w)->stack.capacity = _len; \
|
||||
(w)->visited = (zend_bitset)((w)->stack.buf + _len); \
|
||||
memset((w)->visited, 0, sizeof(zend_ulong) * zend_bitset_len(_len)); \
|
||||
} while (0)
|
||||
|
||||
#define ZEND_WORKLIST_FREE_ALLOCA(w, use_heap) \
|
||||
free_alloca((w)->stack.buf, use_heap)
|
||||
|
||||
static inline int zend_worklist_prepare(zend_arena **arena, zend_worklist *worklist, int len)
|
||||
{
|
||||
ZEND_ASSERT(len >= 0);
|
||||
worklist->visited = (zend_bitset)zend_arena_calloc(arena, sizeof(zend_ulong), zend_bitset_len(len));
|
||||
if (!worklist->visited) {
|
||||
return FAILURE;
|
||||
}
|
||||
return zend_worklist_stack_prepare(arena, &worklist->stack, len);
|
||||
}
|
||||
|
||||
static inline int zend_worklist_len(zend_worklist *worklist)
|
||||
{
|
||||
return worklist->stack.len;
|
||||
}
|
||||
|
||||
static inline int zend_worklist_push(zend_worklist *worklist, int i)
|
||||
{
|
||||
ZEND_ASSERT(i >= 0 && i < worklist->stack.capacity);
|
||||
|
||||
if (zend_bitset_in(worklist->visited, i)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
zend_bitset_incl(worklist->visited, i);
|
||||
zend_worklist_stack_push(&worklist->stack, i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int zend_worklist_peek(zend_worklist *worklist)
|
||||
{
|
||||
return zend_worklist_stack_peek(&worklist->stack);
|
||||
}
|
||||
|
||||
static inline int zend_worklist_pop(zend_worklist *worklist)
|
||||
{
|
||||
/* Does not clear visited flag */
|
||||
return zend_worklist_stack_pop(&worklist->stack);
|
||||
}
|
||||
|
||||
#endif /* _ZEND_WORKLIST_H_ */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: t
|
||||
* End:
|
||||
*/
|
||||
@@ -1157,7 +1157,7 @@ static zend_persistent_script *cache_script_in_file_cache(zend_persistent_script
|
||||
return new_persistent_script;
|
||||
}
|
||||
|
||||
if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level)) {
|
||||
if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
|
||||
return new_persistent_script;
|
||||
}
|
||||
|
||||
@@ -1215,7 +1215,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
|
||||
return new_persistent_script;
|
||||
}
|
||||
|
||||
if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level)) {
|
||||
if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level, ZCG(accel_directives).opt_debug_level)) {
|
||||
return new_persistent_script;
|
||||
}
|
||||
|
||||
@@ -2348,6 +2348,7 @@ static inline int accel_find_sapi(void)
|
||||
"apache2filter",
|
||||
"apache2handler",
|
||||
"litespeed",
|
||||
"uwsgi",
|
||||
NULL
|
||||
};
|
||||
const char **sapi_name;
|
||||
|
||||
@@ -191,6 +191,7 @@ typedef struct _zend_accel_directives {
|
||||
zend_long log_verbosity_level;
|
||||
|
||||
zend_long optimization_level;
|
||||
zend_long opt_debug_level;
|
||||
zend_long max_file_size;
|
||||
zend_long interned_strings_buffer;
|
||||
char *restrict_api;
|
||||
|
||||
@@ -404,6 +404,12 @@ fi
|
||||
Optimizer/nop_removal.c \
|
||||
Optimizer/compact_literals.c \
|
||||
Optimizer/zend_cfg.c \
|
||||
Optimizer/zend_dfg.c \
|
||||
Optimizer/dfa_pass.c \
|
||||
Optimizer/zend_ssa.c \
|
||||
Optimizer/zend_inference.c \
|
||||
Optimizer/zend_func_info.c \
|
||||
Optimizer/zend_call_graph.c \
|
||||
Optimizer/zend_dump.c,
|
||||
shared,,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,,yes)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ if (PHP_OPCACHE != "no") {
|
||||
zend_shared_alloc.c \
|
||||
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
|
||||
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dump.c", "opcache", "OptimizerObj");
|
||||
ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c", "opcache", "OptimizerObj");
|
||||
|
||||
|
||||
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
Bug #71127 (Define in auto_prepend_file is overwrite)
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded('Zend OPcache')) die("skip"); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$file = __DIR__ . "/bug71127.inc";
|
||||
|
||||
file_put_contents($file, "<?php define('FOO', 'bad'); echo FOO;?>");
|
||||
|
||||
define("FOO", "okey");
|
||||
|
||||
include($file);
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
@unlink(__DIR__ . "/bug71127.inc");
|
||||
?>
|
||||
--EXPECTF--
|
||||
Notice: Constant FOO already defined in %sbug71127.inc on line %d
|
||||
okey
|
||||
@@ -294,6 +294,7 @@ ZEND_INI_BEGIN()
|
||||
STD_PHP_INI_ENTRY("opcache.fast_shutdown" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.fast_shutdown, zend_accel_globals, accel_globals)
|
||||
|
||||
STD_PHP_INI_ENTRY("opcache.optimization_level" , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.opt_debug_level" , "0" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.opt_debug_level, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_BOOLEAN("opcache.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals)
|
||||
|
||||
@@ -1283,9 +1283,16 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
|
||||
}
|
||||
|
||||
/* verify header */
|
||||
if (memcmp(info.magic, "OPCACHE", 8) != 0 ||
|
||||
memcmp(info.system_id, ZCG(system_id), 32) != 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s'\n", filename);
|
||||
if (memcmp(info.magic, "OPCACHE", 8) != 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong header)\n", filename);
|
||||
zend_file_cache_flock(fd, LOCK_UN);
|
||||
close(fd);
|
||||
unlink(filename);
|
||||
efree(filename);
|
||||
return NULL;
|
||||
}
|
||||
if (memcmp(info.system_id, ZCG(system_id), 32) != 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
|
||||
zend_file_cache_flock(fd, LOCK_UN);
|
||||
close(fd);
|
||||
unlink(filename);
|
||||
|
||||
+78
-46
@@ -208,6 +208,7 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_notice, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, connection)
|
||||
ZEND_ARG_INFO(0, all_notices)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#ifdef HAVE_PQFTABLE
|
||||
@@ -276,6 +277,7 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, result)
|
||||
ZEND_ARG_INFO(0, numeric_index)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all_columns, 0, 0, 1)
|
||||
@@ -961,29 +963,24 @@ static void _close_pgsql_plink(zend_resource *rsrc)
|
||||
*/
|
||||
static void _php_pgsql_notice_handler(void *resource_id, const char *message)
|
||||
{
|
||||
php_pgsql_notice *notice;
|
||||
zval *notices;
|
||||
zval tmp;
|
||||
char *trimed_message;
|
||||
size_t trimed_message_len;
|
||||
|
||||
if (! PGG(ignore_notices)) {
|
||||
notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
|
||||
notice->message = _php_pgsql_trim_message(message, ¬ice->len);
|
||||
if (PGG(log_notices)) {
|
||||
php_error_docref(NULL, E_NOTICE, "%s", notice->message);
|
||||
notices = zend_hash_index_find(&PGG(notices), (zend_ulong)resource_id);
|
||||
if (!notices) {
|
||||
array_init(&tmp);
|
||||
notices = &tmp;
|
||||
zend_hash_index_update(&PGG(notices), (zend_ulong)resource_id, notices);
|
||||
}
|
||||
zend_hash_index_update_ptr(&PGG(notices), (zend_ulong)resource_id, notice);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define PHP_PGSQL_NOTICE_PTR_DTOR _php_pgsql_notice_ptr_dtor
|
||||
|
||||
/* {{{ _php_pgsql_notice_dtor
|
||||
*/
|
||||
static void _php_pgsql_notice_ptr_dtor(zval *el)
|
||||
{
|
||||
php_pgsql_notice *notice = (php_pgsql_notice *)Z_PTR_P(el);
|
||||
if (notice) {
|
||||
efree(notice->message);
|
||||
efree(notice);
|
||||
trimed_message = _php_pgsql_trim_message(message, &trimed_message_len);
|
||||
if (PGG(log_notices)) {
|
||||
php_error_docref(NULL, E_NOTICE, "%s", trimed_message);
|
||||
}
|
||||
add_next_index_stringl(notices, trimed_message, trimed_message_len);
|
||||
efree(trimed_message);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1096,7 +1093,7 @@ static PHP_GINIT_FUNCTION(pgsql)
|
||||
#endif
|
||||
memset(pgsql_globals, 0, sizeof(zend_pgsql_globals));
|
||||
/* Initilize notice message hash at MINIT only */
|
||||
zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, PHP_PGSQL_NOTICE_PTR_DTOR, 1, 0);
|
||||
zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -1199,6 +1196,7 @@ PHP_MINIT_FUNCTION(pgsql)
|
||||
REGISTER_LONG_CONSTANT("PGSQL_DML_EXEC", PGSQL_DML_EXEC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PGSQL_DML_ASYNC", PGSQL_DML_ASYNC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PGSQL_DML_STRING", PGSQL_DML_STRING, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PGSQL_FETCH_NUM", PGSQL_FETCH_NUM, CONST_CS | CONST_PERSISTENT);
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -2306,15 +2304,16 @@ PHP_FUNCTION(pg_affected_rows)
|
||||
/* }}} */
|
||||
#endif
|
||||
|
||||
/* {{{ proto string pg_last_notice(resource connection)
|
||||
/* {{{ proto mixed pg_last_notice(resource connection [, bool all_notices])
|
||||
Returns the last notice set by the backend */
|
||||
PHP_FUNCTION(pg_last_notice)
|
||||
{
|
||||
zval *pgsql_link = NULL;
|
||||
zval *notice, *notices;
|
||||
PGconn *pg_link;
|
||||
php_pgsql_notice *notice;
|
||||
zend_bool all_notices = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pgsql_link) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|b", &pgsql_link, &all_notices) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2323,10 +2322,26 @@ PHP_FUNCTION(pg_last_notice)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if ((notice = zend_hash_index_find_ptr(&PGG(notices), (zend_ulong)Z_RES_HANDLE_P(pgsql_link))) == NULL) {
|
||||
RETURN_FALSE;
|
||||
/* PHP 7.0 and earlier returns FALSE for empty notice.
|
||||
PHP 7.1> returns empty array or string */
|
||||
notices = zend_hash_index_find(&PGG(notices), (zend_ulong)Z_RES_HANDLE_P(pgsql_link));
|
||||
if (all_notices) {
|
||||
if (notices) {
|
||||
RETURN_ZVAL(notices, 1, 0);
|
||||
} else {
|
||||
array_init(return_value);
|
||||
}
|
||||
} else {
|
||||
if (notices) {
|
||||
zend_hash_internal_pointer_end(Z_ARRVAL_P(notices));
|
||||
if ((notice = zend_hash_get_current_data(Z_ARRVAL_P(notices))) == NULL) {
|
||||
RETURN_EMPTY_STRING();
|
||||
}
|
||||
RETURN_ZVAL(notice, 1, 0);
|
||||
} else {
|
||||
RETURN_EMPTY_STRING();
|
||||
}
|
||||
}
|
||||
RETURN_STRINGL(notice->message, notice->len);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -2870,15 +2885,16 @@ PHP_FUNCTION(pg_fetch_object)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto array pg_fetch_all(resource result)
|
||||
/* {{{ proto array pg_fetch_all(resource result [, bool numeric_index])
|
||||
Fetch all rows into array */
|
||||
PHP_FUNCTION(pg_fetch_all)
|
||||
{
|
||||
zval *result;
|
||||
zend_bool numeric_index = 0;
|
||||
PGresult *pgsql_result;
|
||||
pgsql_result_handle *pg_result;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &result) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|b", &result, &numeric_index) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2888,7 +2904,7 @@ PHP_FUNCTION(pg_fetch_all)
|
||||
|
||||
pgsql_result = pg_result->result;
|
||||
array_init(return_value);
|
||||
if (php_pgsql_result2array(pgsql_result, return_value) == FAILURE) {
|
||||
if (php_pgsql_result2array(pgsql_result, return_value, numeric_index) == FAILURE) {
|
||||
zval_dtor(return_value);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -7002,7 +7018,7 @@ PHP_FUNCTION(pg_delete)
|
||||
|
||||
/* {{{ php_pgsql_result2array
|
||||
*/
|
||||
PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array)
|
||||
PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array, zend_bool numeric_index)
|
||||
{
|
||||
zval row;
|
||||
char *field_name;
|
||||
@@ -7014,23 +7030,39 @@ PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array)
|
||||
if ((pg_numrows = PQntuples(pg_result)) <= 0) {
|
||||
return FAILURE;
|
||||
}
|
||||
for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
|
||||
array_init(&row);
|
||||
for (i = 0, num_fields = PQnfields(pg_result); i < num_fields; i++) {
|
||||
if (PQgetisnull(pg_result, pg_row, i)) {
|
||||
field_name = PQfname(pg_result, i);
|
||||
add_assoc_null(&row, field_name);
|
||||
} else {
|
||||
char *element = PQgetvalue(pg_result, pg_row, i);
|
||||
if (element) {
|
||||
const size_t element_len = strlen(element);
|
||||
|
||||
field_name = PQfname(pg_result, i);
|
||||
add_assoc_stringl(&row, field_name, element, element_len);
|
||||
if (numeric_index) {
|
||||
for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
|
||||
array_init(&row);
|
||||
for (i = 0, num_fields = PQnfields(pg_result); i < num_fields; i++) {
|
||||
if (PQgetisnull(pg_result, pg_row, i)) {
|
||||
add_next_index_null(&row);
|
||||
} else {
|
||||
char *element = PQgetvalue(pg_result, pg_row, i);
|
||||
if (element) {
|
||||
const size_t element_len = strlen(element);
|
||||
add_next_index_stringl(&row, element, element_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
add_index_zval(ret_array, pg_row, &row);
|
||||
}
|
||||
} else {
|
||||
for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
|
||||
array_init(&row);
|
||||
for (i = 0, num_fields = PQnfields(pg_result); i < num_fields; i++) {
|
||||
field_name = PQfname(pg_result, i);
|
||||
if (PQgetisnull(pg_result, pg_row, i)) {
|
||||
add_assoc_null(&row, field_name);
|
||||
} else {
|
||||
char *element = PQgetvalue(pg_result, pg_row, i);
|
||||
if (element) {
|
||||
const size_t element_len = strlen(element);
|
||||
add_assoc_stringl(&row, field_name, element, element_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
add_index_zval(ret_array, pg_row, &row);
|
||||
}
|
||||
add_index_zval(ret_array, pg_row, &row);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
@@ -7076,7 +7108,7 @@ PHP_PGSQL_API int php_pgsql_select(PGconn *pg_link, const char *table, zval *ids
|
||||
|
||||
pg_result = PQexec(pg_link, ZSTR_VAL(querystr.s));
|
||||
if (PQresultStatus(pg_result) == PGRES_TUPLES_OK) {
|
||||
ret = php_pgsql_result2array(pg_result, ret_array);
|
||||
ret = php_pgsql_result2array(pg_result, ret_array, (opt & PGSQL_FETCH_NUM));
|
||||
} else {
|
||||
php_error_docref(NULL, E_NOTICE, "Failed to execute '%s'", ZSTR_VAL(querystr.s));
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ PHP_FUNCTION(pg_select);
|
||||
#define PGSQL_DML_ASYNC (1<<10) /* Do async query */
|
||||
#define PGSQL_DML_STRING (1<<11) /* Return query string */
|
||||
#define PGSQL_DML_ESCAPE (1<<12) /* No convert, but escape only */
|
||||
|
||||
#define PGSQL_FETCH_NUM (1<<13) /* Fetch result with numeric index */
|
||||
|
||||
/* exported functions */
|
||||
PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, zval *meta, zend_bool extended);
|
||||
@@ -219,7 +219,7 @@ PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *val
|
||||
PHP_PGSQL_API int php_pgsql_update(PGconn *pg_link, const char *table, zval *values, zval *ids, zend_ulong opt , zend_string **sql);
|
||||
PHP_PGSQL_API int php_pgsql_delete(PGconn *pg_link, const char *table, zval *ids, zend_ulong opt, zend_string **sql);
|
||||
PHP_PGSQL_API int php_pgsql_select(PGconn *pg_link, const char *table, zval *ids, zval *ret_array, zend_ulong opt, zend_string **sql );
|
||||
PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array);
|
||||
PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array, zend_bool numeric_index);
|
||||
|
||||
/* internal functions */
|
||||
static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent);
|
||||
|
||||
@@ -9,35 +9,51 @@ _skip_lc_messages();
|
||||
|
||||
?>
|
||||
--INI--
|
||||
pgsql.log_notice=1
|
||||
pgsql.ignore_notice=0
|
||||
--FILE--
|
||||
<?php
|
||||
include 'config.inc';
|
||||
include 'lcmess.inc';
|
||||
|
||||
ini_set('pgsql.log_notice', TRUE);
|
||||
ini_set('pgsql.ignore_notice', FALSE);
|
||||
|
||||
$db = pg_connect($conn_str);
|
||||
|
||||
_set_lc_messages();
|
||||
|
||||
$res = pg_query($db, 'SET client_min_messages TO NOTICE;');
|
||||
$res = pg_query($db, 'SET client_min_messages TO NOTICE;');
|
||||
var_dump($res);
|
||||
|
||||
// Get empty notice
|
||||
var_dump(pg_last_notice($db));
|
||||
var_dump(pg_last_notice($db, TRUE));
|
||||
|
||||
pg_query($db, "BEGIN;");
|
||||
pg_query($db, "BEGIN;");
|
||||
pg_query($db, "BEGIN;");
|
||||
pg_query($db, "BEGIN;");
|
||||
|
||||
$msg = pg_last_notice($db);
|
||||
if ($msg === FALSE) {
|
||||
echo "Cannot find notice message in hash\n";
|
||||
var_dump($msg);
|
||||
}
|
||||
echo $msg."\n";
|
||||
echo "pg_last_notice() is Ok\n";
|
||||
|
||||
// Get notices
|
||||
var_dump(pg_last_notice($db));
|
||||
var_dump(pg_last_notice($db, TRUE));
|
||||
?>
|
||||
--EXPECTF--
|
||||
resource(%d) of type (pgsql result)
|
||||
string(0) ""
|
||||
array(0) {
|
||||
}
|
||||
|
||||
Notice: pg_query(): %s already a transaction in progress in %s on line %d
|
||||
%s already a transaction in progress
|
||||
pg_last_notice() is Ok
|
||||
|
||||
Notice: pg_query(): %s already a transaction in progress in %s on line %d
|
||||
|
||||
Notice: pg_query(): %s already a transaction in progress in %s on line %d
|
||||
string(52) "WARNING: there is already a transaction in progress"
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(52) "WARNING: there is already a transaction in progress"
|
||||
[1]=>
|
||||
string(52) "WARNING: there is already a transaction in progress"
|
||||
[2]=>
|
||||
string(52) "WARNING: there is already a transaction in progress"
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ PHP_MSHUTDOWN_FUNCTION(readline)
|
||||
|
||||
PHP_RSHUTDOWN_FUNCTION(readline)
|
||||
{
|
||||
zval_dtor(&_readline_completion);
|
||||
zval_ptr_dtor(&_readline_completion);
|
||||
ZVAL_UNDEF(&_readline_completion);
|
||||
#if HAVE_RL_CALLBACK_READ_CHAR
|
||||
if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
|
||||
@@ -505,7 +505,7 @@ static char **_readline_completion_cb(const char *text, int start, int end)
|
||||
for (i = 0; i < 3; i++) {
|
||||
zval_ptr_dtor(¶ms[i]);
|
||||
}
|
||||
zval_dtor(&_readline_array);
|
||||
zval_ptr_dtor(&_readline_array);
|
||||
|
||||
return matches;
|
||||
}
|
||||
@@ -526,8 +526,8 @@ PHP_FUNCTION(readline_completion_function)
|
||||
}
|
||||
zend_string_release(name);
|
||||
|
||||
zval_dtor(&_readline_completion);
|
||||
ZVAL_DUP(&_readline_completion, arg);
|
||||
zval_ptr_dtor(&_readline_completion);
|
||||
ZVAL_COPY(&_readline_completion, arg);
|
||||
|
||||
rl_attempted_completion_function = _readline_completion_cb;
|
||||
if (rl_attempted_completion_function == NULL) {
|
||||
@@ -552,7 +552,7 @@ static void php_rl_callback_handler(char *the_line)
|
||||
call_user_function(CG(function_table), NULL, &_prepped_callback, &dummy, 1, params);
|
||||
|
||||
zval_ptr_dtor(¶ms[0]);
|
||||
zval_dtor(&dummy);
|
||||
zval_ptr_dtor(&dummy);
|
||||
}
|
||||
|
||||
/* {{{ proto void readline_callback_handler_install(string prompt, mixed callback)
|
||||
@@ -577,10 +577,10 @@ PHP_FUNCTION(readline_callback_handler_install)
|
||||
|
||||
if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
|
||||
rl_callback_handler_remove();
|
||||
zval_dtor(&_prepped_callback);
|
||||
zval_ptr_dtor(&_prepped_callback);
|
||||
}
|
||||
|
||||
ZVAL_DUP(&_prepped_callback, callback);
|
||||
ZVAL_COPY(&_prepped_callback, callback);
|
||||
|
||||
rl_callback_handler_install(prompt, php_rl_callback_handler);
|
||||
|
||||
@@ -604,7 +604,7 @@ PHP_FUNCTION(readline_callback_handler_remove)
|
||||
{
|
||||
if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
|
||||
rl_callback_handler_remove();
|
||||
zval_dtor(&_prepped_callback);
|
||||
zval_ptr_dtor(&_prepped_callback);
|
||||
ZVAL_UNDEF(&_prepped_callback);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
+25
-15
@@ -477,6 +477,28 @@ PHPAPI int php_session_valid_key(const char *key) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
static void php_session_gc(void) /* {{{ */
|
||||
{
|
||||
int nrand;
|
||||
|
||||
/* GC must be done before reading session data. */
|
||||
if ((PS(mod_data) || PS(mod_user_implemented)) && PS(gc_probability) > 0) {
|
||||
int nrdels = -1;
|
||||
|
||||
nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg());
|
||||
if (nrand < PS(gc_probability)) {
|
||||
PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels);
|
||||
#ifdef SESSION_DEBUG
|
||||
if (nrdels != -1) {
|
||||
php_error_docref(NULL, E_NOTICE, "purged %d expired session objects", nrdels);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
|
||||
static void php_session_initialize(void) /* {{{ */
|
||||
{
|
||||
zend_string *val = NULL;
|
||||
@@ -521,6 +543,9 @@ static void php_session_initialize(void) /* {{{ */
|
||||
php_session_reset_id();
|
||||
PS(session_status) = php_session_active;
|
||||
|
||||
/* GC must be done before read */
|
||||
php_session_gc();
|
||||
|
||||
/* Read data */
|
||||
php_session_track_init();
|
||||
if (PS(mod)->s_read(&PS(mod_data), PS(id), &val, PS(gc_maxlifetime)) == FAILURE) {
|
||||
@@ -1513,7 +1538,6 @@ PHPAPI void php_session_start(void) /* {{{ */
|
||||
zval *ppid;
|
||||
zval *data;
|
||||
char *p, *value;
|
||||
int nrand;
|
||||
size_t lensess;
|
||||
|
||||
switch (PS(session_status)) {
|
||||
@@ -1622,20 +1646,6 @@ PHPAPI void php_session_start(void) /* {{{ */
|
||||
|
||||
php_session_initialize();
|
||||
php_session_cache_limiter();
|
||||
|
||||
if ((PS(mod_data) || PS(mod_user_implemented)) && PS(gc_probability) > 0) {
|
||||
int nrdels = -1;
|
||||
|
||||
nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg());
|
||||
if (nrand < PS(gc_probability)) {
|
||||
PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels);
|
||||
#ifdef SESSION_DEBUG
|
||||
if (nrdels != -1) {
|
||||
php_error_docref(NULL, E_NOTICE, "purged %d expired session objects", nrdels);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
@@ -69,17 +69,17 @@ $_SESSION['E'] = 'F';
|
||||
?>
|
||||
--EXPECTF--
|
||||
open: path = /tmp, name = sid
|
||||
read: id = %s
|
||||
gc: maxlifetime = %d
|
||||
read: id = %s
|
||||
write: id = %s, data = A|s:1:"B";
|
||||
close
|
||||
open: path = /tmp, name = sid
|
||||
read: id = %s
|
||||
gc: maxlifetime = %d
|
||||
read: id = %s
|
||||
destroy: id = %s
|
||||
close
|
||||
open: path = /tmp, name = sid
|
||||
read: id = %s
|
||||
gc: maxlifetime = %d
|
||||
read: id = %s
|
||||
write: id = %s, data = E|s:1:"F";
|
||||
close
|
||||
|
||||
@@ -52,9 +52,9 @@ ob_end_flush();
|
||||
*** Testing session_set_save_handler() : variation ***
|
||||
|
||||
Open [%s,PHPSESSID]
|
||||
Read [%s,%s]
|
||||
GC [0]
|
||||
1 deleted
|
||||
Read [%s,%s]
|
||||
array(3) {
|
||||
["Blah"]=>
|
||||
string(12) "Hello World!"
|
||||
@@ -67,20 +67,12 @@ Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;]
|
||||
Close [%s,PHPSESSID]
|
||||
NULL
|
||||
Open [%s,PHPSESSID]
|
||||
Read [%s,%s]
|
||||
GC [0]
|
||||
1 deleted
|
||||
array(3) {
|
||||
["Blah"]=>
|
||||
string(12) "Hello World!"
|
||||
["Foo"]=>
|
||||
bool(false)
|
||||
["Guff"]=>
|
||||
int(1234567890)
|
||||
Read [%s,%s]
|
||||
array(0) {
|
||||
}
|
||||
Destroy [%s,%s]
|
||||
|
||||
Warning: unlink(%s): No such file or directory in %s on line %d
|
||||
Close [%s,PHPSESSID]
|
||||
bool(true)
|
||||
|
||||
|
||||
@@ -62,9 +62,9 @@ string(0) ""
|
||||
bool(true)
|
||||
Open [%s,PHPSESSID]
|
||||
CreateID [PHPT-%d]
|
||||
Read [%s,PHPT-%d]
|
||||
GC [0]
|
||||
1 deleted
|
||||
Read [%s,PHPT-%d]
|
||||
bool(true)
|
||||
string(%d) "PHPT-%d"
|
||||
Write [%s,PHPT-%d,]
|
||||
@@ -76,9 +76,9 @@ string(%d) "PHPT-%d"
|
||||
bool(true)
|
||||
Open [%s,PHPSESSID]
|
||||
ValidateID [%s,PHPT-%d]
|
||||
Read [%s,PHPT-%d]
|
||||
GC [0]
|
||||
1 deleted
|
||||
Read [%s,PHPT-%d]
|
||||
bool(true)
|
||||
Write [%s,PHPT-%d,]
|
||||
Close [%s,PHPSESSID]
|
||||
@@ -88,12 +88,10 @@ string(%d) "PHPT-%d"
|
||||
string(%d) "PHPT-%d"
|
||||
Open [%s,PHPSESSID]
|
||||
ValidateID [%s,PHPT-%d]
|
||||
Read [%s,PHPT-%d]
|
||||
GC [0]
|
||||
1 deleted
|
||||
Read [%s,PHPT-%d]
|
||||
bool(true)
|
||||
Destroy [%s,PHPT-%d]
|
||||
|
||||
Warning: unlink(%ssession_test_PHPT-%s): No such file or directory in %ssave_handler.inc on line %d
|
||||
Close [%s,PHPSESSID]
|
||||
bool(true)
|
||||
|
||||
+8
-2
@@ -130,6 +130,10 @@ static zend_always_inline uint32_t *spl_array_get_pos_ptr(HashTable *ht, spl_arr
|
||||
static void spl_array_object_free_storage(zend_object *object)
|
||||
{
|
||||
spl_array_object *intern = spl_array_from_obj(object);
|
||||
|
||||
if (intern->ht_iter != (uint32_t) -1) {
|
||||
zend_hash_iterator_del(intern->ht_iter);
|
||||
}
|
||||
|
||||
zend_object_std_dtor(&intern->std);
|
||||
|
||||
@@ -1169,8 +1173,8 @@ zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object,
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void ArrayObject::__construct(array|object ar = array() [, int flags = 0 [, string iterator_class = "ArrayIterator"]])
|
||||
proto void ArrayIterator::__construct(array|object ar = array() [, int flags = 0])
|
||||
/* {{{ proto void ArrayObject::__construct([array|object ar = array() [, int flags = 0 [, string iterator_class = "ArrayIterator"]]])
|
||||
proto void ArrayIterator::__construct([array|object ar = array() [, int flags = 0]])
|
||||
Constructs a new array iterator from a path. */
|
||||
SPL_METHOD(Array, __construct)
|
||||
{
|
||||
@@ -1812,6 +1816,8 @@ outexcept:
|
||||
/* {{{ arginfo and function table */
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array___construct, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, array)
|
||||
ZEND_ARG_INFO(0, ar_flags)
|
||||
ZEND_ARG_INFO(0, iterator_class)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetGet, 0, 0, 1)
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Bug #71153: Performance Degradation in ArrayIterator with large arrays
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$n = 200000;
|
||||
|
||||
for ($i = 0; $i < $n; ++$i) {
|
||||
foreach (new ArrayIterator([]) as $v) {}
|
||||
}
|
||||
|
||||
echo "done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
done
|
||||
@@ -3978,22 +3978,17 @@ PHP_FUNCTION(ip2long)
|
||||
Converts an (IPv4) Internet network address into a string in Internet standard dotted format */
|
||||
PHP_FUNCTION(long2ip)
|
||||
{
|
||||
/* "It's a long but it's not, PHP ints are signed */
|
||||
char *ip;
|
||||
size_t ip_len;
|
||||
uint32_t n;
|
||||
zend_ulong ip;
|
||||
struct in_addr myaddr;
|
||||
#ifdef HAVE_INET_PTON
|
||||
char str[40];
|
||||
#endif
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &ip, &ip_len) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &ip) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
n = strtoul(ip, NULL, 0);
|
||||
|
||||
myaddr.s_addr = htonl(n);
|
||||
myaddr.s_addr = htonl(ip);
|
||||
#ifdef HAVE_INET_PTON
|
||||
if (inet_ntop(AF_INET, &myaddr, str, sizeof(str))) {
|
||||
RETURN_STRING(str);
|
||||
|
||||
+6
-33
@@ -30,6 +30,7 @@
|
||||
#include "base64.h"
|
||||
#include "zend_interfaces.h"
|
||||
#include "info.h"
|
||||
#include "php_random.h"
|
||||
|
||||
#if PHP_WIN32
|
||||
#include "win32/winutil.h"
|
||||
@@ -109,8 +110,7 @@ static int php_password_salt_to64(const char *str, const size_t str_len, const s
|
||||
|
||||
static int php_password_make_salt(size_t length, char *ret) /* {{{ */
|
||||
{
|
||||
int buffer_valid = 0;
|
||||
size_t i, raw_length;
|
||||
size_t raw_length;
|
||||
char *buffer;
|
||||
char *result;
|
||||
|
||||
@@ -123,37 +123,10 @@ static int php_password_make_salt(size_t length, char *ret) /* {{{ */
|
||||
|
||||
buffer = (char *) safe_emalloc(raw_length, 1, 1);
|
||||
|
||||
#if PHP_WIN32
|
||||
{
|
||||
BYTE *iv_b = (BYTE *) buffer;
|
||||
if (php_win32_get_random_bytes(iv_b, raw_length) == SUCCESS) {
|
||||
buffer_valid = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
int fd, n;
|
||||
size_t read_bytes = 0;
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
while (read_bytes < raw_length) {
|
||||
n = read(fd, buffer + read_bytes, raw_length - read_bytes);
|
||||
if (n < 0) {
|
||||
break;
|
||||
}
|
||||
read_bytes += (size_t) n;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
if (read_bytes >= raw_length) {
|
||||
buffer_valid = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!buffer_valid) {
|
||||
for (i = 0; i < raw_length; i++) {
|
||||
buffer[i] ^= (char) (255.0 * php_rand() / RAND_MAX);
|
||||
}
|
||||
if (FAILURE == php_random_bytes_silent(buffer, raw_length)) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to generate salt");
|
||||
efree(buffer);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
result = safe_emalloc(length, 1, 1);
|
||||
|
||||
@@ -1330,7 +1330,7 @@ PHP_FUNCTION(stream_get_line)
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool stream_set_blocking(resource socket, int mode)
|
||||
/* {{{ proto bool stream_set_blocking(resource socket, bool mode)
|
||||
Set blocking/non-blocking mode on a socket or stream */
|
||||
PHP_FUNCTION(stream_set_blocking)
|
||||
{
|
||||
|
||||
@@ -1439,7 +1439,7 @@ PHPAPI zend_string *php_string_toupper(zend_string *s)
|
||||
e = c + ZSTR_LEN(s);
|
||||
|
||||
while (c < e) {
|
||||
if (!isupper(*c)) {
|
||||
if (islower(*c)) {
|
||||
register unsigned char *r;
|
||||
zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
|
||||
|
||||
@@ -1508,7 +1508,7 @@ PHPAPI zend_string *php_string_tolower(zend_string *s)
|
||||
e = c + ZSTR_LEN(s);
|
||||
|
||||
while (c < e) {
|
||||
if (!islower(*c)) {
|
||||
if (isupper(*c)) {
|
||||
register unsigned char *r;
|
||||
zend_string *res = zend_string_alloc(ZSTR_LEN(s), 0);
|
||||
|
||||
|
||||
@@ -48,20 +48,22 @@ string(7) "0.0.0.0"
|
||||
int(1118019956)
|
||||
string(14) "66.163.161.116"
|
||||
|
||||
Warning: ip2long() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
Warning: ip2long() expects exactly 1 parameter, 0 given in %sip.php on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
int(1869573999)
|
||||
|
||||
Warning: ip2long() expects parameter 1 to be string, array given in %s on line %d
|
||||
Warning: ip2long() expects parameter 1 to be string, array given in %sip.php on line %d
|
||||
NULL
|
||||
|
||||
Warning: long2ip() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
Warning: long2ip() expects exactly 1 parameter, 0 given in %sip.php on line %d
|
||||
NULL
|
||||
string(13) "255.254.82.80"
|
||||
string(7) "0.0.0.0"
|
||||
|
||||
Warning: long2ip() expects parameter 1 to be string, array given in %s on line %d
|
||||
Warning: long2ip() expects parameter 1 to be integer, string given in %sip.php on line %d
|
||||
NULL
|
||||
|
||||
Warning: long2ip() expects parameter 1 to be integer, array given in %sip.php on line %d
|
||||
NULL
|
||||
Done
|
||||
|
||||
@@ -48,20 +48,22 @@ string(7) "0.0.0.0"
|
||||
int(1118019956)
|
||||
string(14) "66.163.161.116"
|
||||
|
||||
Warning: ip2long() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
Warning: ip2long() expects exactly 1 parameter, 0 given in %sip_x86_64.php on line %d
|
||||
NULL
|
||||
bool(false)
|
||||
bool(false)
|
||||
int(1869573999)
|
||||
|
||||
Warning: ip2long() expects parameter 1 to be string, array given in %s on line %d
|
||||
Warning: ip2long() expects parameter 1 to be string, array given in %sip_x86_64.php on line %d
|
||||
NULL
|
||||
|
||||
Warning: long2ip() expects exactly 1 parameter, 0 given in %s on line %d
|
||||
Warning: long2ip() expects exactly 1 parameter, 0 given in %sip_x86_64.php on line %d
|
||||
NULL
|
||||
string(13) "255.254.82.80"
|
||||
string(7) "0.0.0.0"
|
||||
|
||||
Warning: long2ip() expects parameter 1 to be string, array given in %s on line %d
|
||||
Warning: long2ip() expects parameter 1 to be integer, string given in %sip_x86_64.php on line %d
|
||||
NULL
|
||||
|
||||
Warning: long2ip() expects parameter 1 to be integer, array given in %sip_x86_64.php on line %d
|
||||
NULL
|
||||
Done
|
||||
|
||||
@@ -126,19 +126,19 @@ string(15) "255.255.255.246"
|
||||
string(7) "0.0.0.0"
|
||||
|
||||
--empty array--
|
||||
Error: 2 - long2ip() expects parameter 1 to be string, array given, %s(%d)
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, array given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--int indexed array--
|
||||
Error: 2 - long2ip() expects parameter 1 to be string, array given, %s(%d)
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, array given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--associative array--
|
||||
Error: 2 - long2ip() expects parameter 1 to be string, array given, %s(%d)
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, array given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--nested arrays--
|
||||
Error: 2 - long2ip() expects parameter 1 to be string, array given, %s(%d)
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, array given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--uppercase NULL--
|
||||
@@ -160,28 +160,35 @@ string(7) "0.0.0.1"
|
||||
string(7) "0.0.0.0"
|
||||
|
||||
--empty string DQ--
|
||||
string(7) "0.0.0.0"
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, string given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--empty string SQ--
|
||||
string(7) "0.0.0.0"
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, string given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--string DQ--
|
||||
string(7) "0.0.0.0"
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, string given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--string SQ--
|
||||
string(7) "0.0.0.0"
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, string given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--mixed case string--
|
||||
string(7) "0.0.0.0"
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, string given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--heredoc--
|
||||
string(7) "0.0.0.0"
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, string given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--instance of classWithToString--
|
||||
string(7) "0.0.0.0"
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, object given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--instance of classWithoutToString--
|
||||
Error: 2 - long2ip() expects parameter 1 to be string, object given, %s(%d)
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, object given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
|
||||
--undefined var--
|
||||
@@ -191,6 +198,6 @@ string(7) "0.0.0.0"
|
||||
string(7) "0.0.0.0"
|
||||
|
||||
--resource--
|
||||
Error: 2 - long2ip() expects parameter 1 to be string, resource given, %s(%d)
|
||||
Error: 2 - long2ip() expects parameter 1 to be integer, resource given, %slong2ip_variation1.php(%d)
|
||||
NULL
|
||||
===DONE===
|
||||
|
||||
+5
-5
@@ -111,7 +111,7 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_object, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, parser)
|
||||
ZEND_ARG_INFO(1, obj)
|
||||
ZEND_ARG_INFO(0, obj)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_element_handler, 0, 0, 3)
|
||||
@@ -1169,7 +1169,7 @@ PHP_FUNCTION(xml_set_object)
|
||||
xml_parser *parser;
|
||||
zval *pind, *mythis;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ro/", &pind, &mythis) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ro", &pind, &mythis) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1383,7 +1383,7 @@ PHP_FUNCTION(xml_set_end_namespace_decl_handler)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int xml_parse(resource parser, string data [, int isFinal])
|
||||
/* {{{ proto int xml_parse(resource parser, string data [, bool isFinal])
|
||||
Start parsing an XML document */
|
||||
PHP_FUNCTION(xml_parse)
|
||||
{
|
||||
@@ -1392,9 +1392,9 @@ PHP_FUNCTION(xml_parse)
|
||||
char *data;
|
||||
size_t data_len;
|
||||
int ret;
|
||||
zend_long isFinal = 0;
|
||||
zend_bool isFinal = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &pind, &data, &data_len, &isFinal) == FAILURE) {
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|b", &pind, &data, &data_len, &isFinal) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1622,7 +1622,7 @@ static PHP_FUNCTION(xmlwriter_end_dtd_entity)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool xmlwriter_write_dtd_entity(resource xmlwriter, string name, string content [, int pe [, string pubid [, string sysid [, string ndataid]]]])
|
||||
/* {{{ proto bool xmlwriter_write_dtd_entity(resource xmlwriter, string name, string content [, bool pe [, string pubid [, string sysid [, string ndataid]]]])
|
||||
Write full DTD Entity tag - returns FALSE on error */
|
||||
static PHP_FUNCTION(xmlwriter_write_dtd_entity)
|
||||
{
|
||||
|
||||
+9
-9
@@ -142,14 +142,14 @@ PHP_FUNCTION(header_register_callback)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void sapi_run_header_callback(void)
|
||||
static void sapi_run_header_callback(zval *callback)
|
||||
{
|
||||
int error;
|
||||
zend_fcall_info fci;
|
||||
char *callback_error = NULL;
|
||||
zval retval;
|
||||
|
||||
if (zend_fcall_info_init(&SG(callback_func), 0, &fci, &SG(fci_cache), NULL, &callback_error) == SUCCESS) {
|
||||
if (zend_fcall_info_init(callback, 0, &fci, &SG(fci_cache), NULL, &callback_error) == SUCCESS) {
|
||||
fci.retval = &retval;
|
||||
|
||||
error = zend_call_function(&fci, &SG(fci_cache));
|
||||
@@ -446,7 +446,6 @@ SAPI_API void sapi_activate(void)
|
||||
SG(sapi_headers).http_status_line = NULL;
|
||||
SG(sapi_headers).mimetype = NULL;
|
||||
SG(headers_sent) = 0;
|
||||
SG(callback_run) = 0;
|
||||
ZVAL_UNDEF(&SG(callback_func));
|
||||
SG(read_post_bytes) = 0;
|
||||
SG(request_info).request_body = NULL;
|
||||
@@ -543,8 +542,6 @@ SAPI_API void sapi_deactivate(void)
|
||||
sapi_send_headers_free();
|
||||
SG(sapi_started) = 0;
|
||||
SG(headers_sent) = 0;
|
||||
SG(callback_run) = 0;
|
||||
zval_ptr_dtor(&SG(callback_func));
|
||||
SG(request_info).headers_read = 0;
|
||||
SG(global_request_time) = 0;
|
||||
}
|
||||
@@ -851,7 +848,7 @@ SAPI_API int sapi_send_headers(void)
|
||||
int retval;
|
||||
int ret = FAILURE;
|
||||
|
||||
if (SG(headers_sent) || SG(request_info).no_headers || SG(callback_run)) {
|
||||
if (SG(headers_sent) || SG(request_info).no_headers) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -871,9 +868,12 @@ SAPI_API int sapi_send_headers(void)
|
||||
SG(sapi_headers).send_default_content_type = 0;
|
||||
}
|
||||
|
||||
if (Z_TYPE(SG(callback_func)) != IS_UNDEF && !SG(callback_run)) {
|
||||
SG(callback_run) = 1;
|
||||
sapi_run_header_callback();
|
||||
if (Z_TYPE(SG(callback_func)) != IS_UNDEF) {
|
||||
zval cb;
|
||||
ZVAL_COPY_VALUE(&cb, &SG(callback_func));
|
||||
ZVAL_UNDEF(&SG(callback_func));
|
||||
sapi_run_header_callback(&cb);
|
||||
zval_ptr_dtor(&cb);
|
||||
}
|
||||
|
||||
SG(headers_sent) = 1;
|
||||
|
||||
@@ -136,7 +136,6 @@ typedef struct _sapi_globals_struct {
|
||||
HashTable known_post_content_types;
|
||||
zval callback_func;
|
||||
zend_fcall_info_cache fci_cache;
|
||||
zend_bool callback_run;
|
||||
} sapi_globals_struct;
|
||||
|
||||
|
||||
|
||||
@@ -97,9 +97,6 @@
|
||||
#if HAVE_XML && HAVE_WDDX
|
||||
#include "ext/wddx/php_wddx.h"
|
||||
#endif
|
||||
#ifdef HAVE_SQLITE
|
||||
#include "ext/sqlite/php_sqlite.h"
|
||||
#endif
|
||||
#include "ext/com_dotnet/php_com_dotnet.h"
|
||||
#ifdef HAVE_SPL
|
||||
#include "ext/spl/php_spl.h"
|
||||
@@ -172,9 +169,6 @@ static zend_module_entry *php_builtin_extensions[] = {
|
||||
#if HAVE_XML && HAVE_WDDX
|
||||
,phpext_wddx_ptr
|
||||
#endif
|
||||
#if HAVE_SQLITE
|
||||
,phpext_sqlite_ptr
|
||||
#endif
|
||||
#if HAVE_SPL
|
||||
,phpext_spl_ptr
|
||||
#endif
|
||||
|
||||
+4
-4
@@ -956,10 +956,6 @@ cli_server.color = On
|
||||
; Default is 0, which does not produce any errors.
|
||||
;intl.error_level = E_WARNING
|
||||
|
||||
[sqlite]
|
||||
; http://php.net/sqlite.assoc-case
|
||||
;sqlite.assoc_case = 0
|
||||
|
||||
[sqlite3]
|
||||
;sqlite3.extension_dir =
|
||||
|
||||
@@ -1516,6 +1512,10 @@ url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
|
||||
; http://php.net/session.upload-progress.min-freq
|
||||
;session.upload_progress.min_freq = "1"
|
||||
|
||||
; Only write session data when session data is changed. Enabled by default.
|
||||
; http://php.net/session.lazy-write
|
||||
;session.lazy_write = On
|
||||
|
||||
[Assertion]
|
||||
; Switch whether to compile assertions at all (to have no overhead at run-time)
|
||||
; -1: Do not compile at all
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user