Skip to content

Commit a2dd2ff

Browse files
committed
Improved performance of Function.__call__, Function.skip_hooks and Function.call_trampoline.
1 parent 046a3d4 commit a2dd2ff

File tree

4 files changed

+49
-15
lines changed

4 files changed

+49
-15
lines changed

Diff for: src/core/modules/memory/memory_function.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -259,24 +259,24 @@ void CallHelperVoid(DCCallVM* vm, unsigned long addr)
259259
EXCEPT_SEGV()
260260
}
261261

262-
object CFunction::Call(tuple args, dict kw)
262+
object CFunction::Call(PyObject *args, PyObject *kw)
263263
{
264264
if (!IsCallable())
265265
BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Function is not callable.")
266266

267267
Validate();
268-
if (len(args) != len(m_tArgs))
268+
if (PyTuple_GET_SIZE(args) - 1 != len(m_tArgs))
269269
BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Number of passed arguments is not equal to the required number.")
270270

271271
// Reset VM and set the calling convention
272272
dcReset(g_pCallVM);
273273
dcMode(g_pCallVM, m_iCallingConvention);
274274

275275
// Loop through all passed arguments and add them to the VM
276-
for(int i=0; i < len(args); i++)
276+
for(int i=1; i < PyTuple_GET_SIZE(args); i++)
277277
{
278-
object arg = args[i];
279-
switch(extract<DataType_t>(m_tArgs[i]))
278+
PyObject *arg = PyTuple_GET_ITEM(args, i);
279+
switch(extract<DataType_t>(m_tArgs[i - 1]))
280280
{
281281
case DATA_TYPE_BOOL: dcArgBool(g_pCallVM, extract<bool>(arg)); break;
282282
case DATA_TYPE_CHAR: dcArgChar(g_pCallVM, extract<char>(arg)); break;
@@ -294,8 +294,8 @@ object CFunction::Call(tuple args, dict kw)
294294
case DATA_TYPE_POINTER:
295295
{
296296
unsigned long ulAddr = 0;
297-
if (arg.ptr() != Py_None)
298-
ulAddr = ExtractAddress(arg);
297+
if (arg != Py_None)
298+
ulAddr = ExtractAddress(object(handle<>(borrowed(arg))));
299299

300300
dcArgPointer(g_pCallVM, ulAddr);
301301
break;
@@ -336,7 +336,7 @@ object CFunction::Call(tuple args, dict kw)
336336
return object();
337337
}
338338

339-
object CFunction::CallTrampoline(tuple args, dict kw)
339+
object CFunction::CallTrampoline(PyObject *args, PyObject *kw)
340340
{
341341
CHook* pHook = GetHookManager()->FindHook((void *) m_ulAddr);
342342
if (!pHook)
@@ -346,7 +346,7 @@ object CFunction::CallTrampoline(tuple args, dict kw)
346346
m_iCallingConvention, m_tArgs, m_eReturnType, m_oConverter).Call(args, kw);
347347
}
348348

349-
object CFunction::SkipHooks(tuple args, dict kw)
349+
object CFunction::SkipHooks(PyObject *args, PyObject *kw)
350350
{
351351
CHook* pHook = GetHookManager()->FindHook((void *) m_ulAddr);
352352
if (pHook)

Diff for: src/core/modules/memory/memory_function.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ class CFunction: public CPointer
7171

7272
CFunction* GetTrampoline();
7373

74-
object Call(boost::python::tuple args, dict kw);
75-
object CallTrampoline(boost::python::tuple args, dict kw);
76-
object SkipHooks(boost::python::tuple args, dict kw);
74+
object Call(PyObject *args, PyObject *kw);
75+
object CallTrampoline(PyObject *args, PyObject *kw);
76+
object SkipHooks(PyObject *args, PyObject *kw);
7777

7878
void AddHook(HookType_t eType, PyObject* pCallable);
7979
void RemoveHook(HookType_t eType, PyObject* pCallable);

Diff for: src/core/modules/memory/memory_wrap.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ void export_function(scope _memory)
457457
.def(init<CFunction&>())
458458

459459
.def("__call__",
460-
raw_method(&CFunction::Call),
460+
very_raw_method(&CFunction::Call),
461461
"Calls the function dynamically."
462462
)
463463

@@ -477,12 +477,12 @@ void export_function(scope _memory)
477477
)
478478

479479
.def("call_trampoline",
480-
raw_method(&CFunction::CallTrampoline),
480+
very_raw_method(&CFunction::CallTrampoline),
481481
"Calls the trampoline function dynamically."
482482
)
483483

484484
.def("skip_hooks",
485-
raw_method(&CFunction::SkipHooks),
485+
very_raw_method(&CFunction::SkipHooks),
486486
"Call the function, but skip hooks if there are any."
487487
)
488488

Diff for: src/core/utilities/wrap_macros.h

+34
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
// Includes
3131
//---------------------------------------------------------------------------------
3232
#include "boost/function.hpp"
33+
#include "boost/function_types/parameter_types.hpp"
3334
#include "boost/python.hpp"
3435
using namespace boost::python;
3536

@@ -215,6 +216,39 @@ object raw_method(T func, int min_args = 0)
215216
);
216217
}
217218

219+
template<class T, typename U>
220+
struct very_raw_method_dispatcher
221+
{
222+
public:
223+
very_raw_method_dispatcher(T func):
224+
func(func)
225+
{
226+
}
227+
228+
PyObject *operator()(PyObject *args, PyObject *kwargs)
229+
{
230+
return incref((extract<U &>(PyTuple_GET_ITEM(args, 0))().*func)(args, kwargs).ptr());
231+
}
232+
233+
private:
234+
T func;
235+
};
236+
237+
template<class T>
238+
object very_raw_method(T func, int min_args = 0)
239+
{
240+
return boost::python::detail::make_raw_function(
241+
objects::py_function(
242+
very_raw_method_dispatcher<
243+
T, boost::mpl::at_c<boost::function_types::parameter_types<T>, 0>::type
244+
>(func),
245+
boost::mpl::vector1<PyObject *>(),
246+
min_args + 1,
247+
(std::numeric_limits<unsigned>::max)()
248+
)
249+
);
250+
}
251+
218252
//---------------------------------------------------------------------------------
219253
// Use this macro to define a function or class method that raises a
220254
// NotImplementedError. This is quite hacky, but saves a lot work!

0 commit comments

Comments
 (0)