|
1 /* |
|
2 * Copyright (c) 2015, 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 "runtime/os.hpp" |
|
30 #include <string.h> |
|
31 |
|
32 void DirectivesParser::push_tmp(CompilerDirectives* dir) { |
|
33 dir->set_next(_tmp_top); |
|
34 _tmp_top = dir; |
|
35 } |
|
36 |
|
37 CompilerDirectives* DirectivesParser::pop_tmp() { |
|
38 if (_tmp_top == NULL) { |
|
39 return NULL; |
|
40 } |
|
41 CompilerDirectives* tmp = _tmp_top; |
|
42 _tmp_top = _tmp_top->next(); |
|
43 tmp->set_next(NULL); |
|
44 return tmp; |
|
45 } |
|
46 |
|
47 bool DirectivesParser::parse_string(const char* text, outputStream* st) { |
|
48 DirectivesParser cd(text, st); |
|
49 if (cd.valid()) { |
|
50 return cd.install_directives(); |
|
51 } |
|
52 st->flush(); |
|
53 st->print_cr("Parsing of compiler directives failed"); |
|
54 return false; |
|
55 } |
|
56 |
|
57 bool DirectivesParser::has_file() { |
|
58 return CompilerDirectivesFile != NULL; |
|
59 } |
|
60 |
|
61 bool DirectivesParser::parse_from_flag() { |
|
62 return parse_from_file(CompilerDirectivesFile, tty); |
|
63 } |
|
64 |
|
65 bool DirectivesParser::parse_from_file(const char* filename, outputStream* st) { |
|
66 assert(filename != NULL, "Test before calling this"); |
|
67 if (!parse_from_file_inner(filename, st)) { |
|
68 st->print_cr("Could not load file: %s", filename); |
|
69 return false; |
|
70 } |
|
71 return true; |
|
72 } |
|
73 |
|
74 bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream) { |
|
75 struct stat st; |
|
76 ResourceMark rm; |
|
77 if (os::stat(filename, &st) == 0) { |
|
78 // found file, open it |
|
79 int file_handle = os::open(filename, 0, 0); |
|
80 if (file_handle != -1) { |
|
81 // read contents into resource array |
|
82 char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1); |
|
83 size_t num_read = os::read(file_handle, (char*) buffer, st.st_size); |
|
84 buffer[num_read] = '\0'; |
|
85 // close file |
|
86 os::close(file_handle); |
|
87 return parse_string(buffer, stream); |
|
88 } |
|
89 } |
|
90 return false; |
|
91 } |
|
92 |
|
93 bool DirectivesParser::install_directives() { |
|
94 // Pop from internal temporary stack and push to compileBroker. |
|
95 CompilerDirectives* tmp = pop_tmp(); |
|
96 int i = 0; |
|
97 while (tmp != NULL) { |
|
98 i++; |
|
99 DirectivesStack::push(tmp); |
|
100 tmp = pop_tmp(); |
|
101 } |
|
102 if (i == 0) { |
|
103 _st->print_cr("No directives in file"); |
|
104 return false; |
|
105 } else { |
|
106 _st->print_cr("%i compiler directives added", i); |
|
107 if (PrintCompilerDirectives) { |
|
108 // Print entire directives stack after new has been pushed. |
|
109 DirectivesStack::print(_st); |
|
110 } |
|
111 return true; |
|
112 } |
|
113 } |
|
114 |
|
115 DirectivesParser::DirectivesParser(const char* text, outputStream* st) |
|
116 : JSON(text, false, st), depth(0), current_directive(NULL), current_directiveset(NULL), _tmp_top(NULL) { |
|
117 #ifndef PRODUCT |
|
118 memset(stack, 0, MAX_DEPTH * sizeof(stack[0])); |
|
119 #endif |
|
120 parse(); |
|
121 } |
|
122 |
|
123 DirectivesParser::~DirectivesParser() { |
|
124 } |
|
125 |
|
126 const DirectivesParser::key DirectivesParser::keys[] = { |
|
127 // name, keytype, allow_array, allowed_mask, set_function |
|
128 { "c1", type_c1, 0, mask(type_directives), NULL, UnknownFlagType }, |
|
129 { "c2", type_c2, 0, mask(type_directives), NULL, UnknownFlagType }, |
|
130 { "match", type_match, 1, mask(type_directives), NULL, UnknownFlagType }, |
|
131 { "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType }, |
|
132 { "enable", type_enable, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType }, |
|
133 { "preset", type_preset, 0, mask(type_c1) | mask(type_c2), NULL, UnknownFlagType }, |
|
134 |
|
135 // Global flags |
|
136 #define common_flag_key(name, type, dvalue, compiler) \ |
|
137 { #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag}, |
|
138 compilerdirectives_common_flags(common_flag_key) |
|
139 compilerdirectives_c2_flags(common_flag_key) |
|
140 compilerdirectives_c1_flags(common_flag_key) |
|
141 #undef common_flag_key |
|
142 }; |
|
143 |
|
144 const DirectivesParser::key DirectivesParser::dir_array_key = { |
|
145 "top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level |
|
146 }; |
|
147 const DirectivesParser::key DirectivesParser::dir_key = { |
|
148 "top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level |
|
149 }; |
|
150 const DirectivesParser::key DirectivesParser::value_array_key = { |
|
151 "value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key |
|
152 }; |
|
153 |
|
154 const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) { |
|
155 for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) { |
|
156 if (strncasecmp(keys[i].name, str, len) == 0) { |
|
157 return &keys[i]; |
|
158 } |
|
159 } |
|
160 return NULL; |
|
161 } |
|
162 |
|
163 uint DirectivesParser::mask(keytype kt) { |
|
164 return 1 << (kt + 1); |
|
165 } |
|
166 |
|
167 bool DirectivesParser::push_key(const char* str, size_t len) { |
|
168 bool result = true; |
|
169 const key* k = lookup_key(str, len); |
|
170 |
|
171 if (k == NULL) { |
|
172 // os::strdup |
|
173 char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler); |
|
174 strncpy(s, str, len); |
|
175 s[len] = '\0'; |
|
176 error(KEY_ERROR, "No such key: '%s'.", s); |
|
177 FREE_C_HEAP_ARRAY(char, s); |
|
178 return false; |
|
179 } |
|
180 |
|
181 return push_key(k); |
|
182 } |
|
183 |
|
184 bool DirectivesParser::push_key(const key* k) { |
|
185 assert(k->allowedmask != 0, "not allowed anywhere?"); |
|
186 |
|
187 // Exceeding the stack should not be possible with a valid compiler directive, |
|
188 // and an invalid should abort before this happens |
|
189 assert(depth < MAX_DEPTH, "exceeded stack depth"); |
|
190 if (depth >= MAX_DEPTH) { |
|
191 error(INTERNAL_ERROR, "Stack depth exceeded."); |
|
192 return false; |
|
193 } |
|
194 |
|
195 assert(stack[depth] == NULL, "element not nulled, something is wrong"); |
|
196 |
|
197 if (depth == 0 && !(k->allowedmask & 1)) { |
|
198 error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name); |
|
199 return false; |
|
200 } |
|
201 |
|
202 if (depth > 0) { |
|
203 const key* prev = stack[depth - 1]; |
|
204 if (!(k->allowedmask & mask(prev->type))) { |
|
205 error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name); |
|
206 return false; |
|
207 } |
|
208 } |
|
209 |
|
210 stack[depth] = k; |
|
211 depth++; |
|
212 return true; |
|
213 } |
|
214 |
|
215 const DirectivesParser::key* DirectivesParser::current_key() { |
|
216 assert(depth > 0, "getting key from empty stack"); |
|
217 if (depth == 0) { |
|
218 return NULL; |
|
219 } |
|
220 return stack[depth - 1]; |
|
221 } |
|
222 |
|
223 const DirectivesParser::key* DirectivesParser::pop_key() { |
|
224 assert(depth > 0, "popping empty stack"); |
|
225 if (depth == 0) { |
|
226 error(INTERNAL_ERROR, "Popping empty stack."); |
|
227 return NULL; |
|
228 } |
|
229 depth--; |
|
230 |
|
231 const key* k = stack[depth]; |
|
232 #ifndef PRODUCT |
|
233 stack[depth] = NULL; |
|
234 #endif |
|
235 |
|
236 return k; |
|
237 } |
|
238 |
|
239 bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) { |
|
240 |
|
241 void (DirectiveSet::*test)(void *args); |
|
242 test = option_key->set; |
|
243 |
|
244 switch (t) { |
|
245 case JSON_TRUE: |
|
246 if (option_key->flag_type != boolFlag) { |
|
247 error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]); |
|
248 return false; |
|
249 } else { |
|
250 bool val = true; |
|
251 (set->*test)((void *)&val); |
|
252 } |
|
253 break; |
|
254 |
|
255 case JSON_FALSE: |
|
256 if (option_key->flag_type != boolFlag) { |
|
257 error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]); |
|
258 return false; |
|
259 } else { |
|
260 bool val = false; |
|
261 (set->*test)((void *)&val); |
|
262 } |
|
263 break; |
|
264 |
|
265 case JSON_NUMBER_INT: |
|
266 if (option_key->flag_type != intxFlag) { |
|
267 if (option_key->flag_type == doubleFlag) { |
|
268 double dval = (double)v->int_value; |
|
269 (set->*test)((void *)&dval); |
|
270 break; |
|
271 } |
|
272 error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]); |
|
273 return false; |
|
274 } else { |
|
275 intx ival = v->int_value; |
|
276 (set->*test)((void *)&ival); |
|
277 } |
|
278 break; |
|
279 |
|
280 case JSON_NUMBER_FLOAT: |
|
281 if (option_key->flag_type != doubleFlag) { |
|
282 error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]); |
|
283 return false; |
|
284 } else { |
|
285 double dval = v->double_value; |
|
286 (set->*test)((void *)&dval); |
|
287 } |
|
288 break; |
|
289 |
|
290 case JSON_STRING: |
|
291 if (option_key->flag_type != ccstrFlag) { |
|
292 error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]); |
|
293 return false; |
|
294 } else { |
|
295 char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1, mtCompiler); |
|
296 strncpy(s, v->str.start, v->str.length + 1); |
|
297 s[v->str.length] = '\0'; |
|
298 (set->*test)((void *)&s); |
|
299 } |
|
300 break; |
|
301 |
|
302 default: |
|
303 assert(0, "Should not reach here."); |
|
304 } |
|
305 return true; |
|
306 } |
|
307 |
|
308 bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) { |
|
309 |
|
310 const key* option_key = pop_key(); |
|
311 const key* enclosing_key = current_key(); |
|
312 |
|
313 if (option_key->type == value_array_key.type) { |
|
314 // Multi value array, we are really setting the value |
|
315 // for the key one step further up. |
|
316 option_key = pop_key(); |
|
317 enclosing_key = current_key(); |
|
318 |
|
319 // Repush option_key and multi value marker, since |
|
320 // we need to keep them until all multi values are set. |
|
321 push_key(option_key); |
|
322 push_key(&value_array_key); |
|
323 } |
|
324 |
|
325 switch (option_key->type) { |
|
326 case type_flag: |
|
327 { |
|
328 if (current_directiveset == NULL) { |
|
329 assert(depth == 2, "Must not have active directive set"); |
|
330 |
|
331 if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) { |
|
332 return false; |
|
333 } |
|
334 if(!set_option_flag(t, v, option_key, current_directive->_c2_store)) { |
|
335 return false; |
|
336 } |
|
337 } else { |
|
338 assert(depth > 2, "Must have active current directive set"); |
|
339 if (!set_option_flag(t, v, option_key, current_directiveset)) { |
|
340 return false; |
|
341 } |
|
342 } |
|
343 break; |
|
344 } |
|
345 |
|
346 case type_match: |
|
347 if (t != JSON_STRING) { |
|
348 error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name); |
|
349 return false; |
|
350 } |
|
351 if (enclosing_key->type != type_directives) { |
|
352 error(SYNTAX_ERROR, "Match keyword can only exist inside a directive"); |
|
353 return false; |
|
354 } |
|
355 { |
|
356 char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler); |
|
357 strncpy(s, v->str.start, v->str.length); |
|
358 s[v->str.length] = '\0'; |
|
359 |
|
360 const char* error_msg = NULL; |
|
361 if (!current_directive->add_match(s, error_msg)) { |
|
362 assert (error_msg != NULL, "Must have valid error message"); |
|
363 error(VALUE_ERROR, "Method pattern error: %s", error_msg); |
|
364 } |
|
365 FREE_C_HEAP_ARRAY(char, s); |
|
366 } |
|
367 break; |
|
368 |
|
369 case type_inline: |
|
370 if (t != JSON_STRING) { |
|
371 error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name); |
|
372 return false; |
|
373 } |
|
374 { |
|
375 //char* s = strndup(v->str.start, v->str.length); |
|
376 char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler); |
|
377 strncpy(s, v->str.start, v->str.length); |
|
378 s[v->str.length] = '\0'; |
|
379 |
|
380 const char* error_msg = NULL; |
|
381 if (current_directiveset == NULL) { |
|
382 if (!current_directive->_c1_store->parse_and_add_inline(s, error_msg)) { |
|
383 assert (error_msg != NULL, "Must have valid error message"); |
|
384 error(VALUE_ERROR, "Method pattern error: %s", error_msg); |
|
385 } |
|
386 if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) { |
|
387 assert (error_msg != NULL, "Must have valid error message"); |
|
388 error(VALUE_ERROR, "Method pattern error: %s", error_msg); |
|
389 } |
|
390 } else { |
|
391 if (!current_directiveset->parse_and_add_inline(s, error_msg)) { |
|
392 assert (error_msg != NULL, "Must have valid error message"); |
|
393 error(VALUE_ERROR, "Method pattern error: %s", error_msg); |
|
394 } |
|
395 } |
|
396 FREE_C_HEAP_ARRAY(char, s); |
|
397 } |
|
398 break; |
|
399 |
|
400 case type_c1: |
|
401 current_directiveset = current_directive->_c1_store; |
|
402 if (t != JSON_TRUE && t != JSON_FALSE) { |
|
403 error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name); |
|
404 return false; |
|
405 } |
|
406 break; |
|
407 |
|
408 case type_c2: |
|
409 current_directiveset = current_directive->_c2_store; |
|
410 if (t != JSON_TRUE && t != JSON_FALSE) { |
|
411 error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name); |
|
412 return false; |
|
413 } |
|
414 break; |
|
415 |
|
416 case type_enable: |
|
417 switch (enclosing_key->type) { |
|
418 case type_c1: |
|
419 case type_c2: |
|
420 { |
|
421 if (t != JSON_TRUE && t != JSON_FALSE) { |
|
422 error(VALUE_ERROR, "Key of type %s enclosed in a %s key needs a true or false value", option_key->name, enclosing_key->name); |
|
423 return false; |
|
424 } |
|
425 int val = (t == JSON_TRUE); |
|
426 current_directiveset->set_Enable(&val); |
|
427 break; |
|
428 } |
|
429 |
|
430 case type_directives: |
|
431 error(VALUE_ERROR, "Enable keyword not available for generic directive"); |
|
432 return false; |
|
433 |
|
434 default: |
|
435 error(INTERNAL_ERROR, "Unexpected enclosing type for key %s: %s", option_key->name, enclosing_key->name); |
|
436 ShouldNotReachHere(); |
|
437 return false; |
|
438 } |
|
439 break; |
|
440 |
|
441 default: |
|
442 break; |
|
443 } |
|
444 |
|
445 return true; |
|
446 } |
|
447 |
|
448 bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) { |
|
449 const key* k; |
|
450 |
|
451 if (depth == 0) { |
|
452 switch (t) { |
|
453 case JSON_ARRAY_BEGIN: |
|
454 return push_key(&dir_array_key); |
|
455 |
|
456 case JSON_OBJECT_BEGIN: |
|
457 // push synthetic dir_array |
|
458 push_key(&dir_array_key); |
|
459 assert(depth == 1, "Make sure the stack are aligned with the directives"); |
|
460 break; |
|
461 |
|
462 default: |
|
463 error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive."); |
|
464 return false; |
|
465 } |
|
466 } |
|
467 if (depth == 1) { |
|
468 switch (t) { |
|
469 case JSON_OBJECT_BEGIN: |
|
470 // Parsing a new directive. |
|
471 current_directive = new CompilerDirectives(); |
|
472 return push_key(&dir_key); |
|
473 |
|
474 case JSON_ARRAY_END: |
|
475 k = pop_key(); |
|
476 |
|
477 if (k->type != type_dir_array) { |
|
478 error(SYNTAX_ERROR, "Expected end of directives array"); |
|
479 return false; |
|
480 } |
|
481 return true; |
|
482 |
|
483 default: |
|
484 error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive."); |
|
485 return false; |
|
486 } |
|
487 } else { |
|
488 switch (t) { |
|
489 case JSON_OBJECT_BEGIN: |
|
490 k = current_key(); |
|
491 switch (k->type) { |
|
492 case type_c1: |
|
493 current_directiveset = current_directive->_c1_store; |
|
494 return true; |
|
495 case type_c2: |
|
496 current_directiveset = current_directive->_c2_store; |
|
497 return true; |
|
498 |
|
499 case type_dir_array: |
|
500 return push_key(&dir_key); |
|
501 |
|
502 default: |
|
503 error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name); |
|
504 return false; |
|
505 } |
|
506 return false; |
|
507 |
|
508 case JSON_OBJECT_END: |
|
509 k = pop_key(); |
|
510 switch (k->type) { |
|
511 case type_c1: |
|
512 case type_c2: |
|
513 // This is how we now if options apply to a single or both directive sets |
|
514 current_directiveset = NULL; |
|
515 break; |
|
516 |
|
517 case type_directives: |
|
518 // Check, finish and push to stack! |
|
519 if (current_directive->match() == NULL) { |
|
520 error(INTERNAL_ERROR, "Directive missing required match."); |
|
521 return false; |
|
522 } |
|
523 current_directive->finalize(); |
|
524 push_tmp(current_directive); |
|
525 current_directive = NULL; |
|
526 break; |
|
527 |
|
528 default: |
|
529 error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name); |
|
530 ShouldNotReachHere(); |
|
531 return false; |
|
532 } |
|
533 return true; |
|
534 |
|
535 case JSON_ARRAY_BEGIN: |
|
536 k = current_key(); |
|
537 if (!(k->allow_array_value)) { |
|
538 if (k->type == type_dir_array) { |
|
539 error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object."); |
|
540 } else { |
|
541 error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name); |
|
542 } |
|
543 return false; |
|
544 } |
|
545 return push_key(&value_array_key); |
|
546 |
|
547 case JSON_ARRAY_END: |
|
548 k = pop_key(); // Pop multi value marker |
|
549 assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value"); |
|
550 k = pop_key(); // Pop key for option that was set |
|
551 return true; |
|
552 |
|
553 case JSON_KEY: |
|
554 return push_key(v->str.start, v->str.length); |
|
555 |
|
556 case JSON_STRING: |
|
557 case JSON_NUMBER_INT: |
|
558 case JSON_NUMBER_FLOAT: |
|
559 case JSON_TRUE: |
|
560 case JSON_FALSE: |
|
561 case JSON_NULL: |
|
562 return set_option(t, v); |
|
563 |
|
564 default: |
|
565 error(INTERNAL_ERROR, "Unknown JSON type: %d.", t); |
|
566 ShouldNotReachHere(); |
|
567 return false; |
|
568 } |
|
569 } |
|
570 } |
|
571 |
|
572 #ifndef PRODUCT |
|
573 void DirectivesParser::test(const char* text, bool should_pass) { |
|
574 DirectivesParser cd(text, tty); |
|
575 if (should_pass) { |
|
576 assert(cd.valid() == true, "failed on a valid DirectivesParser string"); |
|
577 if (VerboseInternalVMTests) { |
|
578 tty->print("-- DirectivesParser test passed as expected --\n"); |
|
579 } |
|
580 } else { |
|
581 assert(cd.valid() == false, "succeeded on an invalid DirectivesParser string"); |
|
582 if (VerboseInternalVMTests) { |
|
583 tty->print("-- DirectivesParser test failed as expected --\n"); |
|
584 } |
|
585 } |
|
586 } |
|
587 |
|
588 bool DirectivesParser::test() { |
|
589 DirectivesParser::test("{}", false); |
|
590 DirectivesParser::test("[]", true); |
|
591 DirectivesParser::test("[{}]", false); |
|
592 DirectivesParser::test("[{},{}]", false); |
|
593 DirectivesParser::test("{},{}", false); |
|
594 |
|
595 DirectivesParser::test( |
|
596 "[" "\n" |
|
597 " {" "\n" |
|
598 " match: \"foo/bar.*\"," "\n" |
|
599 " inline : \"+java/util.*\"," "\n" |
|
600 " PrintAssembly: true," "\n" |
|
601 " BreakAtExecute: true," "\n" |
|
602 " }" "\n" |
|
603 "]" "\n", true); |
|
604 |
|
605 DirectivesParser::test( |
|
606 "[" "\n" |
|
607 " [" "\n" |
|
608 " {" "\n" |
|
609 " match: \"foo/bar.*\"," "\n" |
|
610 " inline : \"+java/util.*\"," "\n" |
|
611 " PrintAssembly: true," "\n" |
|
612 " BreakAtExecute: true," "\n" |
|
613 " }" "\n" |
|
614 " ]" "\n" |
|
615 "]" "\n", false); |
|
616 |
|
617 /*DirectivesParser::test( |
|
618 "[" "\n" |
|
619 " {" "\n" |
|
620 " match: \"foo/bar.*\"," "\n" |
|
621 " c1: {" |
|
622 " PrintIntrinsics: false," "\n" |
|
623 " }" "\n" |
|
624 " }" "\n" |
|
625 "]" "\n", false);*/ |
|
626 |
|
627 DirectivesParser::test( |
|
628 "[" "\n" |
|
629 " {" "\n" |
|
630 " match: \"foo/bar.*\"," "\n" |
|
631 " c2: {" "\n" |
|
632 " PrintInlining: false," "\n" |
|
633 " }" "\n" |
|
634 " }" "\n" |
|
635 "]" "\n", true); |
|
636 |
|
637 DirectivesParser::test( |
|
638 "[" "\n" |
|
639 " {" "\n" |
|
640 " match: \"foo/bar.*\"," "\n" |
|
641 " PrintInlining: [" "\n" |
|
642 " true," "\n" |
|
643 " false" "\n" |
|
644 " ]," "\n" |
|
645 " }" "\n" |
|
646 "]" "\n", false); |
|
647 |
|
648 DirectivesParser::test( |
|
649 "[" "\n" |
|
650 " {" |
|
651 " // pattern to match against class+method+signature" "\n" |
|
652 " // leading and trailing wildcard (*) allowed" "\n" |
|
653 " match: \"foo/bar.*\"," "\n" |
|
654 "" "\n" |
|
655 " // override defaults for specified compiler" "\n" |
|
656 " // we may differentiate between levels too. TBD." "\n" |
|
657 " c1: {" "\n" |
|
658 " //override c1 presets " "\n" |
|
659 " DumpReplay: false," "\n" |
|
660 " BreakAtCompile: true," "\n" |
|
661 " }," "\n" |
|
662 "" "\n" |
|
663 " c2: {" "\n" |
|
664 " // control inlining of method" "\n" |
|
665 " // + force inline, - dont inline" "\n" |
|
666 " inline : \"+java/util.*\"," "\n" |
|
667 " PrintInlining: true," "\n" |
|
668 " }," "\n" |
|
669 "" "\n" |
|
670 " // directives outside a specific preset applies to all compilers" "\n" |
|
671 " inline : [ \"+java/util.*\", \"-com/sun.*\"]," "\n" |
|
672 " BreakAtExecute: true," "\n" |
|
673 " Log: true," "\n" |
|
674 " }," "\n" |
|
675 " {" "\n" |
|
676 " // matching several patterns require an array" "\n" |
|
677 " match: [\"baz.*\",\"frob.*\"]," "\n" |
|
678 "" "\n" |
|
679 " // applies to all compilers" "\n" |
|
680 " // + force inline, - dont inline" "\n" |
|
681 " inline : [ \"+java/util.*\", \"-com/sun.*\" ]," "\n" |
|
682 " PrintInlining: true," "\n" |
|
683 "" "\n" |
|
684 " // force matching compiles to be blocking/syncronous" "\n" |
|
685 " PrintNMethods: true" "\n" |
|
686 " }," "\n" |
|
687 "]" "\n", true); |
|
688 |
|
689 // Test max stack depth |
|
690 DirectivesParser::test( |
|
691 "[" "\n" // depth 1: type_dir_array |
|
692 " {" "\n" // depth 2: type_directives |
|
693 " match: \"*.*\"," // match required |
|
694 " c1:" "\n" // depth 3: type_c1 |
|
695 " {" "\n" |
|
696 " inline:" "\n" // depth 4: type_inline |
|
697 " [" "\n" // depth 5: type_value_array |
|
698 " \"foo\"," "\n" |
|
699 " \"bar\"," "\n" |
|
700 " ]" "\n" // depth 3: pop type_value_array and type_inline keys |
|
701 " }" "\n" // depth 2: pop type_c1 key |
|
702 " }" "\n" // depth 1: pop type_directives key |
|
703 "]" "\n", true); // depth 0: pop type_dir_array key |
|
704 |
|
705 // Test max stack depth |
|
706 DirectivesParser::test( |
|
707 "[{c1:{c1:{c1:{c1:{c1:{c1:{c1:{}}}}}}}}]", false); |
|
708 |
|
709 DirectivesParser::test( |
|
710 "[" "\n" |
|
711 " {" "\n" |
|
712 " c1: true," "\n" |
|
713 " c2: true," "\n" |
|
714 " match: true," "\n" |
|
715 " inline: true," "\n" |
|
716 " enable: true," "\n" |
|
717 " c1: {" "\n" |
|
718 " preset: true," "\n" |
|
719 " }" "\n" |
|
720 " }" "\n" |
|
721 "]" "\n", false); |
|
722 |
|
723 return true; |
|
724 } |
|
725 |
|
726 #endif |