Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/compiler/directivesParser.cpp
40930 views
1
/*
2
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "compiler/compileBroker.hpp"
27
#include "compiler/directivesParser.hpp"
28
#include "memory/allocation.inline.hpp"
29
#include "memory/resourceArea.hpp"
30
#include "runtime/os.hpp"
31
#include <string.h>
32
33
void DirectivesParser::push_tmp(CompilerDirectives* dir) {
34
_tmp_depth++;
35
dir->set_next(_tmp_top);
36
_tmp_top = dir;
37
}
38
39
CompilerDirectives* DirectivesParser::pop_tmp() {
40
if (_tmp_top == NULL) {
41
return NULL;
42
}
43
CompilerDirectives* tmp = _tmp_top;
44
_tmp_top = _tmp_top->next();
45
tmp->set_next(NULL);
46
_tmp_depth--;
47
return tmp;
48
}
49
50
void DirectivesParser::clean_tmp() {
51
CompilerDirectives* tmp = pop_tmp();
52
while (tmp != NULL) {
53
delete tmp;
54
tmp = pop_tmp();
55
}
56
assert(_tmp_depth == 0, "Consistency");
57
}
58
59
int DirectivesParser::parse_string(const char* text, outputStream* st) {
60
DirectivesParser cd(text, st, false);
61
if (cd.valid()) {
62
return cd.install_directives();
63
} else {
64
cd.clean_tmp();
65
st->flush();
66
st->print_cr("Parsing of compiler directives failed");
67
return -1;
68
}
69
}
70
71
bool DirectivesParser::has_file() {
72
return CompilerDirectivesFile != NULL;
73
}
74
75
bool DirectivesParser::parse_from_flag() {
76
return parse_from_file(CompilerDirectivesFile, tty);
77
}
78
79
bool DirectivesParser::parse_from_file(const char* filename, outputStream* st) {
80
assert(filename != NULL, "Test before calling this");
81
if (!parse_from_file_inner(filename, st)) {
82
st->print_cr("Could not load file: %s", filename);
83
return false;
84
}
85
return true;
86
}
87
88
bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream) {
89
struct stat st;
90
ResourceMark rm;
91
if (os::stat(filename, &st) == 0) {
92
// found file, open it
93
int file_handle = os::open(filename, 0, 0);
94
if (file_handle != -1) {
95
// read contents into resource array
96
char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
97
ssize_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
98
if (num_read >= 0) {
99
buffer[num_read] = '\0';
100
// close file
101
os::close(file_handle);
102
return parse_string(buffer, stream) > 0;
103
}
104
}
105
}
106
return false;
107
}
108
109
int DirectivesParser::install_directives() {
110
// Check limit
111
if (!DirectivesStack::check_capacity(_tmp_depth, _st)) {
112
clean_tmp();
113
return 0;
114
}
115
116
// Pop from internal temporary stack and push to compileBroker.
117
CompilerDirectives* tmp = pop_tmp();
118
int i = 0;
119
while (tmp != NULL) {
120
i++;
121
DirectivesStack::push(tmp);
122
tmp = pop_tmp();
123
}
124
if (i == 0) {
125
_st->print_cr("No directives in file");
126
return 0;
127
} else {
128
_st->print_cr("%i compiler directives added", i);
129
if (CompilerDirectivesPrint) {
130
// Print entire directives stack after new has been pushed.
131
DirectivesStack::print(_st);
132
}
133
return i;
134
}
135
}
136
137
DirectivesParser::DirectivesParser(const char* text, outputStream* st, bool silent)
138
: JSON(text, silent, st), depth(0), current_directive(NULL), current_directiveset(NULL), _tmp_top(NULL), _tmp_depth(0) {
139
#ifndef PRODUCT
140
memset(stack, 0, MAX_DEPTH * sizeof(stack[0]));
141
#endif
142
parse();
143
}
144
145
DirectivesParser::~DirectivesParser() {
146
assert(_tmp_top == NULL, "Consistency");
147
assert(_tmp_depth == 0, "Consistency");
148
}
149
150
const DirectivesParser::key DirectivesParser::keys[] = {
151
// name, keytype, allow_array, allowed_mask, set_function
152
{ "c1", type_c1, 0, mask(type_directives), NULL, UnknownFlagType },
153
{ "c2", type_c2, 0, mask(type_directives), NULL, UnknownFlagType },
154
{ "match", type_match, 1, mask(type_directives), NULL, UnknownFlagType },
155
{ "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
156
157
// Global flags
158
#define common_flag_key(name, type, dvalue, compiler) \
159
{ #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag},
160
compilerdirectives_common_flags(common_flag_key)
161
compilerdirectives_c2_flags(common_flag_key)
162
compilerdirectives_c1_flags(common_flag_key)
163
#undef common_flag_key
164
};
165
166
const DirectivesParser::key DirectivesParser::dir_array_key = {
167
"top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
168
};
169
const DirectivesParser::key DirectivesParser::dir_key = {
170
"top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
171
};
172
const DirectivesParser::key DirectivesParser::value_array_key = {
173
"value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
174
};
175
176
const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) {
177
for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
178
if (strncasecmp(keys[i].name, str, len) == 0) {
179
return &keys[i];
180
}
181
}
182
return NULL;
183
}
184
185
uint DirectivesParser::mask(keytype kt) {
186
return 1 << (kt + 1);
187
}
188
189
bool DirectivesParser::push_key(const char* str, size_t len) {
190
bool result = true;
191
const key* k = lookup_key(str, len);
192
193
if (k == NULL) {
194
// os::strdup
195
char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
196
strncpy(s, str, len);
197
s[len] = '\0';
198
error(KEY_ERROR, "No such key: '%s'.", s);
199
FREE_C_HEAP_ARRAY(char, s);
200
return false;
201
}
202
203
return push_key(k);
204
}
205
206
bool DirectivesParser::push_key(const key* k) {
207
assert(k->allowedmask != 0, "not allowed anywhere?");
208
209
// Exceeding the stack should not be possible with a valid compiler directive,
210
// and an invalid should abort before this happens
211
assert(depth < MAX_DEPTH, "exceeded stack depth");
212
if (depth >= MAX_DEPTH) {
213
error(INTERNAL_ERROR, "Stack depth exceeded.");
214
return false;
215
}
216
217
assert(stack[depth] == NULL, "element not nulled, something is wrong");
218
219
if (depth == 0 && !(k->allowedmask & 1)) {
220
error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name);
221
return false;
222
}
223
224
if (depth > 0) {
225
const key* prev = stack[depth - 1];
226
if (!(k->allowedmask & mask(prev->type))) {
227
error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name);
228
return false;
229
}
230
}
231
232
stack[depth] = k;
233
depth++;
234
return true;
235
}
236
237
const DirectivesParser::key* DirectivesParser::current_key() {
238
assert(depth > 0, "getting key from empty stack");
239
if (depth == 0) {
240
return NULL;
241
}
242
return stack[depth - 1];
243
}
244
245
const DirectivesParser::key* DirectivesParser::pop_key() {
246
assert(depth > 0, "popping empty stack");
247
if (depth == 0) {
248
error(INTERNAL_ERROR, "Popping empty stack.");
249
return NULL;
250
}
251
depth--;
252
253
const key* k = stack[depth];
254
#ifndef PRODUCT
255
stack[depth] = NULL;
256
#endif
257
258
return k;
259
}
260
261
bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) {
262
263
void (DirectiveSet::*test)(void *args);
264
test = option_key->set;
265
266
switch (t) {
267
case JSON_TRUE:
268
if (option_key->flag_type != boolFlag) {
269
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
270
return false;
271
} else {
272
bool val = true;
273
(set->*test)((void *)&val);
274
}
275
break;
276
277
case JSON_FALSE:
278
if (option_key->flag_type != boolFlag) {
279
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
280
return false;
281
} else {
282
bool val = false;
283
(set->*test)((void *)&val);
284
}
285
break;
286
287
case JSON_NUMBER_INT:
288
if (option_key->flag_type == intxFlag) {
289
intx ival = v->int_value;
290
(set->*test)((void *)&ival);
291
} else if (option_key->flag_type == uintxFlag) {
292
uintx ival = v->uint_value;
293
(set->*test)((void *)&ival);
294
} else if (option_key->flag_type == doubleFlag) {
295
double dval = (double)v->int_value;
296
(set->*test)((void *)&dval);
297
} else {
298
error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]);
299
return false;
300
}
301
break;
302
303
case JSON_NUMBER_FLOAT:
304
if (option_key->flag_type != doubleFlag) {
305
error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]);
306
return false;
307
} else {
308
double dval = v->double_value;
309
(set->*test)((void *)&dval);
310
}
311
break;
312
313
case JSON_STRING:
314
if (option_key->flag_type != ccstrFlag && option_key->flag_type != ccstrlistFlag) {
315
error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]);
316
return false;
317
} else {
318
char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1, mtCompiler);
319
strncpy(s, v->str.start, v->str.length + 1);
320
s[v->str.length] = '\0';
321
(set->*test)((void *)&s);
322
323
if (strncmp(option_key->name, "ControlIntrinsic", 16) == 0) {
324
ControlIntrinsicValidator validator(s, false/*disabled_all*/);
325
326
if (!validator.is_valid()) {
327
error(VALUE_ERROR, "Unrecognized intrinsic detected in ControlIntrinsic: %s", validator.what());
328
return false;
329
}
330
} else if (strncmp(option_key->name, "DisableIntrinsic", 16) == 0) {
331
ControlIntrinsicValidator validator(s, true/*disabled_all*/);
332
333
if (!validator.is_valid()) {
334
error(VALUE_ERROR, "Unrecognized intrinsic detected in DisableIntrinsic: %s", validator.what());
335
return false;
336
}
337
}
338
}
339
break;
340
341
default:
342
assert(0, "Should not reach here.");
343
}
344
return true;
345
}
346
347
bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) {
348
349
const key* option_key = pop_key();
350
const key* enclosing_key = current_key();
351
352
if (option_key->type == value_array_key.type) {
353
// Multi value array, we are really setting the value
354
// for the key one step further up.
355
option_key = pop_key();
356
enclosing_key = current_key();
357
358
// Repush option_key and multi value marker, since
359
// we need to keep them until all multi values are set.
360
push_key(option_key);
361
push_key(&value_array_key);
362
}
363
364
switch (option_key->type) {
365
case type_flag:
366
{
367
if (current_directiveset == NULL) {
368
assert(depth == 2, "Must not have active directive set");
369
370
if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) {
371
return false;
372
}
373
if (!set_option_flag(t, v, option_key, current_directive->_c2_store)) {
374
return false;
375
}
376
} else {
377
assert(depth > 2, "Must have active current directive set");
378
if (!set_option_flag(t, v, option_key, current_directiveset)) {
379
return false;
380
}
381
}
382
break;
383
}
384
385
case type_match:
386
if (t != JSON_STRING) {
387
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
388
return false;
389
}
390
if (enclosing_key->type != type_directives) {
391
error(SYNTAX_ERROR, "Match keyword can only exist inside a directive");
392
return false;
393
}
394
{
395
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
396
strncpy(s, v->str.start, v->str.length);
397
s[v->str.length] = '\0';
398
399
const char* error_msg = NULL;
400
if (!current_directive->add_match(s, error_msg)) {
401
assert (error_msg != NULL, "Must have valid error message");
402
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
403
}
404
FREE_C_HEAP_ARRAY(char, s);
405
}
406
break;
407
408
case type_inline:
409
if (t != JSON_STRING) {
410
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
411
return false;
412
}
413
{
414
//char* s = strndup(v->str.start, v->str.length);
415
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
416
strncpy(s, v->str.start, v->str.length);
417
s[v->str.length] = '\0';
418
419
const char* error_msg = NULL;
420
if (current_directiveset == NULL) {
421
if (current_directive->_c1_store->parse_and_add_inline(s, error_msg)) {
422
if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) {
423
assert (error_msg != NULL, "Must have valid error message");
424
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
425
}
426
} else {
427
assert (error_msg != NULL, "Must have valid error message");
428
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
429
}
430
} else {
431
if (!current_directiveset->parse_and_add_inline(s, error_msg)) {
432
assert (error_msg != NULL, "Must have valid error message");
433
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
434
}
435
}
436
FREE_C_HEAP_ARRAY(char, s);
437
}
438
break;
439
440
case type_c1:
441
current_directiveset = current_directive->_c1_store;
442
if (t != JSON_TRUE && t != JSON_FALSE) {
443
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
444
return false;
445
}
446
break;
447
448
case type_c2:
449
current_directiveset = current_directive->_c2_store;
450
if (t != JSON_TRUE && t != JSON_FALSE) {
451
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
452
return false;
453
}
454
break;
455
456
default:
457
break;
458
}
459
460
return true;
461
}
462
463
bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) {
464
const key* k;
465
466
if (depth == 0) {
467
switch (t) {
468
case JSON_ARRAY_BEGIN:
469
return push_key(&dir_array_key);
470
471
case JSON_OBJECT_BEGIN:
472
// push synthetic dir_array
473
push_key(&dir_array_key);
474
assert(depth == 1, "Make sure the stack are aligned with the directives");
475
break;
476
477
default:
478
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
479
return false;
480
}
481
}
482
if (depth == 1) {
483
switch (t) {
484
case JSON_OBJECT_BEGIN:
485
// Parsing a new directive.
486
current_directive = new CompilerDirectives();
487
return push_key(&dir_key);
488
489
case JSON_ARRAY_END:
490
k = pop_key();
491
492
if (k->type != type_dir_array) {
493
error(SYNTAX_ERROR, "Expected end of directives array");
494
return false;
495
}
496
return true;
497
498
default:
499
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
500
return false;
501
}
502
} else {
503
switch (t) {
504
case JSON_OBJECT_BEGIN:
505
k = current_key();
506
switch (k->type) {
507
case type_c1:
508
current_directiveset = current_directive->_c1_store;
509
return true;
510
case type_c2:
511
current_directiveset = current_directive->_c2_store;
512
return true;
513
514
case type_dir_array:
515
return push_key(&dir_key);
516
517
default:
518
error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name);
519
return false;
520
}
521
return false;
522
523
case JSON_OBJECT_END:
524
k = pop_key();
525
switch (k->type) {
526
case type_c1:
527
case type_c2:
528
// This is how we now if options apply to a single or both directive sets
529
current_directiveset = NULL;
530
break;
531
532
case type_directives:
533
// Check, finish and push to stack!
534
if (current_directive->match() == NULL) {
535
error(INTERNAL_ERROR, "Directive missing required match.");
536
return false;
537
}
538
current_directive->finalize(_st);
539
push_tmp(current_directive);
540
current_directive = NULL;
541
break;
542
543
default:
544
error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
545
ShouldNotReachHere();
546
return false;
547
}
548
return true;
549
550
case JSON_ARRAY_BEGIN:
551
k = current_key();
552
if (!(k->allow_array_value)) {
553
if (k->type == type_dir_array) {
554
error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
555
} else {
556
error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
557
}
558
return false;
559
}
560
return push_key(&value_array_key);
561
562
case JSON_ARRAY_END:
563
k = pop_key(); // Pop multi value marker
564
assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
565
k = pop_key(); // Pop key for option that was set
566
return true;
567
568
case JSON_KEY:
569
return push_key(v->str.start, v->str.length);
570
571
case JSON_STRING:
572
case JSON_NUMBER_INT:
573
case JSON_NUMBER_FLOAT:
574
case JSON_TRUE:
575
case JSON_FALSE:
576
case JSON_NULL:
577
return set_option(t, v);
578
579
default:
580
error(INTERNAL_ERROR, "Unknown JSON type: %d.", t);
581
ShouldNotReachHere();
582
return false;
583
}
584
}
585
}
586
587
588