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