ciReplay.cpp revision 5014:1b6395189726
1/* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24#include "precompiled.hpp"
25#include "ci/ciMethodData.hpp"
26#include "ci/ciReplay.hpp"
27#include "ci/ciUtilities.hpp"
28#include "compiler/compileBroker.hpp"
29#include "memory/allocation.inline.hpp"
30#include "memory/oopFactory.hpp"
31#include "memory/resourceArea.hpp"
32#include "utilities/copy.hpp"
33#include "utilities/macros.hpp"
34
35#ifndef PRODUCT
36
37// ciReplay
38
39typedef struct _ciMethodDataRecord {
40  const char* klass;
41  const char* method;
42  const char* signature;
43  int state;
44  int current_mileage;
45  intptr_t* data;
46  int data_length;
47  char* orig_data;
48  int orig_data_length;
49  int oops_length;
50  jobject* oops_handles;
51  int* oops_offsets;
52} ciMethodDataRecord;
53
54typedef struct _ciMethodRecord {
55  const char* klass;
56  const char* method;
57  const char* signature;
58  int instructions_size;
59  int interpreter_invocation_count;
60  int interpreter_throwout_count;
61  int invocation_counter;
62  int backedge_counter;
63} ciMethodRecord;
64
65class CompileReplay;
66static CompileReplay* replay_state;
67
68class CompileReplay : public StackObj {
69 private:
70  FILE*   stream;
71  Thread* thread;
72  Handle  protection_domain;
73  Handle  loader;
74
75  GrowableArray<ciMethodRecord*>     ci_method_records;
76  GrowableArray<ciMethodDataRecord*> ci_method_data_records;
77
78  const char* _error_message;
79
80  char* bufptr;
81  char* buffer;
82  int   buffer_length;
83  int   buffer_end;
84  int   line_no;
85
86 public:
87  CompileReplay(const char* filename, TRAPS) {
88    thread = THREAD;
89    loader = Handle(thread, SystemDictionary::java_system_loader());
90    stream = fopen(filename, "rt");
91    if (stream == NULL) {
92      fprintf(stderr, "ERROR: Can't open replay file %s\n", filename);
93    }
94    buffer_length = 32;
95    buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
96    _error_message = NULL;
97
98    test();
99  }
100
101  ~CompileReplay() {
102    if (stream != NULL) fclose(stream);
103  }
104
105  void test() {
106    strcpy(buffer, "1 2 foo 4 bar 0x9 \"this is it\"");
107    bufptr = buffer;
108    assert(parse_int("test") == 1, "what");
109    assert(parse_int("test") == 2, "what");
110    assert(strcmp(parse_string(), "foo") == 0, "what");
111    assert(parse_int("test") == 4, "what");
112    assert(strcmp(parse_string(), "bar") == 0, "what");
113    assert(parse_intptr_t("test") == 9, "what");
114    assert(strcmp(parse_quoted_string(), "this is it") == 0, "what");
115  }
116
117  bool had_error() {
118    return _error_message != NULL || thread->has_pending_exception();
119  }
120
121  bool can_replay() {
122    return !(stream == NULL || had_error());
123  }
124
125  void report_error(const char* msg) {
126    _error_message = msg;
127    // Restore the buffer contents for error reporting
128    for (int i = 0; i < buffer_end; i++) {
129      if (buffer[i] == '\0') buffer[i] = ' ';
130    }
131  }
132
133  int parse_int(const char* label) {
134    if (had_error()) {
135      return 0;
136    }
137
138    int v = 0;
139    int read;
140    if (sscanf(bufptr, "%i%n", &v, &read) != 1) {
141      report_error(label);
142    } else {
143      bufptr += read;
144    }
145    return v;
146  }
147
148  intptr_t parse_intptr_t(const char* label) {
149    if (had_error()) {
150      return 0;
151    }
152
153    intptr_t v = 0;
154    int read;
155    if (sscanf(bufptr, INTPTR_FORMAT "%n", &v, &read) != 1) {
156      report_error(label);
157    } else {
158      bufptr += read;
159    }
160    return v;
161  }
162
163  void skip_ws() {
164    // Skip any leading whitespace
165    while (*bufptr == ' ' || *bufptr == '\t') {
166      bufptr++;
167    }
168  }
169
170
171  char* scan_and_terminate(char delim) {
172    char* str = bufptr;
173    while (*bufptr != delim && *bufptr != '\0') {
174      bufptr++;
175    }
176    if (*bufptr != '\0') {
177      *bufptr++ = '\0';
178    }
179    if (bufptr == str) {
180      // nothing here
181      return NULL;
182    }
183    return str;
184  }
185
186  char* parse_string() {
187    if (had_error()) return NULL;
188
189    skip_ws();
190    return scan_and_terminate(' ');
191  }
192
193  char* parse_quoted_string() {
194    if (had_error()) return NULL;
195
196    skip_ws();
197
198    if (*bufptr == '"') {
199      bufptr++;
200      return scan_and_terminate('"');
201    } else {
202      return scan_and_terminate(' ');
203    }
204  }
205
206  const char* parse_escaped_string() {
207    char* result = parse_quoted_string();
208    if (result != NULL) {
209      unescape_string(result);
210    }
211    return result;
212  }
213
214  // Look for the tag 'tag' followed by an
215  bool parse_tag_and_count(const char* tag, int& length) {
216    const char* t = parse_string();
217    if (t == NULL) {
218      return false;
219    }
220
221    if (strcmp(tag, t) != 0) {
222      report_error(tag);
223      return false;
224    }
225    length = parse_int("parse_tag_and_count");
226    return !had_error();
227  }
228
229  // Parse a sequence of raw data encoded as bytes and return the
230  // resulting data.
231  char* parse_data(const char* tag, int& length) {
232    if (!parse_tag_and_count(tag, length)) {
233      return NULL;
234    }
235
236    char * result = NEW_RESOURCE_ARRAY(char, length);
237    for (int i = 0; i < length; i++) {
238      int val = parse_int("data");
239      result[i] = val;
240    }
241    return result;
242  }
243
244  // Parse a standard chunk of data emitted as:
245  //   'tag' <length> # # ...
246  // Where each # is an intptr_t item
247  intptr_t* parse_intptr_data(const char* tag, int& length) {
248    if (!parse_tag_and_count(tag, length)) {
249      return NULL;
250    }
251
252    intptr_t* result = NEW_RESOURCE_ARRAY(intptr_t, length);
253    for (int i = 0; i < length; i++) {
254      skip_ws();
255      intptr_t val = parse_intptr_t("data");
256      result[i] = val;
257    }
258    return result;
259  }
260
261  // Parse a possibly quoted version of a symbol into a symbolOop
262  Symbol* parse_symbol(TRAPS) {
263    const char* str = parse_escaped_string();
264    if (str != NULL) {
265      Symbol* sym = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL);
266      return sym;
267    }
268    return NULL;
269  }
270
271  // Parse a valid klass name and look it up
272  Klass* parse_klass(TRAPS) {
273    const char* str = parse_escaped_string();
274    Symbol* klass_name = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL);
275    if (klass_name != NULL) {
276      Klass* k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD);
277      if (HAS_PENDING_EXCEPTION) {
278        oop throwable = PENDING_EXCEPTION;
279        java_lang_Throwable::print(throwable, tty);
280        tty->cr();
281        report_error(str);
282        return NULL;
283      }
284      return k;
285    }
286    return NULL;
287  }
288
289  // Lookup a klass
290  Klass* resolve_klass(const char* klass, TRAPS) {
291    Symbol* klass_name = SymbolTable::lookup(klass, (int)strlen(klass), CHECK_NULL);
292    return SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, CHECK_NULL);
293  }
294
295  // Parse the standard tuple of <klass> <name> <signature>
296  Method* parse_method(TRAPS) {
297    InstanceKlass* k = (InstanceKlass*)parse_klass(CHECK_NULL);
298    Symbol* method_name = parse_symbol(CHECK_NULL);
299    Symbol* method_signature = parse_symbol(CHECK_NULL);
300    Method* m = k->find_method(method_name, method_signature);
301    if (m == NULL) {
302      report_error("Can't find method");
303    }
304    return m;
305  }
306
307  // Process each line of the replay file executing each command until
308  // the file ends.
309  void process(TRAPS) {
310    line_no = 1;
311    int pos = 0;
312    int c = getc(stream);
313    while(c != EOF) {
314      if (pos + 1 >= buffer_length) {
315        int newl = buffer_length * 2;
316        char* newb = NEW_RESOURCE_ARRAY(char, newl);
317        memcpy(newb, buffer, pos);
318        buffer = newb;
319        buffer_length = newl;
320      }
321      if (c == '\n') {
322        // null terminate it, reset the pointer and process the line
323        buffer[pos] = '\0';
324        buffer_end = pos++;
325        bufptr = buffer;
326        process_command(CHECK);
327        if (had_error()) {
328          tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
329          tty->print_cr("%s", buffer);
330          return;
331        }
332        pos = 0;
333        buffer_end = 0;
334        line_no++;
335      } else if (c == '\r') {
336        // skip LF
337      } else {
338        buffer[pos++] = c;
339      }
340      c = getc(stream);
341    }
342  }
343
344  void process_command(TRAPS) {
345    char* cmd = parse_string();
346    if (cmd == NULL) {
347      return;
348    }
349    if (strcmp("#", cmd) == 0) {
350      // ignore
351    } else if (strcmp("compile", cmd) == 0) {
352      process_compile(CHECK);
353    } else if (strcmp("ciMethod", cmd) == 0) {
354      process_ciMethod(CHECK);
355    } else if (strcmp("ciMethodData", cmd) == 0) {
356      process_ciMethodData(CHECK);
357    } else if (strcmp("staticfield", cmd) == 0) {
358      process_staticfield(CHECK);
359    } else if (strcmp("ciInstanceKlass", cmd) == 0) {
360      process_ciInstanceKlass(CHECK);
361    } else if (strcmp("instanceKlass", cmd) == 0) {
362      process_instanceKlass(CHECK);
363#if INCLUDE_JVMTI
364    } else if (strcmp("JvmtiExport", cmd) == 0) {
365      process_JvmtiExport(CHECK);
366#endif // INCLUDE_JVMTI
367    } else {
368      report_error("unknown command");
369    }
370  }
371
372  // validation of comp_level
373  bool is_valid_comp_level(int comp_level) {
374    const int msg_len = 256;
375    char* msg = NULL;
376    if (!is_compile(comp_level)) {
377      msg = NEW_RESOURCE_ARRAY(char, msg_len);
378      jio_snprintf(msg, msg_len, "%d isn't compilation level", comp_level);
379    } else if (!TieredCompilation && (comp_level != CompLevel_highest_tier)) {
380      msg = NEW_RESOURCE_ARRAY(char, msg_len);
381      switch (comp_level) {
382        case CompLevel_simple:
383          jio_snprintf(msg, msg_len, "compilation level %d requires Client VM or TieredCompilation", comp_level);
384          break;
385        case CompLevel_full_optimization:
386          jio_snprintf(msg, msg_len, "compilation level %d requires Server VM", comp_level);
387          break;
388        default:
389          jio_snprintf(msg, msg_len, "compilation level %d requires TieredCompilation", comp_level);
390      }
391    }
392    if (msg != NULL) {
393      report_error(msg);
394      return false;
395    }
396    return true;
397  }
398
399  // compile <klass> <name> <signature> <entry_bci> <comp_level>
400  void process_compile(TRAPS) {
401    Method* method = parse_method(CHECK);
402    if (had_error()) return;
403    int entry_bci = parse_int("entry_bci");
404    const char* comp_level_label = "comp_level";
405    int comp_level = parse_int(comp_level_label);
406    // old version w/o comp_level
407    if (had_error() && (error_message() == comp_level_label)) {
408      comp_level = CompLevel_full_optimization;
409    }
410    if (!is_valid_comp_level(comp_level)) {
411      return;
412    }
413    Klass* k = method->method_holder();
414    ((InstanceKlass*)k)->initialize(THREAD);
415    if (HAS_PENDING_EXCEPTION) {
416      oop throwable = PENDING_EXCEPTION;
417      java_lang_Throwable::print(throwable, tty);
418      tty->cr();
419      if (ReplayIgnoreInitErrors) {
420        CLEAR_PENDING_EXCEPTION;
421        ((InstanceKlass*)k)->set_init_state(InstanceKlass::fully_initialized);
422      } else {
423        return;
424      }
425    }
426    // Make sure the existence of a prior compile doesn't stop this one
427    nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code();
428    if (nm != NULL) {
429      nm->make_not_entrant();
430    }
431    replay_state = this;
432    CompileBroker::compile_method(method, entry_bci, comp_level,
433                                  methodHandle(), 0, "replay", THREAD);
434    replay_state = NULL;
435    reset();
436  }
437
438  // ciMethod <klass> <name> <signature> <invocation_counter> <backedge_counter> <interpreter_invocation_count> <interpreter_throwout_count> <instructions_size>
439  //
440  //
441  void process_ciMethod(TRAPS) {
442    Method* method = parse_method(CHECK);
443    if (had_error()) return;
444    ciMethodRecord* rec = new_ciMethod(method);
445    rec->invocation_counter = parse_int("invocation_counter");
446    rec->backedge_counter = parse_int("backedge_counter");
447    rec->interpreter_invocation_count = parse_int("interpreter_invocation_count");
448    rec->interpreter_throwout_count = parse_int("interpreter_throwout_count");
449    rec->instructions_size = parse_int("instructions_size");
450  }
451
452  // ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length>
453  void process_ciMethodData(TRAPS) {
454    Method* method = parse_method(CHECK);
455    if (had_error()) return;
456    /* jsut copied from Method, to build interpret data*/
457    if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
458      return;
459    }
460    // methodOopDesc::build_interpreter_method_data(method, CHECK);
461    {
462      // Grab a lock here to prevent multiple
463      // MethodData*s from being created.
464      MutexLocker ml(MethodData_lock, THREAD);
465      if (method->method_data() == NULL) {
466        ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
467        MethodData* method_data = MethodData::allocate(loader_data, method, CHECK);
468        method->set_method_data(method_data);
469      }
470    }
471
472    // collect and record all the needed information for later
473    ciMethodDataRecord* rec = new_ciMethodData(method);
474    rec->state = parse_int("state");
475    rec->current_mileage = parse_int("current_mileage");
476
477    rec->orig_data = parse_data("orig", rec->orig_data_length);
478    if (rec->orig_data == NULL) {
479      return;
480    }
481    rec->data = parse_intptr_data("data", rec->data_length);
482    if (rec->data == NULL) {
483      return;
484    }
485    if (!parse_tag_and_count("oops", rec->oops_length)) {
486      return;
487    }
488    rec->oops_handles = NEW_RESOURCE_ARRAY(jobject, rec->oops_length);
489    rec->oops_offsets = NEW_RESOURCE_ARRAY(int, rec->oops_length);
490    for (int i = 0; i < rec->oops_length; i++) {
491      int offset = parse_int("offset");
492      if (had_error()) {
493        return;
494      }
495      Klass* k = parse_klass(CHECK);
496      rec->oops_offsets[i] = offset;
497      KlassHandle *kh = NEW_C_HEAP_OBJ(KlassHandle, mtCompiler);
498      ::new ((void*)kh) KlassHandle(THREAD, k);
499      rec->oops_handles[i] = (jobject)kh;
500    }
501  }
502
503  // instanceKlass <name>
504  //
505  // Loads and initializes the klass 'name'.  This can be used to
506  // create particular class loading environments
507  void process_instanceKlass(TRAPS) {
508    // just load the referenced class
509    Klass* k = parse_klass(CHECK);
510  }
511
512  // ciInstanceKlass <name> <is_linked> <is_initialized> <length> tag # # # ...
513  //
514  // Load the klass 'name' and link or initialize it.  Verify that the
515  // constant pool is the same length as 'length' and make sure the
516  // constant pool tags are in the same state.
517  void process_ciInstanceKlass(TRAPS) {
518    InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
519    int is_linked = parse_int("is_linked");
520    int is_initialized = parse_int("is_initialized");
521    int length = parse_int("length");
522    if (is_initialized) {
523      k->initialize(THREAD);
524      if (HAS_PENDING_EXCEPTION) {
525        oop throwable = PENDING_EXCEPTION;
526        java_lang_Throwable::print(throwable, tty);
527        tty->cr();
528        if (ReplayIgnoreInitErrors) {
529          CLEAR_PENDING_EXCEPTION;
530          k->set_init_state(InstanceKlass::fully_initialized);
531        } else {
532          return;
533        }
534      }
535    } else if (is_linked) {
536      k->link_class(CHECK);
537    }
538    ConstantPool* cp = k->constants();
539    if (length != cp->length()) {
540      report_error("constant pool length mismatch: wrong class files?");
541      return;
542    }
543
544    int parsed_two_word = 0;
545    for (int i = 1; i < length; i++) {
546      int tag = parse_int("tag");
547      if (had_error()) {
548        return;
549      }
550      switch (cp->tag_at(i).value()) {
551        case JVM_CONSTANT_UnresolvedClass: {
552          if (tag == JVM_CONSTANT_Class) {
553            tty->print_cr("Resolving klass %s at %d", cp->unresolved_klass_at(i)->as_utf8(), i);
554            Klass* k = cp->klass_at(i, CHECK);
555          }
556          break;
557        }
558        case JVM_CONSTANT_Long:
559        case JVM_CONSTANT_Double:
560          parsed_two_word = i + 1;
561
562        case JVM_CONSTANT_ClassIndex:
563        case JVM_CONSTANT_StringIndex:
564        case JVM_CONSTANT_String:
565        case JVM_CONSTANT_UnresolvedClassInError:
566        case JVM_CONSTANT_Fieldref:
567        case JVM_CONSTANT_Methodref:
568        case JVM_CONSTANT_InterfaceMethodref:
569        case JVM_CONSTANT_NameAndType:
570        case JVM_CONSTANT_Utf8:
571        case JVM_CONSTANT_Integer:
572        case JVM_CONSTANT_Float:
573          if (tag != cp->tag_at(i).value()) {
574            report_error("tag mismatch: wrong class files?");
575            return;
576          }
577          break;
578
579        case JVM_CONSTANT_Class:
580          if (tag == JVM_CONSTANT_Class) {
581          } else if (tag == JVM_CONSTANT_UnresolvedClass) {
582            tty->print_cr("Warning: entry was unresolved in the replay data");
583          } else {
584            report_error("Unexpected tag");
585            return;
586          }
587          break;
588
589        case 0:
590          if (parsed_two_word == i) continue;
591
592        default:
593          fatal(err_msg_res("Unexpected tag: %d", cp->tag_at(i).value()));
594          break;
595      }
596
597    }
598  }
599
600  // Initialize a class and fill in the value for a static field.
601  // This is useful when the compile was dependent on the value of
602  // static fields but it's impossible to properly rerun the static
603  // initiailizer.
604  void process_staticfield(TRAPS) {
605    InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
606
607    if (ReplaySuppressInitializers == 0 ||
608        ReplaySuppressInitializers == 2 && k->class_loader() == NULL) {
609      return;
610    }
611
612    assert(k->is_initialized(), "must be");
613
614    const char* field_name = parse_escaped_string();;
615    const char* field_signature = parse_string();
616    fieldDescriptor fd;
617    Symbol* name = SymbolTable::lookup(field_name, (int)strlen(field_name), CHECK);
618    Symbol* sig = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK);
619    if (!k->find_local_field(name, sig, &fd) ||
620        !fd.is_static() ||
621        fd.has_initial_value()) {
622      report_error(field_name);
623      return;
624    }
625
626    oop java_mirror = k->java_mirror();
627    if (field_signature[0] == '[') {
628      int length = parse_int("array length");
629      oop value = NULL;
630
631      if (field_signature[1] == '[') {
632        // multi dimensional array
633        ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK);
634        int rank = 0;
635        while (field_signature[rank] == '[') {
636          rank++;
637        }
638        int* dims = NEW_RESOURCE_ARRAY(int, rank);
639        dims[0] = length;
640        for (int i = 1; i < rank; i++) {
641          dims[i] = 1; // These aren't relevant to the compiler
642        }
643        value = kelem->multi_allocate(rank, dims, CHECK);
644      } else {
645        if (strcmp(field_signature, "[B") == 0) {
646          value = oopFactory::new_byteArray(length, CHECK);
647        } else if (strcmp(field_signature, "[Z") == 0) {
648          value = oopFactory::new_boolArray(length, CHECK);
649        } else if (strcmp(field_signature, "[C") == 0) {
650          value = oopFactory::new_charArray(length, CHECK);
651        } else if (strcmp(field_signature, "[S") == 0) {
652          value = oopFactory::new_shortArray(length, CHECK);
653        } else if (strcmp(field_signature, "[F") == 0) {
654          value = oopFactory::new_singleArray(length, CHECK);
655        } else if (strcmp(field_signature, "[D") == 0) {
656          value = oopFactory::new_doubleArray(length, CHECK);
657        } else if (strcmp(field_signature, "[I") == 0) {
658          value = oopFactory::new_intArray(length, CHECK);
659        } else if (strcmp(field_signature, "[J") == 0) {
660          value = oopFactory::new_longArray(length, CHECK);
661        } else if (field_signature[0] == '[' && field_signature[1] == 'L') {
662          KlassHandle kelem = resolve_klass(field_signature + 1, CHECK);
663          value = oopFactory::new_objArray(kelem(), length, CHECK);
664        } else {
665          report_error("unhandled array staticfield");
666        }
667      }
668      java_mirror->obj_field_put(fd.offset(), value);
669    } else {
670      const char* string_value = parse_escaped_string();
671      if (strcmp(field_signature, "I") == 0) {
672        int value = atoi(string_value);
673        java_mirror->int_field_put(fd.offset(), value);
674      } else if (strcmp(field_signature, "B") == 0) {
675        int value = atoi(string_value);
676        java_mirror->byte_field_put(fd.offset(), value);
677      } else if (strcmp(field_signature, "C") == 0) {
678        int value = atoi(string_value);
679        java_mirror->char_field_put(fd.offset(), value);
680      } else if (strcmp(field_signature, "S") == 0) {
681        int value = atoi(string_value);
682        java_mirror->short_field_put(fd.offset(), value);
683      } else if (strcmp(field_signature, "Z") == 0) {
684        int value = atol(string_value);
685        java_mirror->bool_field_put(fd.offset(), value);
686      } else if (strcmp(field_signature, "J") == 0) {
687        jlong value;
688        if (sscanf(string_value, JLONG_FORMAT, &value) != 1) {
689          fprintf(stderr, "Error parsing long: %s\n", string_value);
690          return;
691        }
692        java_mirror->long_field_put(fd.offset(), value);
693      } else if (strcmp(field_signature, "F") == 0) {
694        float value = atof(string_value);
695        java_mirror->float_field_put(fd.offset(), value);
696      } else if (strcmp(field_signature, "D") == 0) {
697        double value = atof(string_value);
698        java_mirror->double_field_put(fd.offset(), value);
699      } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) {
700        Handle value = java_lang_String::create_from_str(string_value, CHECK);
701        java_mirror->obj_field_put(fd.offset(), value());
702      } else if (field_signature[0] == 'L') {
703        Symbol* klass_name = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK);
704        KlassHandle kelem = resolve_klass(field_signature, CHECK);
705        oop value = ((InstanceKlass*)kelem())->allocate_instance(CHECK);
706        java_mirror->obj_field_put(fd.offset(), value);
707      } else {
708        report_error("unhandled staticfield");
709      }
710    }
711  }
712
713#if INCLUDE_JVMTI
714  void process_JvmtiExport(TRAPS) {
715    const char* field = parse_string();
716    bool value = parse_int("JvmtiExport flag") != 0;
717    if (strcmp(field, "can_access_local_variables") == 0) {
718      JvmtiExport::set_can_access_local_variables(value);
719    } else if (strcmp(field, "can_hotswap_or_post_breakpoint") == 0) {
720      JvmtiExport::set_can_hotswap_or_post_breakpoint(value);
721    } else if (strcmp(field, "can_post_on_exceptions") == 0) {
722      JvmtiExport::set_can_post_on_exceptions(value);
723    } else {
724      report_error("Unrecognized JvmtiExport directive");
725    }
726  }
727#endif // INCLUDE_JVMTI
728
729  // Create and initialize a record for a ciMethod
730  ciMethodRecord* new_ciMethod(Method* method) {
731    ciMethodRecord* rec = NEW_RESOURCE_OBJ(ciMethodRecord);
732    rec->klass =  method->method_holder()->name()->as_utf8();
733    rec->method = method->name()->as_utf8();
734    rec->signature = method->signature()->as_utf8();
735    ci_method_records.append(rec);
736    return rec;
737  }
738
739  // Lookup data for a ciMethod
740  ciMethodRecord* find_ciMethodRecord(Method* method) {
741    const char* klass_name =  method->method_holder()->name()->as_utf8();
742    const char* method_name = method->name()->as_utf8();
743    const char* signature = method->signature()->as_utf8();
744    for (int i = 0; i < ci_method_records.length(); i++) {
745      ciMethodRecord* rec = ci_method_records.at(i);
746      if (strcmp(rec->klass, klass_name) == 0 &&
747          strcmp(rec->method, method_name) == 0 &&
748          strcmp(rec->signature, signature) == 0) {
749        return rec;
750      }
751    }
752    return NULL;
753  }
754
755  // Create and initialize a record for a ciMethodData
756  ciMethodDataRecord* new_ciMethodData(Method* method) {
757    ciMethodDataRecord* rec = NEW_RESOURCE_OBJ(ciMethodDataRecord);
758    rec->klass =  method->method_holder()->name()->as_utf8();
759    rec->method = method->name()->as_utf8();
760    rec->signature = method->signature()->as_utf8();
761    ci_method_data_records.append(rec);
762    return rec;
763  }
764
765  // Lookup data for a ciMethodData
766  ciMethodDataRecord* find_ciMethodDataRecord(Method* method) {
767    const char* klass_name =  method->method_holder()->name()->as_utf8();
768    const char* method_name = method->name()->as_utf8();
769    const char* signature = method->signature()->as_utf8();
770    for (int i = 0; i < ci_method_data_records.length(); i++) {
771      ciMethodDataRecord* rec = ci_method_data_records.at(i);
772      if (strcmp(rec->klass, klass_name) == 0 &&
773          strcmp(rec->method, method_name) == 0 &&
774          strcmp(rec->signature, signature) == 0) {
775        return rec;
776      }
777    }
778    return NULL;
779  }
780
781  const char* error_message() {
782    return _error_message;
783  }
784
785  void reset() {
786    _error_message = NULL;
787    ci_method_records.clear();
788    ci_method_data_records.clear();
789  }
790
791  // Take an ascii string contain \u#### escapes and convert it to utf8
792  // in place.
793  static void unescape_string(char* value) {
794    char* from = value;
795    char* to = value;
796    while (*from != '\0') {
797      if (*from != '\\') {
798        *from++ = *to++;
799      } else {
800        switch (from[1]) {
801          case 'u': {
802            from += 2;
803            jchar value=0;
804            for (int i=0; i<4; i++) {
805              char c = *from++;
806              switch (c) {
807                case '0': case '1': case '2': case '3': case '4':
808                case '5': case '6': case '7': case '8': case '9':
809                  value = (value << 4) + c - '0';
810                  break;
811                case 'a': case 'b': case 'c':
812                case 'd': case 'e': case 'f':
813                  value = (value << 4) + 10 + c - 'a';
814                  break;
815                case 'A': case 'B': case 'C':
816                case 'D': case 'E': case 'F':
817                  value = (value << 4) + 10 + c - 'A';
818                  break;
819                default:
820                  ShouldNotReachHere();
821              }
822            }
823            UNICODE::convert_to_utf8(&value, 1, to);
824            to++;
825            break;
826          }
827          case 't': *to++ = '\t'; from += 2; break;
828          case 'n': *to++ = '\n'; from += 2; break;
829          case 'r': *to++ = '\r'; from += 2; break;
830          case 'f': *to++ = '\f'; from += 2; break;
831          default:
832            ShouldNotReachHere();
833        }
834      }
835    }
836    *from = *to;
837  }
838};
839
840void ciReplay::replay(TRAPS) {
841  int exit_code = replay_impl(THREAD);
842
843  Threads::destroy_vm();
844
845  vm_exit(exit_code);
846}
847
848int ciReplay::replay_impl(TRAPS) {
849  HandleMark hm;
850  ResourceMark rm;
851  // Make sure we don't run with background compilation
852  BackgroundCompilation = false;
853
854  if (ReplaySuppressInitializers > 2) {
855    // ReplaySuppressInitializers > 2 means that we want to allow
856    // normal VM bootstrap but once we get into the replay itself
857    // don't allow any intializers to be run.
858    ReplaySuppressInitializers = 1;
859  }
860
861  if (FLAG_IS_DEFAULT(ReplayDataFile)) {
862    tty->print_cr("ERROR: no compiler replay data file specified (use -XX:ReplayDataFile=replay_pid12345.txt).");
863    return 1;
864  }
865
866  // Load and parse the replay data
867  CompileReplay rp(ReplayDataFile, THREAD);
868  int exit_code = 0;
869  if (rp.can_replay()) {
870    rp.process(THREAD);
871  } else {
872    exit_code = 1;
873    return exit_code;
874  }
875
876  if (HAS_PENDING_EXCEPTION) {
877    oop throwable = PENDING_EXCEPTION;
878    CLEAR_PENDING_EXCEPTION;
879    java_lang_Throwable::print(throwable, tty);
880    tty->cr();
881    java_lang_Throwable::print_stack_trace(throwable, tty);
882    tty->cr();
883    exit_code = 2;
884  }
885
886  if (rp.had_error()) {
887    tty->print_cr("Failed on %s", rp.error_message());
888    exit_code = 1;
889  }
890  return exit_code;
891}
892
893
894void ciReplay::initialize(ciMethodData* m) {
895  if (replay_state == NULL) {
896    return;
897  }
898
899  ASSERT_IN_VM;
900  ResourceMark rm;
901
902  Method* method = m->get_MethodData()->method();
903  ciMethodDataRecord* rec = replay_state->find_ciMethodDataRecord(method);
904  if (rec == NULL) {
905    // This indicates some mismatch with the original environment and
906    // the replay environment though it's not always enough to
907    // interfere with reproducing a bug
908    tty->print_cr("Warning: requesting ciMethodData record for method with no data: ");
909    method->print_name(tty);
910    tty->cr();
911  } else {
912    m->_state = rec->state;
913    m->_current_mileage = rec->current_mileage;
914    if (rec->data_length != 0) {
915      assert(m->_data_size == rec->data_length * (int)sizeof(rec->data[0]), "must agree");
916
917      // Write the correct ciObjects back into the profile data
918      ciEnv* env = ciEnv::current();
919      for (int i = 0; i < rec->oops_length; i++) {
920        KlassHandle *h = (KlassHandle *)rec->oops_handles[i];
921        *(ciMetadata**)(rec->data + rec->oops_offsets[i]) =
922          env->get_metadata((*h)());
923      }
924      // Copy the updated profile data into place as intptr_ts
925#ifdef _LP64
926      Copy::conjoint_jlongs_atomic((jlong *)rec->data, (jlong *)m->_data, rec->data_length);
927#else
928      Copy::conjoint_jints_atomic((jint *)rec->data, (jint *)m->_data, rec->data_length);
929#endif
930    }
931
932    // copy in the original header
933    Copy::conjoint_jbytes(rec->orig_data, (char*)&m->_orig, rec->orig_data_length);
934  }
935}
936
937
938bool ciReplay::should_not_inline(ciMethod* method) {
939  if (replay_state == NULL) {
940    return false;
941  }
942
943  VM_ENTRY_MARK;
944  // ciMethod without a record shouldn't be inlined.
945  return replay_state->find_ciMethodRecord(method->get_Method()) == NULL;
946}
947
948
949void ciReplay::initialize(ciMethod* m) {
950  if (replay_state == NULL) {
951    return;
952  }
953
954  ASSERT_IN_VM;
955  ResourceMark rm;
956
957  Method* method = m->get_Method();
958  ciMethodRecord* rec = replay_state->find_ciMethodRecord(method);
959  if (rec == NULL) {
960    // This indicates some mismatch with the original environment and
961    // the replay environment though it's not always enough to
962    // interfere with reproducing a bug
963    tty->print_cr("Warning: requesting ciMethod record for method with no data: ");
964    method->print_name(tty);
965    tty->cr();
966  } else {
967    EXCEPTION_CONTEXT;
968    MethodCounters* mcs = method->method_counters();
969    // m->_instructions_size = rec->instructions_size;
970    m->_instructions_size = -1;
971    m->_interpreter_invocation_count = rec->interpreter_invocation_count;
972    m->_interpreter_throwout_count = rec->interpreter_throwout_count;
973    if (mcs == NULL) {
974      mcs = Method::build_method_counters(method, CHECK_AND_CLEAR);
975    }
976    mcs->invocation_counter()->_counter = rec->invocation_counter;
977    mcs->backedge_counter()->_counter = rec->backedge_counter;
978  }
979}
980
981bool ciReplay::is_loaded(Method* method) {
982  if (replay_state == NULL) {
983    return true;
984  }
985
986  ASSERT_IN_VM;
987  ResourceMark rm;
988
989  ciMethodRecord* rec = replay_state->find_ciMethodRecord(method);
990  return rec != NULL;
991}
992#endif // PRODUCT
993