From: <zy...@us...> - 2010-06-26 06:04:07
|
Revision: 7072 http://jython.svn.sourceforge.net/jython/?rev=7072&view=rev Author: zyasoft Date: 2010-06-26 06:04:00 +0000 (Sat, 26 Jun 2010) Log Message: ----------- Fixed #1522 by weakening references in class_to_type map (both key and value). However, in certain cases our code expects that these refs are in fact hard, so make all exposed types hard and also by default PyType#fromClass will add a hard ref. In contrast, types imported in that proxy Java classes should now be weak. Added Guava R05 (which includes google collections), to support the desired map. We may wish to strip this down, however, it could be useful in the future too. Modified Paths: -------------- trunk/jython/build.xml trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/core/PyType.java trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java trunk/jython/src/org/python/core/imp.java trunk/jython/src/org/python/modules/zipimport/zipimporter.java trunk/jython/src/org/python/util/Generic.java Added Paths: ----------- trunk/jython/extlibs/guava-r05.jar Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/build.xml 2010-06-26 06:04:00 UTC (rev 7072) @@ -188,6 +188,7 @@ <pathelement path="${extlibs.dir}/asm-3.1.jar" /> <pathelement path="${extlibs.dir}/asm-commons-3.1.jar" /> <pathelement path="${extlibs.dir}/constantine.jar" /> + <pathelement path="${extlibs.dir}/guava-r05.jar" /> <pathelement path="${extlibs.dir}/jaffl.jar"/> <pathelement path="${extlibs.dir}/jffi-Darwin.jar"/> <pathelement path="${extlibs.dir}/jffi-i386-FreeBSD.jar"/> @@ -584,6 +585,8 @@ <zipfileset src="extlibs/asm-commons-3.1.jar"/> <zipfileset src="extlibs/asm-util-3.1.jar"/> <rule pattern="org.objectweb.asm.**" result="org.python.objectweb.asm.@1"/> + <zipfileset src="extlibs/guava-r05.jar"/> + <rule pattern="com.google.**" result="org.python.google.@1"/> <zipfileset src="extlibs/jaffl.jar"/> <zipfileset src="extlibs/jffi-Darwin.jar"/> <zipfileset src="extlibs/jffi-i386-FreeBSD.jar"/> Added: trunk/jython/extlibs/guava-r05.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/extlibs/guava-r05.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/PyJavaType.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -59,7 +59,7 @@ private Set<String> modified; public static PyObject wrapJavaObject(Object o) { - PyObject obj = new PyObjectDerived(PyType.fromClass(o.getClass())); + PyObject obj = new PyObjectDerived(PyType.fromClass(o.getClass(), false)); obj.javaProxy = o; return obj; } Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/PyObject.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -63,7 +63,7 @@ * field to correspond to the specific subclass of <code>PyObject</code> being instantiated. **/ public PyObject() { - objtype = PyType.fromClass(getClass()); + objtype = PyType.fromClass(getClass(), false); } /** Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/PyType.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -22,6 +22,8 @@ import org.python.modules._weakref.WeakrefModule; import org.python.util.Generic; +import com.google.common.collect.MapMaker; + /** * The Python Type object implementation. */ @@ -97,7 +99,8 @@ /** Mapping of Java classes to their PyTypes. */ private static Map<Class<?>, PyType> class_to_type; - + private static Set<PyType> exposedTypes; + /** Mapping of Java classes to their TypeBuilders. */ private static Map<Class<?>, TypeBuilder> classToBuilder; @@ -121,7 +124,15 @@ PyObject[] args, String[] keywords) { // Special case: type(x) should return x.getType() if (args.length == 1 && keywords.length == 0) { - return args[0].getType(); + PyObject obj = args[0]; + PyType objType = obj.getType(); + + // special case for PyStringMap so that it types as a dict + PyType psmType = PyType.fromClass(PyStringMap.class); + if (objType == psmType) { + return PyDictionary.TYPE; + } + return objType; } // If that didn't trigger, we need 3 arguments. but ArgParser below may give a msg // saying type() needs exactly 3. @@ -517,7 +528,7 @@ * followed by the mro of baseClass. */ protected void computeLinearMro(Class<?> baseClass) { - base = PyType.fromClass(baseClass); + base = PyType.fromClass(baseClass, false); mro = new PyType[base.mro.length + 1]; System.arraycopy(base.mro, 0, mro, 1, base.mro.length); mro[0] = this; @@ -622,7 +633,7 @@ dict); javaProxy = proxyClass; - PyType proxyType = PyType.fromClass(proxyClass); + PyType proxyType = PyType.fromClass(proxyClass, false); List<PyObject> cleanedBases = Generic.list(); boolean addedProxyType = false; for (PyObject base : bases) { @@ -908,7 +919,7 @@ PyObject[] computeMro(MROMergeState[] toMerge, List<PyObject> mro) { boolean addedProxy = false; - PyType proxyAsType = javaProxy == null ? null : PyType.fromClass(((Class<?>)javaProxy)); + PyType proxyAsType = javaProxy == null ? null : PyType.fromClass(((Class<?>)javaProxy), false); scan : for (int i = 0; i < toMerge.length; i++) { if (toMerge[i].isMerged()) { continue scan; @@ -1164,7 +1175,7 @@ return null; } - public static void addBuilder(Class<?> forClass, TypeBuilder builder) { + public synchronized static void addBuilder(Class<?> forClass, TypeBuilder builder) { if (classToBuilder == null) { classToBuilder = Generic.map(); } @@ -1181,9 +1192,9 @@ } } - private static PyType addFromClass(Class<?> c, Set<PyJavaType> needsInners) { + private synchronized static PyType addFromClass(Class<?> c, Set<PyJavaType> needsInners) { if (ExposeAsSuperclass.class.isAssignableFrom(c)) { - PyType exposedAs = fromClass(c.getSuperclass()); + PyType exposedAs = fromClass(c.getSuperclass(), false); class_to_type.put(c, exposedAs); return exposedAs; } @@ -1227,7 +1238,7 @@ return builder; } - private static PyType createType(Class<?> c, Set<PyJavaType> needsInners) { + private synchronized static PyType createType(Class<?> c, Set<PyJavaType> needsInners) { PyType newtype; if (c == PyType.class) { newtype = new PyType(false); @@ -1251,18 +1262,25 @@ return newtype; } - // XXX what's the proper scope of this synchronization? given module import lock, might be - // ok to omit this sync here... + // re the synchronization used here: this result is cached in each type obj, + // so we just need to prevent data races. all public methods that access class_to_type + // are themselves synchronized. However, if we use Google Collections/Guava, + // MapMaker only uses ConcurrentMap anyway + public static synchronized PyType fromClass(Class<?> c) { + return fromClass(c, true); + } + + public static synchronized PyType fromClass(Class<?> c, boolean hardRef) { if (class_to_type == null) { - class_to_type = Generic.synchronizedWeakHashMap(); + class_to_type = new MapMaker().weakKeys().weakValues().makeMap(); addFromClass(PyType.class, null); } PyType type = class_to_type.get(c); if (type != null) { return type; } - // We haven't seen this class before, so it's type needs to be created. If it's being + // We haven't seen this class before, so its type needs to be created. If it's being // exposed as a Java class, defer processing its inner types until it's completely // created in case the inner class references a class that references this class. Set<PyJavaType> needsInners = Generic.set(); @@ -1284,10 +1302,17 @@ || ExposeAsSuperclass.class.isAssignableFrom(inner)) { Py.BOOTSTRAP_TYPES.add(inner); } - javaType.dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner)); + javaType.dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner, hardRef)); } } } + if (hardRef && result != null) { + if (exposedTypes == null) { + exposedTypes = Generic.set(); + } + exposedTypes.add(result) ; + } + return result; } @@ -1757,7 +1782,7 @@ private Object readResolve() { if (underlying_class != null) { - return PyType.fromClass(underlying_class); + return PyType.fromClass(underlying_class, false); } PyObject mod = imp.importName(module.intern(), false); PyObject pytyp = mod.__getattr__(name.intern()); Modified: trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java =================================================================== --- trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -73,7 +73,7 @@ add(new ClassAdapter(Class.class) { public PyObject adapt(Object o) { - return PyType.fromClass((Class<?>)o); + return PyType.fromClass((Class<?>)o, false); } }); Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/imp.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -399,7 +399,7 @@ throw Py.JavaError(e); } } - return PyType.fromClass(c); // xxx? + return PyType.fromClass(c, false); // xxx? } static PyObject getPathImporter(PyObject cache, PyList hooks, PyObject p) { Modified: trunk/jython/src/org/python/modules/zipimport/zipimporter.java =================================================================== --- trunk/jython/src/org/python/modules/zipimport/zipimporter.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/modules/zipimport/zipimporter.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -117,7 +117,7 @@ zipimport._zip_directory_cache.__setitem__(archive, files); } } else { - throw zipimport.ZipImportError("not a Zip file"); + throw zipimport.ZipImportError("not a Zip file: " + path); } if (prefix != "" && !prefix.endsWith(File.separator)) { Modified: trunk/jython/src/org/python/util/Generic.java =================================================================== --- trunk/jython/src/org/python/util/Generic.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/util/Generic.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -58,11 +58,6 @@ return new HashMap<K, V>(); } - public static <K, V> Map<K, V> synchronizedWeakHashMap() { - return Collections.synchronizedMap(new WeakHashMap<K, V>()); - } - - /** * Makes a ConcurrentMap using generic types inferred from whatever this is being * assigned to. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |