Skip to content

Commit d907606

Browse files
committed
ext/pdo: Convert def_stmt_ctor_args field to Hashtable*
1 parent 8f8f31a commit d907606

File tree

3 files changed

+41
-34
lines changed

3 files changed

+41
-34
lines changed

Zend/zend_gc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,16 @@ static zend_always_inline void zend_get_gc_buffer_add_zval(
131131
}
132132
}
133133

134+
135+
static zend_always_inline void zend_get_gc_buffer_add_ht(
136+
zend_get_gc_buffer *gc_buffer, HashTable *obj) {
137+
if (UNEXPECTED(gc_buffer->cur == gc_buffer->end)) {
138+
zend_get_gc_buffer_grow(gc_buffer);
139+
}
140+
ZVAL_ARR(gc_buffer->cur, obj);
141+
gc_buffer->cur++;
142+
}
143+
134144
static zend_always_inline void zend_get_gc_buffer_add_obj(
135145
zend_get_gc_buffer *gc_buffer, zend_object *obj) {
136146
if (UNEXPECTED(gc_buffer->cur == gc_buffer->end)) {

ext/pdo/pdo_dbh.c

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -434,11 +434,9 @@ PHP_METHOD(PDO, __construct)
434434
}
435435
/* }}} */
436436

437-
static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry *dbstmt_ce, zval *ctor_args) /* {{{ */
437+
static zval *pdo_stmt_instantiate(pdo_dbh_t *dbh, zval *object, zend_class_entry *dbstmt_ce, HashTable const *ctor_args) /* {{{ */
438438
{
439-
if (!Z_ISUNDEF_P(ctor_args)) {
440-
/* This implies an error within PDO if this does not hold */
441-
ZEND_ASSERT(Z_TYPE_P(ctor_args) == IS_ARRAY);
439+
if (ctor_args) {
442440
if (!dbstmt_ce->constructor) {
443441
zend_throw_error(NULL, "User-supplied statement does not accept constructor arguments");
444442
return NULL;
@@ -475,8 +473,9 @@ PHP_METHOD(PDO, prepare)
475473
{
476474
pdo_stmt_t *stmt;
477475
zend_string *statement;
478-
zval *options = NULL, *value, *item, ctor_args;
476+
zval *options = NULL, *value, *item;
479477
zend_class_entry *dbstmt_ce, *pce;
478+
/* const */ HashTable *ctor_args = NULL;
480479
pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(ZEND_THIS);
481480
pdo_dbh_t *dbh = dbh_obj->inner;
482481

@@ -525,16 +524,14 @@ PHP_METHOD(PDO, prepare)
525524
zend_zval_value_name(value));
526525
RETURN_THROWS();
527526
}
528-
ZVAL_COPY_VALUE(&ctor_args, item);
529-
} else {
530-
ZVAL_UNDEF(&ctor_args);
527+
ctor_args = Z_ARRVAL_P(item);
531528
}
532529
} else {
533530
dbstmt_ce = dbh->def_stmt_ce;
534-
ZVAL_COPY_VALUE(&ctor_args, &dbh->def_stmt_ctor_args);
531+
ctor_args = dbh->def_stmt_ctor_args;
535532
}
536533

537-
if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, &ctor_args)) {
534+
if (!pdo_stmt_instantiate(dbh, return_value, dbstmt_ce, ctor_args)) {
538535
RETURN_THROWS();
539536
}
540537
stmt = Z_PDO_STMT_P(return_value);
@@ -549,11 +546,7 @@ PHP_METHOD(PDO, prepare)
549546
ZVAL_UNDEF(&stmt->lazy_object_ref);
550547

551548
if (dbh->methods->preparer(dbh, statement, stmt, options)) {
552-
if (Z_TYPE(ctor_args) == IS_ARRAY) {
553-
pdo_stmt_construct(stmt, return_value, dbstmt_ce, Z_ARRVAL(ctor_args));
554-
} else {
555-
pdo_stmt_construct(stmt, return_value, dbstmt_ce, /* ctor_args */ NULL);
556-
}
549+
pdo_stmt_construct(stmt, return_value, dbstmt_ce, ctor_args);
557550
return;
558551
}
559552

@@ -817,17 +810,18 @@ static bool pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *value) /
817810
return false;
818811
}
819812
dbh->def_stmt_ce = pce;
820-
if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
821-
zval_ptr_dtor(&dbh->def_stmt_ctor_args);
822-
ZVAL_UNDEF(&dbh->def_stmt_ctor_args);
813+
if (dbh->def_stmt_ctor_args) {
814+
zend_array_release(dbh->def_stmt_ctor_args);
815+
dbh->def_stmt_ctor_args = NULL;
823816
}
824817
if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) {
825818
if (Z_TYPE_P(item) != IS_ARRAY) {
826819
zend_type_error("PDO::ATTR_STATEMENT_CLASS constructor_args must be of type ?array, %s given",
827820
zend_zval_value_name(value));
828821
return false;
829822
}
830-
ZVAL_COPY(&dbh->def_stmt_ctor_args, item);
823+
/* Separate array */
824+
dbh->def_stmt_ctor_args = zend_array_dup(Z_ARRVAL_P(item));
831825
}
832826
return true;
833827
}
@@ -906,9 +900,10 @@ PHP_METHOD(PDO, getAttribute)
906900
case PDO_ATTR_STATEMENT_CLASS:
907901
array_init(return_value);
908902
add_next_index_str(return_value, zend_string_copy(dbh->def_stmt_ce->name));
909-
if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
910-
Z_TRY_ADDREF(dbh->def_stmt_ctor_args);
911-
add_next_index_zval(return_value, &dbh->def_stmt_ctor_args);
903+
if (dbh->def_stmt_ctor_args) {
904+
/* Increment refcount of constructor arguments */
905+
zend_gc_addref(&dbh->def_stmt_ctor_args->gc);
906+
add_next_index_array(return_value, dbh->def_stmt_ctor_args);
912907
}
913908
return;
914909
case PDO_ATTR_DEFAULT_FETCH_MODE:
@@ -1093,7 +1088,7 @@ PHP_METHOD(PDO, query)
10931088

