changeset 3287:659f44b99b6c

Summary: Add an option -XDGenerateValueAsReference under which javac would treat value types as reference types for code generation purposes while treating them as value types for all other purposes (to allow for early user testing.) Reviewed-by: mcimadamore
author sadayapalam
date Fri, 22 Jan 2016 16:25:26 +0530
parents e48d890d4788
children b345d7339ab3
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java test/tools/javac/valhalla/values/GetFieldTest.java test/tools/javac/valhalla/values/NestingTest.java test/tools/javac/valhalla/values/NestingTest2.java test/tools/javac/valhalla/values/SimpleTest.java
diffstat 16 files changed, 420 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Fri Jan 22 16:25:26 2016 +0530
@@ -383,10 +383,6 @@
         return name.isEmpty();
     }
 
-    public boolean isValue() {
-        return type.isValue();
-    }
-
     /** Is this symbol a constructor?
      */
     public boolean isConstructor() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Fri Jan 22 16:25:26 2016 +0530
@@ -302,6 +302,12 @@
                     ((ClassSymbol) sym).members_field = WriteableScope.create(sym);
                     sym.members().enter(new MethodSymbol(PUBLIC, names.init,
                             new MethodType(List.<Type>nil(), voidType, List.<Type>nil(), methodClass), sym));
+                    sym.members().enter(new MethodSymbol(PUBLIC, names.hashCode,
+                            new MethodType(List.<Type>nil(), intType, List.<Type>nil(), methodClass), sym));
+                    sym.members().enter(new MethodSymbol(PUBLIC, names.toString,
+                            new MethodType(List.<Type>nil(), stringType, List.<Type>nil(), methodClass), sym));
+                    sym.members().enter(new MethodSymbol(PUBLIC, names.equals,
+                            new MethodType(List.<Type>of(objectType), booleanType, List.<Type>nil(), methodClass), sym));
                 }
             }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Fri Jan 22 16:25:26 2016 +0530
@@ -156,10 +156,6 @@
         return false;
     }
 
-    public boolean isPrimitiveOrValue() {
-        return isPrimitive() || isValue();
-    }
-
     public boolean isReference() {
         return false;
     }
@@ -606,10 +602,6 @@
         return false;
     }
 
-    public boolean isValue() {
-        return tsym != null && (tsym.flags_field & Flags.VALUE) != 0;
-    }
-
     public boolean isInterface() {
         return (tsym.flags() & INTERFACE) != 0;
     }
@@ -2394,11 +2386,6 @@
         }
 
         @Override
