This commit is contained in:
Alliballibaba
2025-10-19 12:33:59 +02:00
parent 035cbf9f3c
commit 2307fc8ee2
4 changed files with 75 additions and 60 deletions

35
types.c
View File

@@ -23,10 +23,10 @@ void __zend_hash_init__(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor,
zend_array *__zend_new_array__(uint32_t size) { return zend_new_array(size); }
bool is_internal_class(zend_class_entry *entry) {
return entry->create_object != NULL;
return entry->create_object != NULL;
}
//serialize
// serialize
zend_string *__zval_serialize__(zend_object *obj) {
// find serialize in global function table and call it
zval zv;
@@ -36,9 +36,10 @@ zend_string *__zval_serialize__(zend_object *obj) {
zval retval;
zval params[1];
params[0] = zv;
if (call_user_function(EG(function_table), NULL, &func, &retval, 1, params) != SUCCESS) {
zval_ptr_dtor(&func);
return NULL;
if (call_user_function(EG(function_table), NULL, &func, &retval, 1, params) !=
SUCCESS) {
zval_ptr_dtor(&func);
return NULL;
}
zval_ptr_dtor(&func);
@@ -56,28 +57,28 @@ void __zval_unserialize__(zval *retval, zend_string *str) {
zval params[1];
ZVAL_STR(&params[0], str);
if (call_user_function(EG(function_table), NULL, &func, retval, 1, params) != SUCCESS) {
ZVAL_NULL(retval);
if (call_user_function(EG(function_table), NULL, &func, retval, 1, params) !=
SUCCESS) {
ZVAL_NULL(retval);
}
zval_ptr_dtor(&func);
zend_string_release(str);
}
zend_object *__php_object_init__(
zval *zv,
const char *class_name,
size_t class_name_len,
zval *zv, const char *class_name, size_t class_name_len,
zend_class_entry *ce // optional: pass NULL to look up by name
) {
if (!ce) {
zend_string *name =
zend_string_init_interned(class_name, class_name_len, 1);
ce = zend_lookup_class(name);
if (!ce) {
zend_string *name = zend_string_init_interned(class_name, class_name_len, 1);
ce = zend_lookup_class(name);
if (!ce) {
return NULL;
}
return NULL;
}
}
object_init_ex(zv, ce);
object_init_ex(zv, ce);
return Z_OBJ_P(zv);
return Z_OBJ_P(zv);
}

View File

@@ -274,37 +274,47 @@ func PHPValue(value any) unsafe.Pointer {
func phpValue(zval *C.zval, value any) {
switch v := value.(type) {
case nil:
// equvalent of: ZVAL_NULL
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_NULL
case bool:
// equvalent of: ZVAL_BOOL
if v {
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_TRUE
} else {
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_FALSE
}
case int:
// equvalent of: ZVAL_LONG
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_LONG
*(*C.zend_long)(unsafe.Pointer(&zval.value)) = C.zend_long(v)
case int64:
// equvalent of: ZVAL_LONG
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_LONG
*(*C.zend_long)(unsafe.Pointer(&zval.value)) = C.zend_long(v)
case float64:
// equvalent of: ZVAL_DOUBLE
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_DOUBLE
*(*C.double)(unsafe.Pointer(&zval.value)) = C.double(v)
case string:
if v == "" {
// equivalent: ZVAL_EMPTY_STRING
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_INTERNED_STRING_EX
*(**C.zend_string)(unsafe.Pointer(&zval.value)) = C.zend_empty_string
break
}
// equvalent of: ZVAL_STRING
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_STRING_EX
*(**C.zend_string)(unsafe.Pointer(&zval.value)) = phpString(v, false)
case AssociativeArray:
// equvalent of: ZVAL_ARR
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_ARRAY_EX
*(**C.zend_array)(unsafe.Pointer(&zval.value)) = phpArray(v.Map, v.Order)
case map[string]any:
// equvalent of: ZVAL_ARR
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_ARRAY_EX
*(**C.zend_array)(unsafe.Pointer(&zval.value)) = phpArray(v, nil)
case []any:
// equvalent of: ZVAL_ARR
*(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_ARRAY_EX
*(**C.zend_array)(unsafe.Pointer(&zval.value)) = (*C.zend_array)(PHPPackedArray(v))
case Object:

View File

@@ -18,11 +18,7 @@ zend_array *__zend_new_array__(uint32_t size);
bool is_internal_class(zend_class_entry *entry);
zend_string *__zval_serialize__(zend_object *obj);
void __zval_unserialize__(zval *retval, zend_string *str);
zend_object *__php_object_init__(
zval *zv,
const char *class_name,
size_t class_name_len,
zend_class_entry *ce
);
zend_object *__php_object_init__(zval *zv, const char *class_name,
size_t class_name_len, zend_class_entry *ce);
#endif

View File

@@ -2,6 +2,7 @@ package frankenphp
import (
"errors"
"fmt"
"io"
"log/slog"
"testing"
@@ -211,8 +212,8 @@ func BenchmarkFloat(b *testing.B) {
}
func BenchmarkString(b *testing.B) {
message := "Hello, World!"
benchOnPHPThread(b, b.N, func() {
message := "Hello, World!"
phpString := PHPString(message, false)
_ = GoString(phpString)
zendStringRelease(phpString)
@@ -220,15 +221,26 @@ func BenchmarkString(b *testing.B) {
}
func BenchmarkMap(b *testing.B) {
originalMap := map[string]any{
"foo1": "bar1",
"foo2": int64(2),
"foo3": true,
"foo4": 3.14,
"foo5": nil,
}
benchOnPHPThread(b, b.N, func() {
originalMap := map[string]any{
"foo1": "bar1",
"foo2": int64(2),
"foo3": true,
"foo4": 3.14,
"foo5": nil,
}
phpArray := PHPMap(originalMap)
_ = GoMap(phpArray)
zendHashDestroy(phpArray)
})
}
func BenchmarkMap50Entries(b *testing.B) {
originalMap := map[string]any{}
for i := 0; i < 50; i++ {
originalMap[fmt.Sprintf("key%d", i)] = fmt.Sprintf("value%d", i)
}
benchOnPHPThread(b, b.N, func() {
phpArray := PHPMap(originalMap)
_ = GoMap(phpArray)
zendHashDestroy(phpArray)
@@ -236,18 +248,17 @@ func BenchmarkMap(b *testing.B) {
}
func BenchmarkOrderedAssociativeArray(b *testing.B) {
originalArray := AssociativeArray{
Map: map[string]any{
"foo1": "bar1",
"foo2": int64(2),
"foo3": true,
"foo4": 3.14,
"foo5": nil,
},
Order: []string{"foo3", "foo1", "foo4", "foo2", "foo5"},
}
benchOnPHPThread(b, b.N, func() {
originalArray := AssociativeArray{
Map: map[string]any{
"foo1": "bar1",
"foo2": int64(2),
"foo3": true,
"foo4": 3.14,
"foo5": nil,
},
Order: []string{"foo3", "foo1", "foo4", "foo2", "foo5"},
}
phpArray := PHPAssociativeArray(originalArray)
_ = GoAssociativeArray(phpArray)
zendHashDestroy(phpArray)
@@ -255,9 +266,8 @@ func BenchmarkOrderedAssociativeArray(b *testing.B) {
}
func BenchmarkSlice(b *testing.B) {
originalSlice := []any{"bar1", "bar2", "bar3", "bar4", "bar5"}
benchOnPHPThread(b, b.N, func() {
originalSlice := []any{"bar1", "bar2", "bar3", "bar4", "bar5"}
phpArray := PHPPackedArray(originalSlice)
_ = GoPackedArray(phpArray)
zendHashDestroy(phpArray)
@@ -265,18 +275,17 @@ func BenchmarkSlice(b *testing.B) {
}
func BenchmarkObject(b *testing.B) {
originalObject := Object{
ClassName: "stdClass",
Props: map[string]any{
"prop1": "value1",
"prop2": int64(42),
"prop3": true,
"prop4": 3.14,
"prop5": nil,
},
}
benchOnPHPThread(b, b.N, func() {
originalObject := Object{
ClassName: "stdClass",
Props: map[string]any{
"prop1": "value1",
"prop2": int64(42),
"prop3": true,
"prop4": 3.14,
"prop5": nil,
},
}
phpObject := PHPObject(originalObject)
_ = GoObject(phpObject)
zvalPtrDtor(phpObject)
@@ -284,12 +293,11 @@ func BenchmarkObject(b *testing.B) {
}
func BenchmarkEmptyObject(b *testing.B) {
originalObject := Object{
ClassName: "stdClass",
Props: map[string]any{},
}
benchOnPHPThread(b, b.N, func() {
originalObject := Object{
ClassName: "stdClass",
Props: map[string]any{},
}
phpObject := PHPObject(originalObject)
_ = GoObject(phpObject)
zvalPtrDtor(phpObject)