changeset 14050:516eeabb4c62

avoid deadlock in clinit of HotSpotResolvedJavaField
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Tue, 04 Mar 2014 16:12:18 -0800
parents 6b8e10e585df
children e85575f63b60
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java
diffstat 1 files changed, 34 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Mon Mar 03 20:40:23 2014 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Tue Mar 04 16:12:18 2014 -0800
@@ -119,42 +119,47 @@
         return false;
     }
 
-    private static final List<ResolvedJavaField> notEmbeddable = new ArrayList<>();
+    static class Embeddable {
 
-    private static void addResolvedToSet(Field field) {
-        MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
-        notEmbeddable.add(metaAccess.lookupJavaField(field));
-    }
+        // Return true if it's ok to embed the value of a field.
+        public static boolean test(HotSpotResolvedJavaField field) {
+            return !ImmutableCode.getValue() || !fields.contains(field);
+        }
 
-    static {
-        try {
-            addResolvedToSet(Boolean.class.getDeclaredField("TRUE"));
-            addResolvedToSet(Boolean.class.getDeclaredField("FALSE"));
+        private static final List<ResolvedJavaField> fields = new ArrayList<>();
+        static {
+            // Make this initialization lazy so that we don't create cycles between clinit and other
+            // locks that could lead to deadlock.
+            try {
+                MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
+                fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE")));
+                fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE")));
 
-            Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
-            assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName());
-            addResolvedToSet(characterCacheClass.getDeclaredField("cache"));
+                Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
+                assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache")));
 
-            Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
-            assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName());
-            addResolvedToSet(byteCacheClass.getDeclaredField("cache"));
+                Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
+                assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache")));
 
-            Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0];
-            assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName());
-            addResolvedToSet(shortCacheClass.getDeclaredField("cache"));
+                Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0];
+                assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache")));
 
-            Class<?> integerCacheClass = Integer.class.getDeclaredClasses()[0];
-            assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName());
-            addResolvedToSet(integerCacheClass.getDeclaredField("cache"));
+                Class<?> integerCacheClass = Integer.class.getDeclaredClasses()[0];
+                assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache")));
 
-            Class<?> longCacheClass = Long.class.getDeclaredClasses()[0];
-            assert "java.lang.Long$LongCache".equals(longCacheClass.getName());
-            addResolvedToSet(longCacheClass.getDeclaredField("cache"));
+                Class<?> longCacheClass = Long.class.getDeclaredClasses()[0];
+                assert "java.lang.Long$LongCache".equals(longCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache")));
 
-            addResolvedToSet(Throwable.class.getDeclaredField("UNASSIGNED_STACK"));
-            addResolvedToSet(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"));
-        } catch (SecurityException | NoSuchFieldException e) {
-            throw new GraalInternalError(e);
+                fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK")));
+                fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL")));
+            } catch (SecurityException | NoSuchFieldException e) {
+                throw new GraalInternalError(e);
+            }
         }
     }
 
@@ -162,10 +167,7 @@
      * in AOT mode, some fields should never be embedded even for snippets/replacements.
      */
     private boolean isEmbeddable() {
-        if (ImmutableCode.getValue() && notEmbeddable.contains(this)) {
-            return false;
-        }
-        return true;
+        return Embeddable.test(this);
     }
 
     private static final String SystemClassName = "Ljava/lang/System;";