langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java
changeset 1037 c6b315a34dc6
parent 940 0d5cabfaffde
child 1260 a772ba9ba43d
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Jul 28 10:22:10 2008 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java	Fri Aug 01 15:23:18 2008 -0700
@@ -2110,16 +2110,64 @@
 
         Symbol valuesSym = lookupMethod(tree.pos(), names.values,
                                         tree.type, List.<Type>nil());
-        JCTypeCast valuesResult =
-            make.TypeCast(valuesSym.type.getReturnType(),
-                          make.App(make.Select(make.Ident(valuesVar),
-                                               syms.arrayCloneMethod)));
+        List<JCStatement> valuesBody;
+        if (useClone()) {
+            // return (T[]) $VALUES.clone();
+            JCTypeCast valuesResult =
+                make.TypeCast(valuesSym.type.getReturnType(),
+                              make.App(make.Select(make.Ident(valuesVar),
+                                                   syms.arrayCloneMethod)));
+            valuesBody = List.<JCStatement>of(make.Return(valuesResult));
+        } else {
+            // template: T[] $result = new T[$values.length];
+            Name resultName = names.fromString(target.syntheticNameChar() + "result");
+            while (tree.sym.members().lookup(resultName).scope != null) // avoid name clash
+                resultName = names.fromString(resultName + "" + target.syntheticNameChar());
+            VarSymbol resultVar = new VarSymbol(FINAL|SYNTHETIC,
+                                                resultName,
+                                                arrayType,
+                                                valuesSym);
+            JCNewArray resultArray = make.NewArray(make.Type(types.erasure(tree.type)),
+                                  List.of(make.Select(make.Ident(valuesVar), syms.lengthVar)),
+                                  null);
+            resultArray.type = arrayType;
+            JCVariableDecl decl = make.VarDef(resultVar, resultArray);
+
+            // template: System.arraycopy($VALUES, 0, $result, 0, $VALUES.length);
+            if (systemArraycopyMethod == null) {
+                systemArraycopyMethod =
+                    new MethodSymbol(PUBLIC | STATIC,
+                                     names.fromString("arraycopy"),
+                                     new MethodType(List.<Type>of(syms.objectType,
+                                                            syms.intType,
+                                                            syms.objectType,
+                                                            syms.intType,
+                                                            syms.intType),
+                                                    syms.voidType,
+                                                    List.<Type>nil(),
+                                                    syms.methodClass),
+                                     syms.systemType.tsym);
+            }
+            JCStatement copy =
+                make.Exec(make.App(make.Select(make.Ident(syms.systemType.tsym),
+                                               systemArraycopyMethod),
+                          List.of(make.Ident(valuesVar), make.Literal(0),
+                                  make.Ident(resultVar), make.Literal(0),
+                                  make.Select(make.Ident(valuesVar), syms.lengthVar))));
+
+            // template: return $result;
+            JCStatement ret = make.Return(make.Ident(resultVar));
+            valuesBody = List.<JCStatement>of(decl, copy, ret);
+        }
+
         JCMethodDecl valuesDef =
-            make.MethodDef((MethodSymbol)valuesSym,
-                           make.Block(0, List.<JCStatement>nil()
-                                      .prepend(make.Return(valuesResult))));
+             make.MethodDef((MethodSymbol)valuesSym, make.Block(0, valuesBody));
+
         enumDefs.append(valuesDef);
 
+        if (debugLower)
+            System.err.println(tree.sym + ".valuesDef = " + valuesDef);
+
         /** The template for the following code is:
          *
          *     public static E valueOf(String name) {
@@ -2155,6 +2203,17 @@
             addEnumCompatibleMembers(tree);
         }
     }
+        // where
+        private MethodSymbol systemArraycopyMethod;
+        private boolean useClone() {
+            try {
+                Scope.Entry e = syms.objectType.tsym.members().lookup(names.clone);
+                return (e.sym != null);
+            }
+            catch (CompletionFailure e) {
+                return false;
+            }
+        }
 
     /** Translate an enumeration constant and its initializer. */
     private void visitEnumConstantDef(JCVariableDecl var, int ordinal) {