diff a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
@@ -30,33 +30,24 @@
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 
 import java.util.function.ToIntBiFunction;
-import java.util.function.ToIntFunction;
 
 import static com.sun.tools.javac.code.TypeTag.ARRAY;
 import static com.sun.tools.javac.code.TypeTag.BOT;
 import static com.sun.tools.javac.code.TypeTag.DOUBLE;
 import static com.sun.tools.javac.code.TypeTag.INT;
 import static com.sun.tools.javac.code.TypeTag.LONG;
 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
 import static com.sun.tools.javac.jvm.ByteCodes.*;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
-import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
 import static com.sun.tools.javac.jvm.UninitializedType.*;
 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
 import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
 
 /** An internal structure that corresponds to the code attribute of
  *  methods in a classfile. The class also provides some utility operations to
  *  generate bytecode instructions.
  *
@@ -197,10 +188,18 @@
 
     final MethodSymbol meth;
 
     private int letExprStackPos = 0;
 
+    private Map<Integer, Set<VarSymbol>> cpToUnsetFieldsMap = new HashMap<>();
+
+    public Set<VarSymbol> initialUnsetFields;
+
+    public Set<VarSymbol> currentUnsetFields;
+
+    boolean generateEarlyLarvalFrame;
+
     /** Construct a code object, given the settings of the fatcode,
      *  debugging info switches and the CharacterRangeTable.
      */
     public Code(MethodSymbol meth,
                 boolean fatcode,
@@ -209,11 +208,12 @@
                 StackMapFormat stackMap,
                 boolean debugCode,
                 CRTable crt,
                 Symtab syms,
                 Types types,
-                PoolWriter poolWriter) {
+                PoolWriter poolWriter,
+                boolean generateEarlyLarvalFrame) {
         this.meth = meth;
         this.fatcode = fatcode;
         this.lineMap = lineMap;
         this.lineDebugInfo = lineMap != null;
         this.varDebugInfo = varDebugInfo;
@@ -231,10 +231,11 @@
         default:
             this.needStackMap = false;
         }
         state = new State();
         lvar = new LocalVar[20];
+        this.generateEarlyLarvalFrame = generateEarlyLarvalFrame;
     }
 
 
 /* **************************************************************************
  * Typecodes & related stuff
@@ -1081,11 +1082,10 @@
         default:
             throw new AssertionError(mnem(op));
         }
         // postop();
     }
-
     /** Emit an opcode with a four-byte operand field.
      */
     public void emitop4(int op, int od) {
         emitop(op);
         if (!alive) return;
@@ -1228,10 +1228,11 @@
     /** An entry in the stack map. */
     static class StackMapFrame {
         int pc;
         Type[] locals;
         Type[] stack;
+        Set<VarSymbol> unsetFields;
     }
 
     /** A buffer of cldc stack map entries. */
     StackMapFrame[] stackMapBuffer = null;
 
@@ -1323,17 +1324,21 @@
         }
 
         StackMapFrame frame = new StackMapFrame();
         frame.pc = pc;
 
+        boolean hasUninitalizedThis = false;
         int localCount = 0;
         Type[] locals = new Type[localsSize];
         for (int i=0; i<localsSize; i++, localCount++) {
             if (state.defined.isMember(i) && lvar[i] != null) {
                 Type vtype = lvar[i].sym.type;
-                if (!(vtype instanceof UninitializedType))
+                if (!(vtype instanceof UninitializedType)) {
                     vtype = types.erasure(vtype);
+                } else if (vtype.hasTag(TypeTag.UNINITIALIZED_THIS)) {
+                    hasUninitalizedThis = true;
+                }
                 locals[i] = vtype;
                 if (width(vtype) > 1) i++;
             }
         }
         frame.locals = new Type[localCount];
@@ -1355,24 +1360,39 @@
             if (state.stack[i] != null) {
                 frame.stack[stackCount++] = types.erasure(state.stack[i]);
             }
         }
 
+        Set<VarSymbol> unsetFieldsAtPC = cpToUnsetFieldsMap.get(pc);
+        boolean encloseWithEarlyLarvalFrame = unsetFieldsAtPC != null && generateEarlyLarvalFrame && hasUninitalizedThis
+                && !lastFrame.unsetFields.equals(unsetFieldsAtPC);
+
         if (stackMapTableBuffer == null) {
             stackMapTableBuffer = new StackMapTableFrame[20];
         } else {
             stackMapTableBuffer = ArrayUtils.ensureCapacity(
                                     stackMapTableBuffer,
                                     stackMapBufferSize);
         }
-        stackMapTableBuffer[stackMapBufferSize++] =
-                StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
+
+        StackMapTableFrame tableFrame = StackMapTableFrame.getInstance(frame, lastFrame, types, pc);
+        if (encloseWithEarlyLarvalFrame) {
+            tableFrame = new StackMapTableFrame.EarlyLarvalFrame(tableFrame, unsetFieldsAtPC);
+            frame.unsetFields = unsetFieldsAtPC;
+        } else {
+            frame.unsetFields = lastFrame.unsetFields;
+        }
+        stackMapTableBuffer[stackMapBufferSize++] = tableFrame;
 
         frameBeforeLast = lastFrame;
         lastFrame = frame;
     }
 
+    public void addUnsetFieldsAtPC(int pc, Set<VarSymbol> unsetFields) {
+        cpToUnsetFieldsMap.put(pc, unsetFields);
+    }
+
     StackMapFrame getInitialFrame() {
         StackMapFrame frame = new StackMapFrame();
         List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
         int len = arg_types.length();
         int count = 0;
@@ -1390,10 +1410,11 @@
         for (Type arg_type : arg_types) {
             frame.locals[count++] = types.erasure(arg_type);
         }
         frame.pc = -1;
         frame.stack = null;
+        frame.unsetFields = initialUnsetFields;
         return frame;
     }
 
 
 /* ************************************************************************
@@ -1468,10 +1489,13 @@
         }
         if (opcode != dontgoto && isAlive()) {
             result = new Chain(emitJump(opcode),
                                result,
                                state.dup());
+            if (currentUnsetFields != null) {
+                addUnsetFieldsAtPC(result.pc, currentUnsetFields);
+            }
             fixedPc = fatcode;
             if (opcode == goto_) alive = false;
         }
         return result;
     }
@@ -1479,10 +1503,11 @@
     /** Resolve chain to point to given target.
      */
     public void resolve(Chain chain, int target) {
         boolean changed = false;
         State newState = state;
+        int originalTarget = target;
         for (; chain != null; chain = chain.next) {
             Assert.check(state != chain.state
                     && (target > chain.pc || isStatementStart()));
             if (target >= cp) {
                 target = cp;
@@ -1505,17 +1530,25 @@
                     // from the instruction before goto_.
                     alive = true;
                     break;
                 }
             } else {
-                if (fatcode)
+                if (fatcode) {
                     put4(chain.pc + 1, target - chain.pc);
+                    if (cpToUnsetFieldsMap.get(chain.pc) != null) {
+                        addUnsetFieldsAtPC(originalTarget, cpToUnsetFieldsMap.get(chain.pc));
+                    }
+                }
                 else if (target - chain.pc < Short.MIN_VALUE ||
                          target - chain.pc > Short.MAX_VALUE)
                     fatcode = true;
-                else
+                else {
                     put2(chain.pc + 1, target - chain.pc);
+                    if (cpToUnsetFieldsMap.get(chain.pc) != null) {
+                        addUnsetFieldsAtPC(originalTarget, cpToUnsetFieldsMap.get(chain.pc));
+                    }
+                }
                 Assert.check(!alive ||
                     chain.state.stacksize == newState.stacksize &&
                     chain.state.nlocks == newState.nlocks);
             }
             fixedPc = true;
