Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Unified Diff: third_party/ijar/classfile.cc

Issue 1901473003: ๐Ÿž Update version of third_party/ijar (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/ijar/README.chromium ('k') | third_party/ijar/common.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/ijar/classfile.cc
diff --git a/third_party/ijar/classfile.cc b/third_party/ijar/classfile.cc
index 39d24f9dd49686e412ae384f61550b949be6b7b4..9d48429e0cd68aaf08cb25d2f926498bc234e094 100644
--- a/third_party/ijar/classfile.cc
+++ b/third_party/ijar/classfile.cc
@@ -1,6 +1,4 @@
-// Copyright 2001,2007 Alan Donovan. All rights reserved.
-//
-// Author: Alan Donovan <adonovan@google.com>
+// Copyright 2015 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.
@@ -34,11 +32,25 @@
#include <stdlib.h>
#include <string.h>
+#include <set>
+#include <sstream>
#include <string>
#include <vector>
#include "third_party/ijar/common.h"
+namespace {
+// Converts a value to string.
+// Workaround for mingw where std::to_string is not implemented.
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52015.
+template <typename T>
+std::string ToString(const T& value) {
+ std::ostringstream oss;
+ oss << value;
+ return oss.str();
+}
+} // namespace
+
namespace devtools_ijar {
// See Table 4.3 in JVM Spec.
@@ -60,17 +72,19 @@ enum CONSTANT {
};
// See Tables 4.1, 4.4, 4.5 in JVM Spec.
-enum ACCESS {
- ACC_PUBLIC = 0x0001,
- ACC_PRIVATE = 0x0002,
- ACC_PROTECTED = 0x0004,
- ACC_STATIC = 0x0008,
- ACC_FINAL = 0x0010,
- ACC_SYNCHRONIZED = 0x0020,
- ACC_VOLATILE = 0x0040,
- ACC_TRANSIENT = 0x0080,
- ACC_INTERFACE = 0x0200,
- ACC_ABSTRACT = 0x0400
+enum ACCESS {
+ ACC_PUBLIC = 0x0001,
+ ACC_PRIVATE = 0x0002,
+ ACC_PROTECTED = 0x0004,
+ ACC_STATIC = 0x0008,
+ ACC_FINAL = 0x0010,
+ ACC_SYNCHRONIZED = 0x0020,
+ ACC_BRIDGE = 0x0040,
+ ACC_VOLATILE = 0x0040,
+ ACC_TRANSIENT = 0x0080,
+ ACC_INTERFACE = 0x0200,
+ ACC_ABSTRACT = 0x0400,
+ ACC_SYNTHETIC = 0x1000
};
// See Table 4.7.20-A in Java 8 JVM Spec.
@@ -99,6 +113,8 @@ struct Constant;
// TODO(adonovan) these globals are unfortunate
static std::vector<Constant*> const_pool_in; // input constant pool
static std::vector<Constant*> const_pool_out; // output constant_pool
+static std::set<std::string> used_class_names;
+static Constant * class_name;
// Returns the Constant object, given an index into the input constant pool.
// Note: constant(0) == NULL; this invariant is exploited by the
@@ -138,6 +154,10 @@ struct Constant {
// calling slot() on them in turn.
virtual void Keep() {}
+ bool Kept() {
+ return slot_ != 0;
+ }
+
// Returns the index of this constant in the output class's constant
// pool, assigning a slot if not already done.
u2 slot() {
@@ -163,6 +183,13 @@ struct Constant {
u1 tag_;
};
+// Extracts class names from a signature and puts them into the global
+// variable used_class_names.
+//
+// desc: the descriptor class names should be extracted from.
+// p: the position where the extraction should tart.
+void ExtractClassNames(const std::string& desc, size_t* p);
+
// See sec.4.4.1 of JVM spec.
struct Constant_Class : Constant
{
@@ -335,7 +362,7 @@ struct Constant_MethodHandle : Constant
}
std::string Display() {
- return "Constant_MethodHandle::" + std::to_string(reference_kind_) + "::"
+ return "Constant_MethodHandle::" + ToString(reference_kind_) + "::"
+ constant(reference_index_)->Display();
}
@@ -378,7 +405,7 @@ struct Constant_InvokeDynamic : Constant
std::string Display() {
return "Constant_InvokeDynamic::"
- + std::to_string(bootstrap_method_attr_index_) + "::"
+ + ToString(bootstrap_method_attr_index_) + "::"
+ constant(name_and_type_index_)->Display();
}
@@ -397,6 +424,7 @@ struct Attribute {
virtual ~Attribute() {}
virtual void Write(u1 *&p) = 0;
+ virtual void ExtractClassNames() {}
void WriteProlog(u1 *&p, u2 length) {
put_u2be(p, attribute_name_->slot());
@@ -464,10 +492,51 @@ struct InnerClassesAttribute : Attribute {
}
void Write(u1 *&p) {
- WriteProlog(p, 2 + entries_.size() * 8);
- put_u2be(p, entries_.size());
- for (size_t ii = 0; ii < entries_.size(); ++ii) {
- Entry *entry = entries_[ii];
+ std::set<int> kept_entries;
+ // We keep an entry if the constant referring to the inner class is already
+ // kept. Then we mark its outer class and its class name as kept, too, then
+ // iterate until a fixed point is reached.
+ int entry_count;
+ int iteration = 0;
+
+ do {
+ entry_count = kept_entries.size();
+ for (int i_entry = 0; i_entry < static_cast<int>(entries_.size());
+ ++i_entry) {
+ Entry* entry = entries_[i_entry];
+ if (entry->inner_class_info->Kept() ||
+ used_class_names.find(entry->inner_class_info->Display()) !=
+ used_class_names.end() ||
+ entry->outer_class_info == class_name) {
+ if (entry->inner_name == NULL) {
+ // JVMS 4.7.6: inner_name_index is zero iff the class is anonymous
+ continue;
+ }
+
+ kept_entries.insert(i_entry);
+
+ // JVMS 4.7.6: outer_class_info_index is zero for top-level classes
+ if (entry->outer_class_info != NULL) {
+ entry->outer_class_info->slot();
+ }
+
+ entry->inner_name->slot();
+ }
+ }
+ iteration += 1;
+ } while (entry_count != static_cast<int>(kept_entries.size()));
+
+ if (kept_entries.size() == 0) {
+ return;
+ }
+
+ WriteProlog(p, 2 + kept_entries.size() * 8);
+ put_u2be(p, kept_entries.size());
+
+ for (std::set<int>::iterator it = kept_entries.begin();
+ it != kept_entries.end();
+ ++it) {
+ Entry *entry = entries_[*it];
put_u2be(p, entry->inner_class_info == NULL
? 0
: entry->inner_class_info->slot());
@@ -516,6 +585,7 @@ struct EnclosingMethodAttribute : Attribute {
struct ElementValue {
virtual ~ElementValue() {}
virtual void Write(u1 *&p) = 0;
+ virtual void ExtractClassNames() {}
static ElementValue* Read(const u1 *&p);
u1 tag_;
u4 length_;
@@ -555,6 +625,12 @@ struct ClassTypeElementValue : ElementValue {
put_u1(p, tag_);
put_u2be(p, class_info_->slot());
}
+
+ virtual void ExtractClassNames() {
+ size_t idx = 0;
+ devtools_ijar::ExtractClassNames(class_info_->Display(), &idx);
+ }
+
static ClassTypeElementValue *Read(const u1 *&p) {
ClassTypeElementValue *value = new ClassTypeElementValue;
value->class_info_ = constant(get_u2be(p));
@@ -565,16 +641,22 @@ struct ClassTypeElementValue : ElementValue {
struct ArrayTypeElementValue : ElementValue {
virtual ~ArrayTypeElementValue() {
- for (size_t i = 0; i < values_.size(); i++) {
- delete values_[i];
+ for (const auto *value : values_) {
+ delete value;
+ }
+ }
+
+ virtual void ExtractClassNames() {
+ for (auto *value : values_) {
+ value->ExtractClassNames();
}
}
void Write(u1 *&p) {
put_u1(p, tag_);
put_u2be(p, values_.size());
- for (size_t ii = 0; ii < values_.size(); ++ii) {
- values_[ii]->Write(p);
+ for (auto *value : values_) {
+ value->Write(p);
}
}
static ArrayTypeElementValue *Read(const u1 *&p) {
@@ -597,6 +679,12 @@ struct Annotation {
}
}
+ void ExtractClassNames() {
+ for (size_t i = 0; i < element_value_pairs_.size(); i++) {
+ element_value_pairs_[i]->element_value_->ExtractClassNames();
+ }
+ }
+
void Write(u1 *&p) {
put_u2be(p, type_->slot());
put_u2be(p, element_value_pairs_.size());
@@ -662,6 +750,10 @@ struct TypeAnnotation {
delete annotation_;
}
+ void ExtractClassNames() {
+ annotation_->ExtractClassNames();
+ }
+
void Write(u1 *&p) {
put_u1(p, target_type_);
target_info_->Write(p);
@@ -873,6 +965,10 @@ struct AnnotationDefaultAttribute : Attribute {
default_value_->Write(p);
}
+ virtual void ExtractClassNames() {
+ default_value_->ExtractClassNames();
+ }
+
ElementValue *default_value_;
};
@@ -913,6 +1009,11 @@ struct SignatureAttribute : Attribute {
put_u2be(p, signature_->slot());
}
+ virtual void ExtractClassNames() {
+ size_t signature_idx = 0;
+ devtools_ijar::ExtractClassNames(signature_->Display(), &signature_idx);
+ }
+
Constant *signature_;
};
@@ -954,12 +1055,18 @@ struct AnnotationsAttribute : Attribute {
return attr;
}
+ virtual void ExtractClassNames() {
+ for (auto *annotation : annotations_) {
+ annotation->ExtractClassNames();
+ }
+ }
+
void Write(u1 *&p) {
WriteProlog(p, -1);
u1 *payload_start = p - 4;
put_u2be(p, annotations_.size());
- for (size_t ii = 0; ii < annotations_.size(); ++ii) {
- annotations_[ii]->Write(p);
+ for (auto *annotation : annotations_) {
+ annotation->Write(p);
}
put_u4be(payload_start, p - 4 - payload_start); // backpatch length
}
@@ -990,6 +1097,15 @@ struct ParameterAnnotationsAttribute : Attribute {
return attr;
}
+ virtual void ExtractClassNames() {
+ for (size_t i = 0; i < parameter_annotations_.size(); i++) {
+ const std::vector<Annotation*>& annotations = parameter_annotations_[i];
+ for (size_t j = 0; j < annotations.size(); j++) {
+ annotations[j]->ExtractClassNames();
+ }
+ }
+ }
+
void Write(u1 *&p) {
WriteProlog(p, -1);
u1 *payload_start = p - 4;
@@ -1022,6 +1138,12 @@ struct TypeAnnotationsAttribute : Attribute {
return attr;
}
+ virtual void ExtractClassNames() {
+ for (auto *type_annotation : type_annotations_) {
+ type_annotation->ExtractClassNames();
+ }
+ }
+
void Write(u1 *&p) {
WriteProlog(p, -1);
u1 *payload_start = p - 4;
@@ -1035,6 +1157,41 @@ struct TypeAnnotationsAttribute : Attribute {
std::vector<TypeAnnotation*> type_annotations_;
};
+// See JVMS ยง4.7.24
+struct MethodParametersAttribute : Attribute {
+ static MethodParametersAttribute *Read(const u1 *&p, Constant *attribute_name,
+ u4 attribute_length) {
+ auto attr = new MethodParametersAttribute;
+ attr->attribute_name_ = attribute_name;
+ u1 parameters_count = get_u1(p);
+ for (int ii = 0; ii < parameters_count; ++ii) {
+ MethodParameter* parameter = new MethodParameter;
+ parameter->name_ = constant(get_u2be(p));
+ parameter->access_flags_ = get_u2be(p);
+ attr->parameters_.push_back(parameter);
+ }
+ return attr;
+ }
+
+ void Write(u1 *&p) {
+ WriteProlog(p, -1);
+ u1 *payload_start = p - 4;
+ put_u1(p, parameters_.size());
+ for (MethodParameter* parameter : parameters_) {
+ put_u2be(p, parameter->name_->slot());
+ put_u2be(p, parameter->access_flags_);
+ }
+ put_u4be(payload_start, p - 4 - payload_start); // backpatch length
+ }
+
+ struct MethodParameter {
+ Constant *name_;
+ u2 access_flags_;
+ };
+
+ std::vector<MethodParameter*> parameters_;
+};
+
struct GeneralAttribute : Attribute {
static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name,
u4 attribute_length) {
@@ -1068,8 +1225,14 @@ struct HasAttrs {
void ReadAttrs(const u1 *&p);
virtual ~HasAttrs() {
- for (size_t i = 0; i < attributes.size(); i++) {
- delete attributes[i];
+ for (const auto *attribute : attributes) {
+ delete attribute;
+ }
+ }
+
+ void ExtractClassNames() {
+ for (auto *attribute : attributes) {
+ attribute->ExtractClassNames();
}
}
};
@@ -1132,7 +1295,7 @@ struct ClassFile : HasAttrs {
bool ReadConstantPool(const u1 *&p);
- void StripIfAnonymous();
+ bool IsLocalOrAnonymous();
void WriteHeader(u1 *&p) {
put_u4be(p, magic);
@@ -1163,6 +1326,23 @@ struct ClassFile : HasAttrs {
for (size_t ii = 0; ii < methods.size(); ++ii) {
methods[ii]->Write(p);
}
+
+ Attribute* inner_classes = NULL;
+
+ // Make the inner classes attribute the last, so that it can know which
+ // constants were needed
+ for (size_t ii = 0; ii < attributes.size(); ii++) {
+ if (attributes[ii]->attribute_name_->Display() == "InnerClasses") {
+ inner_classes = attributes[ii];
+ attributes.erase(attributes.begin() + ii);
+ break;
+ }
+ }
+
+ if (inner_classes != NULL) {
+ attributes.push_back(inner_classes);
+ }
+
WriteAttrs(p);
}
@@ -1176,12 +1356,14 @@ void HasAttrs::ReadAttrs(const u1 *&p) {
std::string attr_name = attribute_name->Display();
if (attr_name == "SourceFile" ||
+ attr_name == "StackMapTable" ||
attr_name == "LineNumberTable" ||
attr_name == "LocalVariableTable" ||
attr_name == "LocalVariableTypeTable" ||
attr_name == "Code" ||
attr_name == "Synthetic" ||
- attr_name == "BootstrapMethods") {
+ attr_name == "BootstrapMethods" ||
+ attr_name == "SourceDebugExtension") {
p += attribute_length; // drop these attributes
} else if (attr_name == "Exceptions") {
attributes.push_back(ExceptionsAttribute::Read(p, attribute_name));
@@ -1214,10 +1396,11 @@ void HasAttrs::ReadAttrs(const u1 *&p) {
attribute_length));
} else if (attr_name == "RuntimeVisibleTypeAnnotations" ||
attr_name == "RuntimeInvisibleTypeAnnotations") {
- // JSR 308: annotations on types. JDK 7 has no use for these yet, but the
- // Checkers Framework relies on them.
attributes.push_back(TypeAnnotationsAttribute::Read(p, attribute_name,
attribute_length));
+ } else if (attr_name == "MethodParameters") {
+ attributes.push_back(
+ MethodParametersAttribute::Read(p, attribute_name, attribute_length));
} else {
// Skip over unknown attributes with a warning. The JVM spec
// says this is ok, so long as we handle the mandatory attributes.
@@ -1229,10 +1412,19 @@ void HasAttrs::ReadAttrs(const u1 *&p) {
}
void HasAttrs::WriteAttrs(u1 *&p) {
- put_u2be(p, attributes.size());
+ u1* p_size = p;
+
+ put_u2be(p, 0);
+ int n_written_attrs = 0;
for (size_t ii = 0; ii < attributes.size(); ii++) {
+ u1* before = p;
attributes[ii]->Write(p);
+ if (p != before) {
+ n_written_attrs++;
+ }
}
+
+ put_u2be(p_size, n_written_attrs);
}
// See sec.4.4 of JVM spec.
@@ -1335,53 +1527,15 @@ bool ClassFile::ReadConstantPool(const u1 *&p) {
return true;
}
-// Anonymous inner classes are stripped to opaque classes that only extend
-// Object. None of their methods or fields are accessible anyway.
-void ClassFile::StripIfAnonymous() {
- int enclosing_index = -1;
- int inner_classes_index = -1;
-
- for (size_t ii = 0; ii < attributes.size(); ++ii) {
- if (attributes[ii]->attribute_name_->Display() == "EnclosingMethod") {
- enclosing_index = ii;
- } else if (attributes[ii]->attribute_name_->Display() == "InnerClasses") {
- inner_classes_index = ii;
- }
- }
-
- // Presence of an EnclosingMethod attribute indicates a local or anonymous
- // class, which can be stripped.
- if (enclosing_index > -1) {
- // Clear the signature to only extend java.lang.Object.
- super_class = NULL;
- interfaces.clear();
-
- // Clear away all fields (implementation details).
- for (size_t ii = 0; ii < fields.size(); ++ii) {
- delete fields[ii];
- }
- fields.clear();
-
- // Clear away all methods (implementation details).
- for (size_t ii = 0; ii < methods.size(); ++ii) {
- delete methods[ii];
- }
- methods.clear();
-
- // Only preserve the InnerClasses attribute to comply with the spec.
- Attribute *attr = NULL;
- for (size_t ii = 0; ii < attributes.size(); ++ii) {
- if (static_cast<int>(ii) != inner_classes_index) {
- delete attributes[ii];
- } else {
- attr = attributes[ii];
- }
- }
- attributes.clear();
- if (attr != NULL) {
- attributes.push_back(attr);
+bool ClassFile::IsLocalOrAnonymous() {
+ for (const Attribute *attribute : attributes) {
+ if (attribute->attribute_name_->Display() == "EnclosingMethod") {
+ // JVMS 4.7.6: a class must has EnclosingMethod attribute iff it
+ // represents a local class or an anonymous class
+ return true;
}
}
+ return false;
}
static ClassFile *ReadClass(const void *classdata, size_t length) {
@@ -1406,6 +1560,8 @@ static ClassFile *ReadClass(const void *classdata, size_t length) {
clazz->access_flags = get_u2be(p);
clazz->this_class = constant(get_u2be(p));
+ class_name = clazz->this_class;
+
u2 super_class_id = get_u2be(p);
clazz->super_class = super_class_id == 0 ? NULL : constant(super_class_id);
@@ -1418,9 +1574,11 @@ static ClassFile *ReadClass(const void *classdata, size_t length) {
for (int ii = 0; ii < fields_count; ++ii) {
Member *field = Member::Read(p);
- if (!(field->access_flags & ACC_PRIVATE)) { // drop private fields
- clazz->fields.push_back(field);
+ if ((field->access_flags & ACC_PRIVATE) == ACC_PRIVATE) {
+ // drop private fields
+ continue;
}
+ clazz->fields.push_back(field);
}
u2 methods_count = get_u2be(p);
@@ -1430,18 +1588,188 @@ static ClassFile *ReadClass(const void *classdata, size_t length) {
// drop class initializers
if (method->name->Display() == "<clinit>") continue;
- if (!(method->access_flags & ACC_PRIVATE)) { // drop private methods
- clazz->methods.push_back(method);
+ if ((method->access_flags & ACC_PRIVATE) == ACC_PRIVATE) {
+ // drop private methods
+ continue;
}
+ if ((method->access_flags & (ACC_SYNTHETIC | ACC_BRIDGE)) ==
+ ACC_SYNTHETIC) {
+ // drop non-bridge synthetic methods, e.g. package-private synthetic
+ // constructors used to instantiate private nested classes within their
+ // declaring compilation unit
+ continue;
+ }
+ clazz->methods.push_back(method);
}
clazz->ReadAttrs(p);
- clazz->StripIfAnonymous();
return clazz;
}
+// In theory, '/' is also reserved, but it's okay if we just parse package
+// identifiers as part of the class name. Note that signatures are UTF-8, but
+// this works just as well as in plain ASCII.
+static const char *SIGNATURE_NON_IDENTIFIER_CHARS = ".;[<>:";
+
+void Expect(const std::string& desc, size_t* p, char expected) {
+ if (desc[*p] != expected) {
+ fprintf(stderr, "Expected '%c' in '%s' at %zd in signature\n",
+ expected, desc.substr(*p).c_str(), *p);
+ exit(1);
+ }
+
+ *p += 1;
+}
+
+// These functions form a crude recursive descent parser for descriptors and
+// signatures in class files (see JVM spec 4.3).
+//
+// This parser is a bit more liberal than the spec, but this should be fine,
+// because it accepts all valid class files and croaks only on invalid ones.
+void ParseFromClassTypeSignature(const std::string& desc, size_t* p);
+void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p);
+void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p);
+void ParseIdentifier(const std::string& desc, size_t* p);
+void ParseTypeArgumentsOpt(const std::string& desc, size_t* p);
+void ParseMethodDescriptor(const std::string& desc, size_t* p);
+
+void ParseClassTypeSignature(const std::string& desc, size_t* p) {
+ Expect(desc, p, 'L');
+ ParseSimpleClassTypeSignature(desc, p);
+ ParseClassTypeSignatureSuffix(desc, p);
+ Expect(desc, p, ';');
+}
+
+void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p) {
+ ParseIdentifier(desc, p);
+ ParseTypeArgumentsOpt(desc, p);
+}
+
+void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p) {
+ while (desc[*p] == '.') {
+ *p += 1;
+ ParseSimpleClassTypeSignature(desc, p);
+ }
+}
+
+void ParseIdentifier(const std::string& desc, size_t* p) {
+ size_t next = desc.find_first_of(SIGNATURE_NON_IDENTIFIER_CHARS, *p);
+ std::string id = desc.substr(*p, next - *p);
+ used_class_names.insert(id);
+ *p = next;
+}
+
+void ParseTypeArgumentsOpt(const std::string& desc, size_t* p) {
+ if (desc[*p] != '<') {
+ return;
+ }
+
+ *p += 1;
+ while (desc[*p] != '>') {
+ switch (desc[*p]) {
+ case '*':
+ *p += 1;
+ break;
+
+ case '+':
+ case '-':
+ *p += 1;
+ ExtractClassNames(desc, p);
+ break;
+
+ default:
+ ExtractClassNames(desc, p);
+ break;
+ }
+ }
+
+ *p += 1;
+}
+
+void ParseMethodDescriptor(const std::string& desc, size_t* p) {
+ Expect(desc, p, '(');
+ while (desc[*p] != ')') {
+ ExtractClassNames(desc, p);
+ }
+
+ Expect(desc, p, ')');
+ ExtractClassNames(desc, p);
+}
+
+void ParseFormalTypeParameters(const std::string& desc, size_t* p) {
+ Expect(desc, p, '<');
+ while (desc[*p] != '>') {
+ ParseIdentifier(desc, p);
+ Expect(desc, p, ':');
+ if (desc[*p] != ':' && desc[*p] != '>') {
+ ExtractClassNames(desc, p);
+ }
+
+ while (desc[*p] == ':') {
+ Expect(desc, p, ':');
+ ExtractClassNames(desc, p);
+ }
+ }
+
+ Expect(desc, p, '>');
+}
+
+void ExtractClassNames(const std::string& desc, size_t* p) {
+ switch (desc[*p]) {
+ case '<':
+ ParseFormalTypeParameters(desc, p);
+ ExtractClassNames(desc, p);
+ break;
+
+ case 'L':
+ ParseClassTypeSignature(desc, p);
+ break;
+
+ case '[':
+ *p += 1;
+ ExtractClassNames(desc, p);
+ break;
+
+ case 'T':
+ *p += 1;
+ ParseIdentifier(desc, p);
+ Expect(desc, p, ';');
+ break;
+
+ case '(':
+ ParseMethodDescriptor(desc, p);
+ break;
+
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z':
+ case 'V':
+ *p += 1;
+ break;
+
+ default:
+ fprintf(stderr, "Invalid signature %s\n", desc.substr(*p).c_str());
+ }
+}
+
void ClassFile::WriteClass(u1 *&p) {
+ used_class_names.clear();
+ std::vector<Member *> members;
+ members.insert(members.end(), fields.begin(), fields.end());
+ members.insert(members.end(), methods.begin(), methods.end());
+ ExtractClassNames();
+ for (auto *member : members) {
+ size_t idx = 0;
+ devtools_ijar::ExtractClassNames(member->descriptor->Display(), &idx);
+ member->ExtractClassNames();
+ }
+
// We have to write the body out before the header in order to reference
// the essential constants and populate the output constant pool:
u1 *body = new u1[length];
@@ -1454,23 +1782,20 @@ void ClassFile::WriteClass(u1 *&p) {
delete[] body;
}
-
-void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) {
+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) {
// Class is invalid. Simply copy it to the output and call it a day.
put_n(classdata_out, classdata_in, in_length);
+ } else if (clazz->IsLocalOrAnonymous()) {
+ keep = false;
} else {
// Constant pool item zero is a dummy entry. Setting it marks the
// beginning of the output phase; calls to Constant::slot() will
// fail if called prior to this.
const_pool_out.push_back(NULL);
-
- // TODO(bazel-team): We should only keep classes in the InnerClass attributes
- // if they're used in the output. The entries can then be cleaned out of the
- // constant pool in the normal way.
-
clazz->WriteClass(classdata_out);
delete clazz;
@@ -1484,6 +1809,7 @@ void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) {
const_pool_in.clear();
const_pool_out.clear();
+ return keep;
}
} // namespace devtools_ijar
« no previous file with comments | « third_party/ijar/README.chromium ('k') | third_party/ijar/common.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698