32
32
#include " classfile/symbolTable.hpp"
33
33
#include " classfile/systemDictionary.hpp"
34
34
#include " classfile/systemDictionaryShared.hpp"
35
+ #include " interpreter/bytecode.hpp"
36
+ #include " interpreter/bytecodeStream.hpp"
37
+ #include " interpreter/linkResolver.hpp"
35
38
#include " logging/log.hpp"
36
39
#include " logging/logTag.hpp"
37
40
#include " memory/metaspaceShared.hpp"
38
41
#include " memory/resourceArea.hpp"
42
+ #include " oops/constantPool.hpp"
39
43
#include " runtime/handles.inline.hpp"
40
44
#include " runtime/java.hpp"
41
45
#include " runtime/javaCalls.hpp"
@@ -65,6 +69,7 @@ ClassListParser::ClassListParser(const char* file) {
65
69
}
66
70
_line_no = 0 ;
67
71
_interfaces = new (ResourceObj::C_HEAP, mtClass) GrowableArray<int >(10 , mtClass);
72
+ _indy_items = new (ResourceObj::C_HEAP, mtClass) GrowableArray<const char *>(9 , mtClass);
68
73
}
69
74
70
75
ClassListParser::~ClassListParser () {
@@ -127,6 +132,11 @@ bool ClassListParser::parse_one_line() {
127
132
_interfaces->clear ();
128
133
_source = NULL ;
129
134
_interfaces_specified = false ;
135
+ _indy_items->clear ();
136
+
137
+ if (_line[0 ] == ' @' ) {
138
+ return parse_at_tags ();
139
+ }
130
140
131
141
if ((_token = strchr (_line, ' ' )) == NULL ) {
132
142
// No optional arguments are specified.
@@ -139,14 +149,14 @@ bool ClassListParser::parse_one_line() {
139
149
while (*_token) {
140
150
skip_whitespaces ();
141
151
142
- if (parse_int_option (" id:" , &_id)) {
152
+ if (parse_uint_option (" id:" , &_id)) {
143
153
continue ;
144
- } else if (parse_int_option (" super:" , &_super)) {
154
+ } else if (parse_uint_option (" super:" , &_super)) {
145
155
check_already_loaded (" Super class" , _super);
146
156
continue ;
147
157
} else if (skip_token (" interfaces:" )) {
148
158
int i;
149
- while (try_parse_int (&i)) {
159
+ while (try_parse_uint (&i)) {
150
160
check_already_loaded (" Interface" , i);
151
161
_interfaces->append (i);
152
162
}
@@ -175,6 +185,41 @@ bool ClassListParser::parse_one_line() {
175
185
return true ;
176
186
}
177
187
188
+ void ClassListParser::split_tokens_by_whitespace () {
189
+ int start = 0 ;
190
+ int end;
191
+ bool done = false ;
192
+ while (!done) {
193
+ while (_line[start] == ' ' || _line[start] == ' \t ' ) start++;
194
+ end = start;
195
+ while (_line[end] && _line[end] != ' ' && _line[end] != ' \t ' ) end++;
196
+ if (_line[end] == ' \0 ' ) {
197
+ done = true ;
198
+ } else {
199
+ _line[end] = ' \0 ' ;
200
+ }
201
+ _indy_items->append (_line + start);
202
+ start = ++end;
203
+ }
204
+ }
205
+
206
+ bool ClassListParser::parse_at_tags () {
207
+ assert (_line[0 ] == ' @' , " must be" );
208
+ split_tokens_by_whitespace ();
209
+ if (strcmp (_indy_items->at (0 ), LAMBDA_PROXY_TAG) == 0 ) {
210
+ if (_indy_items->length () < 3 ) {
211
+ error (" Line with @ tag has too few items \" %s\" line #%d" , _line, _line_no);
212
+ return false ;
213
+ }
214
+ // set the class name
215
+ _class_name = _indy_items->at (1 );
216
+ return true ;
217
+ } else {
218
+ error (" Invalid @ tag at the beginning of line \" %s\" line #%d" , _line, _line_no);
219
+ return false ;
220
+ }
221
+ }
222
+
178
223
void ClassListParser::skip_whitespaces () {
179
224
while (*_token == ' ' || *_token == ' \t ' ) {
180
225
_token ++;
@@ -191,15 +236,19 @@ void ClassListParser::parse_int(int* value) {
191
236
skip_whitespaces ();
192
237
if (sscanf (_token, " %i" , value) == 1 ) {
193
238
skip_non_whitespaces ();
194
- if (*value < 0 ) {
195
- error (" Error: negative integers not allowed (%d)" , *value);
196
- }
197
239
} else {
198
240
error (" Error: expected integer" );
199
241
}
200
242
}
201
243
202
- bool ClassListParser::try_parse_int (int * value) {
244
+ void ClassListParser::parse_uint (int * value) {
245
+ parse_int (value);
246
+ if (*value < 0 ) {
247
+ error (" Error: negative integers not allowed (%d)" , *value);
248
+ }
249
+ }
250
+
251
+ bool ClassListParser::try_parse_uint (int * value) {
203
252
skip_whitespaces ();
204
253
if (sscanf (_token, " %i" , value) == 1 ) {
205
254
skip_non_whitespaces ();
@@ -230,6 +279,18 @@ bool ClassListParser::parse_int_option(const char* option_name, int* value) {
230
279
return false ;
231
280
}
232
281
282
+ bool ClassListParser::parse_uint_option (const char * option_name, int * value) {
283
+ if (skip_token (option_name)) {
284
+ if (*value != _unspecified) {
285
+ error (" %s specified twice" , option_name);
286
+ } else {
287
+ parse_uint (value);
288
+ return true ;
289
+ }
290
+ }
291
+ return false ;
292
+ }
293
+
233
294
void ClassListParser::print_specified_interfaces () {
234
295
const int n = _interfaces->length ();
235
296
jio_fprintf (defaultStream::error_stream (), " Currently specified interfaces[%d] = {\n " , n);
@@ -336,9 +397,122 @@ InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS
336
397
return k;
337
398
}
338
399
400
+ void ClassListParser::populate_cds_indy_info (const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS) {
401
+ // Caller needs to allocate ResourceMark.
402
+ int type_index = pool->bootstrap_name_and_type_ref_index_at (cp_index);
403
+ int name_index = pool->name_ref_index_at (type_index);
404
+ cii->add_item (pool->symbol_at (name_index)->as_C_string ());
405
+ int sig_index = pool->signature_ref_index_at (type_index);
406
+ cii->add_item (pool->symbol_at (sig_index)->as_C_string ());
407
+ int argc = pool->bootstrap_argument_count_at (cp_index);
408
+ if (argc > 0 ) {
409
+ for (int arg_i = 0 ; arg_i < argc; arg_i++) {
410
+ int arg = pool->bootstrap_argument_index_at (cp_index, arg_i);
411
+ jbyte tag = pool->tag_at (arg).value ();
412
+ if (tag == JVM_CONSTANT_MethodType) {
413
+ cii->add_item (pool->method_type_signature_at (arg)->as_C_string ());
414
+ } else if (tag == JVM_CONSTANT_MethodHandle) {
415
+ cii->add_ref_kind (pool->method_handle_ref_kind_at (arg));
416
+ int callee_index = pool->method_handle_klass_index_at (arg);
417
+ Klass* callee = pool->klass_at (callee_index, THREAD);
418
+ if (callee != NULL ) {
419
+ cii->add_item (callee->name ()->as_C_string ());
420
+ }
421
+ cii->add_item (pool->method_handle_name_ref_at (arg)->as_C_string ());
422
+ cii->add_item (pool->method_handle_signature_ref_at (arg)->as_C_string ());
423
+ } else {
424
+ ShouldNotReachHere ();
425
+ }
426
+ }
427
+ }
428
+ }
429
+
430
+ bool ClassListParser::is_matching_cp_entry (constantPoolHandle &pool, int cp_index, TRAPS) {
431
+ ResourceMark rm (THREAD);
432
+ CDSIndyInfo cii;
433
+ populate_cds_indy_info (pool, cp_index, &cii, THREAD);
434
+ GrowableArray<const char *>* items = cii.items ();
435
+ int indy_info_offset = 2 ;
436
+ if (_indy_items->length () - indy_info_offset != items->length ()) {
437
+ return false ;
438
+ }
439
+ for (int i = 0 ; i < items->length (); i++) {
440
+ if (strcmp (_indy_items->at (i + indy_info_offset), items->at (i)) != 0 ) {
441
+ return false ;
442
+ }
443
+ }
444
+ return true ;
445
+ }
446
+
447
+ void ClassListParser::resolve_indy (Symbol* class_name_symbol, TRAPS) {
448
+
449
+ Handle class_loader (THREAD, SystemDictionary::java_system_loader ());
450
+ Handle protection_domain;
451
+ Klass* klass = SystemDictionary::resolve_or_fail (class_name_symbol, class_loader, protection_domain, true , THREAD); // FIXME should really be just a lookup
452
+ if (klass != NULL && klass->is_instance_klass ()) {
453
+ InstanceKlass* ik = InstanceKlass::cast (klass);
454
+ MetaspaceShared::try_link_class (ik, THREAD);
455
+ assert (!HAS_PENDING_EXCEPTION, " unexpected exception" );
456
+
457
+ ConstantPool* cp = ik->constants ();
458
+ ConstantPoolCache* cpcache = cp->cache ();
459
+ bool found = false ;
460
+ for (int cpcindex = 0 ; cpcindex < cpcache->length (); cpcindex ++) {
461
+ int indy_index = ConstantPool::encode_invokedynamic_index (cpcindex);
462
+ ConstantPoolCacheEntry* cpce = cpcache->entry_at (cpcindex);
463
+ int pool_index = cpce->constant_pool_index ();
464
+ constantPoolHandle pool (THREAD, cp);
465
+ if (pool->tag_at (pool_index).is_invoke_dynamic ()) {
466
+ BootstrapInfo bootstrap_specifier (pool, pool_index, indy_index);
467
+ Handle bsm = bootstrap_specifier.resolve_bsm (THREAD);
468
+ if (!SystemDictionaryShared::is_supported_invokedynamic (&bootstrap_specifier)) {
469
+ tty->print_cr (" is_supported_invokedynamic check failed for cp_index %d" , pool_index);
470
+ continue ;
471
+ }
472
+ if (is_matching_cp_entry (pool, pool_index, THREAD)) {
473
+ found = true ;
474
+ CallInfo info;
475
+ bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic (info, THREAD);
476
+ if (!is_done) {
477
+ // resolve it
478
+ Handle recv;
479
+ LinkResolver::resolve_invoke (info, recv, pool, indy_index, Bytecodes::_invokedynamic, THREAD);
480
+ break ;
481
+ }
482
+ cpce->set_dynamic_call (pool, info);
483
+ if (HAS_PENDING_EXCEPTION) {
484
+ ResourceMark rm (THREAD);
485
+ tty->print (" resolve_indy for class %s has" , class_name_symbol->as_C_string ());
486
+ oop message = java_lang_Throwable::message (PENDING_EXCEPTION);
487
+ if (message != NULL ) {
488
+ char * ex_msg = java_lang_String::as_utf8_string (message);
489
+ tty->print_cr (" exception pending '%s %s'" ,
490
+ PENDING_EXCEPTION->klass ()->external_name (), ex_msg);
491
+ } else {
492
+ tty->print_cr (" exception pending %s " ,
493
+ PENDING_EXCEPTION->klass ()->external_name ());
494
+ }
495
+ exit (1 );
496
+ }
497
+ }
498
+ }
499
+ }
500
+ if (!found) {
501
+ ResourceMark rm (THREAD);
502
+ log_warning (cds)(" No invoke dynamic constant pool entry can be found for class %s. The classlist is probably out-of-date." ,
503
+ class_name_symbol->as_C_string ());
504
+ }
505
+ }
506
+ }
507
+
339
508
Klass* ClassListParser::load_current_class (TRAPS) {
340
509
TempNewSymbol class_name_symbol = SymbolTable::new_symbol (_class_name);
341
510
511
+ if (_indy_items->length () > 0 ) {
512
+ resolve_indy (class_name_symbol, CHECK_NULL);
513
+ return NULL ;
514
+ }
515
+
342
516
Klass* klass = NULL ;
343
517
if (!is_loading_from_source ()) {
344
518
// Load classes for the boot/platform/app loaders only.
0 commit comments