Skip to content

Commit

Permalink
Add support for record attributes to ijar
Browse files Browse the repository at this point in the history
  • Loading branch information
cushon authored and copybara-github committed Oct 4, 2021
1 parent e83858b commit 26229fe
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 19 deletions.
90 changes: 71 additions & 19 deletions third_party/ijar/classfile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,25 @@ struct KeepForCompileAttribute : Attribute {
void Write(u1 *&p) { WriteProlog(p, 0); }
};

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

void WriteAttrs(u1 *&p);
void ReadAttrs(const u1 *&p);

virtual ~HasAttrs() {
for (const auto *attribute : attributes) {
delete attribute;
}
}

void ExtractClassNames() {
for (auto *attribute : attributes) {
attribute->ExtractClassNames();
}
}
};

// See sec.4.7.5 of JVM spec.
struct ExceptionsAttribute : Attribute {

Expand Down Expand Up @@ -1234,6 +1253,55 @@ struct NestMembersAttribute : Attribute {
std::vector<Constant *> classes_;
};

// See JVMS §4.7.30
struct RecordAttribute : Attribute {
static RecordAttribute *Read(const u1 *&p, Constant *attribute_name,
u4 attribute_length) {
auto attr = new RecordAttribute;
attr->attribute_name_ = attribute_name;
attr->attribute_length_ = attribute_length;
u2 components_length = get_u2be(p);
for (int i = 0; i < components_length; ++i) {
attr->components_.push_back(RecordComponentInfo::Read(p));
}
return attr;
}

void Write(u1 *&p) {
u1 *tmp = new u1[attribute_length_];
u1 *start = tmp;
put_u2be(tmp, components_.size());
for (size_t i = 0; i < components_.size(); ++i) {
components_[i]->Write(tmp);
}
u2 length = tmp - start;
WriteProlog(p, length);
memcpy(p, start, length);
p += length;
}

struct RecordComponentInfo : HasAttrs {
void Write(u1 *&p) {
put_u2be(p, name_->slot());
put_u2be(p, descriptor_->slot());
WriteAttrs(p);
}
static RecordComponentInfo *Read(const u1 *&p) {
RecordComponentInfo *value = new RecordComponentInfo;
value->name_ = constant(get_u2be(p));
value->descriptor_ = constant(get_u2be(p));
value->ReadAttrs(p);
return value;
}

Constant *name_;
Constant *descriptor_;
};

u4 attribute_length_;
std::vector<RecordComponentInfo *> components_;
};

struct GeneralAttribute : Attribute {
static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name,
u4 attribute_length) {
Expand All @@ -1260,25 +1328,6 @@ struct GeneralAttribute : Attribute {
* *
**********************************************************************/

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

void WriteAttrs(u1 *&p);
void ReadAttrs(const u1 *&p);

virtual ~HasAttrs() {
for (const auto *attribute : attributes) {
delete attribute;
}
}

void ExtractClassNames() {
for (auto *attribute : attributes) {
attribute->ExtractClassNames();
}
}
};

// A field or method.
// See sec.4.5 and 4.6 of JVM spec.
struct Member : HasAttrs {
Expand Down Expand Up @@ -1451,6 +1500,9 @@ void HasAttrs::ReadAttrs(const u1 *&p) {
} else if (attr_name == "NestMembers") {
attributes.push_back(
NestMembersAttribute::Read(p, attribute_name, attribute_length));
} else if (attr_name == "Record") {
attributes.push_back(
RecordAttribute::Read(p, attribute_name, attribute_length));
} else if (attr_name == "com.google.devtools.ijar.KeepForCompile") {
auto attr = new KeepForCompileAttribute;
attr->attribute_name_ = attribute_name;
Expand Down
1 change: 1 addition & 0 deletions third_party/ijar/test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ sh_test(
# This is a precompiled .jar file because it needs to be compiled with JDK 11.
# TODO(cushon): build from source once we have a JDK 11
"nestmates/nestmates.jar",
"records/records.jar",
":source_debug_extension.jar",
":keep_for_compile_lib.jar",
":largest_regular.jar",
Expand Down
13 changes: 13 additions & 0 deletions third_party/ijar/test/ijar_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ METHODPARAM_JAR=$IJAR_SRCDIR/test/libmethodparameters.jar
METHODPARAM_IJAR=$TEST_TMPDIR/methodparameters_interface.jar
NESTMATES_JAR=$IJAR_SRCDIR/test/nestmates/nestmates.jar
NESTMATES_IJAR=$TEST_TMPDIR/nestmates_interface.jar
RECORDS_JAR=$IJAR_SRCDIR/test/records/records.jar
RECORDS_IJAR=$TEST_TMPDIR/records_interface.jar
SOURCEDEBUGEXT_JAR=$IJAR_SRCDIR/test/source_debug_extension.jar
SOURCEDEBUGEXT_IJAR=$TEST_TMPDIR/source_debug_extension.jar
CENTRAL_DIR_LARGEST_REGULAR=$IJAR_SRCDIR/test/largest_regular.jar
Expand Down Expand Up @@ -532,6 +534,17 @@ function test_nestmates_attribute() {
expect_log "NestHost" "NestHost not preserved!"
}

function test_records_attribute() {
ls $IJAR $RECORDS_JAR

# Check that Java 16 Records attributes are preserved
$IJAR $RECORDS_JAR $RECORDS_IJAR || fail "ijar failed"

$JAVAP -classpath $RECORDS_IJAR -v RecordTest >& $TEST_log \
|| fail "javap failed"
expect_log "Record" "Records not preserved!"
}

function test_source_debug_extension_attribute() {
# Check that SourceDebugExtension attributes are dropped without a warning
$IJAR $SOURCEDEBUGEXT_JAR $SOURCEDEBUGEXT_IJAR >& $TEST_log || fail "ijar failed"
Expand Down
19 changes: 19 additions & 0 deletions third_party/ijar/test/records/RecordTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2021 The Bazel Authors. All rights reserved.
//
// 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.
//
import java.util.List;
import java.util.Map;

/** A class that results in record attributes in Java 16. */
public record RecordTest(List<String> foo, Map<String, Integer> bar) {}
Binary file added third_party/ijar/test/records/records.jar
Binary file not shown.

0 comments on commit 26229fe

Please sign in to comment.