Merge "Omaha #4259 clean up pyjclass optimization for inclusion in jep" into omaha_16.1.1
Former-commit-id: 5d1b229924399e16617347162e97e3210608a8f8
This commit is contained in:
commit
64a82afdc9
2 changed files with 171 additions and 218 deletions
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
jep - Java Embedded Python
|
||||
|
||||
Copyright (c) 2004 - 2008 Mike Johnson.
|
||||
Copyright (c) 2004 - 2011 Mike Johnson.
|
||||
|
||||
This file is licenced under the the zlib/libpng License.
|
||||
|
||||
|
@ -26,13 +26,6 @@
|
|||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
August 2, 2012
|
||||
Modified by Raytheon (c) 2012 Raytheon Company. All Rights Reserved.
|
||||
Modifications marked and described by 'njensen'
|
||||
*/
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
# include "winconfig.h"
|
||||
#endif
|
||||
|
@ -75,7 +68,6 @@ static void pyjclass_dealloc(PyJclass_Object*);
|
|||
|
||||
static jmethodID classGetConstructors = 0;
|
||||
static jmethodID classGetParmTypes = 0;
|
||||
static jmethodID classGetExceptions = 0;
|
||||
|
||||
|
||||
PyJclass_Object* pyjclass_new(JNIEnv *env, PyObject *pyjob) {
|
||||
|
@ -83,13 +75,10 @@ PyJclass_Object* pyjclass_new(JNIEnv *env, PyObject *pyjob) {
|
|||
jobject langClass = NULL;
|
||||
jobjectArray initArray = NULL;
|
||||
PyJobject_Object *pyjobject = NULL;
|
||||
|
||||
// added by njensen
|
||||
int i, k;
|
||||
jobject constructor = NULL;
|
||||
jclass initClass = NULL;
|
||||
jobjectArray parmArray = NULL;
|
||||
int parmLen;
|
||||
int i;
|
||||
|
||||
if(PyType_Ready(&PyJclass_Type) < 0)
|
||||
return NULL;
|
||||
|
@ -131,7 +120,7 @@ PyJclass_Object* pyjclass_new(JNIEnv *env, PyObject *pyjob) {
|
|||
goto EXIT_ERROR;
|
||||
}
|
||||
|
||||
// then, call method
|
||||
// then, call getConstructors()
|
||||
initArray = (jobjectArray) (*env)->CallObjectMethod(env,
|
||||
pyjobject->clazz,
|
||||
classGetConstructors);
|
||||
|
@ -141,12 +130,12 @@ PyJclass_Object* pyjclass_new(JNIEnv *env, PyObject *pyjob) {
|
|||
pyc->initArray = (*env)->NewGlobalRef(env, initArray);
|
||||
pyc->initLen = (*env)->GetArrayLength(env, pyc->initArray);
|
||||
|
||||
// caching below added by njensen
|
||||
pyc->numArgsPerConstructor = malloc(sizeof(int) * pyc->initLen);
|
||||
pyc->constructorArgTypes = (int **) malloc(sizeof(int*) * pyc->initLen);
|
||||
/*
|
||||
* Optimization for faster performance. Cache number of arguments
|
||||
* for each constructor to avoid repeated reflection lookups.
|
||||
*/
|
||||
pyc->numArgsPerInit = malloc(sizeof(int) * pyc->initLen);
|
||||
for(i = 0; i < pyc->initLen; i++) {
|
||||
jmethodID methodId;
|
||||
|
||||
constructor = (*env)->GetObjectArrayElement(env,
|
||||
pyc->initArray,
|
||||
i);
|
||||
|
@ -154,7 +143,7 @@ PyJclass_Object* pyjclass_new(JNIEnv *env, PyObject *pyjob) {
|
|||
goto EXIT_ERROR;
|
||||
|
||||
|
||||
// we need to get the parameters, first
|
||||
// we need to get the class java.lang.reflect.Constructor first
|
||||
initClass = (*env)->GetObjectClass(env, constructor);
|
||||
if(process_java_exception(env) || !initClass)
|
||||
goto EXIT_ERROR;
|
||||
|
@ -168,7 +157,6 @@ PyJclass_Object* pyjclass_new(JNIEnv *env, PyObject *pyjob) {
|
|||
if(process_java_exception(env) || !classGetParmTypes)
|
||||
goto EXIT_ERROR;
|
||||
}
|
||||
|
||||
parmArray = (jobjectArray) (*env)->CallObjectMethod(env,
|
||||
constructor,
|
||||
classGetParmTypes);
|
||||
|
@ -176,32 +164,9 @@ PyJclass_Object* pyjclass_new(JNIEnv *env, PyObject *pyjob) {
|
|||
goto EXIT_ERROR;
|
||||
|
||||
|
||||
// okay, we know how many parameters we need.
|
||||
// just discard the constructors with different counts.
|
||||
parmLen = (*env)->GetArrayLength(env, parmArray);
|
||||
pyc->numArgsPerConstructor[i] = parmLen;
|
||||
pyc->constructorArgTypes[i] = malloc(sizeof(int) * parmLen);
|
||||
|
||||
for(k = 0; k < parmLen; k++) {
|
||||
int paramTypeId = -1;
|
||||
jclass pclazz;
|
||||
jobject paramType =
|
||||
(jclass) (*env)->GetObjectArrayElement(env,
|
||||
parmArray,
|
||||
k);
|
||||
|
||||
if(process_java_exception(env) || !paramType)
|
||||
break;
|
||||
|
||||
pclazz = (*env)->GetObjectClass(env, paramType);
|
||||
if(process_java_exception(env) || !pclazz)
|
||||
goto EXIT_ERROR;
|
||||
|
||||
paramTypeId = get_jtype(env, paramType, pclazz);
|
||||
pyc->constructorArgTypes[i][k] = paramTypeId;
|
||||
}
|
||||
}
|
||||
|
||||
// now we know how many parameters this constructor receives
|
||||
pyc->numArgsPerInit[i] = (*env)->GetArrayLength(env, parmArray);
|
||||
} // end of optimization
|
||||
|
||||
(*env)->PopLocalFrame(env, NULL);
|
||||
return pyc;
|
||||
|
@ -222,18 +187,10 @@ int pyjclass_check(PyObject *obj) {
|
|||
|
||||
static void pyjclass_dealloc(PyJclass_Object *self) {
|
||||
#if USE_DEALLOC
|
||||
int i;
|
||||
JNIEnv *env = pyembed_get_env();
|
||||
if(self->initArray)
|
||||
(*env)->DeleteGlobalRef(env, self->initArray);
|
||||
|
||||
free(self->numArgsPerConstructor);
|
||||
for(i=0; i < self->initLen; i++)
|
||||
{
|
||||
free(self->constructorArgTypes[i]);
|
||||
}
|
||||
free(self->constructorArgTypes);
|
||||
|
||||
free(self->numArgsPerInit);
|
||||
PyObject_Del(self);
|
||||
#endif
|
||||
}
|
||||
|
@ -247,16 +204,14 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
int parmPos = 0;
|
||||
int parmLen = 0;
|
||||
jobjectArray parmArray = NULL;
|
||||
jobjectArray exceptions = NULL;
|
||||
JNIEnv *env;
|
||||
jclass initClass = NULL;
|
||||
jobject constructor = NULL;
|
||||
jvalue *jargs = NULL;
|
||||
int foundArray = 0;
|
||||
PyThreadState *_save;
|
||||
int pyArgLength;
|
||||
Py_ssize_t pyArgLength = 0;
|
||||
|
||||
classCallCount = classCallCount + 1;
|
||||
if(!PyTuple_Check(args)) {
|
||||
PyErr_Format(PyExc_RuntimeError, "args is not a valid tuple");
|
||||
return NULL;
|
||||
|
@ -270,19 +225,18 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
env = pyembed_get_env();
|
||||
|
||||
// use a local frame so we don't have to worry too much about references.
|
||||
// make sure if this method errors out, that this is poped off again
|
||||
// make sure if this method errors out, that this is popped off again
|
||||
(*env)->PushLocalFrame(env, 20);
|
||||
if(process_java_exception(env))
|
||||
return NULL;
|
||||
|
||||
|
||||
// njensen changed below to use cached constructor arguments
|
||||
pyArgLength = PyTuple_Size(args);
|
||||
for(initPos = 0; initPos < self->initLen; initPos++) {
|
||||
jmethodID methodId;
|
||||
|
||||
if(self->numArgsPerConstructor[initPos] != pyArgLength)
|
||||
parmLen = self->numArgsPerInit[initPos];
|
||||
// skip constructors that don't match the correct number of args
|
||||
if(parmLen != pyArgLength) {
|
||||
continue;
|
||||
}
|
||||
|
||||
constructor = (*env)->GetObjectArrayElement(env,
|
||||
self->initArray,
|
||||
|
@ -290,9 +244,7 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
if(process_java_exception(env) || !constructor)
|
||||
goto EXIT_ERROR;
|
||||
|
||||
|
||||
// we need to get the parameters, first
|
||||
|
||||
// get the class java.lang.reflect.Constructor first
|
||||
initClass = (*env)->GetObjectClass(env, constructor);
|
||||
if(process_java_exception(env) || !initClass)
|
||||
goto EXIT_ERROR;
|
||||
|
@ -313,7 +265,6 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
if(process_java_exception(env) || !parmArray)
|
||||
goto EXIT_ERROR;
|
||||
|
||||
parmLen = self->numArgsPerConstructor[initPos];
|
||||
// next, find matching constructor for args
|
||||
// the counts match but maybe not the args themselves.
|
||||
jargs = (jvalue *) PyMem_Malloc(sizeof(jvalue) * parmLen);
|
||||
|
@ -324,7 +275,8 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
|
||||
for(parmPos = 0; parmPos < parmLen; parmPos++) {
|
||||
PyObject *param = PyTuple_GetItem(args, parmPos);
|
||||
int paramTypeId = self->constructorArgTypes[initPos][parmPos];
|
||||
int paramTypeId = -1;
|
||||
jclass pclazz;
|
||||
jobject paramType =
|
||||
(jclass) (*env)->GetObjectArrayElement(env,
|
||||
parmArray,
|
||||
|
@ -333,6 +285,14 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
if(process_java_exception(env) || !paramType)
|
||||
break;
|
||||
|
||||
pclazz = (*env)->GetObjectClass(env, paramType);
|
||||
if(process_java_exception(env) || !pclazz)
|
||||
goto EXIT_ERROR;
|
||||
|
||||
paramTypeId = get_jtype(env, paramType, pclazz);
|
||||
if(PyErr_Occurred() || process_java_exception(env))
|
||||
goto EXIT_ERROR;
|
||||
|
||||
if(paramTypeId == JARRAY_ID)
|
||||
foundArray = 1;
|
||||
|
||||
|
@ -346,7 +306,7 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
if(PyErr_Occurred() || process_java_exception(env))
|
||||
goto EXIT_ERROR;
|
||||
|
||||
continue;
|
||||
continue; // continue checking parameters
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -355,6 +315,7 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
|
||||
// did they match?
|
||||
if(parmPos == parmLen) {
|
||||
jmethodID methodId = NULL;
|
||||
jobject obj = NULL;
|
||||
PyObject *pobj = NULL;
|
||||
|
||||
|
@ -395,9 +356,11 @@ PyObject* pyjclass_call(PyJclass_Object *self,
|
|||
(*env)->PopLocalFrame(env, NULL);
|
||||
return pobj;
|
||||
}
|
||||
// we already closed the local frame, so make
|
||||
// sure to delete this local ref.
|
||||
|
||||
// prevent memory leak
|
||||
if(jargs) {
|
||||
PyMem_Free(jargs);
|
||||
}
|
||||
foundArray = 0;
|
||||
} // for each constructor
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
jep - Java Embedded Python
|
||||
|
||||
Copyright (c) 2004 - 2008 Mike Johnson.
|
||||
Copyright (c) 2004 - 2011 Mike Johnson.
|
||||
|
||||
This file is licenced under the the zlib/libpng License.
|
||||
|
||||
|
@ -26,13 +26,6 @@
|
|||
distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
August 2, 2012
|
||||
Modified by Raytheon (c) 2012 Raytheon Company. All Rights Reserved.
|
||||
Modifications marked and described by 'njensen'
|
||||
*/
|
||||
|
||||
|
||||
// shut up the compiler
|
||||
#ifdef _POSIX_C_SOURCE
|
||||
# undef _POSIX_C_SOURCE
|
||||
|
@ -48,14 +41,11 @@ typedef struct {
|
|||
jobjectArray initArray; /* constructor array */
|
||||
int initLen; /* length of initArray */
|
||||
PyObject *pyjobject; /* pointer to parent */
|
||||
|
||||
int **constructorArgTypes; // added by njensen
|
||||
int *numArgsPerConstructor; // added by njensen
|
||||
int *numArgsPerInit; /* pointer to init arg count */
|
||||
} PyJclass_Object;
|
||||
|
||||
PyJclass_Object* pyjclass_new(JNIEnv*, PyObject*);
|
||||
PyObject* pyjclass_call(PyJclass_Object*, PyObject*, PyObject*);
|
||||
int pyjclass_check(PyObject*);
|
||||
extern long classCallCount;
|
||||
|
||||
#endif // ndef pyjclass
|
||||
|
|
Loading…
Add table
Reference in a new issue