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