Skip to content

Instantly share code, notes, and snippets.

@moriyoshi
Created April 4, 2009 05:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moriyoshi/90119 to your computer and use it in GitHub Desktop.
Save moriyoshi/90119 to your computer and use it in GitHub Desktop.
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