hotspot/src/share/vm/compiler/directivesParser.cpp
changeset 33451 0712796e4039
child 33480 e4cef6796874
equal deleted inserted replaced
33450:08222df07d0d 33451:0712796e4039
       
     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