1 /*
2  * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #include "precompiled.hpp"
26 #include "jvm.h"
27 #include "ci/ciMethodData.hpp"
28 #include "ci/ciReplay.hpp"
29 #include "ci/ciSymbol.hpp"
30 #include "ci/ciKlass.hpp"
31 #include "ci/ciUtilities.inline.hpp"
32 #include "classfile/symbolTable.hpp"
33 #include "compiler/compileBroker.hpp"
34 #include "memory/allocation.inline.hpp"
35 #include "memory/oopFactory.hpp"
36 #include "memory/resourceArea.hpp"
37 #include "oops/constantPool.hpp"
38 #include "oops/method.inline.hpp"
39 #include "oops/oop.inline.hpp"
40 #include "runtime/fieldDescriptor.inline.hpp"
41 #include "runtime/handles.inline.hpp"
42 #include "utilities/copy.hpp"
43 #include "utilities/macros.hpp"
44 #include "utilities/utf8.hpp"
45 
46 #ifndef PRODUCT
47 
48 // ciReplay
49 
50 typedef struct _ciMethodDataRecord {
51   const char* _klass_name;
52   const char* _method_name;
53   const char* _signature;
54 
55   int _state;
56   int _current_mileage;
57 
58   intptr_t* _data;
59   char*     _orig_data;
60   Klass**   _classes;
61   Method**  _methods;
62   int*      _classes_offsets;
63   int*      _methods_offsets;
64   int       _data_length;
65   int       _orig_data_length;
66   int       _classes_length;
67   int       _methods_length;
68 } ciMethodDataRecord;
69 
70 typedef struct _ciMethodRecord {
71   const char* _klass_name;
72   const char* _method_name;
73   const char* _signature;
74 
75   int _instructions_size;
76   int _interpreter_invocation_count;
77   int _interpreter_throwout_count;
78   int _invocation_counter;
79   int _backedge_counter;
80 } ciMethodRecord;
81 
82 typedef struct _ciInlineRecord {
83   const char* _klass_name;
84   const char* _method_name;
85   const char* _signature;
86 
87   int _inline_depth;
88   int _inline_bci;
89 } ciInlineRecord;
90 
91 class  CompileReplay;
92 static CompileReplay* replay_state;
93 
94 class CompileReplay : public StackObj {
95  private:
96   FILE*   _stream;
97   Thread* _thread;
98   Handle  _protection_domain;
99   Handle  _loader;
100 
101   GrowableArray<ciMethodRecord*>     _ci_method_records;
102   GrowableArray<ciMethodDataRecord*> _ci_method_data_records;
103 
104   // Use pointer because we may need to return inline records
105   // without destroying them.
106   GrowableArray<ciInlineRecord*>*    _ci_inline_records;
107 
108   const char* _error_message;
109 
110   char* _bufptr;
111   char* _buffer;
112   int   _buffer_length;
113   int   _buffer_pos;
114 
115   // "compile" data
116   ciKlass* _iklass;
117   Method*  _imethod;
118   int      _entry_bci;
119   int      _comp_level;
120 
121  public:
CompileReplay(const char * filename,TRAPS)122   CompileReplay(const char* filename, TRAPS) {
123     _thread = THREAD;
124     _loader = Handle(_thread, SystemDictionary::java_system_loader());
125     _protection_domain = Handle();
126 
127     _stream = fopen(filename, "rt");
128     if (_stream == NULL) {
129       fprintf(stderr, "ERROR: Can't open replay file %s\n", filename);
130     }
131 
132     _ci_inline_records = NULL;
133     _error_message = NULL;
134 
135     _buffer_length = 32;
136     _buffer = NEW_RESOURCE_ARRAY(char, _buffer_length);
137     _bufptr = _buffer;
138     _buffer_pos = 0;
139 
140     _imethod = NULL;
141     _iklass  = NULL;
142     _entry_bci  = 0;
143     _comp_level = 0;
144 
145     test();
146   }
147 
~CompileReplay()148   ~CompileReplay() {
149     if (_stream != NULL) fclose(_stream);
150   }
151 
test()152   void test() {
153     strcpy(_buffer, "1 2 foo 4 bar 0x9 \"this is it\"");
154     _bufptr = _buffer;
155     assert(parse_int("test") == 1, "what");
156     assert(parse_int("test") == 2, "what");
157     assert(strcmp(parse_string(), "foo") == 0, "what");
158     assert(parse_int("test") == 4, "what");
159     assert(strcmp(parse_string(), "bar") == 0, "what");
160     assert(parse_intptr_t("test") == 9, "what");
161     assert(strcmp(parse_quoted_string(), "this is it") == 0, "what");
162   }
163 
had_error()164   bool had_error() {
165     return _error_message != NULL || _thread->has_pending_exception();
166   }
167 
can_replay()168   bool can_replay() {
169     return !(_stream == NULL || had_error());
170   }
171 
report_error(const char * msg)172   void report_error(const char* msg) {
173     _error_message = msg;
174     // Restore the _buffer contents for error reporting
175     for (int i = 0; i < _buffer_pos; i++) {
176       if (_buffer[i] == '\0') _buffer[i] = ' ';
177     }
178   }
179 
parse_int(const char * label)180   int parse_int(const char* label) {
181     if (had_error()) {
182       return 0;
183     }
184 
185     int v = 0;
186     int read;
187     if (sscanf(_bufptr, "%i%n", &v, &read) != 1) {
188       report_error(label);
189     } else {
190       _bufptr += read;
191     }
192     return v;
193   }
194 
parse_intptr_t(const char * label)195   intptr_t parse_intptr_t(const char* label) {
196     if (had_error()) {
197       return 0;
198     }
199 
200     intptr_t v = 0;
201     int read;
202     if (sscanf(_bufptr, INTPTR_FORMAT "%n", &v, &read) != 1) {
203       report_error(label);
204     } else {
205       _bufptr += read;
206     }
207     return v;
208   }
209 
skip_ws()210   void skip_ws() {
211     // Skip any leading whitespace
212     while (*_bufptr == ' ' || *_bufptr == '\t') {
213       _bufptr++;
214     }
215   }
216 
217 
scan_and_terminate(char delim)218   char* scan_and_terminate(char delim) {
219     char* str = _bufptr;
220     while (*_bufptr != delim && *_bufptr != '\0') {
221       _bufptr++;
222     }
223     if (*_bufptr != '\0') {
224       *_bufptr++ = '\0';
225     }
226     if (_bufptr == str) {
227       // nothing here
228       return NULL;
229     }
230     return str;
231   }
232 
parse_string()233   char* parse_string() {
234     if (had_error()) return NULL;
235 
236     skip_ws();
237     return scan_and_terminate(' ');
238   }
239 
parse_quoted_string()240   char* parse_quoted_string() {
241     if (had_error()) return NULL;
242 
243     skip_ws();
244 
245     if (*_bufptr == '"') {
246       _bufptr++;
247       return scan_and_terminate('"');
248     } else {
249       return scan_and_terminate(' ');
250     }
251   }
252 
parse_escaped_string()253   const char* parse_escaped_string() {
254     char* result = parse_quoted_string();
255     if (result != NULL) {
256       unescape_string(result);
257     }
258     return result;
259   }
260 
261   // Look for the tag 'tag' followed by an
parse_tag_and_count(const char * tag,int & length)262   bool parse_tag_and_count(const char* tag, int& length) {
263     const char* t = parse_string();
264     if (t == NULL) {
265       return false;
266     }
267 
268     if (strcmp(tag, t) != 0) {
269       report_error(tag);
270       return false;
271     }
272     length = parse_int("parse_tag_and_count");
273     return !had_error();
274   }
275 
276   // Parse a sequence of raw data encoded as bytes and return the
277   // resulting data.
parse_data(const char * tag,int & length)278   char* parse_data(const char* tag, int& length) {
279     int read_size = 0;
280     if (!parse_tag_and_count(tag, read_size)) {
281       return NULL;
282     }
283 
284     int actual_size = sizeof(MethodData);
285     char *result = NEW_RESOURCE_ARRAY(char, actual_size);
286     int i = 0;
287     if (read_size != actual_size) {
288       tty->print_cr("Warning: ciMethodData parsing sees MethodData size %i in file, current is %i", read_size,
289                     actual_size);
290       // Replay serializes the entire MethodData, but the data is at the end.
291       // If the MethodData instance size has changed, we can pad or truncate in the beginning
292       int padding = actual_size - read_size;
293       if (padding > 0) {
294         // pad missing data with zeros
295         tty->print_cr("- Padding MethodData");
296         for (; i < padding; i++) {
297           result[i] = 0;
298         }
299       } else if (padding < 0) {
300         // drop some data
301         tty->print_cr("- Truncating MethodData");
302         for (int j = 0; j < -padding; j++) {
303           int val = parse_int("data");
304           // discard val
305         }
306       }
307     }
308 
309     assert(i < actual_size, "At least some data must remain to be copied");
310     for (; i < actual_size; i++) {
311       int val = parse_int("data");
312       result[i] = val;
313     }
314     length = actual_size;
315     return result;
316   }
317 
318   // Parse a standard chunk of data emitted as:
319   //   'tag' <length> # # ...
320   // Where each # is an intptr_t item
parse_intptr_data(const char * tag,int & length)321   intptr_t* parse_intptr_data(const char* tag, int& length) {
322     if (!parse_tag_and_count(tag, length)) {
323       return NULL;
324     }
325 
326     intptr_t* result = NEW_RESOURCE_ARRAY(intptr_t, length);
327     for (int i = 0; i < length; i++) {
328       skip_ws();
329       intptr_t val = parse_intptr_t("data");
330       result[i] = val;
331     }
332     return result;
333   }
334 
335   // Parse a possibly quoted version of a symbol into a symbolOop
parse_symbol(TRAPS)336   Symbol* parse_symbol(TRAPS) {
337     const char* str = parse_escaped_string();
338     if (str != NULL) {
339       Symbol* sym = SymbolTable::new_symbol(str);
340       return sym;
341     }
342     return NULL;
343   }
344 
345   // Parse a valid klass name and look it up
parse_klass(TRAPS)346   Klass* parse_klass(TRAPS) {
347     const char* str = parse_escaped_string();
348     Symbol* klass_name = SymbolTable::new_symbol(str);
349     if (klass_name != NULL) {
350       Klass* k = NULL;
351       if (_iklass != NULL) {
352         k = (Klass*)_iklass->find_klass(ciSymbol::make(klass_name->as_C_string()))->constant_encoding();
353       } else {
354         k = SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, THREAD);
355       }
356       if (HAS_PENDING_EXCEPTION) {
357         oop throwable = PENDING_EXCEPTION;
358         java_lang_Throwable::print(throwable, tty);
359         tty->cr();
360         report_error(str);
361         if (ReplayIgnoreInitErrors) {
362           CLEAR_PENDING_EXCEPTION;
363           _error_message = NULL;
364         }
365         return NULL;
366       }
367       return k;
368     }
369     return NULL;
370   }
371 
372   // Lookup a klass
resolve_klass(const char * klass,TRAPS)373   Klass* resolve_klass(const char* klass, TRAPS) {
374     Symbol* klass_name = SymbolTable::new_symbol(klass);
375     return SystemDictionary::resolve_or_fail(klass_name, _loader, _protection_domain, true, THREAD);
376   }
377 
378   // Parse the standard tuple of <klass> <name> <signature>
parse_method(TRAPS)379   Method* parse_method(TRAPS) {
380     InstanceKlass* k = (InstanceKlass*)parse_klass(CHECK_NULL);
381     if (k == NULL) {
382       report_error("Can't find holder klass");
383       return NULL;
384     }
385     Symbol* method_name = parse_symbol(CHECK_NULL);
386     Symbol* method_signature = parse_symbol(CHECK_NULL);
387     Method* m = k->find_method(method_name, method_signature);
388     if (m == NULL) {
389       report_error("Can't find method");
390     }
391     return m;
392   }
393 
get_line(int c)394   int get_line(int c) {
395     while(c != EOF) {
396       if (_buffer_pos + 1 >= _buffer_length) {
397         int new_length = _buffer_length * 2;
398         // Next call will throw error in case of OOM.
399         _buffer = REALLOC_RESOURCE_ARRAY(char, _buffer, _buffer_length, new_length);
400         _buffer_length = new_length;
401       }
402       if (c == '\n') {
403         c = getc(_stream); // get next char
404         break;
405       } else if (c == '\r') {
406         // skip LF
407       } else {
408         _buffer[_buffer_pos++] = c;
409       }
410       c = getc(_stream);
411     }
412     // null terminate it, reset the pointer
413     _buffer[_buffer_pos] = '\0'; // NL or EOF
414     _buffer_pos = 0;
415     _bufptr = _buffer;
416     return c;
417   }
418 
419   // Process each line of the replay file executing each command until
420   // the file ends.
process(TRAPS)421   void process(TRAPS) {
422     int line_no = 1;
423     int c = getc(_stream);
424     while(c != EOF) {
425       c = get_line(c);
426       process_command(THREAD);
427       if (had_error()) {
428         tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
429         if (ReplayIgnoreInitErrors) {
430           CLEAR_PENDING_EXCEPTION;
431           _error_message = NULL;
432         } else {
433           return;
434         }
435       }
436       line_no++;
437     }
438   }
439 
process_command(TRAPS)440   void process_command(TRAPS) {
441     char* cmd = parse_string();
442     if (cmd == NULL) {
443       return;
444     }
445     if (strcmp("#", cmd) == 0) {
446       // ignore
447     } else if (strcmp("compile", cmd) == 0) {
448       process_compile(CHECK);
449     } else if (strcmp("ciMethod", cmd) == 0) {
450       process_ciMethod(CHECK);
451     } else if (strcmp("ciMethodData", cmd) == 0) {
452       process_ciMethodData(CHECK);
453     } else if (strcmp("staticfield", cmd) == 0) {
454       process_staticfield(CHECK);
455     } else if (strcmp("ciInstanceKlass", cmd) == 0) {
456       process_ciInstanceKlass(CHECK);
457     } else if (strcmp("instanceKlass", cmd) == 0) {
458       process_instanceKlass(CHECK);
459 #if INCLUDE_JVMTI
460     } else if (strcmp("JvmtiExport", cmd) == 0) {
461       process_JvmtiExport(CHECK);
462 #endif // INCLUDE_JVMTI
463     } else {
464       report_error("unknown command");
465     }
466   }
467 
468   // validation of comp_level
is_valid_comp_level(int comp_level)469   bool is_valid_comp_level(int comp_level) {
470     const int msg_len = 256;
471     char* msg = NULL;
472     if (!is_compile(comp_level)) {
473       msg = NEW_RESOURCE_ARRAY(char, msg_len);
474       jio_snprintf(msg, msg_len, "%d isn't compilation level", comp_level);
475     } else if (!TieredCompilation && (comp_level != CompLevel_highest_tier)) {
476       msg = NEW_RESOURCE_ARRAY(char, msg_len);
477       switch (comp_level) {
478         case CompLevel_simple:
479           jio_snprintf(msg, msg_len, "compilation level %d requires Client VM or TieredCompilation", comp_level);
480           break;
481         case CompLevel_full_optimization:
482           jio_snprintf(msg, msg_len, "compilation level %d requires Server VM", comp_level);
483           break;
484         default:
485           jio_snprintf(msg, msg_len, "compilation level %d requires TieredCompilation", comp_level);
486       }
487     }
488     if (msg != NULL) {
489       report_error(msg);
490       return false;
491     }
492     return true;
493   }
494 
495   // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ...
process_inline(ciMethod * imethod,Method * m,int entry_bci,int comp_level,TRAPS)496   void* process_inline(ciMethod* imethod, Method* m, int entry_bci, int comp_level, TRAPS) {
497     _imethod    = m;
498     _iklass     = imethod->holder();
499     _entry_bci  = entry_bci;
500     _comp_level = comp_level;
501     int line_no = 1;
502     int c = getc(_stream);
503     while(c != EOF) {
504       c = get_line(c);
505       // Expecting only lines with "compile" command in inline replay file.
506       char* cmd = parse_string();
507       if (cmd == NULL || strcmp("compile", cmd) != 0) {
508         return NULL;
509       }
510       process_compile(CHECK_NULL);
511       if (had_error()) {
512         tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
513         tty->print_cr("%s", _buffer);
514         return NULL;
515       }
516       if (_ci_inline_records != NULL && _ci_inline_records->length() > 0) {
517         // Found inlining record for the requested method.
518         return _ci_inline_records;
519       }
520       line_no++;
521     }
522     return NULL;
523   }
524 
525   // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ...
process_compile(TRAPS)526   void process_compile(TRAPS) {
527     Method* method = parse_method(CHECK);
528     if (had_error()) return;
529     int entry_bci = parse_int("entry_bci");
530     const char* comp_level_label = "comp_level";
531     int comp_level = parse_int(comp_level_label);
532     // old version w/o comp_level
533     if (had_error() && (error_message() == comp_level_label)) {
534       // use highest available tier
535       if (TieredCompilation) {
536         comp_level = TieredStopAtLevel;
537       } else {
538         comp_level = CompLevel_highest_tier;
539       }
540     }
541     if (!is_valid_comp_level(comp_level)) {
542       return;
543     }
544     if (_imethod != NULL) {
545       // Replay Inlining
546       if (entry_bci != _entry_bci || comp_level != _comp_level) {
547         return;
548       }
549       const char* iklass_name  = _imethod->method_holder()->name()->as_utf8();
550       const char* imethod_name = _imethod->name()->as_utf8();
551       const char* isignature   = _imethod->signature()->as_utf8();
552       const char* klass_name   = method->method_holder()->name()->as_utf8();
553       const char* method_name  = method->name()->as_utf8();
554       const char* signature    = method->signature()->as_utf8();
555       if (strcmp(iklass_name,  klass_name)  != 0 ||
556           strcmp(imethod_name, method_name) != 0 ||
557           strcmp(isignature,   signature)   != 0) {
558         return;
559       }
560     }
561     int inline_count = 0;
562     if (parse_tag_and_count("inline", inline_count)) {
563       // Record inlining data
564       _ci_inline_records = new GrowableArray<ciInlineRecord*>();
565       for (int i = 0; i < inline_count; i++) {
566         int depth = parse_int("inline_depth");
567         int bci = parse_int("inline_bci");
568         if (had_error()) {
569           break;
570         }
571         Method* inl_method = parse_method(CHECK);
572         if (had_error()) {
573           break;
574         }
575         new_ciInlineRecord(inl_method, bci, depth);
576       }
577     }
578     if (_imethod != NULL) {
579       return; // Replay Inlining
580     }
581     InstanceKlass* ik = method->method_holder();
582     ik->initialize(THREAD);
583     if (HAS_PENDING_EXCEPTION) {
584       oop throwable = PENDING_EXCEPTION;
585       java_lang_Throwable::print(throwable, tty);
586       tty->cr();
587       if (ReplayIgnoreInitErrors) {
588         CLEAR_PENDING_EXCEPTION;
589         ik->set_init_state(InstanceKlass::fully_initialized);
590       } else {
591         return;
592       }
593     }
594     // Make sure the existence of a prior compile doesn't stop this one
595     CompiledMethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code();
596     if (nm != NULL) {
597       nm->make_not_entrant();
598     }
599     replay_state = this;
600     CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level,
601                                   methodHandle(), 0, CompileTask::Reason_Replay, THREAD);
602     replay_state = NULL;
603     reset();
604   }
605 
606   // ciMethod <klass> <name> <signature> <invocation_counter> <backedge_counter> <interpreter_invocation_count> <interpreter_throwout_count> <instructions_size>
607   //
608   //
process_ciMethod(TRAPS)609   void process_ciMethod(TRAPS) {
610     Method* method = parse_method(CHECK);
611     if (had_error()) return;
612     ciMethodRecord* rec = new_ciMethod(method);
613     rec->_invocation_counter = parse_int("invocation_counter");
614     rec->_backedge_counter = parse_int("backedge_counter");
615     rec->_interpreter_invocation_count = parse_int("interpreter_invocation_count");
616     rec->_interpreter_throwout_count = parse_int("interpreter_throwout_count");
617     rec->_instructions_size = parse_int("instructions_size");
618   }
619 
620   // ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length> # ... methods <length>
process_ciMethodData(TRAPS)621   void process_ciMethodData(TRAPS) {
622     Method* method = parse_method(CHECK);
623     if (had_error()) return;
624     /* just copied from Method, to build interpret data*/
625 
626     // To be properly initialized, some profiling in the MDO needs the
627     // method to be rewritten (number of arguments at a call for
628     // instance)
629     method->method_holder()->link_class(CHECK);
630     // methodOopDesc::build_interpreter_method_data(method, CHECK);
631     {
632       // Grab a lock here to prevent multiple
633       // MethodData*s from being created.
634       MutexLocker ml(MethodData_lock, THREAD);
635       if (method->method_data() == NULL) {
636         ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
637         MethodData* method_data = MethodData::allocate(loader_data, methodHandle(THREAD, method), CHECK);
638         method->set_method_data(method_data);
639       }
640     }
641 
642     // collect and record all the needed information for later
643     ciMethodDataRecord* rec = new_ciMethodData(method);
644     rec->_state = parse_int("state");
645     rec->_current_mileage = parse_int("current_mileage");
646 
647     rec->_orig_data = parse_data("orig", rec->_orig_data_length);
648     if (rec->_orig_data == NULL) {
649       return;
650     }
651     rec->_data = parse_intptr_data("data", rec->_data_length);
652     if (rec->_data == NULL) {
653       return;
654     }
655     if (!parse_tag_and_count("oops", rec->_classes_length)) {
656       return;
657     }
658     rec->_classes = NEW_RESOURCE_ARRAY(Klass*, rec->_classes_length);
659     rec->_classes_offsets = NEW_RESOURCE_ARRAY(int, rec->_classes_length);
660     for (int i = 0; i < rec->_classes_length; i++) {
661       int offset = parse_int("offset");
662       if (had_error()) {
663         return;
664       }
665       Klass* k = parse_klass(CHECK);
666       rec->_classes_offsets[i] = offset;
667       rec->_classes[i] = k;
668     }
669 
670     if (!parse_tag_and_count("methods", rec->_methods_length)) {
671       return;
672     }
673     rec->_methods = NEW_RESOURCE_ARRAY(Method*, rec->_methods_length);
674     rec->_methods_offsets = NEW_RESOURCE_ARRAY(int, rec->_methods_length);
675     for (int i = 0; i < rec->_methods_length; i++) {
676       int offset = parse_int("offset");
677       if (had_error()) {
678         return;
679       }
680       Method* m = parse_method(CHECK);
681       rec->_methods_offsets[i] = offset;
682       rec->_methods[i] = m;
683     }
684   }
685 
686   // instanceKlass <name>
687   //
688   // Loads and initializes the klass 'name'.  This can be used to
689   // create particular class loading environments
process_instanceKlass(TRAPS)690   void process_instanceKlass(TRAPS) {
691     // just load the referenced class
692     Klass* k = parse_klass(CHECK);
693   }
694 
695   // ciInstanceKlass <name> <is_linked> <is_initialized> <length> tag # # # ...
696   //
697   // Load the klass 'name' and link or initialize it.  Verify that the
698   // constant pool is the same length as 'length' and make sure the
699   // constant pool tags are in the same state.
process_ciInstanceKlass(TRAPS)700   void process_ciInstanceKlass(TRAPS) {
701     InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
702     if (k == NULL) {
703       return;
704     }
705     int is_linked = parse_int("is_linked");
706     int is_initialized = parse_int("is_initialized");
707     int length = parse_int("length");
708     if (is_initialized) {
709       k->initialize(THREAD);
710       if (HAS_PENDING_EXCEPTION) {
711         oop throwable = PENDING_EXCEPTION;
712         java_lang_Throwable::print(throwable, tty);
713         tty->cr();
714         if (ReplayIgnoreInitErrors) {
715           CLEAR_PENDING_EXCEPTION;
716           k->set_init_state(InstanceKlass::fully_initialized);
717         } else {
718           return;
719         }
720       }
721     } else if (is_linked) {
722       k->link_class(CHECK);
723     }
724     ConstantPool* cp = k->constants();
725     if (length != cp->length()) {
726       report_error("constant pool length mismatch: wrong class files?");
727       return;
728     }
729 
730     int parsed_two_word = 0;
731     for (int i = 1; i < length; i++) {
732       int tag = parse_int("tag");
733       if (had_error()) {
734         return;
735       }
736       switch (cp->tag_at(i).value()) {
737         case JVM_CONSTANT_UnresolvedClass: {
738           if (tag == JVM_CONSTANT_Class) {
739             tty->print_cr("Resolving klass %s at %d", cp->klass_name_at(i)->as_utf8(), i);
740             Klass* k = cp->klass_at(i, CHECK);
741           }
742           break;
743         }
744         case JVM_CONSTANT_Long:
745         case JVM_CONSTANT_Double:
746           parsed_two_word = i + 1;
747 
748         case JVM_CONSTANT_ClassIndex:
749         case JVM_CONSTANT_StringIndex:
750         case JVM_CONSTANT_String:
751         case JVM_CONSTANT_UnresolvedClassInError:
752         case JVM_CONSTANT_Fieldref:
753         case JVM_CONSTANT_Methodref:
754         case JVM_CONSTANT_InterfaceMethodref:
755         case JVM_CONSTANT_NameAndType:
756         case JVM_CONSTANT_Utf8:
757         case JVM_CONSTANT_Integer:
758         case JVM_CONSTANT_Float:
759         case JVM_CONSTANT_MethodHandle:
760         case JVM_CONSTANT_MethodType:
761         case JVM_CONSTANT_Dynamic:
762         case JVM_CONSTANT_InvokeDynamic:
763           if (tag != cp->tag_at(i).value()) {
764             report_error("tag mismatch: wrong class files?");
765             return;
766           }
767           break;
768 
769         case JVM_CONSTANT_Class:
770           if (tag == JVM_CONSTANT_Class) {
771           } else if (tag == JVM_CONSTANT_UnresolvedClass) {
772             tty->print_cr("Warning: entry was unresolved in the replay data");
773           } else {
774             report_error("Unexpected tag");
775             return;
776           }
777           break;
778 
779         case 0:
780           if (parsed_two_word == i) continue;
781 
782         default:
783           fatal("Unexpected tag: %d", cp->tag_at(i).value());
784           break;
785       }
786 
787     }
788   }
789 
790   // Initialize a class and fill in the value for a static field.
791   // This is useful when the compile was dependent on the value of
792   // static fields but it's impossible to properly rerun the static
793   // initiailizer.
process_staticfield(TRAPS)794   void process_staticfield(TRAPS) {
795     InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
796 
797     if (k == NULL || ReplaySuppressInitializers == 0 ||
798         (ReplaySuppressInitializers == 2 && k->class_loader() == NULL)) {
799       return;
800     }
801 
802     assert(k->is_initialized(), "must be");
803 
804     const char* field_name = parse_escaped_string();
805     const char* field_signature = parse_string();
806     fieldDescriptor fd;
807     Symbol* name = SymbolTable::new_symbol(field_name);
808     Symbol* sig = SymbolTable::new_symbol(field_signature);
809     if (!k->find_local_field(name, sig, &fd) ||
810         !fd.is_static() ||
811         fd.has_initial_value()) {
812       report_error(field_name);
813       return;
814     }
815 
816     oop java_mirror = k->java_mirror();
817     if (field_signature[0] == JVM_SIGNATURE_ARRAY) {
818       int length = parse_int("array length");
819       oop value = NULL;
820 
821       if (field_signature[1] == JVM_SIGNATURE_ARRAY) {
822         // multi dimensional array
823         ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK);
824         if (kelem == NULL) {
825           return;
826         }
827         int rank = 0;
828         while (field_signature[rank] == JVM_SIGNATURE_ARRAY) {
829           rank++;
830         }
831         jint* dims = NEW_RESOURCE_ARRAY(jint, rank);
832         dims[0] = length;
833         for (int i = 1; i < rank; i++) {
834           dims[i] = 1; // These aren't relevant to the compiler
835         }
836         value = kelem->multi_allocate(rank, dims, CHECK);
837       } else {
838         if (strcmp(field_signature, "[B") == 0) {
839           value = oopFactory::new_byteArray(length, CHECK);
840         } else if (strcmp(field_signature, "[Z") == 0) {
841           value = oopFactory::new_boolArray(length, CHECK);
842         } else if (strcmp(field_signature, "[C") == 0) {
843           value = oopFactory::new_charArray(length, CHECK);
844         } else if (strcmp(field_signature, "[S") == 0) {
845           value = oopFactory::new_shortArray(length, CHECK);
846         } else if (strcmp(field_signature, "[F") == 0) {
847           value = oopFactory::new_floatArray(length, CHECK);
848         } else if (strcmp(field_signature, "[D") == 0) {
849           value = oopFactory::new_doubleArray(length, CHECK);
850         } else if (strcmp(field_signature, "[I") == 0) {
851           value = oopFactory::new_intArray(length, CHECK);
852         } else if (strcmp(field_signature, "[J") == 0) {
853           value = oopFactory::new_longArray(length, CHECK);
854         } else if (field_signature[0] == JVM_SIGNATURE_ARRAY &&
855                    field_signature[1] == JVM_SIGNATURE_CLASS) {
856           Klass* kelem = resolve_klass(field_signature + 1, CHECK);
857           value = oopFactory::new_objArray(kelem, length, CHECK);
858         } else {
859           report_error("unhandled array staticfield");
860         }
861       }
862       java_mirror->obj_field_put(fd.offset(), value);
863     } else {
864       const char* string_value = parse_escaped_string();
865       if (strcmp(field_signature, "I") == 0) {
866         int value = atoi(string_value);
867         java_mirror->int_field_put(fd.offset(), value);
868       } else if (strcmp(field_signature, "B") == 0) {
869         int value = atoi(string_value);
870         java_mirror->byte_field_put(fd.offset(), value);
871       } else if (strcmp(field_signature, "C") == 0) {
872         int value = atoi(string_value);
873         java_mirror->char_field_put(fd.offset(), value);
874       } else if (strcmp(field_signature, "S") == 0) {
875         int value = atoi(string_value);
876         java_mirror->short_field_put(fd.offset(), value);
877       } else if (strcmp(field_signature, "Z") == 0) {
878         int value = atoi(string_value);
879         java_mirror->bool_field_put(fd.offset(), value);
880       } else if (strcmp(field_signature, "J") == 0) {
881         jlong value;
882         if (sscanf(string_value, JLONG_FORMAT, &value) != 1) {
883           fprintf(stderr, "Error parsing long: %s\n", string_value);
884           return;
885         }
886         java_mirror->long_field_put(fd.offset(), value);
887       } else if (strcmp(field_signature, "F") == 0) {
888         float value = atof(string_value);
889         java_mirror->float_field_put(fd.offset(), value);
890       } else if (strcmp(field_signature, "D") == 0) {
891         double value = atof(string_value);
892         java_mirror->double_field_put(fd.offset(), value);
893       } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) {
894         Handle value = java_lang_String::create_from_str(string_value, CHECK);
895         java_mirror->obj_field_put(fd.offset(), value());
896       } else if (field_signature[0] == JVM_SIGNATURE_CLASS) {
897         Klass* k = resolve_klass(string_value, CHECK);
898         oop value = InstanceKlass::cast(k)->allocate_instance(CHECK);
899         java_mirror->obj_field_put(fd.offset(), value);
900       } else {
901         report_error("unhandled staticfield");
902       }
903     }
904   }
905 
906 #if INCLUDE_JVMTI
process_JvmtiExport(TRAPS)907   void process_JvmtiExport(TRAPS) {
908     const char* field = parse_string();
909     bool value = parse_int("JvmtiExport flag") != 0;
910     if (strcmp(field, "can_access_local_variables") == 0) {
911       JvmtiExport::set_can_access_local_variables(value);
912     } else if (strcmp(field, "can_hotswap_or_post_breakpoint") == 0) {
913       JvmtiExport::set_can_hotswap_or_post_breakpoint(value);
914     } else if (strcmp(field, "can_post_on_exceptions") == 0) {
915       JvmtiExport::set_can_post_on_exceptions(value);
916     } else {
917       report_error("Unrecognized JvmtiExport directive");
918     }
919   }
920 #endif // INCLUDE_JVMTI
921 
922   // Create and initialize a record for a ciMethod
new_ciMethod(Method * method)923   ciMethodRecord* new_ciMethod(Method* method) {
924     ciMethodRecord* rec = NEW_RESOURCE_OBJ(ciMethodRecord);
925     rec->_klass_name =  method->method_holder()->name()->as_utf8();
926     rec->_method_name = method->name()->as_utf8();
927     rec->_signature = method->signature()->as_utf8();
928     _ci_method_records.append(rec);
929     return rec;
930   }
931 
932   // Lookup data for a ciMethod
find_ciMethodRecord(Method * method)933   ciMethodRecord* find_ciMethodRecord(Method* method) {
934     const char* klass_name =  method->method_holder()->name()->as_utf8();
935     const char* method_name = method->name()->as_utf8();
936     const char* signature = method->signature()->as_utf8();
937     for (int i = 0; i < _ci_method_records.length(); i++) {
938       ciMethodRecord* rec = _ci_method_records.at(i);
939       if (strcmp(rec->_klass_name, klass_name) == 0 &&
940           strcmp(rec->_method_name, method_name) == 0 &&
941           strcmp(rec->_signature, signature) == 0) {
942         return rec;
943       }
944     }
945     return NULL;
946   }
947 
948   // Create and initialize a record for a ciMethodData
new_ciMethodData(Method * method)949   ciMethodDataRecord* new_ciMethodData(Method* method) {
950     ciMethodDataRecord* rec = NEW_RESOURCE_OBJ(ciMethodDataRecord);
951     rec->_klass_name =  method->method_holder()->name()->as_utf8();
952     rec->_method_name = method->name()->as_utf8();
953     rec->_signature = method->signature()->as_utf8();
954     _ci_method_data_records.append(rec);
955     return rec;
956   }
957 
958   // Lookup data for a ciMethodData
find_ciMethodDataRecord(Method * method)959   ciMethodDataRecord* find_ciMethodDataRecord(Method* method) {
960     const char* klass_name =  method->method_holder()->name()->as_utf8();
961     const char* method_name = method->name()->as_utf8();
962     const char* signature = method->signature()->as_utf8();
963     for (int i = 0; i < _ci_method_data_records.length(); i++) {
964       ciMethodDataRecord* rec = _ci_method_data_records.at(i);
965       if (strcmp(rec->_klass_name, klass_name) == 0 &&
966           strcmp(rec->_method_name, method_name) == 0 &&
967           strcmp(rec->_signature, signature) == 0) {
968         return rec;
969       }
970     }
971     return NULL;
972   }
973 
974   // Create and initialize a record for a ciInlineRecord
new_ciInlineRecord(Method * method,int bci,int depth)975   ciInlineRecord* new_ciInlineRecord(Method* method, int bci, int depth) {
976     ciInlineRecord* rec = NEW_RESOURCE_OBJ(ciInlineRecord);
977     rec->_klass_name =  method->method_holder()->name()->as_utf8();
978     rec->_method_name = method->name()->as_utf8();
979     rec->_signature = method->signature()->as_utf8();
980     rec->_inline_bci = bci;
981     rec->_inline_depth = depth;
982     _ci_inline_records->append(rec);
983     return rec;
984   }
985 
986   // Lookup inlining data for a ciMethod
find_ciInlineRecord(Method * method,int bci,int depth)987   ciInlineRecord* find_ciInlineRecord(Method* method, int bci, int depth) {
988     if (_ci_inline_records != NULL) {
989       return find_ciInlineRecord(_ci_inline_records, method, bci, depth);
990     }
991     return NULL;
992   }
993 
find_ciInlineRecord(GrowableArray<ciInlineRecord * > * records,Method * method,int bci,int depth)994   static ciInlineRecord* find_ciInlineRecord(GrowableArray<ciInlineRecord*>*  records,
995                                       Method* method, int bci, int depth) {
996     if (records != NULL) {
997       const char* klass_name  = method->method_holder()->name()->as_utf8();
998       const char* method_name = method->name()->as_utf8();
999       const char* signature   = method->signature()->as_utf8();
1000       for (int i = 0; i < records->length(); i++) {
1001         ciInlineRecord* rec = records->at(i);
1002         if ((rec->_inline_bci == bci) &&
1003             (rec->_inline_depth == depth) &&
1004             (strcmp(rec->_klass_name, klass_name) == 0) &&
1005             (strcmp(rec->_method_name, method_name) == 0) &&
1006             (strcmp(rec->_signature, signature) == 0)) {
1007           return rec;
1008         }
1009       }
1010     }
1011     return NULL;
1012   }
1013 
error_message()1014   const char* error_message() {
1015     return _error_message;
1016   }
1017 
reset()1018   void reset() {
1019     _error_message = NULL;
1020     _ci_method_records.clear();
1021     _ci_method_data_records.clear();
1022   }
1023 
1024   // Take an ascii string contain \u#### escapes and convert it to utf8
1025   // in place.
unescape_string(char * value)1026   static void unescape_string(char* value) {
1027     char* from = value;
1028     char* to = value;
1029     while (*from != '\0') {
1030       if (*from != '\\') {
1031         *from++ = *to++;
1032       } else {
1033         switch (from[1]) {
1034           case 'u': {
1035             from += 2;
1036             jchar value=0;
1037             for (int i=0; i<4; i++) {
1038               char c = *from++;
1039               switch (c) {
1040                 case '0': case '1': case '2': case '3': case '4':
1041                 case '5': case '6': case '7': case '8': case '9':
1042                   value = (value << 4) + c - '0';
1043                   break;
1044                 case 'a': case 'b': case 'c':
1045                 case 'd': case 'e': case 'f':
1046                   value = (value << 4) + 10 + c - 'a';
1047                   break;
1048                 case 'A': case 'B': case 'C':
1049                 case 'D': case 'E': case 'F':
1050                   value = (value << 4) + 10 + c - 'A';
1051                   break;
1052                 default:
1053                   ShouldNotReachHere();
1054               }
1055             }
1056             UNICODE::convert_to_utf8(&value, 1, to);
1057             to++;
1058             break;
1059           }
1060           case 't': *to++ = '\t'; from += 2; break;
1061           case 'n': *to++ = '\n'; from += 2; break;
1062           case 'r': *to++ = '\r'; from += 2; break;
1063           case 'f': *to++ = '\f'; from += 2; break;
1064           default:
1065             ShouldNotReachHere();
1066         }
1067       }
1068     }
1069     *from = *to;
1070   }
1071 };
1072 
replay(TRAPS)1073 void ciReplay::replay(TRAPS) {
1074   int exit_code = replay_impl(THREAD);
1075 
1076   Threads::destroy_vm();
1077 
1078   vm_exit(exit_code);
1079 }
1080 
load_inline_data(ciMethod * method,int entry_bci,int comp_level)1081 void* ciReplay::load_inline_data(ciMethod* method, int entry_bci, int comp_level) {
1082   if (FLAG_IS_DEFAULT(InlineDataFile)) {
1083     tty->print_cr("ERROR: no inline replay data file specified (use -XX:InlineDataFile=inline_pid12345.txt).");
1084     return NULL;
1085   }
1086 
1087   VM_ENTRY_MARK;
1088   // Load and parse the replay data
1089   CompileReplay rp(InlineDataFile, THREAD);
1090   if (!rp.can_replay()) {
1091     tty->print_cr("ciReplay: !rp.can_replay()");
1092     return NULL;
1093   }
1094   void* data = rp.process_inline(method, method->get_Method(), entry_bci, comp_level, THREAD);
1095   if (HAS_PENDING_EXCEPTION) {
1096     Handle throwable(THREAD, PENDING_EXCEPTION);
1097     CLEAR_PENDING_EXCEPTION;
1098     java_lang_Throwable::print_stack_trace(throwable, tty);
1099     tty->cr();
1100     return NULL;
1101   }
1102 
1103   if (rp.had_error()) {
1104     tty->print_cr("ciReplay: Failed on %s", rp.error_message());
1105     return NULL;
1106   }
1107   return data;
1108 }
1109 
replay_impl(TRAPS)1110 int ciReplay::replay_impl(TRAPS) {
1111   HandleMark hm;
1112   ResourceMark rm;
1113 
1114   if (ReplaySuppressInitializers > 2) {
1115     // ReplaySuppressInitializers > 2 means that we want to allow
1116     // normal VM bootstrap but once we get into the replay itself
1117     // don't allow any intializers to be run.
1118     ReplaySuppressInitializers = 1;
1119   }
1120 
1121   if (FLAG_IS_DEFAULT(ReplayDataFile)) {
1122     tty->print_cr("ERROR: no compiler replay data file specified (use -XX:ReplayDataFile=replay_pid12345.txt).");
1123     return 1;
1124   }
1125 
1126   // Load and parse the replay data
1127   CompileReplay rp(ReplayDataFile, THREAD);
1128   int exit_code = 0;
1129   if (rp.can_replay()) {
1130     rp.process(THREAD);
1131   } else {
1132     exit_code = 1;
1133     return exit_code;
1134   }
1135 
1136   if (HAS_PENDING_EXCEPTION) {
1137     Handle throwable(THREAD, PENDING_EXCEPTION);
1138     CLEAR_PENDING_EXCEPTION;
1139     java_lang_Throwable::print_stack_trace(throwable, tty);
1140     tty->cr();
1141     exit_code = 2;
1142   }
1143 
1144   if (rp.had_error()) {
1145     tty->print_cr("Failed on %s", rp.error_message());
1146     exit_code = 1;
1147   }
1148   return exit_code;
1149 }
1150 
initialize(ciMethodData * m)1151 void ciReplay::initialize(ciMethodData* m) {
1152   if (replay_state == NULL) {
1153     return;
1154   }
1155 
1156   ASSERT_IN_VM;
1157   ResourceMark rm;
1158 
1159   Method* method = m->get_MethodData()->method();
1160   ciMethodDataRecord* rec = replay_state->find_ciMethodDataRecord(method);
1161   if (rec == NULL) {
1162     // This indicates some mismatch with the original environment and
1163     // the replay environment though it's not always enough to
1164     // interfere with reproducing a bug
1165     tty->print_cr("Warning: requesting ciMethodData record for method with no data: ");
1166     method->print_name(tty);
1167     tty->cr();
1168   } else {
1169     m->_state = rec->_state;
1170     m->_current_mileage = rec->_current_mileage;
1171     if (rec->_data_length != 0) {
1172       assert(m->_data_size + m->_extra_data_size == rec->_data_length * (int)sizeof(rec->_data[0]) ||
1173              m->_data_size == rec->_data_length * (int)sizeof(rec->_data[0]), "must agree");
1174 
1175       // Write the correct ciObjects back into the profile data
1176       ciEnv* env = ciEnv::current();
1177       for (int i = 0; i < rec->_classes_length; i++) {
1178         Klass *k = rec->_classes[i];
1179         // In case this class pointer is is tagged, preserve the tag bits
1180         intptr_t status = 0;
1181         if (k != NULL) {
1182           status = ciTypeEntries::with_status(env->get_metadata(k)->as_klass(), rec->_data[rec->_classes_offsets[i]]);
1183         }
1184         rec->_data[rec->_classes_offsets[i]] = status;
1185       }
1186       for (int i = 0; i < rec->_methods_length; i++) {
1187         Method *m = rec->_methods[i];
1188         *(ciMetadata**)(rec->_data + rec->_methods_offsets[i]) =
1189           env->get_metadata(m);
1190       }
1191       // Copy the updated profile data into place as intptr_ts
1192 #ifdef _LP64
1193       Copy::conjoint_jlongs_atomic((jlong *)rec->_data, (jlong *)m->_data, rec->_data_length);
1194 #else
1195       Copy::conjoint_jints_atomic((jint *)rec->_data, (jint *)m->_data, rec->_data_length);
1196 #endif
1197     }
1198 
1199     // copy in the original header
1200     Copy::conjoint_jbytes(rec->_orig_data, (char*)&m->_orig, rec->_orig_data_length);
1201   }
1202 }
1203 
1204 
should_not_inline(ciMethod * method)1205 bool ciReplay::should_not_inline(ciMethod* method) {
1206   if (replay_state == NULL) {
1207     return false;
1208   }
1209   VM_ENTRY_MARK;
1210   // ciMethod without a record shouldn't be inlined.
1211   return replay_state->find_ciMethodRecord(method->get_Method()) == NULL;
1212 }
1213 
should_inline(void * data,ciMethod * method,int bci,int inline_depth)1214 bool ciReplay::should_inline(void* data, ciMethod* method, int bci, int inline_depth) {
1215   if (data != NULL) {
1216     GrowableArray<ciInlineRecord*>*  records = (GrowableArray<ciInlineRecord*>*)data;
1217     VM_ENTRY_MARK;
1218     // Inline record are ordered by bci and depth.
1219     return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) != NULL;
1220   } else if (replay_state != NULL) {
1221     VM_ENTRY_MARK;
1222     // Inline record are ordered by bci and depth.
1223     return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) != NULL;
1224   }
1225   return false;
1226 }
1227 
should_not_inline(void * data,ciMethod * method,int bci,int inline_depth)1228 bool ciReplay::should_not_inline(void* data, ciMethod* method, int bci, int inline_depth) {
1229   if (data != NULL) {
1230     GrowableArray<ciInlineRecord*>*  records = (GrowableArray<ciInlineRecord*>*)data;
1231     VM_ENTRY_MARK;
1232     // Inline record are ordered by bci and depth.
1233     return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) == NULL;
1234   } else if (replay_state != NULL) {
1235     VM_ENTRY_MARK;
1236     // Inline record are ordered by bci and depth.
1237     return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) == NULL;
1238   }
1239   return false;
1240 }
1241 
initialize(ciMethod * m)1242 void ciReplay::initialize(ciMethod* m) {
1243   if (replay_state == NULL) {
1244     return;
1245   }
1246 
1247   ASSERT_IN_VM;
1248   ResourceMark rm;
1249 
1250   Method* method = m->get_Method();
1251   ciMethodRecord* rec = replay_state->find_ciMethodRecord(method);
1252   if (rec == NULL) {
1253     // This indicates some mismatch with the original environment and
1254     // the replay environment though it's not always enough to
1255     // interfere with reproducing a bug
1256     tty->print_cr("Warning: requesting ciMethod record for method with no data: ");
1257     method->print_name(tty);
1258     tty->cr();
1259   } else {
1260     EXCEPTION_CONTEXT;
1261     // m->_instructions_size = rec->_instructions_size;
1262     m->_instructions_size = -1;
1263     m->_interpreter_invocation_count = rec->_interpreter_invocation_count;
1264     m->_interpreter_throwout_count = rec->_interpreter_throwout_count;
1265     MethodCounters* mcs = method->get_method_counters(CHECK_AND_CLEAR);
1266     guarantee(mcs != NULL, "method counters allocation failed");
1267     mcs->invocation_counter()->_counter = rec->_invocation_counter;
1268     mcs->backedge_counter()->_counter = rec->_backedge_counter;
1269   }
1270 }
1271 
is_loaded(Method * method)1272 bool ciReplay::is_loaded(Method* method) {
1273   if (replay_state == NULL) {
1274     return true;
1275   }
1276 
1277   ASSERT_IN_VM;
1278   ResourceMark rm;
1279 
1280   ciMethodRecord* rec = replay_state->find_ciMethodRecord(method);
1281   return rec != NULL;
1282 }
1283 #endif // PRODUCT
1284