changeset 18507:c2b45b536677

Constant fold elements of switch table and enum values() arrays
author Andreas Woess <andreas.woess@jku.at>
date Tue, 25 Nov 2014 20:26:59 +0100
parents 97026ca2a86e
children f56a5c4cd859
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java
diffstat 3 files changed, 40 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Tue Nov 25 13:08:57 2014 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Tue Nov 25 20:26:59 2014 +0100
@@ -274,6 +274,8 @@
     public static final OptionValue<Boolean> MatchExpressions = new OptionValue<>(true);
     @Option(help = "Constant fold final fields with default values.")
     public static final OptionValue<Boolean> TrustFinalDefaultFields = new OptionValue<>(true);
+    @Option(help = "Mark well-known stable fields as such.")
+    public static final OptionValue<Boolean> ImplicitStableValues = new OptionValue<>(true);
 
 
     /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Tue Nov 25 13:08:57 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Tue Nov 25 20:26:59 2014 +0100
@@ -172,10 +172,13 @@
 
         if (receiver == null) {
             assert hotspotField.isStatic();
-            if (hotspotField.isFinal()) {
+            if (hotspotField.isFinal() || hotspotField.isStable()) {
                 ResolvedJavaType holder = hotspotField.getDeclaringClass();
                 if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable(hotspotField)) {
-                    return readFieldValue(field, receiver);
+                    JavaConstant value = readFieldValue(field, receiver);
+                    if (hotspotField.isFinal() || !value.isDefaultForKind()) {
+                        return value;
+                    }
                 }
             }
         } else {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java	Tue Nov 25 13:08:57 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java	Tue Nov 25 20:26:59 2014 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectTypeImpl.*;
 
@@ -143,6 +144,9 @@
             return true;
         }
         assert getAnnotation(Stable.class) == null;
+        if (ImplicitStableValues.getValue() && isImplicitStableField()) {
+            return true;
+        }
         return false;
     }
 
@@ -165,4 +169,33 @@
             return null;
         }
     }
+
+    private boolean isArray() {
+        JavaType fieldType = getType();
+        return fieldType instanceof ResolvedJavaType && ((ResolvedJavaType) fieldType).isArray();
+    }
+
+    private boolean isImplicitStableField() {
+        if (isSynthetic()) {
+            if (isSyntheticImplicitStableField()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isSyntheticImplicitStableField() {
+        assert this.isSynthetic();
+        if (isStatic() && isArray()) {
+            if (isFinal() && name.equals("$VALUES") || name.equals("ENUM$VALUES")) {
+                // generated int[] field for EnumClass::values()
+                return true;
+            } else if (name.startsWith("$SwitchMap$") || name.startsWith("$SWITCH_TABLE$")) {
+                // javac and ecj generate a static field in an inner class for a switch on an enum
+                // named $SwitchMap$p$k$g$EnumClass and $SWITCH_TABLE$p$k$g$EnumClass, respectively
+                return true;
+            }
+        }
+        return false;
+    }
 }