mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8255489: Unify the parsing of @lambda-proxy and @lambda-form-invokers tags in a classlist
Reviewed-by: iklam, minqi
This commit is contained in:
parent
0f48603394
commit
36c150b199
9 changed files with 65 additions and 34 deletions
|
@ -115,13 +115,6 @@ bool ClassListParser::parse_one_line() {
|
|||
_line_len = len;
|
||||
}
|
||||
|
||||
// Check if the line is output TRACE_RESOLVE
|
||||
if (strncmp(_line, LambdaFormInvokers::lambda_form_invoker_tag(),
|
||||
strlen(LambdaFormInvokers::lambda_form_invoker_tag())) == 0) {
|
||||
LambdaFormInvokers::append(os::strdup((const char*)_line, mtInternal));
|
||||
continue;
|
||||
}
|
||||
|
||||
// valid line
|
||||
break;
|
||||
}
|
||||
|
@ -133,6 +126,7 @@ bool ClassListParser::parse_one_line() {
|
|||
_source = NULL;
|
||||
_interfaces_specified = false;
|
||||
_indy_items->clear();
|
||||
_lambda_form_line = false;
|
||||
|
||||
if (_line[0] == '@') {
|
||||
return parse_at_tags();
|
||||
|
@ -185,8 +179,8 @@ bool ClassListParser::parse_one_line() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ClassListParser::split_tokens_by_whitespace() {
|
||||
int start = 0;
|
||||
void ClassListParser::split_tokens_by_whitespace(int offset) {
|
||||
int start = offset;
|
||||
int end;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
|
@ -203,19 +197,40 @@ void ClassListParser::split_tokens_by_whitespace() {
|
|||
}
|
||||
}
|
||||
|
||||
int ClassListParser::split_at_tag_from_line() {
|
||||
_token = _line;
|
||||
char* ptr;
|
||||
if ((ptr = strchr(_line, ' ')) == NULL) {
|
||||
error("Too few items following the @ tag \"%s\" line #%d", _line, _line_no);
|
||||
return 0;
|
||||
}
|
||||
*ptr++ = '\0';
|
||||
while (*ptr == ' ' || *ptr == '\t') ptr++;
|
||||
return (int)(ptr - _line);
|
||||
}
|
||||
|
||||
bool ClassListParser::parse_at_tags() {
|
||||
assert(_line[0] == '@', "must be");
|
||||
split_tokens_by_whitespace();
|
||||
if (strcmp(_indy_items->at(0), LAMBDA_PROXY_TAG) == 0) {
|
||||
if (_indy_items->length() < 3) {
|
||||
error("Line with @ tag has too few items \"%s\" line #%d", _line, _line_no);
|
||||
int offset;
|
||||
if ((offset = split_at_tag_from_line()) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
|
||||
split_tokens_by_whitespace(offset);
|
||||
if (_indy_items->length() < 2) {
|
||||
error("Line with @ tag has too few items \"%s\" line #%d", _token, _line_no);
|
||||
return false;
|
||||
}
|
||||
// set the class name
|
||||
_class_name = _indy_items->at(1);
|
||||
_class_name = _indy_items->at(0);
|
||||
return true;
|
||||
} else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
|
||||
LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
|
||||
_lambda_form_line = true;
|
||||
return true;
|
||||
} else {
|
||||
error("Invalid @ tag at the beginning of line \"%s\" line #%d", _line, _line_no);
|
||||
error("Invalid @ tag at the beginning of line \"%s\" line #%d", _token, _line_no);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -432,7 +447,7 @@ bool ClassListParser::is_matching_cp_entry(constantPoolHandle &pool, int cp_inde
|
|||
CDSIndyInfo cii;
|
||||
populate_cds_indy_info(pool, cp_index, &cii, THREAD);
|
||||
GrowableArray<const char*>* items = cii.items();
|
||||
int indy_info_offset = 2;
|
||||
int indy_info_offset = 1;
|
||||
if (_indy_items->length() - indy_info_offset != items->length()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/hashtable.inline.hpp"
|
||||
|
||||
#define LAMBDA_PROXY_TAG "@lambda-proxy:"
|
||||
#define LAMBDA_PROXY_TAG "@lambda-proxy"
|
||||
#define LAMBDA_FORM_TAG "@lambda-form-invoker"
|
||||
|
||||
class ID2KlassTable : public KVHashtable<int, InstanceKlass*, mtInternal> {
|
||||
public:
|
||||
|
@ -99,6 +100,7 @@ class ClassListParser : public StackObj {
|
|||
GrowableArray<int>* _interfaces;
|
||||
bool _interfaces_specified;
|
||||
const char* _source;
|
||||
bool _lambda_form_line;
|
||||
|
||||
bool parse_int_option(const char* option_name, int* value);
|
||||
bool parse_uint_option(const char* option_name, int* value);
|
||||
|
@ -120,7 +122,8 @@ public:
|
|||
return _instance;
|
||||
}
|
||||
bool parse_one_line();
|
||||
void split_tokens_by_whitespace();
|
||||
void split_tokens_by_whitespace(int offset);
|
||||
int split_at_tag_from_line();
|
||||
bool parse_at_tags();
|
||||
char* _token;
|
||||
void error(const char* msg, ...);
|
||||
|
@ -162,6 +165,8 @@ public:
|
|||
|
||||
bool is_loading_from_source();
|
||||
|
||||
bool lambda_form_line() { return _lambda_form_line; }
|
||||
|
||||
// Look up the super or interface of the current class being loaded
|
||||
// (in this->load_current_class()).
|
||||
InstanceKlass* lookup_super_for_current_class(Symbol* super_name);
|
||||
|
|
|
@ -66,9 +66,7 @@ void LambdaFormInvokers::regenerate_holder_classes(TRAPS) {
|
|||
int len = _lambdaform_lines->length();
|
||||
objArrayHandle list_lines = oopFactory::new_objArray_handle(SystemDictionary::String_klass(), len, CHECK);
|
||||
for (int i = 0; i < len; i++) {
|
||||
char* record = _lambdaform_lines->at(i);
|
||||
record += strlen(lambda_form_invoker_tag()) + 1; // skip the @lambda_form_invoker prefix
|
||||
Handle h_line = java_lang_String::create_from_str(record, CHECK);
|
||||
Handle h_line = java_lang_String::create_from_str(_lambdaform_lines->at(i), CHECK);
|
||||
list_lines->obj_at_put(i, h_line());
|
||||
}
|
||||
|
||||
|
|
|
@ -42,9 +42,5 @@ class LambdaFormInvokers : public AllStatic {
|
|||
static GrowableArray<char*>* lambdaform_lines() {
|
||||
return _lambdaform_lines;
|
||||
}
|
||||
|
||||
static const char* lambda_form_invoker_tag() {
|
||||
return "@lambda-form-invoker";
|
||||
}
|
||||
};
|
||||
#endif // SHARE_MEMORY_LAMBDAFORMINVOKERS_HPP
|
||||
|
|
|
@ -1096,6 +1096,9 @@ int MetaspaceShared::preload_classes(const char* class_list_path, TRAPS) {
|
|||
int class_count = 0;
|
||||
|
||||
while (parser.parse_one_line()) {
|
||||
if (parser.lambda_form_line()) {
|
||||
continue;
|
||||
}
|
||||
Klass* klass = parser.load_current_class(THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
if (klass == NULL &&
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "precompiled.hpp"
|
||||
#include "jvm.h"
|
||||
#include "classfile/classFileStream.hpp"
|
||||
#include "classfile/classListParser.hpp"
|
||||
#include "classfile/classListWriter.hpp"
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
|
@ -32,7 +33,6 @@
|
|||
#include "classfile/classLoadInfo.hpp"
|
||||
#include "classfile/javaAssertions.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/lambdaFormInvokers.hpp"
|
||||
#include "classfile/moduleEntry.hpp"
|
||||
#include "classfile/modules.hpp"
|
||||
#include "classfile/packageEntry.hpp"
|
||||
|
@ -3883,7 +3883,7 @@ JVM_ENTRY(void, JVM_LogLambdaFormInvoker(JNIEnv *env, jstring line))
|
|||
Handle h_line (THREAD, JNIHandles::resolve_non_null(line));
|
||||
char* c_line = java_lang_String::as_utf8_string(h_line());
|
||||
ClassListWriter w;
|
||||
w.stream()->print_cr("%s %s", LambdaFormInvokers::lambda_form_invoker_tag(), c_line);
|
||||
w.stream()->print_cr("%s %s", LAMBDA_FORM_TAG, c_line);
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
JVM_END
|
||||
|
|
|
@ -42,7 +42,7 @@ public class BadBSM {
|
|||
|
||||
OutputAnalyzer out = TestCommon.dump(appJar,
|
||||
TestCommon.list("WrongBSM",
|
||||
"@lambda-proxy: WrongBSM 7"));
|
||||
"@lambda-proxy WrongBSM 7"));
|
||||
out.shouldHaveExitValue(0);
|
||||
out.shouldContain( "is_supported_invokedynamic check failed for cp_index 7");
|
||||
}
|
||||
|
|
|
@ -105,5 +105,12 @@ public class DumpClassListWithLF extends ClassListFormatBase {
|
|||
"Hello",
|
||||
"@lambda-form-invoker [SPECIES_RESOLVE] java.lang.invoke.BoundMethodHandle$Species_L L"),
|
||||
"Incorrect number of items in the line: 3");
|
||||
// 10. The line with incorrect (less) number of items.
|
||||
dumpShouldFail(
|
||||
"TESTCASE 10: With incorrect @lambda-form-invoker tag",
|
||||
appJar, classlist(
|
||||
"Hello",
|
||||
"@lambda-form-invoker-xxx [LF_RESOLVE] java.lang.invoke.DirectMethodHandle$Holder invokeStatic"),
|
||||
"Invalid @ tag at the beginning of line \"@lambda-form-invoker-xxx\" line #2");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,35 +43,42 @@ public class LambdaProxyClasslist {
|
|||
// 1. No error with a correct @lambda-proxy entry.
|
||||
OutputAnalyzer out = TestCommon.dump(appJar,
|
||||
TestCommon.list("LambHello",
|
||||
"@lambda-proxy: LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()V"));
|
||||
"@lambda-proxy LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()V"));
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
// 2. Error if the @lambda-proxy entry is too short.
|
||||
out = TestCommon.dump(appJar,
|
||||
TestCommon.list("LambHello",
|
||||
"@lambda-proxy: LambHello"));
|
||||
"@lambda-proxy LambHello"));
|
||||
out.shouldContain("An error has occurred while processing class list file")
|
||||
.shouldContain("Line with @ tag has too few items \"@lambda-proxy:\" line #2")
|
||||
.shouldContain("Line with @ tag has too few items \"@lambda-proxy\" line #2")
|
||||
.shouldContain("class list format error")
|
||||
.shouldHaveExitValue(1);
|
||||
|
||||
// 3. Warning message if there's an incorrect signature in the @lambda-proxy entry.
|
||||
out = TestCommon.dump(appJar,
|
||||
TestCommon.list("LambHello",
|
||||
"@lambda-proxy: LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()Z"));
|
||||
"@lambda-proxy LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()Z"));
|
||||
out.shouldContain("[warning][cds] No invoke dynamic constant pool entry can be found for class LambHello. The classlist is probably out-of-date.")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// 4. More blank spaces in between items should be fine.
|
||||
out = TestCommon.dump(appJar,
|
||||
TestCommon.list("LambHello",
|
||||
"@lambda-proxy: LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()V"));
|
||||
"@lambda-proxy LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()V"));
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
// 5. Trailing spaces at the end of the @lambda-proxy line should be fine.
|
||||
out = TestCommon.dump(appJar,
|
||||
TestCommon.list("LambHello",
|
||||
"@lambda-proxy: LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()V "));
|
||||
"@lambda-proxy LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()V "));
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
// 6. Error on invalid @lambda-proxy tag
|
||||
out = TestCommon.dump(appJar,
|
||||
TestCommon.list("LambHello",
|
||||
"@lambda-proxy: LambHello run ()Ljava/lang/Runnable; ()V REF_invokeStatic LambHello lambda$doTest$0 ()V ()V"));
|
||||
out.shouldContain("Invalid @ tag at the beginning of line \"@lambda-proxy:\" line #2")
|
||||
.shouldHaveExitValue(1);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue