1.1 --- a/src/share/vm/ci/ciReplay.cpp Wed Jan 08 12:05:19 2014 +0100 1.2 +++ b/src/share/vm/ci/ciReplay.cpp Wed Jan 08 10:25:50 2014 -0800 1.3 @@ -24,6 +24,8 @@ 1.4 #include "precompiled.hpp" 1.5 #include "ci/ciMethodData.hpp" 1.6 #include "ci/ciReplay.hpp" 1.7 +#include "ci/ciSymbol.hpp" 1.8 +#include "ci/ciKlass.hpp" 1.9 #include "ci/ciUtilities.hpp" 1.10 #include "compiler/compileBroker.hpp" 1.11 #include "memory/allocation.inline.hpp" 1.12 @@ -37,74 +39,107 @@ 1.13 // ciReplay 1.14 1.15 typedef struct _ciMethodDataRecord { 1.16 - const char* klass; 1.17 - const char* method; 1.18 - const char* signature; 1.19 - int state; 1.20 - int current_mileage; 1.21 - intptr_t* data; 1.22 - int data_length; 1.23 - char* orig_data; 1.24 - int orig_data_length; 1.25 - int oops_length; 1.26 - jobject* oops_handles; 1.27 - int* oops_offsets; 1.28 + const char* _klass_name; 1.29 + const char* _method_name; 1.30 + const char* _signature; 1.31 + 1.32 + int _state; 1.33 + int _current_mileage; 1.34 + 1.35 + intptr_t* _data; 1.36 + char* _orig_data; 1.37 + jobject* _oops_handles; 1.38 + int* _oops_offsets; 1.39 + int _data_length; 1.40 + int _orig_data_length; 1.41 + int _oops_length; 1.42 } ciMethodDataRecord; 1.43 1.44 typedef struct _ciMethodRecord { 1.45 - const char* klass; 1.46 - const char* method; 1.47 - const char* signature; 1.48 - int instructions_size; 1.49 - int interpreter_invocation_count; 1.50 - int interpreter_throwout_count; 1.51 - int invocation_counter; 1.52 - int backedge_counter; 1.53 + const char* _klass_name; 1.54 + const char* _method_name; 1.55 + const char* _signature; 1.56 + 1.57 + int _instructions_size; 1.58 + int _interpreter_invocation_count; 1.59 + int _interpreter_throwout_count; 1.60 + int _invocation_counter; 1.61 + int _backedge_counter; 1.62 } ciMethodRecord; 1.63 1.64 -class CompileReplay; 1.65 +typedef struct _ciInlineRecord { 1.66 + const char* _klass_name; 1.67 + const char* _method_name; 1.68 + const char* _signature; 1.69 + 1.70 + int _inline_depth; 1.71 + int _inline_bci; 1.72 +} ciInlineRecord; 1.73 + 1.74 +class CompileReplay; 1.75 static CompileReplay* replay_state; 1.76 1.77 class CompileReplay : public StackObj { 1.78 private: 1.79 - FILE* stream; 1.80 - Thread* thread; 1.81 - Handle protection_domain; 1.82 - Handle loader; 1.83 + FILE* _stream; 1.84 + Thread* _thread; 1.85 + Handle _protection_domain; 1.86 + Handle _loader; 1.87 1.88 - GrowableArray<ciMethodRecord*> ci_method_records; 1.89 - GrowableArray<ciMethodDataRecord*> ci_method_data_records; 1.90 + GrowableArray<ciMethodRecord*> _ci_method_records; 1.91 + GrowableArray<ciMethodDataRecord*> _ci_method_data_records; 1.92 + 1.93 + // Use pointer because we may need to return inline records 1.94 + // without destroying them. 1.95 + GrowableArray<ciInlineRecord*>* _ci_inline_records; 1.96 1.97 const char* _error_message; 1.98 1.99 - char* bufptr; 1.100 - char* buffer; 1.101 - int buffer_length; 1.102 - int buffer_end; 1.103 - int line_no; 1.104 + char* _bufptr; 1.105 + char* _buffer; 1.106 + int _buffer_length; 1.107 + int _buffer_pos; 1.108 + 1.109 + // "compile" data 1.110 + ciKlass* _iklass; 1.111 + Method* _imethod; 1.112 + int _entry_bci; 1.113 + int _comp_level; 1.114 1.115 public: 1.116 CompileReplay(const char* filename, TRAPS) { 1.117 - thread = THREAD; 1.118 - loader = Handle(thread, SystemDictionary::java_system_loader()); 1.119 - stream = fopen(filename, "rt"); 1.120 - if (stream == NULL) { 1.121 + _thread = THREAD; 1.122 + _loader = Handle(_thread, SystemDictionary::java_system_loader()); 1.123 + _protection_domain = Handle(); 1.124 + 1.125 + _stream = fopen(filename, "rt"); 1.126 + if (_stream == NULL) { 1.127 fprintf(stderr, "ERROR: Can't open replay file %s\n", filename); 1.128 } 1.129 - buffer_length = 32; 1.130 - buffer = NEW_RESOURCE_ARRAY(char, buffer_length); 1.131 + 1.132 + _ci_inline_records = NULL; 1.133 _error_message = NULL; 1.134 1.135 + _buffer_length = 32; 1.136 + _buffer = NEW_RESOURCE_ARRAY(char, _buffer_length); 1.137 + _bufptr = _buffer; 1.138 + _buffer_pos = 0; 1.139 + 1.140 + _imethod = NULL; 1.141 + _iklass = NULL; 1.142 + _entry_bci = 0; 1.143 + _comp_level = 0; 1.144 + 1.145 test(); 1.146 } 1.147 1.148 ~CompileReplay() { 1.149 - if (stream != NULL) fclose(stream); 1.150 + if (_stream != NULL) fclose(_stream); 1.151 } 1.152 1.153 void test() { 1.154 - strcpy(buffer, "1 2 foo 4 bar 0x9 \"this is it\""); 1.155 - bufptr = buffer; 1.156 + strcpy(_buffer, "1 2 foo 4 bar 0x9 \"this is it\""); 1.157 + _bufptr = _buffer; 1.158 assert(parse_int("test") == 1, "what"); 1.159 assert(parse_int("test") == 2, "what"); 1.160 assert(strcmp(parse_string(), "foo") == 0, "what"); 1.161 @@ -115,18 +150,18 @@ 1.162 } 1.163 1.164 bool had_error() { 1.165 - return _error_message != NULL || thread->has_pending_exception(); 1.166 + return _error_message != NULL || _thread->has_pending_exception(); 1.167 } 1.168 1.169 bool can_replay() { 1.170 - return !(stream == NULL || had_error()); 1.171 + return !(_stream == NULL || had_error()); 1.172 } 1.173 1.174 void report_error(const char* msg) { 1.175 _error_message = msg; 1.176 - // Restore the buffer contents for error reporting 1.177 - for (int i = 0; i < buffer_end; i++) { 1.178 - if (buffer[i] == '\0') buffer[i] = ' '; 1.179 + // Restore the _buffer contents for error reporting 1.180 + for (int i = 0; i < _buffer_pos; i++) { 1.181 + if (_buffer[i] == '\0') _buffer[i] = ' '; 1.182 } 1.183 } 1.184 1.185 @@ -137,10 +172,10 @@ 1.186 1.187 int v = 0; 1.188 int read; 1.189 - if (sscanf(bufptr, "%i%n", &v, &read) != 1) { 1.190 + if (sscanf(_bufptr, "%i%n", &v, &read) != 1) { 1.191 report_error(label); 1.192 } else { 1.193 - bufptr += read; 1.194 + _bufptr += read; 1.195 } 1.196 return v; 1.197 } 1.198 @@ -152,31 +187,31 @@ 1.199 1.200 intptr_t v = 0; 1.201 int read; 1.202 - if (sscanf(bufptr, INTPTR_FORMAT "%n", &v, &read) != 1) { 1.203 + if (sscanf(_bufptr, INTPTR_FORMAT "%n", &v, &read) != 1) { 1.204 report_error(label); 1.205 } else { 1.206 - bufptr += read; 1.207 + _bufptr += read; 1.208 } 1.209 return v; 1.210 } 1.211 1.212 void skip_ws() { 1.213 // Skip any leading whitespace 1.214 - while (*bufptr == ' ' || *bufptr == '\t') { 1.215 - bufptr++; 1.216 + while (*_bufptr == ' ' || *_bufptr == '\t') { 1.217 + _bufptr++; 1.218 } 1.219 } 1.220 1.221 1.222 char* scan_and_terminate(char delim) { 1.223 - char* str = bufptr; 1.224 - while (*bufptr != delim && *bufptr != '\0') { 1.225 - bufptr++; 1.226 + char* str = _bufptr; 1.227 + while (*_bufptr != delim && *_bufptr != '\0') { 1.228 + _bufptr++; 1.229 } 1.230 - if (*bufptr != '\0') { 1.231 - *bufptr++ = '\0'; 1.232 + if (*_bufptr != '\0') { 1.233 + *_bufptr++ = '\0'; 1.234 } 1.235 - if (bufptr == str) { 1.236 + if (_bufptr == str) { 1.237 // nothing here 1.238 return NULL; 1.239 } 1.240 @@ -195,8 +230,8 @@ 1.241 1.242 skip_ws(); 1.243 1.244 - if (*bufptr == '"') { 1.245 - bufptr++; 1.246 + if (*_bufptr == '"') { 1.247 + _bufptr++; 1.248 return scan_and_terminate('"'); 1.249 } else { 1.250 return scan_and_terminate(' '); 1.251 @@ -273,7 +308,12 @@ 1.252 const char* str = parse_escaped_string(); 1.253 Symbol* klass_name = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL); 1.254 if (klass_name != NULL) { 1.255 - Klass* k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD); 1.256 + Klass* k = NULL; 1.257 + if (_iklass != NULL) { 1.258 + k = (Klass*)_iklass->find_klass(ciSymbol::make(klass_name->as_C_string()))->constant_encoding(); 1.259 + } else { 1.260 + k = SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, THREAD); 1.261 + } 1.262 if (HAS_PENDING_EXCEPTION) { 1.263 oop throwable = PENDING_EXCEPTION; 1.264 java_lang_Throwable::print(throwable, tty); 1.265 @@ -289,7 +329,7 @@ 1.266 // Lookup a klass 1.267 Klass* resolve_klass(const char* klass, TRAPS) { 1.268 Symbol* klass_name = SymbolTable::lookup(klass, (int)strlen(klass), CHECK_NULL); 1.269 - return SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, CHECK_NULL); 1.270 + return SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, CHECK_NULL); 1.271 } 1.272 1.273 // Parse the standard tuple of <klass> <name> <signature> 1.274 @@ -304,40 +344,45 @@ 1.275 return m; 1.276 } 1.277 1.278 + int get_line(int c) { 1.279 + while(c != EOF) { 1.280 + if (_buffer_pos + 1 >= _buffer_length) { 1.281 + int new_length = _buffer_length * 2; 1.282 + // Next call will throw error in case of OOM. 1.283 + _buffer = REALLOC_RESOURCE_ARRAY(char, _buffer, _buffer_length, new_length); 1.284 + _buffer_length = new_length; 1.285 + } 1.286 + if (c == '\n') { 1.287 + c = getc(_stream); // get next char 1.288 + break; 1.289 + } else if (c == '\r') { 1.290 + // skip LF 1.291 + } else { 1.292 + _buffer[_buffer_pos++] = c; 1.293 + } 1.294 + c = getc(_stream); 1.295 + } 1.296 + // null terminate it, reset the pointer 1.297 + _buffer[_buffer_pos] = '\0'; // NL or EOF 1.298 + _buffer_pos = 0; 1.299 + _bufptr = _buffer; 1.300 + return c; 1.301 + } 1.302 + 1.303 // Process each line of the replay file executing each command until 1.304 // the file ends. 1.305 void process(TRAPS) { 1.306 - line_no = 1; 1.307 - int pos = 0; 1.308 - int c = getc(stream); 1.309 + int line_no = 1; 1.310 + int c = getc(_stream); 1.311 while(c != EOF) { 1.312 - if (pos + 1 >= buffer_length) { 1.313 - int newl = buffer_length * 2; 1.314 - char* newb = NEW_RESOURCE_ARRAY(char, newl); 1.315 - memcpy(newb, buffer, pos); 1.316 - buffer = newb; 1.317 - buffer_length = newl; 1.318 + c = get_line(c); 1.319 + process_command(CHECK); 1.320 + if (had_error()) { 1.321 + tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message); 1.322 + tty->print_cr("%s", _buffer); 1.323 + return; 1.324 } 1.325 - if (c == '\n') { 1.326 - // null terminate it, reset the pointer and process the line 1.327 - buffer[pos] = '\0'; 1.328 - buffer_end = pos++; 1.329 - bufptr = buffer; 1.330 - process_command(CHECK); 1.331 - if (had_error()) { 1.332 - tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message); 1.333 - tty->print_cr("%s", buffer); 1.334 - return; 1.335 - } 1.336 - pos = 0; 1.337 - buffer_end = 0; 1.338 - line_no++; 1.339 - } else if (c == '\r') { 1.340 - // skip LF 1.341 - } else { 1.342 - buffer[pos++] = c; 1.343 - } 1.344 - c = getc(stream); 1.345 + line_no++; 1.346 } 1.347 } 1.348 1.349 @@ -396,7 +441,37 @@ 1.350 return true; 1.351 } 1.352 1.353 - // compile <klass> <name> <signature> <entry_bci> <comp_level> 1.354 + // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ... 1.355 + void* process_inline(ciMethod* imethod, Method* m, int entry_bci, int comp_level, TRAPS) { 1.356 + _imethod = m; 1.357 + _iklass = imethod->holder(); 1.358 + _entry_bci = entry_bci; 1.359 + _comp_level = comp_level; 1.360 + int line_no = 1; 1.361 + int c = getc(_stream); 1.362 + while(c != EOF) { 1.363 + c = get_line(c); 1.364 + // Expecting only lines with "compile" command in inline replay file. 1.365 + char* cmd = parse_string(); 1.366 + if (cmd == NULL || strcmp("compile", cmd) != 0) { 1.367 + return NULL; 1.368 + } 1.369 + process_compile(CHECK_NULL); 1.370 + if (had_error()) { 1.371 + tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message); 1.372 + tty->print_cr("%s", _buffer); 1.373 + return NULL; 1.374 + } 1.375 + if (_ci_inline_records != NULL && _ci_inline_records->length() > 0) { 1.376 + // Found inlining record for the requested method. 1.377 + return _ci_inline_records; 1.378 + } 1.379 + line_no++; 1.380 + } 1.381 + return NULL; 1.382 + } 1.383 + 1.384 + // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ... 1.385 void process_compile(TRAPS) { 1.386 Method* method = parse_method(CHECK); 1.387 if (had_error()) return; 1.388 @@ -410,6 +485,43 @@ 1.389 if (!is_valid_comp_level(comp_level)) { 1.390 return; 1.391 } 1.392 + if (_imethod != NULL) { 1.393 + // Replay Inlining 1.394 + if (entry_bci != _entry_bci || comp_level != _comp_level) { 1.395 + return; 1.396 + } 1.397 + const char* iklass_name = _imethod->method_holder()->name()->as_utf8(); 1.398 + const char* imethod_name = _imethod->name()->as_utf8(); 1.399 + const char* isignature = _imethod->signature()->as_utf8(); 1.400 + const char* klass_name = method->method_holder()->name()->as_utf8(); 1.401 + const char* method_name = method->name()->as_utf8(); 1.402 + const char* signature = method->signature()->as_utf8(); 1.403 + if (strcmp(iklass_name, klass_name) != 0 || 1.404 + strcmp(imethod_name, method_name) != 0 || 1.405 + strcmp(isignature, signature) != 0) { 1.406 + return; 1.407 + } 1.408 + } 1.409 + int inline_count = 0; 1.410 + if (parse_tag_and_count("inline", inline_count)) { 1.411 + // Record inlining data 1.412 + _ci_inline_records = new GrowableArray<ciInlineRecord*>(); 1.413 + for (int i = 0; i < inline_count; i++) { 1.414 + int depth = parse_int("inline_depth"); 1.415 + int bci = parse_int("inline_bci"); 1.416 + if (had_error()) { 1.417 + break; 1.418 + } 1.419 + Method* inl_method = parse_method(CHECK); 1.420 + if (had_error()) { 1.421 + break; 1.422 + } 1.423 + new_ciInlineRecord(inl_method, bci, depth); 1.424 + } 1.425 + } 1.426 + if (_imethod != NULL) { 1.427 + return; // Replay Inlining 1.428 + } 1.429 Klass* k = method->method_holder(); 1.430 ((InstanceKlass*)k)->initialize(THREAD); 1.431 if (HAS_PENDING_EXCEPTION) { 1.432 @@ -442,11 +554,11 @@ 1.433 Method* method = parse_method(CHECK); 1.434 if (had_error()) return; 1.435 ciMethodRecord* rec = new_ciMethod(method); 1.436 - rec->invocation_counter = parse_int("invocation_counter"); 1.437 - rec->backedge_counter = parse_int("backedge_counter"); 1.438 - rec->interpreter_invocation_count = parse_int("interpreter_invocation_count"); 1.439 - rec->interpreter_throwout_count = parse_int("interpreter_throwout_count"); 1.440 - rec->instructions_size = parse_int("instructions_size"); 1.441 + rec->_invocation_counter = parse_int("invocation_counter"); 1.442 + rec->_backedge_counter = parse_int("backedge_counter"); 1.443 + rec->_interpreter_invocation_count = parse_int("interpreter_invocation_count"); 1.444 + rec->_interpreter_throwout_count = parse_int("interpreter_throwout_count"); 1.445 + rec->_instructions_size = parse_int("instructions_size"); 1.446 } 1.447 1.448 // ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length> 1.449 @@ -471,32 +583,32 @@ 1.450 1.451 // collect and record all the needed information for later 1.452 ciMethodDataRecord* rec = new_ciMethodData(method); 1.453 - rec->state = parse_int("state"); 1.454 - rec->current_mileage = parse_int("current_mileage"); 1.455 + rec->_state = parse_int("state"); 1.456 + rec->_current_mileage = parse_int("current_mileage"); 1.457 1.458 - rec->orig_data = parse_data("orig", rec->orig_data_length); 1.459 - if (rec->orig_data == NULL) { 1.460 + rec->_orig_data = parse_data("orig", rec->_orig_data_length); 1.461 + if (rec->_orig_data == NULL) { 1.462 return; 1.463 } 1.464 - rec->data = parse_intptr_data("data", rec->data_length); 1.465 - if (rec->data == NULL) { 1.466 + rec->_data = parse_intptr_data("data", rec->_data_length); 1.467 + if (rec->_data == NULL) { 1.468 return; 1.469 } 1.470 - if (!parse_tag_and_count("oops", rec->oops_length)) { 1.471 + if (!parse_tag_and_count("oops", rec->_oops_length)) { 1.472 return; 1.473 } 1.474 - rec->oops_handles = NEW_RESOURCE_ARRAY(jobject, rec->oops_length); 1.475 - rec->oops_offsets = NEW_RESOURCE_ARRAY(int, rec->oops_length); 1.476 - for (int i = 0; i < rec->oops_length; i++) { 1.477 + rec->_oops_handles = NEW_RESOURCE_ARRAY(jobject, rec->_oops_length); 1.478 + rec->_oops_offsets = NEW_RESOURCE_ARRAY(int, rec->_oops_length); 1.479 + for (int i = 0; i < rec->_oops_length; i++) { 1.480 int offset = parse_int("offset"); 1.481 if (had_error()) { 1.482 return; 1.483 } 1.484 Klass* k = parse_klass(CHECK); 1.485 - rec->oops_offsets[i] = offset; 1.486 + rec->_oops_offsets[i] = offset; 1.487 KlassHandle *kh = NEW_C_HEAP_OBJ(KlassHandle, mtCompiler); 1.488 ::new ((void*)kh) KlassHandle(THREAD, k); 1.489 - rec->oops_handles[i] = (jobject)kh; 1.490 + rec->_oops_handles[i] = (jobject)kh; 1.491 } 1.492 } 1.493 1.494 @@ -570,6 +682,9 @@ 1.495 case JVM_CONSTANT_Utf8: 1.496 case JVM_CONSTANT_Integer: 1.497 case JVM_CONSTANT_Float: 1.498 + case JVM_CONSTANT_MethodHandle: 1.499 + case JVM_CONSTANT_MethodType: 1.500 + case JVM_CONSTANT_InvokeDynamic: 1.501 if (tag != cp->tag_at(i).value()) { 1.502 report_error("tag mismatch: wrong class files?"); 1.503 return; 1.504 @@ -729,10 +844,10 @@ 1.505 // Create and initialize a record for a ciMethod 1.506 ciMethodRecord* new_ciMethod(Method* method) { 1.507 ciMethodRecord* rec = NEW_RESOURCE_OBJ(ciMethodRecord); 1.508 - rec->klass = method->method_holder()->name()->as_utf8(); 1.509 - rec->method = method->name()->as_utf8(); 1.510 - rec->signature = method->signature()->as_utf8(); 1.511 - ci_method_records.append(rec); 1.512 + rec->_klass_name = method->method_holder()->name()->as_utf8(); 1.513 + rec->_method_name = method->name()->as_utf8(); 1.514 + rec->_signature = method->signature()->as_utf8(); 1.515 + _ci_method_records.append(rec); 1.516 return rec; 1.517 } 1.518 1.519 @@ -741,11 +856,11 @@ 1.520 const char* klass_name = method->method_holder()->name()->as_utf8(); 1.521 const char* method_name = method->name()->as_utf8(); 1.522 const char* signature = method->signature()->as_utf8(); 1.523 - for (int i = 0; i < ci_method_records.length(); i++) { 1.524 - ciMethodRecord* rec = ci_method_records.at(i); 1.525 - if (strcmp(rec->klass, klass_name) == 0 && 1.526 - strcmp(rec->method, method_name) == 0 && 1.527 - strcmp(rec->signature, signature) == 0) { 1.528 + for (int i = 0; i < _ci_method_records.length(); i++) { 1.529 + ciMethodRecord* rec = _ci_method_records.at(i); 1.530 + if (strcmp(rec->_klass_name, klass_name) == 0 && 1.531 + strcmp(rec->_method_name, method_name) == 0 && 1.532 + strcmp(rec->_signature, signature) == 0) { 1.533 return rec; 1.534 } 1.535 } 1.536 @@ -755,10 +870,10 @@ 1.537 // Create and initialize a record for a ciMethodData 1.538 ciMethodDataRecord* new_ciMethodData(Method* method) { 1.539 ciMethodDataRecord* rec = NEW_RESOURCE_OBJ(ciMethodDataRecord); 1.540 - rec->klass = method->method_holder()->name()->as_utf8(); 1.541 - rec->method = method->name()->as_utf8(); 1.542 - rec->signature = method->signature()->as_utf8(); 1.543 - ci_method_data_records.append(rec); 1.544 + rec->_klass_name = method->method_holder()->name()->as_utf8(); 1.545 + rec->_method_name = method->name()->as_utf8(); 1.546 + rec->_signature = method->signature()->as_utf8(); 1.547 + _ci_method_data_records.append(rec); 1.548 return rec; 1.549 } 1.550 1.551 @@ -767,25 +882,65 @@ 1.552 const char* klass_name = method->method_holder()->name()->as_utf8(); 1.553 const char* method_name = method->name()->as_utf8(); 1.554 const char* signature = method->signature()->as_utf8(); 1.555 - for (int i = 0; i < ci_method_data_records.length(); i++) { 1.556 - ciMethodDataRecord* rec = ci_method_data_records.at(i); 1.557 - if (strcmp(rec->klass, klass_name) == 0 && 1.558 - strcmp(rec->method, method_name) == 0 && 1.559 - strcmp(rec->signature, signature) == 0) { 1.560 + for (int i = 0; i < _ci_method_data_records.length(); i++) { 1.561 + ciMethodDataRecord* rec = _ci_method_data_records.at(i); 1.562 + if (strcmp(rec->_klass_name, klass_name) == 0 && 1.563 + strcmp(rec->_method_name, method_name) == 0 && 1.564 + strcmp(rec->_signature, signature) == 0) { 1.565 return rec; 1.566 } 1.567 } 1.568 return NULL; 1.569 } 1.570 1.571 + // Create and initialize a record for a ciInlineRecord 1.572 + ciInlineRecord* new_ciInlineRecord(Method* method, int bci, int depth) { 1.573 + ciInlineRecord* rec = NEW_RESOURCE_OBJ(ciInlineRecord); 1.574 + rec->_klass_name = method->method_holder()->name()->as_utf8(); 1.575 + rec->_method_name = method->name()->as_utf8(); 1.576 + rec->_signature = method->signature()->as_utf8(); 1.577 + rec->_inline_bci = bci; 1.578 + rec->_inline_depth = depth; 1.579 + _ci_inline_records->append(rec); 1.580 + return rec; 1.581 + } 1.582 + 1.583 + // Lookup inlining data for a ciMethod 1.584 + ciInlineRecord* find_ciInlineRecord(Method* method, int bci, int depth) { 1.585 + if (_ci_inline_records != NULL) { 1.586 + return find_ciInlineRecord(_ci_inline_records, method, bci, depth); 1.587 + } 1.588 + return NULL; 1.589 + } 1.590 + 1.591 + static ciInlineRecord* find_ciInlineRecord(GrowableArray<ciInlineRecord*>* records, 1.592 + Method* method, int bci, int depth) { 1.593 + if (records != NULL) { 1.594 + const char* klass_name = method->method_holder()->name()->as_utf8(); 1.595 + const char* method_name = method->name()->as_utf8(); 1.596 + const char* signature = method->signature()->as_utf8(); 1.597 + for (int i = 0; i < records->length(); i++) { 1.598 + ciInlineRecord* rec = records->at(i); 1.599 + if ((rec->_inline_bci == bci) && 1.600 + (rec->_inline_depth == depth) && 1.601 + (strcmp(rec->_klass_name, klass_name) == 0) && 1.602 + (strcmp(rec->_method_name, method_name) == 0) && 1.603 + (strcmp(rec->_signature, signature) == 0)) { 1.604 + return rec; 1.605 + } 1.606 + } 1.607 + } 1.608 + return NULL; 1.609 + } 1.610 + 1.611 const char* error_message() { 1.612 return _error_message; 1.613 } 1.614 1.615 void reset() { 1.616 _error_message = NULL; 1.617 - ci_method_records.clear(); 1.618 - ci_method_data_records.clear(); 1.619 + _ci_method_records.clear(); 1.620 + _ci_method_data_records.clear(); 1.621 } 1.622 1.623 // Take an ascii string contain \u#### escapes and convert it to utf8 1.624 @@ -845,6 +1000,37 @@ 1.625 vm_exit(exit_code); 1.626 } 1.627 1.628 +void* ciReplay::load_inline_data(ciMethod* method, int entry_bci, int comp_level) { 1.629 + if (FLAG_IS_DEFAULT(InlineDataFile)) { 1.630 + tty->print_cr("ERROR: no inline replay data file specified (use -XX:InlineDataFile=inline_pid12345.txt)."); 1.631 + return NULL; 1.632 + } 1.633 + 1.634 + VM_ENTRY_MARK; 1.635 + // Load and parse the replay data 1.636 + CompileReplay rp(InlineDataFile, THREAD); 1.637 + if (!rp.can_replay()) { 1.638 + tty->print_cr("ciReplay: !rp.can_replay()"); 1.639 + return NULL; 1.640 + } 1.641 + void* data = rp.process_inline(method, method->get_Method(), entry_bci, comp_level, THREAD); 1.642 + if (HAS_PENDING_EXCEPTION) { 1.643 + oop throwable = PENDING_EXCEPTION; 1.644 + CLEAR_PENDING_EXCEPTION; 1.645 + java_lang_Throwable::print(throwable, tty); 1.646 + tty->cr(); 1.647 + java_lang_Throwable::print_stack_trace(throwable, tty); 1.648 + tty->cr(); 1.649 + return NULL; 1.650 + } 1.651 + 1.652 + if (rp.had_error()) { 1.653 + tty->print_cr("ciReplay: Failed on %s", rp.error_message()); 1.654 + return NULL; 1.655 + } 1.656 + return data; 1.657 +} 1.658 + 1.659 int ciReplay::replay_impl(TRAPS) { 1.660 HandleMark hm; 1.661 ResourceMark rm; 1.662 @@ -890,7 +1076,6 @@ 1.663 return exit_code; 1.664 } 1.665 1.666 - 1.667 void ciReplay::initialize(ciMethodData* m) { 1.668 if (replay_state == NULL) { 1.669 return; 1.670 @@ -909,28 +1094,28 @@ 1.671 method->print_name(tty); 1.672 tty->cr(); 1.673 } else { 1.674 - m->_state = rec->state; 1.675 - m->_current_mileage = rec->current_mileage; 1.676 - if (rec->data_length != 0) { 1.677 - assert(m->_data_size == rec->data_length * (int)sizeof(rec->data[0]), "must agree"); 1.678 + m->_state = rec->_state; 1.679 + m->_current_mileage = rec->_current_mileage; 1.680 + if (rec->_data_length != 0) { 1.681 + assert(m->_data_size == rec->_data_length * (int)sizeof(rec->_data[0]), "must agree"); 1.682 1.683 // Write the correct ciObjects back into the profile data 1.684 ciEnv* env = ciEnv::current(); 1.685 - for (int i = 0; i < rec->oops_length; i++) { 1.686 - KlassHandle *h = (KlassHandle *)rec->oops_handles[i]; 1.687 - *(ciMetadata**)(rec->data + rec->oops_offsets[i]) = 1.688 + for (int i = 0; i < rec->_oops_length; i++) { 1.689 + KlassHandle *h = (KlassHandle *)rec->_oops_handles[i]; 1.690 + *(ciMetadata**)(rec->_data + rec->_oops_offsets[i]) = 1.691 env->get_metadata((*h)()); 1.692 } 1.693 // Copy the updated profile data into place as intptr_ts 1.694 #ifdef _LP64 1.695 - Copy::conjoint_jlongs_atomic((jlong *)rec->data, (jlong *)m->_data, rec->data_length); 1.696 + Copy::conjoint_jlongs_atomic((jlong *)rec->_data, (jlong *)m->_data, rec->_data_length); 1.697 #else 1.698 - Copy::conjoint_jints_atomic((jint *)rec->data, (jint *)m->_data, rec->data_length); 1.699 + Copy::conjoint_jints_atomic((jint *)rec->_data, (jint *)m->_data, rec->_data_length); 1.700 #endif 1.701 } 1.702 1.703 // copy in the original header 1.704 - Copy::conjoint_jbytes(rec->orig_data, (char*)&m->_orig, rec->orig_data_length); 1.705 + Copy::conjoint_jbytes(rec->_orig_data, (char*)&m->_orig, rec->_orig_data_length); 1.706 } 1.707 } 1.708 1.709 @@ -939,12 +1124,38 @@ 1.710 if (replay_state == NULL) { 1.711 return false; 1.712 } 1.713 - 1.714 VM_ENTRY_MARK; 1.715 // ciMethod without a record shouldn't be inlined. 1.716 return replay_state->find_ciMethodRecord(method->get_Method()) == NULL; 1.717 } 1.718 1.719 +bool ciReplay::should_inline(void* data, ciMethod* method, int bci, int inline_depth) { 1.720 + if (data != NULL) { 1.721 + GrowableArray<ciInlineRecord*>* records = (GrowableArray<ciInlineRecord*>*)data; 1.722 + VM_ENTRY_MARK; 1.723 + // Inline record are ordered by bci and depth. 1.724 + return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) != NULL; 1.725 + } else if (replay_state != NULL) { 1.726 + VM_ENTRY_MARK; 1.727 + // Inline record are ordered by bci and depth. 1.728 + return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) != NULL; 1.729 + } 1.730 + return false; 1.731 +} 1.732 + 1.733 +bool ciReplay::should_not_inline(void* data, ciMethod* method, int bci, int inline_depth) { 1.734 + if (data != NULL) { 1.735 + GrowableArray<ciInlineRecord*>* records = (GrowableArray<ciInlineRecord*>*)data; 1.736 + VM_ENTRY_MARK; 1.737 + // Inline record are ordered by bci and depth. 1.738 + return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) == NULL; 1.739 + } else if (replay_state != NULL) { 1.740 + VM_ENTRY_MARK; 1.741 + // Inline record are ordered by bci and depth. 1.742 + return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) == NULL; 1.743 + } 1.744 + return false; 1.745 +} 1.746 1.747 void ciReplay::initialize(ciMethod* m) { 1.748 if (replay_state == NULL) { 1.749 @@ -965,14 +1176,14 @@ 1.750 tty->cr(); 1.751 } else { 1.752 EXCEPTION_CONTEXT; 1.753 - // m->_instructions_size = rec->instructions_size; 1.754 + // m->_instructions_size = rec->_instructions_size; 1.755 m->_instructions_size = -1; 1.756 - m->_interpreter_invocation_count = rec->interpreter_invocation_count; 1.757 - m->_interpreter_throwout_count = rec->interpreter_throwout_count; 1.758 + m->_interpreter_invocation_count = rec->_interpreter_invocation_count; 1.759 + m->_interpreter_throwout_count = rec->_interpreter_throwout_count; 1.760 MethodCounters* mcs = method->get_method_counters(CHECK_AND_CLEAR); 1.761 guarantee(mcs != NULL, "method counters allocation failed"); 1.762 - mcs->invocation_counter()->_counter = rec->invocation_counter; 1.763 - mcs->backedge_counter()->_counter = rec->backedge_counter; 1.764 + mcs->invocation_counter()->_counter = rec->_invocation_counter; 1.765 + mcs->backedge_counter()->_counter = rec->_backedge_counter; 1.766 } 1.767 } 1.768