Created
April 4, 2009 05:02
-
-
Save moriyoshi/90119 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: Zend/zend.c | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend.c,v | |
retrieving revision 1.308.2.12.2.35.2.28 | |
diff -u -r1.308.2.12.2.35.2.28 zend.c | |
--- Zend/zend.c 2 Jan 2009 13:14:49 -0000 1.308.2.12.2.35.2.28 | |
+++ Zend/zend.c 4 Apr 2009 04:55:46 -0000 | |
@@ -543,6 +543,7 @@ | |
EG(current_execute_data) = NULL; | |
EG(current_module) = NULL; | |
EG(exit_status) = 0; | |
+ EG(error_handling_frame) = NULL; | |
EG(active) = 0; | |
} | |
/* }}} */ | |
Index: Zend/zend_compile.c | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_compile.c,v | |
retrieving revision 1.647.2.27.2.41.2.102 | |
diff -u -r1.647.2.27.2.41.2.102 zend_compile.c | |
--- Zend/zend_compile.c 26 Jan 2009 22:54:19 -0000 1.647.2.27.2.41.2.102 | |
+++ Zend/zend_compile.c 4 Apr 2009 04:55:46 -0000 | |
@@ -1879,13 +1879,13 @@ | |
long current, distance; | |
if (CG(labels) == NULL || | |
- zend_hash_find(CG(labels), Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void**)&dest) == FAILURE) { | |
+ zend_hash_find(CG(labels), Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant)+1, (void**)&dest) == FAILURE) { | |
if (pass2) { | |
CG(in_compilation) = 1; | |
CG(active_op_array) = op_array; | |
CG(zend_lineno) = opline->lineno; | |
- zend_error(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL(opline->op2.u.constant)); | |
+ zend_error(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL(opline->op1.u.constant)); | |
} else { | |
/* Label is not defined. Delay to pass 2. */ | |
INC_BPC(op_array); | |
@@ -1893,8 +1893,9 @@ | |
} | |
} | |
+ zval_dtor(&opline->op1.u.constant); | |
+ SET_UNUSED(opline->op1); | |
opline->op1.u.opline_num = dest->opline_num; | |
- zval_dtor(&opline->op2.u.constant); | |
/* Check that we are not moving into loop or switch */ | |
current = opline->extended_value; | |
@@ -1910,14 +1911,15 @@ | |
current = op_array->brk_cont_array[current].parent; | |
} | |
- if (distance == 0) { | |
+ if (distance == 0 && opline->opcode != ZEND_ON_EVENT_GOTO) { | |
/* Nothing to break out of, optimize to ZEND_JMP */ | |
opline->opcode = ZEND_JMP; | |
opline->extended_value = 0; | |
SET_UNUSED(opline->op2); | |
} else { | |
/* Set real break distance */ | |
- ZVAL_LONG(&opline->op2.u.constant, distance); | |
+ opline->result.op_type = IS_CONST; | |
+ ZVAL_LONG(&opline->result.u.constant, distance); | |
} | |
if (pass2) { | |
@@ -1932,8 +1934,20 @@ | |
opline->opcode = ZEND_GOTO; | |
opline->extended_value = CG(active_op_array)->current_brk_cont; | |
- SET_UNUSED(opline->op1); | |
- opline->op2 = *label; | |
+ opline->op1 = *label; | |
+ SET_UNUSED(opline->op2); | |
+ zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC); | |
+} | |
+/* }}} */ | |
+ | |
+void zend_do_on_event_goto(const znode *event, const znode *label TSRMLS_DC) /* {{{ */ | |
+{ | |
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); | |
+ | |
+ opline->opcode = ZEND_ON_EVENT_GOTO; | |
+ opline->extended_value = CG(active_op_array)->current_brk_cont; | |
+ opline->op1 = *label; | |
+ opline->op2 = *event; | |
zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC); | |
} | |
/* }}} */ | |
Index: Zend/zend_compile.h | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_compile.h,v | |
retrieving revision 1.316.2.8.2.12.2.39 | |
diff -u -r1.316.2.8.2.12.2.39 zend_compile.h | |
--- Zend/zend_compile.h 26 Jan 2009 22:54:20 -0000 1.316.2.8.2.12.2.39 | |
+++ Zend/zend_compile.h 4 Apr 2009 04:55:46 -0000 | |
@@ -22,6 +22,8 @@ | |
#ifndef ZEND_COMPILE_H | |
#define ZEND_COMPILE_H | |
+#include <setjmp.h> | |
+ | |
#include "zend.h" | |
#ifdef HAVE_STDARG_H | |
@@ -324,6 +326,10 @@ | |
zval *current_this; | |
zval *current_object; | |
struct _zend_op *call_opline; | |
+ struct _zend_op *error_jmp; | |
+ struct _zend_execute_data *prev_error_handling_frame; | |
+ void (*prev_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); | |
+ JMP_BUF error_jmp_buf; | |
}; | |
#define EX(element) execute_data.element | |
@@ -545,6 +551,7 @@ | |
void zend_do_label(znode *label TSRMLS_DC); | |
void zend_do_goto(const znode *label TSRMLS_DC); | |
+void zend_do_on_event_goto(const znode *event, const znode *label TSRMLS_DC); | |
void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC); | |
void zend_release_labels(TSRMLS_D); | |
Index: Zend/zend_globals.h | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_globals.h,v | |
retrieving revision 1.141.2.3.2.7.2.22 | |
diff -u -r1.141.2.3.2.7.2.22 zend_globals.h | |
--- Zend/zend_globals.h 16 Jan 2009 00:57:43 -0000 1.141.2.3.2.7.2.22 | |
+++ Zend/zend_globals.h 4 Apr 2009 04:55:46 -0000 | |
@@ -254,6 +254,8 @@ | |
zend_bool active; | |
+ struct _zend_execute_data *error_handling_frame; | |
+ | |
void *reserved[ZEND_MAX_RESERVED_RESOURCES]; | |
}; | |
Index: Zend/zend_language_parser.y | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_language_parser.y,v | |
retrieving revision 1.160.2.4.2.8.2.34 | |
diff -u -r1.160.2.4.2.8.2.34 zend_language_parser.y | |
--- Zend/zend_language_parser.y 26 Jan 2009 22:54:20 -0000 1.160.2.4.2.8.2.34 | |
+++ Zend/zend_language_parser.y 4 Apr 2009 04:55:46 -0000 | |
@@ -148,6 +148,7 @@ | |
%token T_NS_C | |
%token T_DIR | |
%token T_NS_SEPARATOR | |
+%token T_ON | |
%% /* Rules */ | |
@@ -262,6 +263,7 @@ | |
additional_catches { zend_do_mark_last_catch(&$7, &$18 TSRMLS_CC); } | |
| T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); } | |
| T_GOTO T_STRING ';' { zend_do_goto(&$2 TSRMLS_CC); } | |
+ | T_ON T_STRING T_GOTO T_STRING ';' { zend_do_on_event_goto(&$2, &$4 TSRMLS_CC); } | |
; | |
Index: Zend/zend_language_scanner.l | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v | |
retrieving revision 1.131.2.11.2.13.2.35 | |
diff -u -r1.131.2.11.2.13.2.35 zend_language_scanner.l | |
--- Zend/zend_language_scanner.l 9 Jan 2009 17:21:12 -0000 1.131.2.11.2.13.2.35 | |
+++ Zend/zend_language_scanner.l 4 Apr 2009 04:55:47 -0000 | |
@@ -1034,6 +1034,10 @@ | |
return T_GOTO; | |
} | |
+<ST_IN_SCRIPTING>"on" { | |
+ return T_ON; | |
+} | |
+ | |
<ST_IN_SCRIPTING>"echo" { | |
return T_ECHO; | |
} | |
Index: Zend/zend_opcode.c | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_opcode.c,v | |
retrieving revision 1.110.2.6.2.3.2.10 | |
diff -u -r1.110.2.6.2.3.2.10 zend_opcode.c | |
--- Zend/zend_opcode.c 31 Dec 2008 11:15:32 -0000 1.110.2.6.2.3.2.10 | |
+++ Zend/zend_opcode.c 4 Apr 2009 04:55:47 -0000 | |
@@ -391,6 +391,7 @@ | |
} | |
switch (opline->opcode) { | |
case ZEND_GOTO: | |
+ case ZEND_ON_EVENT_GOTO: | |
if (Z_TYPE(opline->op2.u.constant) != IS_LONG) { | |
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); | |
} | |
Index: Zend/zend_vm_def.h | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_vm_def.h,v | |
retrieving revision 1.59.2.29.2.48.2.84 | |
diff -u -r1.59.2.29.2.48.2.84 zend_vm_def.h | |
--- Zend/zend_vm_def.h 26 Jan 2009 22:54:20 -0000 1.59.2.29.2.48.2.84 | |
+++ Zend/zend_vm_def.h 4 Apr 2009 04:55:47 -0000 | |
@@ -2128,6 +2128,10 @@ | |
zend_bool nested; | |
zend_op_array *op_array = EX(op_array); | |
+ if (EG(error_handling_frame) == EG(current_execute_data)) { | |
+ zend_error_cb = EG(current_execute_data)->prev_error_cb; | |
+ EG(error_handling_frame) = EG(current_execute_data)->prev_error_handling_frame; | |
+ } | |
EG(current_execute_data) = EX(prev_execute_data); | |
EG(opline_ptr) = NULL; | |
if (!EG(active_symbol_table)) { | |
@@ -2801,7 +2805,7 @@ | |
zend_op *opline = EX(opline); | |
zend_brk_cont_element *el; | |
- el = zend_brk_cont(&opline->op2.u.constant, opline->extended_value, | |
+ el = zend_brk_cont(&opline->result.u.constant, opline->extended_value, | |
EX(op_array), EX(Ts) TSRMLS_CC); | |
brk_opline = EX(op_array)->opcodes + el->brk; | |
@@ -2821,6 +2825,53 @@ | |
ZEND_VM_JMP(opline->op1.u.jmp_addr); | |
} | |
+ZEND_VM_HANDLER(116, ZEND_ON_EVENT_GOTO, ANY, CONST) | |
+{ | |
+ zend_op *opline = EX(opline); | |
+ convert_to_string(&opline->op2.u.constant); | |
+ | |
+ if (zend_binary_strcasecmp(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant), "error", sizeof("error") - 1) != 0) { | |
+ zend_error_noreturn(E_ERROR, "Unknown event type: %s", Z_STRVAL(opline->op2.u.constant)); | |
+ } | |
+ | |
+ EX(prev_error_handling_frame) = EG(error_handling_frame); | |
+ EX(prev_error_cb) = zend_error_cb; | |
+ EG(error_handling_frame) = execute_data; | |
+ EX(error_jmp) = EX(opline); | |
+ zend_error_cb = zend_error_jmp_handler; | |
+ if (SETJMP(EX(error_jmp_buf))) { | |
+ zend_op *brk_opline; | |
+ zend_op *opline; | |
+ zend_brk_cont_element *el; | |
+ execute_data = EG(current_execute_data); | |
+ opline = EX(error_jmp); | |
+ | |
+ if (Z_LVAL(opline->result.u.constant) > 0) { | |
+ el = zend_brk_cont(&opline->result.u.constant, opline->extended_value, | |
+ EX(op_array), EX(Ts) TSRMLS_CC); | |
+ | |
+ brk_opline = EX(op_array)->opcodes + el->brk; | |
+ | |
+ switch (brk_opline->opcode) { | |
+ case ZEND_SWITCH_FREE: | |
+ if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) { | |
+ zend_switch_free(&EX_T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC); | |
+ } | |
+ break; | |
+ case ZEND_FREE: | |
+ if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) { | |
+ zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var); | |
+ } | |
+ break; | |
+ } | |
+ } | |
+ ZEND_VM_SET_OPCODE(opline->op1.u.jmp_addr); | |
+ ZEND_VM_LEAVE(); | |
+ } else { | |
+ ZEND_VM_NEXT_OPCODE(); | |
+ } | |
+} | |
+ | |
ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) | |
{ | |
zend_op *opline = EX(opline); | |
Index: Zend/zend_vm_execute.skl | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_vm_execute.skl,v | |
retrieving revision 1.2.2.2.2.1.2.9 | |
diff -u -r1.2.2.2.2.1.2.9 zend_vm_execute.skl | |
--- Zend/zend_vm_execute.skl 11 Jun 2008 13:18:41 -0000 1.2.2.2.2.1.2.9 | |
+++ Zend/zend_vm_execute.skl 4 Apr 2009 04:55:49 -0000 | |
@@ -33,6 +33,9 @@ | |
EX(symbol_table) = EG(active_symbol_table); | |
EX(prev_execute_data) = EG(current_execute_data); | |
EG(current_execute_data) = execute_data; | |
+ EX(error_jmp) = NULL; | |
+ EX(prev_error_handling_frame) = NULL; | |
+ EX(prev_error_cb) = NULL; | |
EX(nested) = nested; | |
nested = 1; | |
@@ -75,8 +78,51 @@ | |
zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); | |
} | |
+static void zend_error_jmp_handler(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); | |
+ | |
{%EXTERNAL_EXECUTOR%} | |
+void zend_error_jmp_handler(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) | |
+{ | |
+ TSRMLS_FETCH(); | |
+ zend_execute_data *execute_data = EG(current_execute_data); | |
+ | |
+ while (execute_data != EG(error_handling_frame)) { | |
+ if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { | |
+ zval_ptr_dtor(&EX_T(EX(opline)->result.u.var).var.ptr); | |
+ zend_vm_stack_clear_multiple(TSRMLS_C); | |
+ } | |
+ | |
+ zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); | |
+ execute_data = EG(current_execute_data); | |
+#ifndef ZEND_VM_EXPORT | |
+ if (zend_execute != execute) { | |
+ zend_vm_stack_clear_multiple(TSRMLS_C); | |
+ } | |
+#else | |
+ zend_vm_stack_clear_multiple(TSRMLS_C); | |
+#endif | |
+ EG(return_value_ptr_ptr) = EX(original_return_value); | |
+ EG(active_symbol_table) = EX(symbol_table); | |
+ /* symbol table should have been cleaned up in zend_leave_helper */ | |
+ if (EX(function_state).function->type == ZEND_USER_FUNCTION || | |
+ EX(function_state).function->common.scope) { | |
+ EG(This) = EX(current_this); | |
+ EG(scope) = EX(current_scope); | |
+ EG(called_scope) = EX(current_called_scope); | |
+ } | |
+ EX(object) = EX(current_object); | |
+ EX(called_scope) = DECODE_CTOR(EX(called_scope)); | |
+ } | |
+ | |
+ if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { | |
+ zval_ptr_dtor(&EX_T(EX(opline)->result.u.var).var.ptr); | |
+ zend_vm_stack_clear_multiple(TSRMLS_C); | |
+ } | |
+ | |
+ LONGJMP(EX(error_jmp_buf), 1); | |
+} | |
+ | |
void {%INITIALIZER_NAME%}(void) | |
{ | |
{%EXTERNAL_LABELS%} | |
Index: Zend/zend_vm_opcodes.h | |
=================================================================== | |
RCS file: /repository/ZendEngine2/zend_vm_opcodes.h,v | |
retrieving revision 1.42.2.17.2.1.2.8 | |
diff -u -r1.42.2.17.2.1.2.8 zend_vm_opcodes.h | |
--- Zend/zend_vm_opcodes.h 31 Dec 2008 11:15:35 -0000 1.42.2.17.2.1.2.8 | |
+++ Zend/zend_vm_opcodes.h 4 Apr 2009 04:55:49 -0000 | |
@@ -133,6 +133,7 @@ | |
#define ZEND_INIT_STATIC_METHOD_CALL 113 | |
#define ZEND_ISSET_ISEMPTY_VAR 114 | |
#define ZEND_ISSET_ISEMPTY_DIM_OBJ 115 | |
+#define ZEND_ON_EVENT_GOTO 116 | |
#define ZEND_PRE_INC_OBJ 132 | |
#define ZEND_PRE_DEC_OBJ 133 | |
#define ZEND_POST_INC_OBJ 134 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment