Merge "Assert the ownership of Code."
diff --git a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
index 519bd58..b151ef8 100644
--- a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
@@ -123,7 +123,7 @@
     DexCode code = method.getCode().asDexCode();
     // As we have rewritten the code, we now know that its highest string index that is not
     // a jumbo-string is firstJumboString (actually the previous string, but we do not have that).
-    method.setDexCode(new DexCode(
+    method.setCode(new DexCode(
         code.registerSize,
         code.incomingRegisterSize,
         code.outgoingRegisterSize,
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index e41120d..d588ab5 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -206,6 +206,7 @@
       GraphLense graphLense,
       InternalOptions options,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     return internalBuild(encodedMethod, appInfo, graphLense, options, null, null, origin);
   }
 
@@ -218,6 +219,7 @@
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     assert valueNumberGenerator != null;
     assert callerPosition != null;
     return internalBuild(
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 0484a63..187756a 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -16,6 +16,18 @@
 
 public abstract class Code extends CachedHashValueDexItem {
 
+  private DexEncodedMethod owner;
+
+  public void setOwner(DexEncodedMethod encodedMethod) {
+    // When this Code is un/linked to DexEncodedMethod, the ownership should be updated accordingly.
+    owner = encodedMethod;
+  }
+
+  public DexEncodedMethod getOwner() {
+    // build*IR() will check if the current Code belongs to the given DexEncodedMethod.
+    return owner;
+  }
+
   public abstract IRCode buildIR(
       DexEncodedMethod encodedMethod,
       AppInfo appInfo,
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index d0c40e1..d5f8001 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -193,6 +193,7 @@
       GraphLense graphLense,
       InternalOptions options,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     DexSourceCode source =
         new DexSourceCode(
             this,
@@ -213,6 +214,7 @@
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     DexSourceCode source =
         new DexSourceCode(
             this,
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index e90839c..c540d24 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -116,6 +116,7 @@
     this.parameterAnnotationsList = parameterAnnotationsList;
     this.code = code;
     assert code == null || !accessFlags.isAbstract();
+    setCodeOwnership();
   }
 
   public DexEncodedMethod(
@@ -276,7 +277,9 @@
   }
 
   public void setCode(Code code) {
+    voidCodeOwnership();
     this.code = code;
+    setCodeOwnership();
   }
 
   public void setCode(
@@ -284,7 +287,7 @@
       RegisterAllocator registerAllocator,
       InternalOptions options) {
     final DexBuilder builder = new DexBuilder(ir, registerAllocator, options);
-    code = builder.build(method.getArity());
+    setCode(builder.build(method.getArity()));
   }
 
   @Override
@@ -316,12 +319,21 @@
     return code;
   }
 
-  public void setDexCode(DexCode code) {
-    this.code = code;
+  public void removeCode() {
+    voidCodeOwnership();
+    code = null;
   }
 
-  public void removeCode() {
-    code = null;
+  private void setCodeOwnership() {
+    if (code != null) {
+      code.setOwner(this);
+    }
+  }
+
+  private void voidCodeOwnership() {
+    if (code != null) {
+      code.setOwner(null);
+    }
   }
 
   public boolean hasDebugPositions() {
@@ -389,6 +401,7 @@
 
   public DexEncodedMethod toAbstractMethod() {
     accessFlags.setAbstract();
+    voidCodeOwnership();
     this.code = null;
     return this;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/JarCode.java b/src/main/java/com/android/tools/r8/graph/JarCode.java
index 28143ad..629017b 100644
--- a/src/main/java/com/android/tools/r8/graph/JarCode.java
+++ b/src/main/java/com/android/tools/r8/graph/JarCode.java
@@ -113,6 +113,7 @@
       GraphLense graphLense,
       InternalOptions options,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     triggerDelayedParsingIfNeccessary();
     return options.debug
         ? internalBuildWithLocals(encodedMethod, appInfo, graphLense, options, null, null)
@@ -128,6 +129,7 @@
       ValueNumberGenerator generator,
       Position callerPosition,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     assert generator != null;
     triggerDelayedParsingIfNeccessary();
     return options.debug
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index b6eb879..f1c1700 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -146,6 +146,8 @@
     assert this.context != null;
     this.code = code;
     this.context = null;
+    // Propagate the ownership of LazyCfCode to CfCode.
+    code.setOwner(this.getOwner());
   }
 
   @Override
@@ -180,6 +182,7 @@
       GraphLense graphLense,
       InternalOptions options,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     return asCfCode().buildIR(encodedMethod, appInfo, graphLense, options, origin);
   }
 
@@ -192,6 +195,7 @@
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     return asCfCode()
         .buildInliningIR(
             encodedMethod,
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 5f8fd6b..5397be4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -1170,6 +1170,7 @@
         GraphLense graphLense,
         InternalOptions options,
         Origin origin) {
+      assert getOwner() == encodedMethod;
       OutlineSourceCode source = new OutlineSourceCode(outline);
       return new IRBuilder(encodedMethod, appInfo, source, options).build();
     }
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
index aa6be96..df273a7 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
@@ -53,6 +53,7 @@
       GraphLense graphLense,
       InternalOptions options,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     return new IRBuilder(encodedMethod, appInfo, sourceCodeProvider.get(), options).build();
   }
 
@@ -65,6 +66,7 @@
       ValueNumberGenerator valueNumberGenerator,
       Position callerPosition,
       Origin origin) {
+    assert getOwner() == encodedMethod;
     IRBuilder builder =
         new IRBuilder(
             encodedMethod, appInfo, sourceCodeProvider.get(), options, valueNumberGenerator);