zend_opcode.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@php.net> |
  16. | Zeev Suraski <zeev@php.net> |
  17. | Dmitry Stogov <dmitry@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #include <stdio.h>
  21. #include "zend.h"
  22. #include "zend_alloc.h"
  23. #include "zend_compile.h"
  24. #include "zend_extensions.h"
  25. #include "zend_API.h"
  26. #include "zend_sort.h"
  27. #include "zend_vm.h"
  28. static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array)
  29. {
  30. if (extension->op_array_ctor) {
  31. extension->op_array_ctor(op_array);
  32. }
  33. }
  34. static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array)
  35. {
  36. if (extension->op_array_dtor) {
  37. extension->op_array_dtor(op_array);
  38. }
  39. }
  40. void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size)
  41. {
  42. op_array->type = type;
  43. op_array->arg_flags[0] = 0;
  44. op_array->arg_flags[1] = 0;
  45. op_array->arg_flags[2] = 0;
  46. op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t));
  47. *op_array->refcount = 1;
  48. op_array->last = 0;
  49. op_array->opcodes = emalloc(initial_ops_size * sizeof(zend_op));
  50. op_array->last_var = 0;
  51. op_array->vars = NULL;
  52. op_array->T = 0;
  53. op_array->function_name = NULL;
  54. op_array->filename = zend_get_compiled_filename();
  55. op_array->doc_comment = NULL;
  56. op_array->arg_info = NULL;
  57. op_array->num_args = 0;
  58. op_array->required_num_args = 0;
  59. op_array->scope = NULL;
  60. op_array->prototype = NULL;
  61. op_array->live_range = NULL;
  62. op_array->try_catch_array = NULL;
  63. op_array->last_live_range = 0;
  64. op_array->static_variables = NULL;
  65. op_array->last_try_catch = 0;
  66. op_array->fn_flags = 0;
  67. op_array->last_literal = 0;
  68. op_array->literals = NULL;
  69. op_array->run_time_cache = NULL;
  70. op_array->cache_size = 0;
  71. memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
  72. if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_CTOR) {
  73. zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array);
  74. }
  75. }
  76. ZEND_API void destroy_zend_function(zend_function *function)
  77. {
  78. zval tmp;
  79. ZVAL_PTR(&tmp, function);
  80. zend_function_dtor(&tmp);
  81. }
  82. ZEND_API void zend_function_dtor(zval *zv)
  83. {
  84. zend_function *function = Z_PTR_P(zv);
  85. if (function->type == ZEND_USER_FUNCTION) {
  86. ZEND_ASSERT(function->common.function_name);
  87. destroy_op_array(&function->op_array);
  88. /* op_arrays are allocated on arena, so we don't have to free them */
  89. } else {
  90. ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION);
  91. ZEND_ASSERT(function->common.function_name);
  92. zend_string_release_ex(function->common.function_name, 1);
  93. if ((function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
  94. !function->common.scope && function->common.arg_info) {
  95. uint32_t i;
  96. uint32_t num_args = function->common.num_args + 1;
  97. zend_arg_info *arg_info = function->common.arg_info - 1;
  98. if (function->common.fn_flags & ZEND_ACC_VARIADIC) {
  99. num_args++;
  100. }
  101. for (i = 0 ; i < num_args; i++) {
  102. if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
  103. zend_string_release_ex(ZEND_TYPE_NAME(arg_info[i].type), 1);
  104. }
  105. }
  106. free(arg_info);
  107. }
  108. if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) {
  109. pefree(function, 1);
  110. }
  111. }
  112. }
  113. ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
  114. {
  115. if (CE_STATIC_MEMBERS(ce)) {
  116. zval *static_members = CE_STATIC_MEMBERS(ce);
  117. zval *p = static_members;
  118. zval *end = p + ce->default_static_members_count;
  119. #ifdef ZTS
  120. CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL;
  121. #else
  122. ce->static_members_table = NULL;
  123. #endif
  124. while (p != end) {
  125. i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
  126. p++;
  127. }
  128. efree(static_members);
  129. }
  130. }
  131. void _destroy_zend_class_traits_info(zend_class_entry *ce)
  132. {
  133. if (ce->num_traits > 0 && ce->traits) {
  134. efree(ce->traits);
  135. }
  136. if (ce->trait_aliases) {
  137. size_t i = 0;
  138. while (ce->trait_aliases[i]) {
  139. if (ce->trait_aliases[i]->trait_method.method_name) {
  140. zend_string_release_ex(ce->trait_aliases[i]->trait_method.method_name, 0);
  141. }
  142. if (ce->trait_aliases[i]->trait_method.class_name) {
  143. zend_string_release_ex(ce->trait_aliases[i]->trait_method.class_name, 0);
  144. }
  145. if (ce->trait_aliases[i]->alias) {
  146. zend_string_release_ex(ce->trait_aliases[i]->alias, 0);
  147. }
  148. efree(ce->trait_aliases[i]);
  149. i++;
  150. }
  151. efree(ce->trait_aliases);
  152. }
  153. if (ce->trait_precedences) {
  154. int i = 0;
  155. int j;
  156. while (ce->trait_precedences[i]) {
  157. zend_string_release_ex(ce->trait_precedences[i]->trait_method.method_name, 0);
  158. zend_string_release_ex(ce->trait_precedences[i]->trait_method.class_name, 0);
  159. for (j = 0; j < ce->trait_precedences[i]->num_excludes; j++) {
  160. zend_string_release_ex(ce->trait_precedences[i]->exclude_class_names[j], 0);
  161. }
  162. efree(ce->trait_precedences[i]);
  163. i++;
  164. }
  165. efree(ce->trait_precedences);
  166. }
  167. }
  168. ZEND_API void destroy_zend_class(zval *zv)
  169. {
  170. zend_property_info *prop_info;
  171. zend_class_entry *ce = Z_PTR_P(zv);
  172. zend_function *fn;
  173. if (--ce->refcount > 0) {
  174. return;
  175. }
  176. switch (ce->type) {
  177. case ZEND_USER_CLASS:
  178. if (ce->default_properties_table) {
  179. zval *p = ce->default_properties_table;
  180. zval *end = p + ce->default_properties_count;
  181. while (p != end) {
  182. i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
  183. p++;
  184. }
  185. efree(ce->default_properties_table);
  186. }
  187. if (ce->default_static_members_table) {
  188. zval *p = ce->default_static_members_table;
  189. zval *end = p + ce->default_static_members_count;
  190. while (p != end) {
  191. i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
  192. p++;
  193. }
  194. efree(ce->default_static_members_table);
  195. }
  196. ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
  197. if (prop_info->ce == ce ||
  198. ((prop_info->flags & ZEND_ACC_SHADOW) && prop_info->ce == ce->parent)) {
  199. zend_string_release_ex(prop_info->name, 0);
  200. if (prop_info->doc_comment) {
  201. zend_string_release_ex(prop_info->doc_comment, 0);
  202. }
  203. }
  204. } ZEND_HASH_FOREACH_END();
  205. zend_hash_destroy(&ce->properties_info);
  206. zend_string_release_ex(ce->name, 0);
  207. zend_hash_destroy(&ce->function_table);
  208. if (zend_hash_num_elements(&ce->constants_table)) {
  209. zend_class_constant *c;
  210. ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
  211. if (c->ce == ce) {
  212. zval_ptr_dtor_nogc(&c->value);
  213. if (c->doc_comment) {
  214. zend_string_release_ex(c->doc_comment, 0);
  215. }
  216. }
  217. } ZEND_HASH_FOREACH_END();
  218. }
  219. zend_hash_destroy(&ce->constants_table);
  220. if (ce->num_interfaces > 0 && ce->interfaces) {
  221. efree(ce->interfaces);
  222. }
  223. if (ce->info.user.doc_comment) {
  224. zend_string_release_ex(ce->info.user.doc_comment, 0);
  225. }
  226. _destroy_zend_class_traits_info(ce);
  227. break;
  228. case ZEND_INTERNAL_CLASS:
  229. if (ce->default_properties_table) {
  230. zval *p = ce->default_properties_table;
  231. zval *end = p + ce->default_properties_count;
  232. while (p != end) {
  233. zval_internal_ptr_dtor(p);
  234. p++;
  235. }
  236. free(ce->default_properties_table);
  237. }
  238. if (ce->default_static_members_table) {
  239. zval *p = ce->default_static_members_table;
  240. zval *end = p + ce->default_static_members_count;
  241. while (p != end) {
  242. zval_internal_ptr_dtor(p);
  243. p++;
  244. }
  245. free(ce->default_static_members_table);
  246. }
  247. zend_hash_destroy(&ce->properties_info);
  248. zend_string_release_ex(ce->name, 1);
  249. /* TODO: eliminate this loop for classes without functions with arg_info */
  250. ZEND_HASH_FOREACH_PTR(&ce->function_table, fn) {
  251. if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
  252. fn->common.scope == ce) {
  253. /* reset function scope to allow arg_info removing */
  254. fn->common.scope = NULL;
  255. }
  256. } ZEND_HASH_FOREACH_END();
  257. zend_hash_destroy(&ce->function_table);
  258. if (zend_hash_num_elements(&ce->constants_table)) {
  259. zend_class_constant *c;
  260. ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
  261. if (c->ce == ce) {
  262. zval_internal_ptr_dtor(&c->value);
  263. if (c->doc_comment) {
  264. zend_string_release_ex(c->doc_comment, 1);
  265. }
  266. }
  267. free(c);
  268. } ZEND_HASH_FOREACH_END();
  269. zend_hash_destroy(&ce->constants_table);
  270. }
  271. if (ce->iterator_funcs_ptr) {
  272. free(ce->iterator_funcs_ptr);
  273. }
  274. if (ce->num_interfaces > 0) {
  275. free(ce->interfaces);
  276. }
  277. free(ce);
  278. break;
  279. }
  280. }
  281. void zend_class_add_ref(zval *zv)
  282. {
  283. zend_class_entry *ce = Z_PTR_P(zv);
  284. ce->refcount++;
  285. }
  286. ZEND_API void destroy_op_array(zend_op_array *op_array)
  287. {
  288. uint32_t i;
  289. if (op_array->static_variables &&
  290. !(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
  291. if (GC_DELREF(op_array->static_variables) == 0) {
  292. zend_array_destroy(op_array->static_variables);
  293. }
  294. }
  295. if (op_array->run_time_cache && !op_array->function_name) {
  296. efree(op_array->run_time_cache);
  297. op_array->run_time_cache = NULL;
  298. }
  299. if (!op_array->refcount || --(*op_array->refcount) > 0) {
  300. return;
  301. }
  302. efree_size(op_array->refcount, sizeof(*(op_array->refcount)));
  303. if (op_array->vars) {
  304. i = op_array->last_var;
  305. while (i > 0) {
  306. i--;
  307. zend_string_release_ex(op_array->vars[i], 0);
  308. }
  309. efree(op_array->vars);
  310. }
  311. if (op_array->literals) {
  312. zval *literal = op_array->literals;
  313. zval *end = literal + op_array->last_literal;
  314. while (literal < end) {
  315. zval_ptr_dtor_nogc(literal);
  316. literal++;
  317. }
  318. if (ZEND_USE_ABS_CONST_ADDR
  319. || !(op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO)) {
  320. efree(op_array->literals);
  321. }
  322. }
  323. efree(op_array->opcodes);
  324. if (op_array->function_name) {
  325. zend_string_release_ex(op_array->function_name, 0);
  326. }
  327. if (op_array->doc_comment) {
  328. zend_string_release_ex(op_array->doc_comment, 0);
  329. }
  330. if (op_array->live_range) {
  331. efree(op_array->live_range);
  332. }
  333. if (op_array->try_catch_array) {
  334. efree(op_array->try_catch_array);
  335. }
  336. if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_DTOR) {
  337. if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
  338. zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array);
  339. }
  340. }
  341. if (op_array->arg_info) {
  342. uint32_t num_args = op_array->num_args;
  343. zend_arg_info *arg_info = op_array->arg_info;
  344. if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
  345. arg_info--;
  346. num_args++;
  347. }
  348. if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
  349. num_args++;
  350. }
  351. for (i = 0 ; i < num_args; i++) {
  352. if (arg_info[i].name) {
  353. zend_string_release_ex(arg_info[i].name, 0);
  354. }
  355. if (ZEND_TYPE_IS_CLASS(arg_info[i].type)) {
  356. zend_string_release_ex(ZEND_TYPE_NAME(arg_info[i].type), 0);
  357. }
  358. }
  359. efree(arg_info);
  360. }
  361. }
  362. static void zend_update_extended_info(zend_op_array *op_array)
  363. {
  364. zend_op *opline = op_array->opcodes, *end=opline+op_array->last;
  365. while (opline<end) {
  366. if (opline->opcode == ZEND_EXT_STMT) {
  367. if (opline+1<end) {
  368. if ((opline+1)->opcode == ZEND_EXT_STMT) {
  369. opline->opcode = ZEND_NOP;
  370. opline++;
  371. continue;
  372. }
  373. if (opline+1<end) {
  374. opline->lineno = (opline+1)->lineno;
  375. }
  376. } else {
  377. opline->opcode = ZEND_NOP;
  378. }
  379. }
  380. opline++;
  381. }
  382. }
  383. static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array)
  384. {
  385. if (extension->op_array_handler) {
  386. extension->op_array_handler(op_array);
  387. }
  388. }
  389. static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num)
  390. {
  391. int i;
  392. for (i = 0; i < op_array->last_try_catch; i++) {
  393. if ((op_num < op_array->try_catch_array[i].finally_op ||
  394. op_num >= op_array->try_catch_array[i].finally_end)
  395. && (dst_num >= op_array->try_catch_array[i].finally_op &&
  396. dst_num <= op_array->try_catch_array[i].finally_end)) {
  397. CG(in_compilation) = 1;
  398. CG(active_op_array) = op_array;
  399. CG(zend_lineno) = op_array->opcodes[op_num].lineno;
  400. zend_error_noreturn(E_COMPILE_ERROR, "jump into a finally block is disallowed");
  401. } else if ((op_num >= op_array->try_catch_array[i].finally_op
  402. && op_num <= op_array->try_catch_array[i].finally_end)
  403. && (dst_num > op_array->try_catch_array[i].finally_end
  404. || dst_num < op_array->try_catch_array[i].finally_op)) {
  405. CG(in_compilation) = 1;
  406. CG(active_op_array) = op_array;
  407. CG(zend_lineno) = op_array->opcodes[op_num].lineno;
  408. zend_error_noreturn(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
  409. }
  410. }
  411. }
  412. static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) {
  413. int nest_levels = opline->op2.num;
  414. int array_offset = opline->op1.num;
  415. zend_brk_cont_element *jmp_to;
  416. do {
  417. jmp_to = &CG(context).brk_cont_array[array_offset];
  418. if (nest_levels > 1) {
  419. array_offset = jmp_to->parent;
  420. }
  421. } while (--nest_levels > 0);
  422. return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
  423. }
  424. /* Live ranges must be sorted by increasing start opline */
  425. static int cmp_live_range(const zend_live_range *a, const zend_live_range *b) {
  426. return a->start - b->start;
  427. }
  428. static void swap_live_range(zend_live_range *a, zend_live_range *b) {
  429. zend_live_range tmp = *a;
  430. *a = *b;
  431. *b = tmp;
  432. }
  433. static void zend_sort_live_ranges(zend_op_array *op_array) {
  434. zend_sort(op_array->live_range, op_array->last_live_range, sizeof(zend_live_range),
  435. (compare_func_t) cmp_live_range, (swap_func_t) swap_live_range);
  436. }
  437. ZEND_API int pass_two(zend_op_array *op_array)
  438. {
  439. zend_op *opline, *end;
  440. if (!ZEND_USER_CODE(op_array->type)) {
  441. return 0;
  442. }
  443. if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
  444. zend_update_extended_info(op_array);
  445. }
  446. if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) {
  447. if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER) {
  448. zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array);
  449. }
  450. }
  451. if (CG(context).vars_size != op_array->last_var) {
  452. op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var);
  453. CG(context).vars_size = op_array->last_var;
  454. }
  455. #if ZEND_USE_ABS_CONST_ADDR
  456. if (CG(context).opcodes_size != op_array->last) {
  457. op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
  458. CG(context).opcodes_size = op_array->last;
  459. }
  460. if (CG(context).literals_size != op_array->last_literal) {
  461. op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal);
  462. CG(context).literals_size = op_array->last_literal;
  463. }
  464. #else
  465. op_array->opcodes = (zend_op *) erealloc(op_array->opcodes,
  466. ZEND_MM_ALIGNED_SIZE_EX(sizeof(zend_op) * op_array->last, 16) +
  467. sizeof(zval) * op_array->last_literal);
  468. if (op_array->literals) {
  469. memcpy(((char*)op_array->opcodes) + ZEND_MM_ALIGNED_SIZE_EX(sizeof(zend_op) * op_array->last, 16),
  470. op_array->literals, sizeof(zval) * op_array->last_literal);
  471. efree(op_array->literals);
  472. op_array->literals = (zval*)(((char*)op_array->opcodes) + ZEND_MM_ALIGNED_SIZE_EX(sizeof(zend_op) * op_array->last, 16));
  473. }
  474. CG(context).opcodes_size = op_array->last;
  475. CG(context).literals_size = op_array->last_literal;
  476. #endif
  477. /* Needs to be set directly after the opcode/literal reallocation, to ensure destruction
  478. * happens correctly if any of the following fixups generate a fatal error. */
  479. op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
  480. opline = op_array->opcodes;
  481. end = opline + op_array->last;
  482. while (opline < end) {
  483. switch (opline->opcode) {
  484. case ZEND_RECV_INIT:
  485. {
  486. zval *val = CT_CONSTANT(opline->op2);
  487. if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
  488. uint32_t slot = ZEND_MM_ALIGNED_SIZE_EX(op_array->cache_size, 8);
  489. Z_CACHE_SLOT_P(val) = slot;
  490. op_array->cache_size += sizeof(zval);
  491. }
  492. }
  493. break;
  494. case ZEND_FAST_CALL:
  495. opline->op1.opline_num = op_array->try_catch_array[opline->op1.num].finally_op;
  496. ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
  497. break;
  498. case ZEND_BRK:
  499. case ZEND_CONT:
  500. {
  501. uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline);
  502. if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
  503. zend_check_finally_breakout(op_array, opline - op_array->opcodes, jmp_target);
  504. }
  505. opline->opcode = ZEND_JMP;
  506. opline->op1.opline_num = jmp_target;
  507. opline->op2.num = 0;
  508. ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
  509. }
  510. break;
  511. case ZEND_GOTO:
  512. zend_resolve_goto_label(op_array, opline);
  513. if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
  514. zend_check_finally_breakout(op_array, opline - op_array->opcodes, opline->op1.opline_num);
  515. }
  516. /* break omitted intentionally */
  517. case ZEND_JMP:
  518. ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
  519. break;
  520. case ZEND_JMPZNZ:
  521. /* absolute index to relative offset */
  522. opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
  523. /* break omitted intentionally */
  524. case ZEND_JMPZ:
  525. case ZEND_JMPNZ:
  526. case ZEND_JMPZ_EX:
  527. case ZEND_JMPNZ_EX:
  528. case ZEND_JMP_SET:
  529. case ZEND_COALESCE:
  530. case ZEND_FE_RESET_R:
  531. case ZEND_FE_RESET_RW:
  532. ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
  533. break;
  534. case ZEND_ASSERT_CHECK:
  535. {
  536. /* If result of assert is unused, result of check is unused as well */
  537. zend_op *call = &op_array->opcodes[opline->op2.opline_num - 1];
  538. if (call->opcode == ZEND_EXT_FCALL_END) {
  539. call--;
  540. }
  541. if (call->result_type == IS_UNUSED) {
  542. opline->result_type = IS_UNUSED;
  543. }
  544. ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
  545. break;
  546. }
  547. case ZEND_DECLARE_ANON_CLASS:
  548. case ZEND_DECLARE_ANON_INHERITED_CLASS:
  549. case ZEND_FE_FETCH_R:
  550. case ZEND_FE_FETCH_RW:
  551. /* absolute index to relative offset */
  552. opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
  553. break;
  554. case ZEND_CATCH:
  555. if (!(opline->extended_value & ZEND_LAST_CATCH)) {
  556. ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2);
  557. }
  558. break;
  559. case ZEND_RETURN:
  560. case ZEND_RETURN_BY_REF:
  561. if (op_array->fn_flags & ZEND_ACC_GENERATOR) {
  562. opline->opcode = ZEND_GENERATOR_RETURN;
  563. }
  564. break;
  565. case ZEND_SWITCH_LONG:
  566. case ZEND_SWITCH_STRING:
  567. {
  568. /* absolute indexes to relative offsets */
  569. HashTable *jumptable = Z_ARRVAL_P(CT_CONSTANT(opline->op2));
  570. zval *zv;
  571. ZEND_HASH_FOREACH_VAL(jumptable, zv) {
  572. Z_LVAL_P(zv) = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, Z_LVAL_P(zv));
  573. } ZEND_HASH_FOREACH_END();
  574. opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
  575. break;
  576. }
  577. }
  578. if (opline->op1_type == IS_CONST) {
  579. ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op1);
  580. } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
  581. opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var);
  582. }
  583. if (opline->op2_type == IS_CONST) {
  584. ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline, opline->op2);
  585. } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
  586. opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var);
  587. }
  588. if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
  589. opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var);
  590. }
  591. ZEND_VM_SET_OPCODE_HANDLER(opline);
  592. opline++;
  593. }
  594. if (op_array->live_range) {
  595. int i;
  596. zend_sort_live_ranges(op_array);
  597. for (i = 0; i < op_array->last_live_range; i++) {
  598. op_array->live_range[i].var =
  599. (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) |
  600. (op_array->live_range[i].var & ZEND_LIVE_MASK);
  601. }
  602. }
  603. return 0;
  604. }
  605. ZEND_API unary_op_type get_unary_op(int opcode)
  606. {
  607. switch (opcode) {
  608. case ZEND_BW_NOT:
  609. return (unary_op_type) bitwise_not_function;
  610. case ZEND_BOOL_NOT:
  611. return (unary_op_type) boolean_not_function;
  612. default:
  613. return (unary_op_type) NULL;
  614. }
  615. }
  616. ZEND_API binary_op_type get_binary_op(int opcode)
  617. {
  618. switch (opcode) {
  619. case ZEND_ADD:
  620. case ZEND_ASSIGN_ADD:
  621. return (binary_op_type) add_function;
  622. case ZEND_SUB:
  623. case ZEND_ASSIGN_SUB:
  624. return (binary_op_type) sub_function;
  625. case ZEND_MUL:
  626. case ZEND_ASSIGN_MUL:
  627. return (binary_op_type) mul_function;
  628. case ZEND_POW:
  629. case ZEND_ASSIGN_POW:
  630. return (binary_op_type) pow_function;
  631. case ZEND_DIV:
  632. case ZEND_ASSIGN_DIV:
  633. return (binary_op_type) div_function;
  634. case ZEND_MOD:
  635. case ZEND_ASSIGN_MOD:
  636. return (binary_op_type) mod_function;
  637. case ZEND_SL:
  638. case ZEND_ASSIGN_SL:
  639. return (binary_op_type) shift_left_function;
  640. case ZEND_SR:
  641. case ZEND_ASSIGN_SR:
  642. return (binary_op_type) shift_right_function;
  643. case ZEND_FAST_CONCAT:
  644. case ZEND_CONCAT:
  645. case ZEND_ASSIGN_CONCAT:
  646. return (binary_op_type) concat_function;
  647. case ZEND_IS_IDENTICAL:
  648. return (binary_op_type) is_identical_function;
  649. case ZEND_IS_NOT_IDENTICAL:
  650. return (binary_op_type) is_not_identical_function;
  651. case ZEND_IS_EQUAL:
  652. case ZEND_CASE:
  653. return (binary_op_type) is_equal_function;
  654. case ZEND_IS_NOT_EQUAL:
  655. return (binary_op_type) is_not_equal_function;
  656. case ZEND_IS_SMALLER:
  657. return (binary_op_type) is_smaller_function;
  658. case ZEND_IS_SMALLER_OR_EQUAL:
  659. return (binary_op_type) is_smaller_or_equal_function;
  660. case ZEND_SPACESHIP:
  661. return (binary_op_type) compare_function;
  662. case ZEND_BW_OR:
  663. case ZEND_ASSIGN_BW_OR:
  664. return (binary_op_type) bitwise_or_function;
  665. case ZEND_BW_AND:
  666. case ZEND_ASSIGN_BW_AND:
  667. return (binary_op_type) bitwise_and_function;
  668. case ZEND_BW_XOR:
  669. case ZEND_ASSIGN_BW_XOR:
  670. return (binary_op_type) bitwise_xor_function;
  671. case ZEND_BOOL_XOR:
  672. return (binary_op_type) boolean_xor_function;
  673. default:
  674. return (binary_op_type) NULL;
  675. }
  676. }
  677. /*
  678. * Local variables:
  679. * tab-width: 4
  680. * c-basic-offset: 4
  681. * indent-tabs-mode: t
  682. * End:
  683. * vim600: sw=4 ts=4 fdm=marker
  684. * vim<600: sw=4 ts=4
  685. */