src/share/vm/ci/ciReplay.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/ci/ciReplay.cpp	Fri Dec 27 17:10:19 2013
--- new/src/share/vm/ci/ciReplay.cpp	Fri Dec 27 17:10:19 2013

*** 22,31 **** --- 22,33 ---- */ #include "precompiled.hpp" #include "ci/ciMethodData.hpp" #include "ci/ciReplay.hpp" + #include "ci/ciSymbol.hpp" + #include "ci/ciKlass.hpp" #include "ci/ciUtilities.hpp" #include "compiler/compileBroker.hpp" #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp"
*** 60,69 **** --- 62,79 ---- int interpreter_throwout_count; int invocation_counter; int backedge_counter; } ciMethodRecord; + typedef struct _ciInlineRecord { + const char* klass; + const char* method; + const char* signature; + int inline_depth; + int bci; + } ciInlineRecord; + class CompileReplay; static CompileReplay* replay_state; class CompileReplay : public StackObj { private:
*** 72,81 **** --- 82,94 ---- Handle protection_domain; Handle loader; GrowableArray<ciMethodRecord*> ci_method_records; GrowableArray<ciMethodDataRecord*> ci_method_data_records; + // Use pointer because we may need to retirn inline records + // without destroying. + GrowableArray<ciInlineRecord*>* ci_inline_records; const char* _error_message; char* bufptr; char* buffer;
*** 271,281 **** --- 284,299 ---- // Parse a valid klass name and look it up Klass* parse_klass(TRAPS) { const char* str = parse_escaped_string(); Symbol* klass_name = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL); if (klass_name != NULL) { ! Klass* k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD); ! Klass* k = NULL; + if (_iklass != NULL) { + k = (Klass*)_iklass->find_klass(ciSymbol::make(klass_name->as_C_string()))->constant_encoding(); + } else { + k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD); + } if (HAS_PENDING_EXCEPTION) { oop throwable = PENDING_EXCEPTION; java_lang_Throwable::print(throwable, tty); tty->cr(); report_error(str);
*** 305,314 **** --- 323,337 ---- } // Process each line of the replay file executing each command until // the file ends. void process(TRAPS) { + _imethod = NULL; + _iklass = NULL; + _entry_bci = 0; + _comp_level = 0; + line_no = 1; int pos = 0; int c = getc(stream); while(c != EOF) { if (pos + 1 >= buffer_length) {
*** 394,404 **** --- 417,482 ---- return false; } return true; } // compile <klass> <name> <signature> <entry_bci> <comp_level> + ciKlass* _iklass; + Method* _imethod; + int _entry_bci; + int _comp_level; + + // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ... + void* process_inline(ciMethod* imethod, Method* m, int entry_bci, int comp_level, TRAPS) { + _imethod = m; + _iklass = imethod->holder(); + _entry_bci = entry_bci; + _comp_level = comp_level; + line_no = 1; + int pos = 0; + int c = getc(stream); + while(c != EOF) { + if (pos + 1 >= buffer_length) { + int newl = buffer_length * 2; + char* newb = NEW_RESOURCE_ARRAY(char, newl); + memcpy(newb, buffer, pos); + buffer = newb; + buffer_length = newl; + } + if (c == '\n') { + // null terminate it, reset the pointer and process the line + buffer[pos] = '\0'; + buffer_end = pos++; + bufptr = buffer; + { + char* cmd = parse_string(); + if (cmd == NULL || strcmp("compile", cmd) != 0) { + return NULL; + } + process_compile(CHECK_NULL); + if (ci_inline_records != NULL && ci_inline_records->length() > 0) { + return ci_inline_records; + } + } + if (had_error()) { + tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message); + tty->print_cr("%s", buffer); + return NULL; + } + pos = 0; + buffer_end = 0; + line_no++; + } else if (c == '\r') { + // skip LF + } else { + buffer[pos++] = c; + } + c = getc(stream); + } + return NULL; + } + + // compile <klass> <name> <signature> <entry_bci> <comp_level> inline <count> <depth> <bci> <klass> <name> <signature> ... void process_compile(TRAPS) { Method* method = parse_method(CHECK); if (had_error()) return; int entry_bci = parse_int("entry_bci"); const char* comp_level_label = "comp_level";
*** 408,417 **** --- 486,532 ---- comp_level = CompLevel_full_optimization; } if (!is_valid_comp_level(comp_level)) { return; } + if (_imethod != NULL) { + // Replay Inlinig + if (entry_bci != _entry_bci || comp_level != _comp_level) { + return; + } + const char* iklass_name = _imethod->method_holder()->name()->as_utf8(); + const char* imethod_name = _imethod->name()->as_utf8(); + const char* isignature = _imethod->signature()->as_utf8(); + const char* klass_name = method->method_holder()->name()->as_utf8(); + const char* method_name = method->name()->as_utf8(); + const char* signature = method->signature()->as_utf8(); + if (strcmp(iklass_name, klass_name) != 0 || + strcmp(imethod_name, method_name) != 0 || + strcmp(isignature, signature) != 0) { + return; + } + } + int inline_count = 0; + if (parse_tag_and_count("inline", inline_count)) { + // Record inlining data + ci_inline_records = new GrowableArray<ciInlineRecord*>(); + for (int i = 0; i < inline_count; i++) { + int depth = parse_int("inline_depth"); + int bci = parse_int("inline_bci"); + if (had_error()) { + break; + } + Method* inl_method = parse_method(CHECK); + if (had_error()) { + break; + } + new_ciInlineRecord(inl_method, bci, depth); + } + } + if (_imethod != NULL) { + return; // Replay Inlining + } Klass* k = method->method_holder(); ((InstanceKlass*)k)->initialize(THREAD); if (HAS_PENDING_EXCEPTION) { oop throwable = PENDING_EXCEPTION; java_lang_Throwable::print(throwable, tty);
*** 568,577 **** --- 683,695 ---- case JVM_CONSTANT_InterfaceMethodref: case JVM_CONSTANT_NameAndType: case JVM_CONSTANT_Utf8: case JVM_CONSTANT_Integer: case JVM_CONSTANT_Float: + case JVM_CONSTANT_MethodHandle: + case JVM_CONSTANT_MethodType: + case JVM_CONSTANT_InvokeDynamic: if (tag != cp->tag_at(i).value()) { report_error("tag mismatch: wrong class files?"); return; } break;
*** 776,785 **** --- 894,955 ---- } } return NULL; } + // Create and initialize a record for a ciInlineRecord + ciInlineRecord* new_ciInlineRecord(Method* method, int bci, int depth) { + ciInlineRecord* rec = NEW_RESOURCE_OBJ(ciInlineRecord); + rec->klass = method->method_holder()->name()->as_utf8(); + rec->method = method->name()->as_utf8(); + rec->signature = method->signature()->as_utf8(); + rec->bci = bci; + rec->inline_depth = depth; + ci_inline_records->append(rec); + return rec; + } + + // Lookup inlining data for a ciMethod + ciInlineRecord* find_ciInlineRecord(Method* method, int bci, int inline_depth) { + if (ci_inline_records != NULL) { + const char* klass_name = method->method_holder()->name()->as_utf8(); + const char* method_name = method->name()->as_utf8(); + const char* signature = method->signature()->as_utf8(); + for (int i = 0; i < ci_inline_records->length(); i++) { + ciInlineRecord* rec = ci_inline_records->at(i); + if ((rec->bci == bci) && + (rec->inline_depth == inline_depth) && + (strcmp(rec->klass, klass_name) == 0) && + (strcmp(rec->method, method_name) == 0) && + (strcmp(rec->signature, signature) == 0)) { + return rec; + } + } + } + return NULL; + } + + static ciInlineRecord* find_ciInlineRecord(GrowableArray<ciInlineRecord*>* records, + Method* method, int bci, int inline_depth) { + if (records != NULL) { + const char* klass_name = method->method_holder()->name()->as_utf8(); + const char* method_name = method->name()->as_utf8(); + const char* signature = method->signature()->as_utf8(); + for (int i = 0; i < records->length(); i++) { + ciInlineRecord* rec = records->at(i); + if ((rec->bci == bci) && + (rec->inline_depth == inline_depth) && + (strcmp(rec->klass, klass_name) == 0) && + (strcmp(rec->method, method_name) == 0) && + (strcmp(rec->signature, signature) == 0)) { + return rec; + } + } + } + return NULL; + } + const char* error_message() { return _error_message; } void reset() {
*** 843,857 **** --- 1013,1058 ---- Threads::destroy_vm(); vm_exit(exit_code); } + void* ciReplay::load_inline_data(ciMethod* method, int entry_bci, int comp_level) { + if (FLAG_IS_DEFAULT(InlineDataFile)) { + tty->print_cr("ERROR: no inline replay data file specified (use -XX:InlineDataFile=inline_pid12345.txt)."); + return NULL; + } + + VM_ENTRY_MARK; + // Load and parse the replay data + CompileReplay rp(InlineDataFile, THREAD); + if (!rp.can_replay()) { + tty->print_cr("ciReplay: !rp.can_replay()"); + return NULL; + } + void* data = rp.process_inline(method, method->get_Method(), entry_bci, comp_level, THREAD); + if (HAS_PENDING_EXCEPTION) { + oop throwable = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + java_lang_Throwable::print(throwable, tty); + tty->cr(); + java_lang_Throwable::print_stack_trace(throwable, tty); + tty->cr(); + return NULL; + } + + if (rp.had_error()) { + tty->print_cr("ciReplay: Failed on %s", rp.error_message()); + return NULL; + } + return data; + } + int ciReplay::replay_impl(TRAPS) { HandleMark hm; ResourceMark rm; // Make sure we don't run with background compilation ! // BackgroundCompilation = false; if (ReplaySuppressInitializers > 2) { // ReplaySuppressInitializers > 2 means that we want to allow // normal VM bootstrap but once we get into the replay itself // don't allow any intializers to be run.
*** 888,898 **** --- 1089,1098 ---- exit_code = 1; } return exit_code; } void ciReplay::initialize(ciMethodData* m) { if (replay_state == NULL) { return; }
*** 937,952 **** --- 1137,1178 ---- bool ciReplay::should_not_inline(ciMethod* method) { if (replay_state == NULL) { return false; } VM_ENTRY_MARK; // ciMethod without a record shouldn't be inlined. return replay_state->find_ciMethodRecord(method->get_Method()) == NULL; } + bool ciReplay::should_inline(void* data, ciMethod* method, int bci, int inline_depth) { + if (data != NULL) { + GrowableArray<ciInlineRecord*>* records = (GrowableArray<ciInlineRecord*>*)data; + VM_ENTRY_MARK; + // Inline record are ordered by bci and depth. + return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) != NULL; + } else if (replay_state != NULL) { + VM_ENTRY_MARK; + // Inline record are ordered by bci and depth. + return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) != NULL; + } + return false; + } + + bool ciReplay::should_not_inline(void* data, ciMethod* method, int bci, int inline_depth) { + if (data != NULL) { + GrowableArray<ciInlineRecord*>* records = (GrowableArray<ciInlineRecord*>*)data; + VM_ENTRY_MARK; + // Inline record are ordered by bci and depth. + return CompileReplay::find_ciInlineRecord(records, method->get_Method(), bci, inline_depth) == NULL; + } else if (replay_state != NULL) { + VM_ENTRY_MARK; + // Inline record are ordered by bci and depth. + return replay_state->find_ciInlineRecord(method->get_Method(), bci, inline_depth) == NULL; + } + return false; + } void ciReplay::initialize(ciMethod* m) { if (replay_state == NULL) { return; }

src/share/vm/ci/ciReplay.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File