Skip to content

Commit

Permalink
ijar Kotlin handling
Browse files Browse the repository at this point in the history
Remove unused handling of the `KeepForCompile` attribute, and instead check for
the `@kotlin.Metadata` annotation and preserve all Kotlin classes.

bazelbuild#4549

RELNOTES: Make ijar / java_import preserve classes with `@kotlin.Metadata` annotations
PiperOrigin-RevId: 441243993
  • Loading branch information
cushon authored and fmeum committed Apr 27, 2022
1 parent b840615 commit 1ef134a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 47 deletions.
40 changes: 14 additions & 26 deletions third_party/ijar/classfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ struct Attribute {
virtual ~Attribute() {}
virtual void Write(u1 *&p) = 0;
virtual void ExtractClassNames() {}
virtual bool KeepForCompile() const { return false; }

void WriteProlog(u1 *&p, u2 length) {
put_u2be(p, attribute_name_->slot());
Expand All @@ -434,10 +435,6 @@ struct Attribute {
Constant *attribute_name_;
};

struct KeepForCompileAttribute : Attribute {
void Write(u1 *&p) { WriteProlog(p, 0); }
};

struct HasAttrs {
std::vector<Attribute*> attributes;

Expand Down Expand Up @@ -1080,6 +1077,15 @@ struct AnnotationsAttribute : Attribute {
}
}

virtual bool KeepForCompile() const {
for (auto *annotation : annotations_) {
if (annotation->type_->Display() == "Lkotlin/Metadata;") {
return true;
}
}
return false;
}

void Write(u1 *&p) {
WriteProlog(p, -1);
u1 *payload_start = p - 4;
Expand Down Expand Up @@ -1410,7 +1416,7 @@ struct ClassFile : HasAttrs {

bool ReadConstantPool(const u1 *&p);

bool IsExplicitlyKept();
bool KeepForCompile();

bool IsLocalOrAnonymous();

Expand Down Expand Up @@ -1530,10 +1536,6 @@ void HasAttrs::ReadAttrs(const u1 *&p) {
} else if (attr_name == "PermittedSubclasses") {
attributes.push_back(
PermittedSubclassesAttribute::Read(p, attribute_name));
} else if (attr_name == "com.google.devtools.ijar.KeepForCompile") {
auto attr = new KeepForCompileAttribute;
attr->attribute_name_ = attribute_name;
attributes.push_back(attr);
} else {
// Skip over unknown attributes with a warning. The JVM spec
// says this is ok, so long as we handle the mandatory attributes.
Expand Down Expand Up @@ -1677,23 +1679,17 @@ bool ClassFile::IsLocalOrAnonymous() {

static bool HasKeepForCompile(const std::vector<Attribute *> attributes) {
for (const Attribute *attribute : attributes) {
if (attribute->attribute_name_->Display() ==
"com.google.devtools.ijar.KeepForCompile") {
if (attribute->KeepForCompile()) {
return true;
}
}
return false;
}

bool ClassFile::IsExplicitlyKept() {
bool ClassFile::KeepForCompile() {
if (HasKeepForCompile(attributes)) {
return true;
}
for (const Member *method : methods) {
if (HasKeepForCompile(method->attributes)) {
return true;
}
}
return false;
}

Expand Down Expand Up @@ -1744,12 +1740,6 @@ static ClassFile *ReadClass(const void *classdata, size_t length) {
for (int ii = 0; ii < methods_count; ++ii) {
Member *method = Member::Read(p);

if (HasKeepForCompile(method->attributes)) {
// Always keep methods marked as such
clazz->methods.push_back(method);
continue;
}

// drop class initializers
if (method->name->Display() == "<clinit>") continue;

Expand Down Expand Up @@ -1950,10 +1940,8 @@ void ClassFile::WriteClass(u1 *&p) {
bool StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) {
ClassFile *clazz = ReadClass(classdata_in, in_length);
bool keep = true;
if (clazz == NULL || clazz->IsExplicitlyKept()) {
if (clazz == NULL || clazz->KeepForCompile()) {
// Class is invalid or kept. Simply copy it to the output and call it a day.
// TODO: If kept, only emit methods marked with KeepForCompile attribute,
// as opposed to the entire type.
put_n(classdata_out, classdata_in, in_length);
} else if (clazz->IsLocalOrAnonymous()) {
keep = false;
Expand Down
27 changes: 11 additions & 16 deletions third_party/ijar/test/GenKeepForCompile.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ByteVector;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
* GenKeepForCompile creates a jarfile containing a class definition that has the KeepForCOmpile
* attribute.
* GenKeepForCompile creates a jarfile containing a class definition that has the kotlin.Metadata
* annotation.
*/
public class GenKeepForCompile implements Opcodes {

Expand Down Expand Up @@ -62,7 +60,15 @@ public static byte[] dump() throws Exception {
AnnotationVisitor annotationVisitor1 = annotationVisitor0.visitArray("d1");
annotationVisitor1.visit(
null,
"\u0000\u0014\n\u0000\n\u0002\u0010\u000e\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0002\u0010\u0008\u001a!\u0010\u0000\u001a\u00020\u0001*\u00020\u00022\u0012\u0010\u0003\u001a\u000e\u0012\u0004\u0012\u00020\u0005\u0012\u0004\u0012\u00020\u00010\u0004H\u0086\u0008");
"\u0000\u0014\n"
+ "\u0000\n"
+ "\u0002\u0010\u000e\n"
+ "\u0002\u0018\u0002\n"
+ "\u0000\n"
+ "\u0002\u0018\u0002\n"
+ "\u0002\u0010\u0008\u001a!\u0010\u0000\u001a\u00020\u0001*\u00020\u00022\u0012"
+ "\u0010\u0003\u001a\u000e\u0012\u0004\u0012\u00020\u0005\u0012\u0004\u0012\u00020"
+ "\u00010\u0004H\u0086\u0008");
annotationVisitor1.visitEnd();
}
{
Expand Down Expand Up @@ -103,17 +109,6 @@ public static byte[] dump() throws Exception {
methodVisitor.visitParameterAnnotation(1, "Lorg/jetbrains/annotations/NotNull;", false);
annotationVisitor0.visitEnd();
}
// ATTRIBUTE com.google.devtools.ijar.KeepForCompile
// ASM-ifier doesn't emit attributes it does not know about :( - emitting by hand here.
methodVisitor.visitAttribute(
new Attribute("com.google.devtools.ijar.KeepForCompile") {
@Override
public ByteVector write(
ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
// nothing to write, just get the attribute's name in the file.
return new ByteVector();
}
});

methodVisitor.visitCode();
Label label0 = new Label();
Expand Down
5 changes: 0 additions & 5 deletions third_party/ijar/test/ijar_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -576,11 +576,6 @@ function test_keep_for_compile() {
grep -c "// Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull" ||
true)
check_eq 2 $lines "Output jar should have kept method body"
attr=$($JAVAP -classpath $TEST_TMPDIR/keep.jar -v -p \
functions.car.CarInlineUtilsKt |
strings |
grep -c "com.google.devtools.ijar.KeepForCompile" || true)
check_eq 2 $attr "Output jar should have kept KeepForCompile attribute."
}

function test_central_dir_largest_regular() {
Expand Down

0 comments on commit 1ef134a

Please sign in to comment.