diff options
| author | Nikita Popov <nikic@php.net> | 2012-05-29 02:31:56 +0200 |
|---|---|---|
| committer | Nikita Popov <nikic@php.net> | 2012-05-29 02:31:56 +0200 |
| commit | b770b221e0b3036708deb9e22dacf296402787f0 (patch) | |
| tree | 0e6b2088943418b17a81b1f2aa5495e63efd872a | |
| parent | 4aab08b64c2318775be6d8e629747ac66a108485 (diff) | |
| download | php-git-b770b221e0b3036708deb9e22dacf296402787f0.tar.gz | |
Make the GOTO and SWITCH VMs work again
| -rw-r--r-- | Zend/zend_vm_def.h | 7 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.h | 28 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.skl | 7 | ||||
| -rw-r--r-- | Zend/zend_vm_gen.php | 12 |
4 files changed, 41 insertions, 13 deletions
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 04b65950dc..47d5ec4098 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5203,6 +5203,7 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) *EG(return_value_ptr_ptr) = return_value; /* back up some executor globals */ + SAVE_OPLINE(); EX(current_this) = EG(This); EX(current_scope) = EG(scope); EX(current_called_scope) = EG(called_scope); @@ -5248,6 +5249,8 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) zend_vm_stack_clear_multiple(TSRMLS_C); + LOAD_REGS(); + LOAD_OPLINE(); ZEND_VM_INC_OPCODE(); ZEND_VM_LEAVE(); } @@ -5293,6 +5296,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV, ANY) FREE_OP1_IF_VAR(); } + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c195148c97..bd22768a3a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -393,10 +393,10 @@ static zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array * if (op_array->this_var != -1 && EG(This)) { Z_ADDREF_P(EG(This)); /* For $this pointer */ if (!EG(active_symbol_table)) { - EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var); - *EX_CV(op_array->this_var) = EG(This); + EX(CVs)[op_array->this_var] = (zval **) EX(CVs) + op_array->last_var + op_array->this_var; + *EX(CVs)[op_array->this_var] = EG(This); } else { - if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) { + if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) &EX(CVs)[op_array->this_var])==FAILURE) { Z_DELREF_P(EG(This)); } } @@ -425,7 +425,6 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) EG(in_execution) = 1; -zend_vm_enter: LOAD_REGS(); LOAD_OPLINE(); @@ -444,8 +443,10 @@ zend_vm_enter: return; case 2: execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); + break; case 3: execute_data = EG(current_execute_data); + break; default: break; } @@ -1185,6 +1186,7 @@ static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP *EG(return_value_ptr_ptr) = return_value; /* back up some executor globals */ + SAVE_OPLINE(); EX(current_this) = EG(This); EX(current_scope) = EG(scope); EX(current_called_scope) = EG(called_scope); @@ -1230,6 +1232,8 @@ static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP zend_vm_stack_clear_multiple(TSRMLS_C); + LOAD_REGS(); + LOAD_OPLINE(); ZEND_VM_INC_OPCODE(); ZEND_VM_LEAVE(); } @@ -3067,6 +3071,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS } + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } @@ -7704,6 +7712,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } @@ -12419,6 +12431,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; } + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } @@ -28304,6 +28320,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index d251e55344..e77c7cb3c6 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -54,10 +54,10 @@ static zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array * if (op_array->this_var != -1 && EG(This)) { Z_ADDREF_P(EG(This)); /* For $this pointer */ if (!EG(active_symbol_table)) { - EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var); - *EX_CV(op_array->this_var) = EG(This); + EX(CVs)[op_array->this_var] = (zval **) EX(CVs) + op_array->last_var + op_array->this_var; + *EX(CVs)[op_array->this_var] = EG(This); } else { - if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) { + if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) &EX(CVs)[op_array->this_var])==FAILURE) { Z_DELREF_P(EG(This)); } } @@ -88,7 +88,6 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC) EG(in_execution) = 1; -zend_vm_enter: LOAD_REGS(); LOAD_OPLINE(); diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index b7fd874264..ee2b0b2f2d 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -856,7 +856,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define LOAD_REGS() do {Ts = EX(Ts); CVs = EX(CVs);} while (0)\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); - out($f,"#define ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\n"); + out($f,"#define ZEND_VM_ENTER() execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); LOAD_REGS(); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); @@ -892,7 +892,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define LOAD_REGS() do {Ts = EX(Ts); CVs = EX(CVs);} while (0)\n"); out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n"); out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); - out($f,"#define ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\n"); + out($f,"#define ZEND_VM_ENTER() execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); LOAD_REGS(); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); @@ -932,7 +932,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, // Emit array of labels of opcode handlers and code for // zend_opcode_handlers initialization $prolog = $m[1]; - out($f,$prolog."if (op_array == NULL) {\n"); + out($f,$prolog."if (execute_data == NULL) {\n"); out($f,$prolog."\tstatic const opcode_handler_t labels[] = {\n"); gen_labels($f, $spec, $kind, $prolog."\t\t"); out($f,$prolog."\t};\n"); @@ -977,8 +977,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, $m[1]."\t\treturn;\n". $m[1]."\tcase 2:\n" . $m[1]."\t\texecute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC);\n". + $m[1]."\t\tbreak;\n" . $m[1]."\tcase 3:\n" . $m[1]."\t\texecute_data = EG(current_execute_data);\n". + $m[1]."\t\tbreak;\n" . $m[1]."\tdefault:\n". $m[1]."\t\tbreak;\n". $m[1]."}".$m[3]."\n"); @@ -1005,9 +1007,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, $prolog = $m[1]; if ($kind == ZEND_VM_KIND_GOTO) { // Labels are defined in the executor itself, so we call it - // with op_array NULL and it sets zend_opcode_handlers array + // with execute_data NULL and it sets zend_opcode_handlers array out($f,$prolog."TSRMLS_FETCH();\n"); - out($f,$prolog."zend_execute(NULL TSRMLS_CC);\n"); + out($f,$prolog.$executor_name."_ex(NULL TSRMLS_CC);\n"); } else { if ($old) { // Reserving space for user-defined opcodes |
