diff options
author | mikaelpeltier <mikaelpeltier@google.com> | 2014-04-11 09:28:18 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-04-11 09:28:18 +0000 |
commit | 18d990d24d1f1daf87d20fee4605ee1de7c4b4ac (patch) | |
tree | f57c23036740086d91cb085be986bfdaab4e592a | |
parent | 96d2943092031f6201093754c808f29dec7c6e6c (diff) | |
parent | f227060968f467c0aac1a435333d73e938567171 (diff) | |
download | toolchain_jack-18d990d24d1f1daf87d20fee4605ee1de7c4b4ac.zip toolchain_jack-18d990d24d1f1daf87d20fee4605ee1de7c4b4ac.tar.gz toolchain_jack-18d990d24d1f1daf87d20fee4605ee1de7c4b4ac.tar.bz2 |
Merge "Split dex file writing into prepare and writing stage" into jack-wip-dev
8 files changed, 115 insertions, 32 deletions
diff --git a/dx/src/com/android/jack/dx/dex/file/DexFile.java b/dx/src/com/android/jack/dx/dex/file/DexFile.java index 027cb25..413911b 100644 --- a/dx/src/com/android/jack/dx/dex/file/DexFile.java +++ b/dx/src/com/android/jack/dx/dex/file/DexFile.java @@ -105,11 +105,10 @@ public final class DexFile { /** {@code >= 40;} maximum width of the file dump */ private int dumpWidth; - /** List of constant index mapping that must be used to remap binary */ - private List<CstIndexMap> cstIndexMaps; - - public DexFile(DexOptions dexOptions, List<CstIndexMap> cstIndexMaps) { - this.cstIndexMaps = cstIndexMaps; + /** + * Constructs an instance. It is initially empty. + */ + public DexFile(DexOptions dexOptions) { this.dexOptions = dexOptions; header = new HeaderSection(this); @@ -149,13 +148,6 @@ public final class DexFile { } /** - * Constructs an instance. It is initially empty. - */ - public DexFile(DexOptions dexOptions) { - this(dexOptions, null); - } - - /** * Returns true if this dex doesn't contain any class defs. */ public boolean isEmpty() { @@ -496,26 +488,23 @@ public final class DexFile { } /** - * Returns the contents of this instance as a {@code .dex} file, - * in a {@link ByteArrayAnnotatedOutput} instance. + * Prepares this instance for writing. This performs any necessary prerequisites, including + * particularly adding stuff to other sections and places all the items in this instance at + * particular offsets. * - * @param annotate whether or not to keep annotations - * @param verbose if annotating, whether to be verbose - * @return {@code non-null;} a {@code .dex} file for this instance + * @param cstIndexMaps list used to map offsets from a dex file to this instance */ - private ByteArrayAnnotatedOutput toDex0(boolean annotate, boolean verbose) { - /* - * The following is ordered so that the prepare() calls which - * add items happen before the calls to the sections that get - * added to. - */ - -if (cstIndexMaps != null) { + public void prepare(List<CstIndexMap> cstIndexMaps) { + if (cstIndexMaps != null) { for (CstIndexMap cstIndexMap : cstIndexMaps) { cstIndexMap.mergeConstantsIntoDexFile(this); } } + /** + * The following is ordered so that the prepare() calls which add items happen before the calls + * to the sections that get added to. + */ classDefs.prepare(); classData.prepare(); wordData.prepare(); @@ -569,6 +558,32 @@ if (cstIndexMaps != null) { // Write out all the sections. fileSize = offset; + } + + /** + * Returns the contents of this instance as a {@code .dex} file, + * in a {@link ByteArrayAnnotatedOutput} instance. + * + * @param annotate whether or not to keep annotations + * @param verbose if annotating, whether to be verbose + * @return {@code non-null;} a {@code .dex} file for this instance + */ + private ByteArrayAnnotatedOutput toDex0(boolean annotate, boolean verbose) { + classDefs.throwIfNotPrepared(); + classData.throwIfNotPrepared(); + wordData.throwIfNotPrepared(); + byteData.throwIfNotPrepared(); + methodIds.throwIfNotPrepared(); + fieldIds.throwIfNotPrepared(); + protoIds.throwIfNotPrepared(); + typeLists.throwIfNotPrepared(); + typeIds.throwIfNotPrepared(); + stringIds.throwIfNotPrepared(); + stringData.throwIfNotPrepared(); + header.throwIfNotPrepared(); + + // Write out all the sections. + int count = sections.length; byte[] barr = new byte[fileSize]; ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(barr); diff --git a/dx/src/com/android/jack/dx/dex/file/ImportedCodeItem.java b/dx/src/com/android/jack/dx/dex/file/ImportedCodeItem.java index 0bf8a04..09d368b 100644 --- a/dx/src/com/android/jack/dx/dex/file/ImportedCodeItem.java +++ b/dx/src/com/android/jack/dx/dex/file/ImportedCodeItem.java @@ -51,7 +51,7 @@ public final class ImportedCodeItem extends OffsettedItem implements * {@code non-null;} map index values used into code that references {@link Constant} from one * dex file into index values compliant with another dex file. */ - private CstIndexMap cstIndexMap; + private final CstIndexMap cstIndexMap; /** Array of remapped instructions */ private DecodedInstruction[] remappedInstructions; @@ -314,6 +314,10 @@ public final class ImportedCodeItem extends OffsettedItem implements throw new AssertionError("Not yet supported"); } + public CstIndexMap getCstIndexMap() { + return cstIndexMap; + } + private class GenericVisitor implements CodeReader.Visitor { @Override @@ -327,7 +331,7 @@ public final class ImportedCodeItem extends OffsettedItem implements */ private class StringRemapper implements CodeReader.Visitor { - private DexFile file; + private final DexFile file; public StringRemapper(DexFile dex) { this.file = dex; @@ -351,7 +355,7 @@ public final class ImportedCodeItem extends OffsettedItem implements */ private class FieldRemapper implements CodeReader.Visitor { - private DexFile file; + private final DexFile file; public FieldRemapper(DexFile dex) { this.file = dex; @@ -369,7 +373,7 @@ public final class ImportedCodeItem extends OffsettedItem implements */ private class TypeRemapper implements CodeReader.Visitor { - private DexFile file; + private final DexFile file; public TypeRemapper(DexFile dex) { this.file = dex; @@ -387,7 +391,7 @@ public final class ImportedCodeItem extends OffsettedItem implements */ private class MethodRemapper implements CodeReader.Visitor { - private DexFile file; + private final DexFile file; public MethodRemapper(DexFile dex) { this.file = dex; diff --git a/jack/src/com/android/jack/Jack.java b/jack/src/com/android/jack/Jack.java index 240c941..8ada4b7 100644 --- a/jack/src/com/android/jack/Jack.java +++ b/jack/src/com/android/jack/Jack.java @@ -30,6 +30,7 @@ import com.android.jack.backend.ResourceWriter; import com.android.jack.backend.dex.ClassAnnotationBuilder; import com.android.jack.backend.dex.ClassDefItemBuilder; import com.android.jack.backend.dex.DexFileBuilder; +import com.android.jack.backend.dex.DexFilePreparer; import com.android.jack.backend.dex.DexFileWriter; import com.android.jack.backend.dex.DexZipWriter; import com.android.jack.backend.dex.EncodedFieldBuilder; @@ -972,6 +973,8 @@ public abstract class Jack { packagePlan.append(PackageChecker.class); } } + + planBuilder.append(DexFilePreparer.class); } private static void fillJavaToJaycePlan( @@ -1365,6 +1368,8 @@ public abstract class Jack { if (hasSanityChecks) { planBuilder.append(ParentSetterChecker.class); } + + planBuilder.append(DexFilePreparer.class); } @Nonnull diff --git a/jack/src/com/android/jack/backend/dex/DexFileBuilder.java b/jack/src/com/android/jack/backend/dex/DexFileBuilder.java index 910f6c0..b331c9a 100644 --- a/jack/src/com/android/jack/backend/dex/DexFileBuilder.java +++ b/jack/src/com/android/jack/backend/dex/DexFileBuilder.java @@ -39,6 +39,8 @@ import javax.annotation.Nonnull; @Name("DexFileBuilder") @Transform(add = DexFileMarker.class) public class DexFileBuilder implements RunnableSchedulable<JSession> { + + @Nonnull private final DexFile dexFile = new DexFile(new DexOptions()); /** diff --git a/jack/src/com/android/jack/backend/dex/DexFilePreparer.java b/jack/src/com/android/jack/backend/dex/DexFilePreparer.java new file mode 100644 index 0000000..3709e9a --- /dev/null +++ b/jack/src/com/android/jack/backend/dex/DexFilePreparer.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.backend.dex; + +import com.android.jack.dx.dex.file.DexFile; +import com.android.jack.ir.ast.JSession; +import com.android.jack.scheduling.marker.DexCodeMarker; +import com.android.jack.scheduling.marker.DexFileMarker; +import com.android.sched.item.Description; +import com.android.sched.item.Name; +import com.android.sched.schedulable.Constraint; +import com.android.sched.schedulable.RunnableSchedulable; +import com.android.sched.schedulable.Transform; + +import javax.annotation.Nonnull; + +/** + * Prepare dex file to be written later. + */ +@Description("Prepare dex file to be written later") +@Name("DexFilePreparer") +@Transform(add = {DexFileMarker.Prepared.class}) +@Constraint(need = {DexCodeMarker.class, DexFileMarker.Complete.class}) +public class DexFilePreparer implements RunnableSchedulable<JSession> { + + @Override + public void run(@Nonnull JSession session) throws Exception { + DexFileMarker dexFileMarker = session.getMarker(DexFileMarker.class); + assert dexFileMarker != null; + DexFile dexFile = dexFileMarker.getDexFile(); + assert dexFile != null; + dexFile.prepare(null); + } +}
\ No newline at end of file diff --git a/jack/src/com/android/jack/backend/dex/DexFileWriter.java b/jack/src/com/android/jack/backend/dex/DexFileWriter.java index d158a34..199a3f8 100644 --- a/jack/src/com/android/jack/backend/dex/DexFileWriter.java +++ b/jack/src/com/android/jack/backend/dex/DexFileWriter.java @@ -42,7 +42,7 @@ import javax.annotation.Nonnull; */ @Description("Write dex into a file") @Name("DexFileWriter") -@Constraint(need = {DexFileMarker.Complete.class}) +@Constraint(need = {DexFileMarker.Prepared.class}) @Produce(DexFileProduct.class) @Support(DexNonZipOutput.class) public class DexFileWriter implements RunnableSchedulable<JSession> { diff --git a/jack/src/com/android/jack/backend/dex/DexZipWriter.java b/jack/src/com/android/jack/backend/dex/DexZipWriter.java index c692c90..99d0e04 100644 --- a/jack/src/com/android/jack/backend/dex/DexZipWriter.java +++ b/jack/src/com/android/jack/backend/dex/DexZipWriter.java @@ -46,7 +46,7 @@ import javax.annotation.Nonnull; */ @Description("Write dex into a zip") @Name("DexZipWriter") -@Constraint(need = {DexFileMarker.Complete.class}) +@Constraint(need = {DexFileMarker.Prepared.class}) @Produce(DexFileProduct.class) @Support(DexZipOutput.class) public class DexZipWriter extends DexFileWriter { diff --git a/jack/src/com/android/jack/scheduling/marker/DexFileMarker.java b/jack/src/com/android/jack/scheduling/marker/DexFileMarker.java index 5a621b9..f32ef18 100644 --- a/jack/src/com/android/jack/scheduling/marker/DexFileMarker.java +++ b/jack/src/com/android/jack/scheduling/marker/DexFileMarker.java @@ -92,6 +92,15 @@ public final class DexFileMarker implements Marker { public static final class ClassAnnotation implements Tag { } + /** + * This tag means that the {@code DexFile}s contained into the {@Code DexFileMarker} are prepared + * and ready to be written in an {@code OutputStream}. + */ + @Description("The DexFile contained into the DexFileMarker is prepared.") + @Name("DexFileMarker.Prepared") + public static final class Prepared implements Tag { + } + public DexFileMarker(@Nonnull DexFile dexFile) { this.dexFile = dexFile; } |