Skip to content

Commit ec11ab8

Browse files
committed
Use Vectorcall APIs
1 parent 0c1b138 commit ec11ab8

1 file changed

Lines changed: 107 additions & 31 deletions

File tree

bson/_cbsonmodule.c

Lines changed: 107 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ static PyObject* datetime_ms_from_millis(PyObject* self, long long millis){
356356
if (!(ll_millis = PyLong_FromLongLong(millis))){
357357
return NULL;
358358
}
359-
dt = PyObject_CallFunctionObjArgs(state->DatetimeMS, ll_millis, NULL);
359+
PyObject* args[1] = {ll_millis};
360+
dt = PyObject_Vectorcall(state->DatetimeMS, args, 1, NULL);
360361
Py_DECREF(ll_millis);
361362
return dt;
362363
}
@@ -401,7 +402,9 @@ static PyObject* decode_datetime(PyObject* self, long long millis, const codec_o
401402
int64_t min_millis_offset = 0;
402403
int64_t max_millis_offset = 0;
403404
if (options->tz_aware && options->tzinfo && options->tzinfo != Py_None) {
404-
PyObject* utcoffset = PyObject_CallMethodObjArgs(options->tzinfo, state->_utcoffset_str, state->min_datetime, NULL);
405+
PyObject* utcoffset_args[2] = {options->tzinfo, state->min_datetime};
406+
PyObject* utcoffset = PyObject_VectorcallMethod(
407+
state->_utcoffset_str, utcoffset_args, 2, NULL);
405408
if (utcoffset == NULL) {
406409
return 0;
407410
}
@@ -420,7 +423,9 @@ static PyObject* decode_datetime(PyObject* self, long long millis, const codec_o
420423
(PyDateTime_DELTA_GET_MICROSECONDS(utcoffset) / 1000);
421424
}
422425
Py_DECREF(utcoffset);
423-
utcoffset = PyObject_CallMethodObjArgs(options->tzinfo, state->_utcoffset_str, state->max_datetime, NULL);
426+
utcoffset_args[1] = state->max_datetime;
427+
utcoffset = PyObject_VectorcallMethod(
428+
state->_utcoffset_str, utcoffset_args, 2, NULL);
424429
if (utcoffset == NULL) {
425430
return 0;
426431
}
@@ -481,7 +486,9 @@ static PyObject* decode_datetime(PyObject* self, long long millis, const codec_o
481486

482487
/* convert to local time */
483488
if (options->tzinfo != Py_None) {
484-
PyObject* temp = PyObject_CallMethodObjArgs(value, state->_astimezone_str, options->tzinfo, NULL);
489+
PyObject* astimezone_args[2] = {value, options->tzinfo};
490+
PyObject* temp = PyObject_VectorcallMethod(
491+
state->_astimezone_str, astimezone_args, 2, NULL);
485492
Py_DECREF(value);
486493
value = temp;
487494
}
@@ -688,7 +695,8 @@ static int _load_python_objects(PyObject* module) {
688695
return 1;
689696
}
690697

691-
compiled = PyObject_CallFunction(re_compile, "O", empty_string);
698+
PyObject* compile_args[1] = {empty_string};
699+
compiled = PyObject_Vectorcall(re_compile, compile_args, 1, NULL);
692700
Py_DECREF(re_compile);
693701
if (compiled == NULL) {
694702
state->REType = NULL;
@@ -1244,7 +1252,9 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
12441252
case 100:
12451253
{
12461254
/* DBRef */
1247-
PyObject* as_doc = PyObject_CallMethodObjArgs(value, state->_as_doc_str, NULL);
1255+
PyObject* as_doc_args[1] = {value};
1256+
PyObject* as_doc = PyObject_VectorcallMethod(
1257+
state->_as_doc_str, as_doc_args, 1, NULL);
12481258
if (!as_doc) {
12491259
return 0;
12501260
}
@@ -1400,7 +1410,9 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
14001410
return write_unicode(buffer, value);
14011411
} else if (PyDateTime_Check(value)) {
14021412
long long millis;
1403-
PyObject* utcoffset = PyObject_CallMethodObjArgs(value, state->_utcoffset_str , NULL);
1413+
PyObject* utcoffset_args[1] = {value};
1414+
PyObject* utcoffset = PyObject_VectorcallMethod(
1415+
state->_utcoffset_str, utcoffset_args, 1, NULL);
14041416
if (utcoffset == NULL)
14051417
return 0;
14061418
if (utcoffset != Py_None) {
@@ -1439,7 +1451,9 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
14391451
if (!(uuid_rep_obj = PyLong_FromLong(options->uuid_rep))) {
14401452
return 0;
14411453
}
1442-
binary_value = PyObject_CallMethodObjArgs(state->Binary, state->_from_uuid_str, value, uuid_rep_obj, NULL);
1454+
PyObject* from_uuid_args[3] = {state->Binary, value, uuid_rep_obj};
1455+
binary_value = PyObject_VectorcallMethod(
1456+
state->_from_uuid_str, from_uuid_args, 3, NULL);
14431457
Py_DECREF(uuid_rep_obj);
14441458

14451459
if (binary_value == NULL) {
@@ -1469,7 +1483,8 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
14691483
if (converter != NULL) {
14701484
/* Transform types that have a registered converter.
14711485
* A new reference is created upon transformation. */
1472-
new_value = PyObject_CallFunctionObjArgs(converter, value, NULL);
1486+
PyObject* converter_args[1] = {value};
1487+
new_value = PyObject_Vectorcall(converter, converter_args, 1, NULL);
14731488
if (new_value == NULL) {
14741489
return 0;
14751490
}
@@ -1483,8 +1498,9 @@ static int _write_element_to_buffer(PyObject* self, buffer_t buffer,
14831498
/* Try the fallback encoder if one is provided and we have not already
14841499
* attempted to use the fallback encoder. */
14851500
if (!in_fallback_call && options->type_registry.has_fallback_encoder) {
1486-
new_value = PyObject_CallFunctionObjArgs(
1487-
options->type_registry.fallback_encoder, value, NULL);
1501+
PyObject* fallback_args[1] = {value};
1502+
new_value = PyObject_Vectorcall(
1503+
options->type_registry.fallback_encoder, fallback_args, 1, NULL);
14881504
if (new_value == NULL) {
14891505
// propagate any exception raised by the callback
14901506
return 0;
@@ -1685,7 +1701,8 @@ void handle_invalid_doc_error(PyObject* dict) {
16851701
goto cleanup;
16861702
}
16871703
// Add doc to the error instance as a property.
1688-
new_evalue = PyObject_CallFunctionObjArgs(InvalidDocument, new_msg, dict, NULL);
1704+
PyObject* exc_args[2] = {new_msg, dict};
1705+
new_evalue = PyObject_Vectorcall(InvalidDocument, exc_args, 2, NULL);
16891706
Py_DECREF(evalue);
16901707
Py_DECREF(etype);
16911708
etype = InvalidDocument;
@@ -1961,7 +1978,8 @@ static PyObject *_dbref_hook(PyObject* self, PyObject* value) {
19611978
PyMapping_DelItem(value, state->_dollar_db_str);
19621979
}
19631980

1964-
ret = PyObject_CallFunctionObjArgs(state->DBRef, ref, id, database, value, NULL);
1981+
PyObject* dbref_args[4] = {ref, id, database, value};
1982+
ret = PyObject_Vectorcall(state->DBRef, dbref_args, 4, NULL);
19651983
Py_DECREF(value);
19661984
} else {
19671985
ret = value;
@@ -2177,7 +2195,13 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
21772195
goto uuiderror;
21782196
}
21792197

2180-
binary_value = PyObject_CallFunction(state->Binary, "(Oi)", data, subtype);
2198+
PyObject* subtype_obj = PyLong_FromLong(subtype);
2199+
if (!subtype_obj) {
2200+
goto uuiderror;
2201+
}
2202+
PyObject* binary_args[2] = {data, subtype_obj};
2203+
binary_value = PyObject_Vectorcall(state->Binary, binary_args, 2, NULL);
2204+
Py_DECREF(subtype_obj);
21812205
if (binary_value == NULL) {
21822206
goto uuiderror;
21832207
}
@@ -2192,7 +2216,9 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
21922216
if (!uuid_rep_obj) {
21932217
goto uuiderror;
21942218
}
2195-
value = PyObject_CallMethodObjArgs(binary_value, state->_as_uuid_str, uuid_rep_obj, NULL);
2219+
PyObject* as_uuid_args[2] = {binary_value, uuid_rep_obj};
2220+
value = PyObject_VectorcallMethod(
2221+
state->_as_uuid_str, as_uuid_args, 2, NULL);
21962222
Py_DECREF(uuid_rep_obj);
21972223
}
21982224

@@ -2211,7 +2237,8 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
22112237
Py_DECREF(data);
22122238
goto invalid;
22132239
}
2214-
value = PyObject_CallFunctionObjArgs(state->Binary, data, st, NULL);
2240+
PyObject* binary_args[2] = {data, st};
2241+
value = PyObject_Vectorcall(state->Binary, binary_args, 2, NULL);
22152242
Py_DECREF(st);
22162243
Py_DECREF(data);
22172244
if (!value) {
@@ -2232,7 +2259,13 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
22322259
if (max < 12) {
22332260
goto invalid;
22342261
}
2235-
value = PyObject_CallFunction(state->ObjectId, "y#", buffer + *position, (Py_ssize_t)12);
2262+
PyObject* oid_bytes = PyBytes_FromStringAndSize(buffer + *position, 12);
2263+
if (!oid_bytes) {
2264+
goto invalid;
2265+
}
2266+
PyObject* oid_args[1] = {oid_bytes};
2267+
value = PyObject_Vectorcall(state->ObjectId, oid_args, 1, NULL);
2268+
Py_DECREF(oid_bytes);
22362269
*position += 12;
22372270
break;
22382271
}
@@ -2311,7 +2344,14 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
23112344
}
23122345
*position += (unsigned)flags_length + 1;
23132346

2314-
value = PyObject_CallFunction(state->Regex, "Oi", pattern, flags);
2347+
PyObject* flags_obj = PyLong_FromLong(flags);
2348+
if (!flags_obj) {
2349+
Py_DECREF(pattern);
2350+
goto invalid;
2351+
}
2352+
PyObject* regex_args[2] = {pattern, flags_obj};
2353+
value = PyObject_Vectorcall(state->Regex, regex_args, 2, NULL);
2354+
Py_DECREF(flags_obj);
23152355
Py_DECREF(pattern);
23162356
break;
23172357
}
@@ -2344,13 +2384,21 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
23442384
}
23452385
*position += coll_length;
23462386

2347-
id = PyObject_CallFunction(state->ObjectId, "y#", buffer + *position, (Py_ssize_t)12);
2387+
PyObject* oid_bytes = PyBytes_FromStringAndSize(buffer + *position, 12);
2388+
if (!oid_bytes) {
2389+
Py_DECREF(collection);
2390+
goto invalid;
2391+
}
2392+
PyObject* oid_args[1] = {oid_bytes};
2393+
id = PyObject_Vectorcall(state->ObjectId, oid_args, 1, NULL);
2394+
Py_DECREF(oid_bytes);
23482395
if (!id) {
23492396
Py_DECREF(collection);
23502397
goto invalid;
23512398
}
23522399
*position += 12;
2353-
value = PyObject_CallFunctionObjArgs(state->DBRef, collection, id, NULL);
2400+
PyObject* dbref_args[2] = {collection, id};
2401+
value = PyObject_Vectorcall(state->DBRef, dbref_args, 2, NULL);
23542402
Py_DECREF(collection);
23552403
Py_DECREF(id);
23562404
break;
@@ -2380,7 +2428,8 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
23802428
goto invalid;
23812429
}
23822430
*position += value_length;
2383-
value = PyObject_CallFunctionObjArgs(state->Code, code, NULL, NULL);
2431+
PyObject* code_args[1] = {code};
2432+
value = PyObject_Vectorcall(state->Code, code_args, 1, NULL);
23842433
Py_DECREF(code);
23852434
break;
23862435
}
@@ -2446,7 +2495,8 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
24462495
}
24472496
*position += scope_size;
24482497

2449-
value = PyObject_CallFunctionObjArgs(state->Code, code, scope, NULL);
2498+
PyObject* code_scope_args[2] = {code, scope};
2499+
value = PyObject_Vectorcall(state->Code, code_scope_args, 2, NULL);
24502500
Py_DECREF(code);
24512501
Py_DECREF(scope);
24522502
break;
@@ -2476,7 +2526,19 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
24762526
memcpy(&time, buffer + *position + 4, 4);
24772527
inc = BSON_UINT32_FROM_LE(inc);
24782528
time = BSON_UINT32_FROM_LE(time);
2479-
value = PyObject_CallFunction(state->Timestamp, "II", time, inc);
2529+
PyObject* time_obj = PyLong_FromUnsignedLong(time);
2530+
if (!time_obj) {
2531+
goto invalid;
2532+
}
2533+
PyObject* inc_obj = PyLong_FromUnsignedLong(inc);
2534+
if (!inc_obj) {
2535+
Py_DECREF(time_obj);
2536+
goto invalid;
2537+
}
2538+
PyObject* ts_args[2] = {time_obj, inc_obj};
2539+
value = PyObject_Vectorcall(state->Timestamp, ts_args, 2, NULL);
2540+
Py_DECREF(time_obj);
2541+
Py_DECREF(inc_obj);
24802542
*position += 8;
24812543
break;
24822544
}
@@ -2488,7 +2550,13 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
24882550
}
24892551
memcpy(&ll, buffer + *position, 8);
24902552
ll = (int64_t)BSON_UINT64_FROM_LE(ll);
2491-
value = PyObject_CallFunction(state->BSONInt64, "L", ll);
2553+
PyObject* ll_obj = PyLong_FromLongLong(ll);
2554+
if (!ll_obj) {
2555+
goto invalid;
2556+
}
2557+
PyObject* int64_args[1] = {ll_obj};
2558+
value = PyObject_Vectorcall(state->BSONInt64, int64_args, 1, NULL);
2559+
Py_DECREF(ll_obj);
24922560
*position += 8;
24932561
break;
24942562
}
@@ -2501,19 +2569,21 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
25012569
if (!_bytes_obj) {
25022570
goto invalid;
25032571
}
2504-
value = PyObject_CallMethodObjArgs(state->Decimal128, state->_from_bid_str, _bytes_obj, NULL);
2572+
PyObject* dec128_args[2] = {state->Decimal128, _bytes_obj};
2573+
value = PyObject_VectorcallMethod(
2574+
state->_from_bid_str, dec128_args, 2, NULL);
25052575
Py_DECREF(_bytes_obj);
25062576
*position += 16;
25072577
break;
25082578
}
25092579
case 255:
25102580
{
2511-
value = PyObject_CallFunctionObjArgs(state->MinKey, NULL);
2581+
value = PyObject_Vectorcall(state->MinKey, NULL, 0, NULL);
25122582
break;
25132583
}
25142584
case 127:
25152585
{
2516-
value = PyObject_CallFunctionObjArgs(state->MaxKey, NULL);
2586+
value = PyObject_Vectorcall(state->MaxKey, NULL, 0, NULL);
25172587
break;
25182588
}
25192589
default:
@@ -2565,7 +2635,8 @@ static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer,
25652635
}
25662636
converter = PyDict_GetItem(options->type_registry.decoder_map, value_type);
25672637
if (converter != NULL) {
2568-
PyObject* new_value = PyObject_CallFunctionObjArgs(converter, value, NULL);
2638+
PyObject* converter_args[1] = {value};
2639+
PyObject* new_value = PyObject_Vectorcall(converter, converter_args, 1, NULL);
25692640
Py_DECREF(value_type);
25702641
Py_DECREF(value);
25712642
return new_value;
@@ -2790,9 +2861,14 @@ static PyObject* elements_to_dict(PyObject* self, const char* string,
27902861
const codec_options_t* options) {
27912862
PyObject* result;
27922863
if (options->is_raw_bson) {
2793-
return PyObject_CallFunction(
2794-
options->document_class, "y#O",
2795-
string, max, options->options_obj);
2864+
PyObject* bson_bytes = PyBytes_FromStringAndSize(string, max);
2865+
if (!bson_bytes) {
2866+
return NULL;
2867+
}
2868+
PyObject* raw_args[2] = {bson_bytes, options->options_obj};
2869+
result = PyObject_Vectorcall(options->document_class, raw_args, 2, NULL);
2870+
Py_DECREF(bson_bytes);
2871+
return result;
27962872
}
27972873
if (Py_EnterRecursiveCall(" while decoding a BSON document"))
27982874
return NULL;

0 commit comments

Comments
 (0)