-        public boolean isPrimitiveOrValue() {
-            return true;
-        }
-
-        @Override
         public String stringValue() {
             return "any";
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Jan 22 16:25:26 2016 +0530
@@ -97,6 +97,7 @@
     final boolean allowTypeSpecialization;
     final Check chk;
     final Enter enter;
+    private boolean foldValueAsReference;
     JCDiagnostic.Factory diags;
     List<Warner> warnStack = List.nil();
     final Name capturedName;
@@ -293,10 +294,24 @@
 
     /** Is this type compatible with an 'val' type-variable? */
     public boolean isValueCompatible(Type t) {
-        return t.isPrimitiveOrValue() ||
+        return isPrimitiveOrValue(t) ||
                 (t.hasTag(TYPEVAR) && getTypeVarKind((TypeVar)t) == TypeVarKind.VAL);
     }
 
+    public void foldValueAsReference(boolean fold) {
+        foldValueAsReference = fold;
+    }
+
+    public boolean isValue(Type t) {
+        return foldValueAsReference ? false
+                                    : t.hasTag(TypeTag.VAL_BOUND) ? true
+                                    : t.tsym != null && (t.tsym.flags_field & Flags.VALUE) != 0;
+    }
+
+    public boolean isPrimitiveOrValue(Type t) {
+        return t.isPrimitive() || isValue(t);
+    }
+
     /**
      * Is the given type an 'any' type-variable?
      */
@@ -320,7 +335,7 @@
                     return t.getParameterTypes().prepend(t.getReturnType()).stream().anyMatch(this::isSpecialized);
                 case CLASS:
                     return isVirtualizable((ClassType)t) || directSupertypes(t).stream().anyMatch(this::isSpecialized) ||
-                        t.allparams().stream().anyMatch(Type::isPrimitiveOrValue);
+                        t.allparams().stream().anyMatch(this::isPrimitiveOrValue);
                 case ARRAY:
                     return isSpecialized(elemtype(t));
                 default:
@@ -428,7 +443,7 @@
     private UnaryVisitor<Boolean> specializableTypeArg = new UnaryVisitor<Boolean>() {
         @Override
         public Boolean visitType(Type t, Void aVoid) {
-            return t.isPrimitiveOrValue();
+            return isPrimitiveOrValue(t);
         }
 
         @Override
@@ -557,11 +572,11 @@
         boolean tPrimitive = t.isPrimitive();
         boolean sPrimitive = s.isPrimitive();
 
-        if (tAnyInferenceVar && s.isPrimitiveOrValue()) {
+        if (tAnyInferenceVar && isPrimitiveOrValue(s)) {
             //special conversion rule from inference var to primitive/value (no boxing)
             ((UndetVar)t).addBound(InferenceBound.UPPER, s, this);
             return true;
-        } else if (sAnyInferenceVar && t.isPrimitiveOrValue()) {
+        } else if (sAnyInferenceVar && isPrimitiveOrValue(t)) {
             //special conversion rule from primitive/value to inference var (no boxing)
             ((UndetVar)s).addBound(InferenceBound.LOWER, t, this);
             return true;
@@ -1122,7 +1137,7 @@
                  case BOT:
                      //note - 'null' cannot be assigned to an 'any' type-variable - nor to value types
                      return
-                         s.hasTag(BOT) || (s.hasTag(CLASS) && !s.isValue()) || s.hasTag(ARRAY) ||
+                         s.hasTag(BOT) || (s.hasTag(CLASS) && !isValue(s)) || s.hasTag(ARRAY) ||
                                  (s.hasTag(TYPEVAR) && !isAnyTypeVar(s));
                  case VAL_BOUND:
                      return s.hasTag(TypeTag.VAL_BOUND) || s.hasTag(ANY_BOUND);
@@ -1800,7 +1815,7 @@
 
             @Override
             public Boolean visitClassType(ClassType t, Type s) {
-                if (s.hasTag(ERROR) || s.hasTag(BOT) && !t.isValue() || s.hasTag(TypeTag.ANY_BOUND))
+                if (s.hasTag(ERROR) || s.hasTag(BOT) && !isValue(t) || s.hasTag(TypeTag.ANY_BOUND))
                     return true;
 
                 if (s.hasTag(TypeTag.VAL_BOUND)) {
@@ -3549,7 +3564,7 @@
             static ArgTypeKind fromType(Type t, Types types) {
                 if (types.isSpecializableTypeVar(t)) {
                     return SPECIALIZABLE_TVAR;
-                } else if (t.isPrimitiveOrValue()) {
+                } else if (types.isPrimitiveOrValue(t)) {
                     return VALUE;
                 } else {
                     return OTHER;
@@ -5120,7 +5135,7 @@
     }
 
     TypeArgMapper referenceTargsAsFormals =
-            new TypeArgMapper(Type::isPrimitiveOrValue, (actual, formal) -> formal);
+            new TypeArgMapper(this::isPrimitiveOrValue, (actual, formal) -> formal);
 
     TypeArgMapper referenceTargsAsErasedFormals =
             new TypeArgMapper(this::isTypeArgumentSpecializable,
@@ -5608,7 +5623,7 @@
                     append('V');
                     break;
                 case CLASS:
-                    if (type.isValue())
+                    if (!types.foldValueAsReference && types.isValue(type)) // VM does not like 'Q' descriptors yet
                         append('Q');
                     else
                         append('L');
@@ -5840,7 +5855,7 @@
                 //compute name string
                 List<String> specNames =
                         Tuple2.zip(List.range(0, typeargs.length()), typeargs).stream()
-                                .filter(p -> p.elem1.isPrimitiveOrValue())
+                                .filter(p -> isPrimitiveOrValue(p.elem1))
                                 .map(p -> String.join("=", p.elem0.toString(), typeSig(p.elem1)))
                                 .collect(List.collector());
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Jan 22 16:25:26 2016 +0530
@@ -1123,7 +1123,7 @@
                 annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym, tree.pos());
                 annotate.flush();
             }
-            if (tree.sym.owner.type.isValue() && (tree.mods.flags & Flags.FINAL) == 0) {
+            if (types.isValue(tree.sym.owner.type) && (tree.mods.flags & Flags.FINAL) == 0) {
                 log.error(tree.pos(), "value.field.must.be.final");
             }
         }
@@ -1936,7 +1936,7 @@
             // identity hash code is uncomputable for value instances.
             final Symbol symbol = TreeInfo.symbol(tree.meth);
             if (symbol != null && symbol.name == names.identityHashCode && symbol.owner.flatName() == names.java_lang_System) {
-                if (tree.args.length() == 1 && tree.args.head.type.isValue())
+                if (tree.args.length() == 1 && types.isValue(tree.args.head.type))
                     log.error(tree.pos(), "value.does.not.support", "identityHashCode");
             }
 
@@ -2118,7 +2118,7 @@
                  ((JCVariableDecl) env.tree).init != tree))
                 log.error(tree.pos(), "enum.cant.be.instantiated");
 
-            if (clazztype.isValue() != tree.isValue) {
+            if (types.isValue(clazztype) != tree.isValue) {
                 log.error(tree.pos(), Errors.GarbledValueReferenceInstantiation);
             }
             boolean isSpeculativeDiamondInferenceRound = TreeInfo.isDiamond(tree) &&
@@ -3249,7 +3249,7 @@
                 if (!types.isCastable(left, right, new Warner(tree.pos()))) {
                     log.error(tree.pos(), "incomparable.types", left, right);
                 }
-                if (left.isValue() || right.isValue()) {
+                if (types.isValue(left) || types.isValue(right)) {
                     log.error(tree.pos(), "value.does.not.support", tree.operator.name.toString());
                 }
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Fri Jan 22 16:25:26 2016 +0530
@@ -734,7 +734,7 @@
 
     Type checkRefType(DiagnosticPosition pos, Type t, boolean acceptsAllTvars) {
         if (((acceptsAllTvars ? t.hasTag(TYPEVAR) : false) ||
-                t.isReference()) && !t.isValue())
+                t.isReference()) && !types.isValue(t))
             return t;
         else
             return typeTagError(pos,
@@ -748,7 +748,7 @@
      *  @param t             The type to be checked.
      */
     Type checkWildcardType(DiagnosticPosition pos, Type t) {
-        if (t.hasTag(TYPEVAR) && t.isReference() && !t.isValue())
+        if (t.hasTag(TYPEVAR) && t.isReference() && !types.isValue(t))
             return t;
         else
             return typeTagError(pos,
@@ -1131,7 +1131,7 @@
             } else if (a.hasTag(WILDCARD) &&
                     ((WildcardType)a).type.hasTag(ANY_BOUND)) {
                 return false;
-            } else if (a.isPrimitiveOrValue()) {
+            } else if (types.isPrimitiveOrValue(a)) {
                 return bound.hasTag(TypeTag.VAL_BOUND);
             } else if (!a.hasTag(WILDCARD)) {
                 a = types.cvarUpperBound(a);
@@ -1452,7 +1452,7 @@
 
                 BoundChecker<JCExpression> bc = new ClassBoundChecker<>(tree.type, args);
                 bc.onFailure((actual, formal, pos) -> {
-                    if (actual.isPrimitiveOrValue() || types.isSpecializableTypeVar(actual)) {
+                    if (types.isPrimitiveOrValue(actual) || types.isSpecializableTypeVar(actual)) {
                         checkRefType(pos, actual);
                     } else {
                         log.error(pos, "not.within.bounds", actual, formal);
@@ -2255,7 +2255,7 @@
                     JCVariableDecl field = (JCVariableDecl) l.head;
                     if (!field.sym.isStatic()) {
                         Type fieldType = field.sym.type;
-                        if (fieldType.isValue()) {
+                        if (types.isValue(fieldType)) {
                             checkNonCyclicMembership((ClassSymbol) fieldType.tsym, field.pos());
                         }
                     }
@@ -2274,7 +2274,9 @@
             }
             try {
                 c.flags_field |= LOCKED;
-                for (Symbol fld : c.members().getSymbols(instanceValueFieldFilter, NON_RECURSIVE)) {
+                for (Symbol fld : c.members().getSymbols(s -> s.kind == VAR &&
+                                                              !s.isStatic() &&
+                                                              types.isValue(s.type), NON_RECURSIVE)) {
                     checkNonCyclicMembership((ClassSymbol) fld.type.tsym, pos);
                 }
             } finally {
@@ -2282,9 +2284,6 @@
             }
         }
 
-        private Filter<Symbol> instanceValueFieldFilter = s -> s.kind == VAR &&
-                                                          !s.isStatic() &&
-                                                          s.type.isValue();
 
     void checkNonCyclicDecl(JCClassDecl tree) {
         CycleChecker cc = new CycleChecker();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Jan 22 16:25:26 2016 +0530
@@ -3577,7 +3577,7 @@
             /* If this is an ill conceived attempt to invoke jlO methods not available on value types,
                issue a distinct message that spells out the programmer's error.
             */
-            if (kind == ABSENT_MTH && site.isValue()) {
+            if (kind == ABSENT_MTH && types.isValue(site)) {
                 int argSize = argtypes.size();
                 switch (name.toString()) {
                     case "wait":
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Fri Jan 22 16:25:26 2016 +0530
@@ -906,7 +906,7 @@
                 typeAnnotations.validateTypeAnnotationsSignatures(env, (JCClassDecl)env.tree);
             }
 
-            if (tree.sym.type.isValue()) {
+            if (types.isValue(tree.sym.type)) {
                 chk.checkNonCyclicMembership(tree);
             }
         }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Jan 22 16:25:26 2016 +0530
@@ -63,6 +63,8 @@
 
     private final Options options;
 
+    private final boolean foldValueAsReference;
+
     /** Switch: verbose output.
      */
     private boolean verbose;
@@ -142,6 +144,8 @@
     /** Sole signature generator */
     private final CWSignatureGenerator signatureGen;
 
+    private final Symtab syms;
+
     /** Switch: new constant pool mode support */
     private final boolean genericClassFile;
 
@@ -173,7 +177,7 @@
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
         signatureGen = new CWSignatureGenerator(types);
-
+        syms = Symtab.instance(context);
         verbose        = options.isSet(VERBOSE);
         scramble       = options.isSet("-scramble");
         scrambleAll    = options.isSet("-scrambleAll");
@@ -186,6 +190,8 @@
 
         genericClassFile = options.isSet("genericClassFile");
 
+        foldValueAsReference = options.isSet("GenerateValueAsReference");
+
         String dumpModFlags = options.get("dumpmodifiers");
         dumpClassModifiers =
             (dumpModFlags != null && dumpModFlags.indexOf('c') != -1);
@@ -1055,7 +1061,7 @@
             acount += writeBytecodeMapping(m);
             m.code = null; // to conserve space
         }
-        if (m.name == names.vminit) {
+        if (!foldValueAsReference && m.name == names.vminit) {
             int alenIdx = writeAttr(names.ValueFactory);
             writeValueFactory(m);
             endAttr(alenIdx);
@@ -1623,6 +1629,9 @@
         poolwriter = c.poolWriter;
 
         Type supertype = types.supertype(c.type);
+        // j.l.__Value is tagged as final incorrectly leading to verification errors ...
+        if (foldValueAsReference && supertype == syms.valueClassType)
+            supertype = syms.objectType;
         List<Type> interfaces = types.interfaces(c.type);
         List<Type> typarams = c.type.getTypeArguments();
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Fri Jan 22 16:25:26 2016 +0530
@@ -74,6 +74,7 @@
     private final Names names;
     private final Target target;
     private final Map<Type,Symbol> stringBufferAppend;
+    private final boolean foldValueAsReference;
     private Name accessDollar;
     private final Types types;
     private final Lower lower;
@@ -129,6 +130,7 @@
         allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
         allowBetterNullChecks = target.hasObjects();
         genericClassFile = options.isSet("genericClassFile");
+        foldValueAsReference = options.isSet("GenerateValueAsReference");
 
         // ignore cldc because we cannot have both stackmap formats
         this.stackMap = StackMapFormat.JSR202;
@@ -391,7 +393,7 @@
      * ValueFactory attribute, which is constructed here on the spot.
      */
     int makeRef(DiagnosticPosition pos, Type type, List<Type> args) {
-        assert type.isValue();
+        assert types.isValue(type);
         MethodType mtype = new MethodType(args, type, List.nil(), syms.methodClass);
         MethodSymbol sym = new MethodSymbol(Flags.VALUEFACTORY, names.vminit, mtype, type.tsym);
         env.enclClass.sym.members_field.enterIfAbsent(sym);
@@ -1888,7 +1890,7 @@
             code.pendingStatPos = tmpPos;
             r.load();
             emitAndMarkIfNeeded1(returnType, types::isSpecializableTypeVar,
-                    () -> code.emitop0(returnType.isValue() ? vreturn :
+                    () -> code.emitop0(types.isValue(returnType) ? vreturn :
                             (ireturn + Code.truncate(Code.typecode(erasedReturnType)))));
         } else {
             /*  If we have a statement like:
@@ -1917,6 +1919,22 @@
  *************************************************************************/
 
     public void visitApply(JCMethodInvocation tree) {
+        if (foldValueAsReference) {
+            if (tree.meth.hasTag(Tag.IDENT)) {
+                JCIdent id = (JCIdent) tree.meth;
+                if (id.name == names._super && id.sym.owner == syms.valueClassType.tsym) {
+                    id.sym = id.sym.clone(syms.objectType.tsym);
+                }
+            } else if (tree.meth.hasTag(Tag.SELECT)) {
+                JCFieldAccess fieldAccess = (JCFieldAccess) tree.meth;
+                if (fieldAccess.selected.hasTag(Tag.IDENT)) {
+                    JCIdent id = (JCIdent) fieldAccess.selected;
+                    if (id.name == names._super && fieldAccess.sym.owner == syms.valueClassType.tsym) {
+                        fieldAccess.sym = fieldAccess.sym.clone(syms.objectType.tsym);
+                    }
+                }
+            }
+        }
         setTypeAnnotationPositions(tree.pos);
         // Generate code for method.
         Item m = genExpr(tree.meth, methodType);
@@ -2021,7 +2039,7 @@
 
         Type newType = TreeInfo.unerasedTypeOrType(tree);
 
-        if (newType.isValue()) {
+        if (types.isValue(newType)) {
             // For values, the creation sequence is simpler: push all arguments, then emit vnew.
             // Abuse the constructor signature to determine the arguments.
             List<Type> parameterTypes = tree.constructor.externalType(types).getParameterTypes();
@@ -2080,7 +2098,7 @@
                 nerrs++;
             }
             int elemcode = Code.arraycode(erasedElementType);
-            if (erasedElementType.isValue()) {
+            if (types.isValue(erasedElementType)) {
                 code.emitVnewarray(makeRef(tree, erasedType), erasedType);
             } else if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
                 emitAndMarkIfNeeded2(tree, sigType, (ref) -> code.emitAnewarray(ref, erasedType), t -> types.elemtype(t));
@@ -2090,7 +2108,7 @@
                 while (types.isArray(u)) {
                     u = types.elemtype(u);
                 }
-                if (u.isValue()) {
+                if (types.isValue(u)) {
                     emitAndMarkIfNeeded2(tree, sigType, (ref) -> code.emitMultivnewarray(ndims, ref, erasedType), null);
                 } else {
                     emitAndMarkIfNeeded2(tree, sigType, (ref) -> code.emitMultianewarray(ndims, ref, erasedType), null);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java	Fri Jan 22 16:25:26 2016 +0530
@@ -733,7 +733,7 @@
         }
 
         Item load() {
-            if (type.isValue())
+            if (types.isValue(type))
                 code.emitop0(vaload);
             else
                 code.emitop0(iaload + typecode);
@@ -741,7 +741,7 @@
         }
 
         void store() {
-            if (type.isValue())
+            if (types.isValue(type))
                 code.emitop0(vastore);
             else
                 code.emitop0(iastore + typecode);
@@ -784,7 +784,7 @@
         }
 
         Item load() {
-            if (type.isValue())
+            if (types.isValue(type))
                 code.emitop1w(vload, 0);
             else
                 code.emitop0(aload_0);
@@ -821,7 +821,7 @@
         }
 
         Item load() {
-            if (type.isValue())
+            if (types.isValue(type))
                 code.emitop1w(vload, reg);
             else if (reg <= 3)
                 code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
@@ -831,7 +831,7 @@
         }
 
         void store() {
-            if (type.isValue())
+            if (types.isValue(type))
                 code.emitop1w(vstore, reg);
             else if (reg <= 3)
                 code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
@@ -1021,7 +1021,7 @@
         }
 
         Item load() {
-            code.emitop2(member.enclClass().type.isValue() ? vgetfield : getfield, pool.putSymbol(member));
+            code.emitop2(types.isValue(member.enclClass().type) ? vgetfield : getfield, pool.putSymbol(member));
             return stackItem[typecode];
         }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Thu Jan 21 16:30:27 2016 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java	Fri Jan 22 16:25:26 2016 +0530
@@ -90,6 +90,8 @@
     /** The context key for the compiler. */
     public static final Context.Key<JavaCompiler> compilerKey = new Context.Key<>();
 
+    private final boolean foldValueAsReference;
+
     /** Get the JavaCompiler instance for this context. */
     public static JavaCompiler instance(Context context) {
         JavaCompiler instance = context.get(compilerKey);
@@ -403,7 +405,7 @@
         devVerbose    = options.isSet("dev");
         processPcks   = options.isSet("process.packages");
         werror        = options.isSet(WERROR);
-
+        foldValueAsReference = options.isSet("GenerateValueAsReference");
         verboseCompilePolicy = options.isSet("verboseCompilePolicy");
 
         if (attrParseOnly)
@@ -713,6 +715,7 @@
      */
     JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
         try {
+            types.foldValueAsReference(foldValueAsReference);
             if (gen.genClass(env, cdef) && (errorCount() == 0))
                 return writer.writeClass(cdef.sym);
         } catch (ClassWriter.PoolOverflow ex) {
@@ -722,6 +725,8 @@
                       ex.value.substring(0, 20));
         } catch (CompletionFailure ex) {
             chk.completionError(cdef.pos(), ex);
+        } finally {
+            types.foldValueAsReference(false);
         }
         return null;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/values/GetFieldTest.java	Fri Jan 22 16:25:26 2016 +0530
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Runtime tests for value types with field accesses.
+ * @compile -XDGenerateValueAsReference GetFieldTest.java
+ * @run main GetFieldTest
+ */
+
+public class GetFieldTest {
+
+    __ByValue final static class Point {
+        final int x;
+        final int y;
+
+        private Point(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        public static Point createPoint(int x, int y) {
+            System.gc();
+            return __Make Point(x, y);
+        }
+    }
+
+    static Point staticPoint;
+    Point myPoint;
+
+    static void fieldTest(Point p) {
+        staticPoint = p;
+        if (p.x  != staticPoint.x || p.y != staticPoint.y)
+            throw new AssertionError("Wrong co-ordinates");
+    }
+
+    static void fieldTest2(Point p) {
+        if (staticPoint.x != 1 || staticPoint.y != 2 || p.x != 5 || p.y != 6)
+            throw new AssertionError("Wrong co-ordinates");
+    }
+
+    public static void main(String[] args) {
+        Point p = Point.createPoint(1, 2);
+        Point p2 = f(p);
+        fieldTest(p2);
+        GetFieldTest test = new GetFieldTest();
+        test.myPoint = Point.createPoint(5, 6);
+        fieldTest2(test.myPoint);
+    }
+
+    static Point f(Point p) {
+        Point q = p;
+        return q;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/values/NestingTest.java	Fri Jan 22 16:25:26 2016 +0530
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Runtime tests for value types with values being embedded in values.
+ * @compile -XDGenerateValueAsReference NestingTest.java
+ * @run main NestingTest
+ */
+
+public class NestingTest {
+
+    __ByValue final static class Point {
+        final int x;
+        final int y;
+
+        private Point(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        public static Point createPoint(int x, int y) {
+            System.gc();
+            return __Make Point(x, y);
+        }
+    }
+
+    __ByValue final static class Square {
+
+        final public Point p0;
+        final public Point p1;
+
+        private Square(Point p0, Point p1) {
+            this.p0 = p0;
+            this.p1 = p1;
+        }
+
+        public static Square createSquare(Point p0, Point p1) {
+            return __Make Square(p0, p1);
+        }
+    }
+
+    __ByValue final static class TwoSquares {
+        final public Square s0;
+        final public Square s1;
+
+        private TwoSquares(Square s0, Square s1) {
+            this.s0 = s0;
+            this.s1 = s1;
+        }
+
+        public static TwoSquares createTwoSquares(Square s0, Square s1) {
+             return __Make TwoSquares(s0, s1);
+        }
+
+    }
+
+    static void printPoint(Point p) {
+        System.out.println("Point(" + p.x + "," + p.y + ")");
+    }
+
+    static void printSquare(Square s) {
+        System.out.println("Square:");
+        System.out.print("\t");
+        printPoint(s.p0);
+        System.out.print("\t");
+        printPoint(s.p1);
+    }
+
+    public static void main(String[] args) {
+        Point p0 = Point.createPoint(5, 6);
+        Point p1 = Point.createPoint(7, 8);
+        Square s = Square.createSquare(p0, p1);
+        if (s.p0.x != 5 || s.p0.y != 6 || s.p1.x != 7 || s.p1.y != 8)
+            throw new AssertionError("Unexpected co-ordinates");
+
+        p0 = Point.createPoint(2, 1);
+        p1 = Point.createPoint(4, 3);
+        Point p2 = Point.createPoint(6, 5);
+        Point p3 = Point.createPoint(8, 7);
+        Square s0 = Square.createSquare(p0, p1);
+        Square s1 = Square.createSquare(p2, p3);
+        TwoSquares ts = TwoSquares.createTwoSquares(s0, s1);
+        if (ts.s0.p0.x != 2 || ts.s0.p0.y != 1 || ts.s0.p1.x != 4 || ts.s0.p1.y != 3 || ts.s1.p0.x != 6
+                || ts.s1.p0.y != 5 || ts.s1.p1.x != 8 || ts.s1.p1.y != 7)
+            throw new AssertionError("Unexpected co-ordinates");
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/values/NestingTest2.java	Fri Jan 22 16:25:26 2016 +0530
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Runtime tests for value types with values being embedded in values.
+ * @compile -XDGenerateValueAsReference NestingTest2.java
+ * @run main NestingTest2
+ */
+
+public class NestingTest2 {
+
+    __ByValue final static class NestedVT2 {
+        final public IntByteValueType v0;
+        final public IntByteValueType v1;
+
+        private NestedVT2(IntByteValueType v0, IntByteValueType v1) {
+            this.v0 = v0;
+            this.v1 = v1;
+        }
+
+        public static NestedVT2 createNestedVT2(IntByteValueType v0, IntByteValueType v1) {
+            return __Make NestedVT2(v0, v1);
+        }
+    }
+
+    __ByValue final static class IntByteValueType {
+        final public int i;
+        final public byte b;
+
+        private IntByteValueType(int i, byte b) {
+            this.i = i;
+            this.b = b;
+        }
+
+        public static IntByteValueType createIntByteValueType(int i, byte b) {
+            return __Make IntByteValueType(i, b);
+        }
+    }
+
+    public static void main(String[] args) {
+        IntByteValueType v0 = IntByteValueType.createIntByteValueType(1, (byte) 2);
+        IntByteValueType v1 = IntByteValueType.createIntByteValueType(3, (byte) 4);
+        NestedVT2 v3 = NestedVT2.createNestedVT2(v0, v1);
+        if (v3.v0.i != 1 || v3.v0.b != 2 || v3.v1.i != 3 || v3.v1.b != 4)
+            throw new AssertionError("Unexpected data");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/valhalla/values/SimpleTest.java	Fri Jan 22 16:25:26 2016 +0530
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Simple value types run time test
+ * @compile -XDGenerateValueAsReference SimpleTest.java
+ * @run main SimpleTest
+ */
+
+public class SimpleTest {
+    __ByValue final static class Point {
+        final int x;
+        final int y;
+
+        private Point(int x, int y) {
+            this.x = x;
+            this.y = y;
+        }
+
+        public static Point createPoint(int x, int y) {
+            System.gc();
+            return __Make Point(x, y);
+        }
+    }
+
+    public static void main(String[] args) {
+        Point p = Point.createPoint(11, 22);
+        Point p2 = f(p);
+        int x = p2.x;
+        int y = p2.y;
+        if (x != 11 || y != 22) {
+            throw new AssertionError("Unexpected co-ordinates");
+        }
+        Point[] parray = pointArrayTest();
+        if (parray.length != 2 ||
+                parray[0].x != 1 || parray[0].y != 2 ||
+                parray[1].x != 3 || parray[1].y != 4)
+                    throw new AssertionError("Unexpected co-ordinates");
+
+        System.gc();
+    }
+
+    static Point f(Point p) {
+        Point q = p;
+        return q;
+    }
+
+    static Point[] pointArrayTest() {
+        Point[] ps = new Point[2];
+        ps[0] = Point.createPoint(1, 2);
+        ps[1] = Point.createPoint(3, 4);
+        System.gc();
+        return ps;
+    }
+}