src/share/vm/ci/ciReplay.cpp

changeset 6217
849eb7bfceac
parent 5907
c775af091fe9
child 6655
653e11c86c5a
     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  

mercurial