Skip to content

Commit 4646d0e

Browse files
committed
Minimal JIT support
1 parent d0d1425 commit 4646d0e

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--TEST--
2+
Partial application JIT 001
3+
--FILE--
4+
<?php
5+
(function ($a,$b) { var_dump($a, $b); })(1, ...)(2);
6+
?>
7+
--EXPECT--
8+
int(1)
9+
int(2)

Zend/zend_partial.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323

2424
BEGIN_EXTERN_C()
2525

26-
/* This macro depends on zend_closure structure layout */
2726
#define ZEND_PARTIAL_OBJECT(func) \
28-
((zend_object*)((char*)(func) - XtOffsetOf(struct{uint32_t a; zend_function b;}, b) - sizeof(zval) - sizeof(zend_function) - sizeof(zend_object)))
27+
((zend_object*)((char*)(func) - zend_partial_func_offset()))
2928

3029
typedef struct _zend_partial zend_partial;
3130

@@ -47,6 +46,17 @@ zend_result zend_partial_init_call(zend_execute_data *call);
4746

4847
bool zend_is_partial_function(zend_function *function);
4948

49+
/* Offset of zend_partial.func */
50+
static zend_always_inline size_t zend_partial_func_offset(void) {
51+
return XtOffsetOf(struct {
52+
zend_object a;
53+
zend_function b;
54+
zval c;
55+
uint32_t d;
56+
zend_function func;
57+
}, func);
58+
}
59+
5060
END_EXTERN_C()
5161

5262
#endif

ext/opcache/jit/zend_jit.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ static int zend_jit_needs_call_chain(zend_call_info *call_info, uint32_t b, cons
298298
case ZEND_DO_FCALL_BY_NAME:
299299
case ZEND_DO_FCALL:
300300
case ZEND_CALLABLE_CONVERT:
301+
case ZEND_CALLABLE_CONVERT_PARTIAL:
301302
return 0;
302303
case ZEND_SEND_VAL:
303304
case ZEND_SEND_VAR:
@@ -383,6 +384,7 @@ static int zend_jit_needs_call_chain(zend_call_info *call_info, uint32_t b, cons
383384
case ZEND_DO_FCALL_BY_NAME:
384385
case ZEND_DO_FCALL:
385386
case ZEND_CALLABLE_CONVERT:
387+
case ZEND_CALLABLE_CONVERT_PARTIAL:
386388
end = opline;
387389
if (end - op_array->opcodes >= ssa->cfg.blocks[b].start + ssa->cfg.blocks[b].len) {
388390
/* INIT_FCALL and DO_FCALL in different BasicBlocks */
@@ -862,6 +864,7 @@ static bool zend_jit_dec_call_level(uint8_t opcode)
862864
case ZEND_DO_UCALL:
863865
case ZEND_DO_FCALL_BY_NAME:
864866
case ZEND_CALLABLE_CONVERT:
867+
case ZEND_CALLABLE_CONVERT_PARTIAL:
865868
return true;
866869
default:
867870
return false;

ext/opcache/jit/zend_jit_ir.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* +----------------------------------------------------------------------+
1717
*/
1818

19+
#include "zend_partial.h"
1920
#include "jit/ir/ir.h"
2021
#include "jit/ir/ir_builder.h"
2122

ext/opcache/jit/zend_jit_vm_helpers.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <ZendAccelerator.h>
2828
#include "Optimizer/zend_func_info.h"
2929
#include "Optimizer/zend_call_graph.h"
30+
#include "zend_partial.h"
3031
#include "zend_jit.h"
3132

3233
#include "zend_jit_internal.h"
@@ -59,6 +60,8 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPC
5960
OBJ_RELEASE(Z_OBJ(execute_data->This));
6061
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
6162
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
63+
} else if (UNEXPECTED(call_info & ZEND_CALL_FAKE_CLOSURE)) {
64+
OBJ_RELEASE(ZEND_PARTIAL_OBJECT(EX(func)));
6265
}
6366
if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
6467
zend_free_extra_named_params(EX(extra_named_params));
@@ -100,6 +103,8 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_top_func_helper(ZEND_OPCODE
100103
}
101104
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
102105
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
106+
} else if (UNEXPECTED(call_info & ZEND_CALL_FAKE_CLOSURE)) {
107+
OBJ_RELEASE(ZEND_PARTIAL_OBJECT(EX(func)));
103108
}
104109
execute_data = EG(current_execute_data);
105110
#ifdef HAVE_GCC_GLOBAL_REGS
@@ -692,7 +697,9 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
692697
(zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array);
693698
offset = jit_extension->offset;
694699
if (!op_array->function_name
695-
|| (op_array->fn_flags & ZEND_ACC_CLOSURE)) {
700+
|| (op_array->fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_FAKE_CLOSURE))) {
701+
/* op_array is a copy that may be freed during tracing. Also, it
702+
* may be bound to a custom scope. Fetch the original op_array. */
696703
op_array = jit_extension->op_array;
697704
}
698705

@@ -977,7 +984,8 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
977984
TRACE_RECORD(ZEND_JIT_TRACE_DO_ICALL, 0, func);
978985
}
979986
} else if (opline->opcode == ZEND_INCLUDE_OR_EVAL
980-
|| opline->opcode == ZEND_CALLABLE_CONVERT) {
987+
|| opline->opcode == ZEND_CALLABLE_CONVERT
988+
|| opline->opcode == ZEND_CALLABLE_CONVERT_PARTIAL) {
981989
/* TODO: Support tracing JIT for ZEND_CALLABLE_CONVERT. */
982990
stop = ZEND_JIT_TRACE_STOP_INTERPRETER;
983991
break;
@@ -1016,7 +1024,9 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
10161024
}
10171025
offset = jit_extension->offset;
10181026
if (!op_array->function_name
1019-
|| (op_array->fn_flags & ZEND_ACC_CLOSURE)) {
1027+
|| (op_array->fn_flags & (ZEND_ACC_CLOSURE|ZEND_ACC_FAKE_CLOSURE))) {
1028+
/* op_array is a copy that may be freed during tracing. Also, it
1029+
* may be bound to a custom scope. Fetch the original op_array. */
10201030
op_array = jit_extension->op_array;
10211031
}
10221032

0 commit comments

Comments
 (0)