10941089
PDO_DBH_CLEAR_ERR();
10951090

1096-
if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, &dbh->def_stmt_ctor_args)) {
1091+
if (!pdo_stmt_instantiate(dbh, return_value, dbh->def_stmt_ce, dbh->def_stmt_ctor_args)) {
10971092
RETURN_THROWS();
10981093
}
10991094
stmt = Z_PDO_STMT_P(return_value);
@@ -1122,11 +1117,7 @@ PHP_METHOD(PDO, query)
11221117
stmt->executed = 1;
11231118
}
11241119
if (ret) {
1125-
if (Z_TYPE(dbh->def_stmt_ctor_args) == IS_ARRAY) {
1126-
pdo_stmt_construct(stmt, return_value, dbh->def_stmt_ce, Z_ARRVAL(dbh->def_stmt_ctor_args));
1127-
} else {
1128-
pdo_stmt_construct(stmt, return_value, dbh->def_stmt_ce, /* ctor_args */ NULL);
1129-
}
1120+
pdo_stmt_construct(stmt, return_value, dbh->def_stmt_ce, dbh->def_stmt_ctor_args);
11301121
return;
11311122
}
11321123
}
@@ -1320,7 +1311,9 @@ static HashTable *dbh_get_gc(zend_object *object, zval **gc_data, int *gc_count)
13201311
{
13211312
pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(object);
13221313
zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create();
1323-
zend_get_gc_buffer_add_zval(gc_buffer, &dbh->def_stmt_ctor_args);
1314+
if (dbh->def_stmt_ctor_args) {
1315+
zend_get_gc_buffer_add_ht(gc_buffer, dbh->def_stmt_ctor_args);
1316+
}
13241317
if (dbh->methods && dbh->methods->get_gc) {
13251318
dbh->methods->get_gc(dbh, gc_buffer);
13261319
}
@@ -1382,10 +1375,6 @@ static void dbh_free(pdo_dbh_t *dbh, bool free_persistent)
13821375
pefree((char *)dbh->persistent_id, dbh->is_persistent);
13831376
}
13841377

1385-
if (!Z_ISUNDEF(dbh->def_stmt_ctor_args)) {
1386-
zval_ptr_dtor(&dbh->def_stmt_ctor_args);
1387-
}
1388-
13891378
for (i = 0; i < PDO_DBH_DRIVER_METHOD_KIND__MAX; i++) {
13901379
if (dbh->cls_methods[i]) {
13911380
zend_hash_destroy(dbh->cls_methods[i]);
@@ -1413,6 +1402,13 @@ static void pdo_dbh_free_storage(zend_object *std)
14131402
if (dbh->is_persistent && dbh->methods && dbh->methods->persistent_shutdown) {
14141403
dbh->methods->persistent_shutdown(dbh);
14151404
}
1405+
1406+
/* TODO ? Freeing of constructor arguments is handles via GC */
1407+
if (dbh->def_stmt_ctor_args) {
1408+
zend_array_release(dbh->def_stmt_ctor_args);
1409+
//zend_hash_destroy(dbh->def_stmt_ctor_args);
1410+
}
1411+
14161412
zend_object_std_dtor(std);
14171413
dbh_free(dbh, 0);
14181414
}
@@ -1427,6 +1423,7 @@ zend_object *pdo_dbh_new(zend_class_entry *ce)
14271423
rebuild_object_properties(&dbh->std);
14281424
dbh->inner = ecalloc(1, sizeof(pdo_dbh_t));
14291425
dbh->inner->def_stmt_ce = pdo_dbstmt_ce;
1426+
dbh->inner->def_stmt_ctor_args = NULL;
14301427

14311428
return &dbh->std;
14321429
}

ext/pdo/php_pdo_driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ struct _pdo_dbh_t {
487487

488488
zend_class_entry *def_stmt_ce;
489489

490-
zval def_stmt_ctor_args;
490+
HashTable *def_stmt_ctor_args;
491491

492492
/* when calling PDO::query(), we need to keep the error
493493
* context from the statement around until we next clear it.

0 commit comments

Comments
 (0)