int main(int argc, char **argv) { ArgumentSet args; ArgumentMap kwargs; process_args(argc, argv, args, kwargs); if(kwargs.count("help")) { usage(argc, argv); return 0; } if(kwargs.count("list")) { UnitTestDriver::s_driver().list_tests(); return 0; } if(kwargs.count("sizes")) { set_test_sizes(kwargs["sizes"]); } else { set_test_sizes("default"); } bool passed = UnitTestDriver::s_driver().run_tests(args, kwargs); if (kwargs.count("concise")) std::cout << ((passed) ? "PASSED" : "FAILED") << std::endl; return (passed) ? EXIT_SUCCESS : EXIT_FAILURE; }
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { for (int i = 0; i < _arg_size; i++) { if (vars.contains(i)) _arg_returned.set(i); } _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated()); _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); }
int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); QString title = "This is a ctags wrapper. Does not require sooo many options.\nVersion: "; title.append(BUILD_VERSION); ArgumentParser parser(argc, argv); parser.set_title(title); parser.add_argument("--clear", "store_true", "clear"); parser.add_argument("--gen", "store_true", "gen"); parser.add_argument("--help", "store_true", "help"); parser.add_argument("-h", "store_true", "help"); ArgumentMap vm = parser.parse_args(); if (app.arguments().count() == 1) { parser.print_help(); return 1; } if (vm.count("help") > 0) { parser.print_help(); return 0; } QString path = QPath::join( QStringList()<<DATA_PATH << qos.env["PROJECT"] ); QString tagfile = QPath::join(path,"c.txt"); if (vm.count("clear") > 0) { if (!qos.remove(tagfile) ) return 1; } if (vm.count("gen") > 0) { if (!qos.is_dir(path)) { if (!qos.makedirs(path)) { qos.printerr("Could not create folders"); return 1; } } QString cwd = qos.getcwd(); QSubProcess proc; proc.start( QStringList()<<"ctags"<<"-a"<<"--tag-relative=no"<<"-R"<<"-f"<<tagfile<<" "<<cwd); } QTimer::singleShot(1,&app, SLOT(quit())); return app.exec(); }
void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { StateInfo *d_state = blockstates+dest->index(); int nlocals = _method->max_locals(); // exceptions may cause transfer of control to handlers in the middle of a // block, so we don't merge the incoming state of exception handlers if (dest->is_handler()) return; if (!d_state->_initialized ) { // destination not initialized, just copy for (int i = 0; i < nlocals; i++) { d_state->_vars[i] = s_state->_vars[i]; } for (int i = 0; i < s_state->_stack_height; i++) { d_state->_stack[i] = s_state->_stack[i]; } d_state->_stack_height = s_state->_stack_height; d_state->_max_stack = s_state->_max_stack; d_state->_initialized = true; } else if (!dest->processed()) { // we have not yet walked the bytecodes of dest, we can merge // the states assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); for (int i = 0; i < nlocals; i++) { d_state->_vars[i].set_union(s_state->_vars[i]); } for (int i = 0; i < s_state->_stack_height; i++) { d_state->_stack[i].set_union(s_state->_stack[i]); } } else { // the bytecodes of dest have already been processed, mark any // arguments in the source state which are not in the dest state // as global escape. // Future refinement: we only need to mark these variable to the // maximum escape of any variables in dest state assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); ArgumentMap extra_vars; for (int i = 0; i < nlocals; i++) { ArgumentMap t; t = s_state->_vars[i]; t.set_difference(d_state->_vars[i]); extra_vars.set_union(t); } for (int i = 0; i < s_state->_stack_height; i++) { ArgumentMap t; t.clear(); t = s_state->_stack[i]; t.set_difference(d_state->_stack[i]); extra_vars.set_union(t); } set_global_escape(extra_vars); } }
// return true if any element of vars is an argument bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { for (int i = 0; i < _arg_size; i++) { if (vars.contains(i)) return true; } return false; }
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) { for (int i = 0; i <= _arg_size; i++) { if (vars.contains(i)) { bm.clear_bit(i); } } }
// return true if all argument elements of vars are returned bool BCEscapeAnalyzer::returns_all(ArgumentMap vars) { for (int i = 0; i < _arg_size; i++) { if (vars.contains(i) && !_arg_returned.test(i)) { return false; } } return true; }
// return true if any element of vars is an arg_stack argument bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ if (_conservative) return true; for (int i = 0; i < _arg_size; i++) { if (vars.contains(i) && _arg_stack.test(i)) return true; } return false; }
StateInfo() { empty_map.clear(); }
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, VectorSet &bm) { for (int i = 0; i < _arg_size; i++) { if (vars.contains(i)) { bm >>= i; } }
void BCEscapeAnalyzer::iterate_blocks(Arena *arena) { int numblocks = _methodBlocks->num_blocks(); int stkSize = _method->max_stack(); int numLocals = _method->max_locals(); StateInfo state; int datacount = (numblocks + 1) * (stkSize + numLocals); int datasize = datacount * sizeof(ArgumentMap); StateInfo *blockstates = (StateInfo *) arena->Amalloc(_methodBlocks->num_blocks() * sizeof(StateInfo)); ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); ArgumentMap *dp = statedata; state._vars = dp; dp += numLocals; state._stack = dp; dp += stkSize; state._initialized = false; state._max_stack = stkSize; for (int i = 0; i < numblocks; i++) { blockstates[i]._vars = dp; dp += numLocals; blockstates[i]._stack = dp; dp += stkSize; blockstates[i]._initialized = false; blockstates[i]._stack_height = 0; blockstates[i]._max_stack = stkSize; } GrowableArray<ciBlock *> worklist(arena, numblocks / 4, 0, NULL); GrowableArray<ciBlock *> successors(arena, 4, 0, NULL); _methodBlocks->clear_processed(); // initialize block 0 state from method signature ArgumentMap allVars; // all oop arguments to method ciSignature* sig = method()->signature(); int j = 0; if (!method()->is_static()) { // record information for "this" blockstates[0]._vars[j].set(j); allVars.add(j); j++; } for (int i = 0; i < sig->count(); i++) { ciType* t = sig->type_at(i); if (!t->is_primitive_type()) { blockstates[0]._vars[j].set(j); allVars.add(j); } j += t->size(); } blockstates[0]._initialized = true; assert(j == _arg_size, "just checking"); ArgumentMap unknown_map; unknown_map.add_unknown(); worklist.push(_methodBlocks->block_containing(0)); while(worklist.length() > 0) { ciBlock *blk = worklist.pop(); StateInfo *blkState = blockstates+blk->index(); if (blk->is_handler() || blk->is_ret_target()) { // for an exception handler or a target of a ret instruction, we assume the worst case, // that any variable or stack slot could contain any argument for (int i = 0; i < numLocals; i++) { state._vars[i] = allVars; } if (blk->is_handler()) { state._stack_height = 1; } else { state._stack_height = blkState->_stack_height; } for (int i = 0; i < state._stack_height; i++) { state._stack[i] = allVars; } } else { for (int i = 0; i < numLocals; i++) { state._vars[i] = blkState->_vars[i]; } for (int i = 0; i < blkState->_stack_height; i++) { state._stack[i] = blkState->_stack[i]; } state._stack_height = blkState->_stack_height; } iterate_one_block(blk, state, successors); // if this block has any exception handlers, push them // onto successor list if (blk->has_handler()) { DEBUG_ONLY(int handler_count = 0;) int blk_start = blk->start_bci(); int blk_end = blk->limit_bci(); for (int i = 0; i < numblocks; i++) { ciBlock *b = _methodBlocks->block(i); if (b->is_handler()) { int ex_start = b->ex_start_bci(); int ex_end = b->ex_limit_bci(); if ((ex_start >= blk_start && ex_start < blk_end) || (ex_end > blk_start && ex_end <= blk_end)) { successors.push(b); } DEBUG_ONLY(handler_count++;) } }
void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) { int i; // retrieve information about the callee ciInstanceKlass* klass = target->holder(); ciInstanceKlass* calling_klass = method()->holder(); ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder); ciInstanceKlass* actual_recv = callee_holder; // compute size of arguments int arg_size = target->arg_size(); if (!target->is_loaded() && code == Bytecodes::_invokestatic) { arg_size--; } int arg_base = MAX2(state._stack_height - arg_size, 0); // direct recursive calls are skipped if they can be bound statically without introducing // dependencies and if parameters are passed at the same position as in the current method // other calls are skipped if there are no unescaped arguments passed to them bool directly_recursive = (method() == target) && (code != Bytecodes::_invokevirtual || target->is_final_method() || state._stack[arg_base] .is_empty()); // check if analysis of callee can safely be skipped bool skip_callee = true; for (i = state._stack_height - 1; i >= arg_base && skip_callee; i--) { ArgumentMap arg = state._stack[i]; skip_callee = !is_argument(arg) || !is_arg_stack(arg) || (directly_recursive && arg.is_singleton(i - arg_base)); } if (skip_callee) { TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8())); for (i = 0; i < arg_size; i++) { set_method_escape(state.raw_pop()); } return; } // determine actual method (use CHA if necessary) ciMethod* inline_target = NULL; if (target->is_loaded() && klass->is_loaded() &&(klass->is_initialized()||(klass->is_interface()&&target->holder()->is_initialized())) && target->will_link(klass, callee_holder, code)) { if (code == Bytecodes::_invokestatic || code == Bytecodes::_invokespecial ||(code==Bytecodes::_invokevirtual&&target->is_final_method())){ inline_target = target; } else { inline_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv); } } if (inline_target != NULL && !is_recursive_call(inline_target)) { // analyze callee BCEscapeAnalyzer analyzer(inline_target, this); // adjust escape state of actual parameters bool must_record_dependencies = false; for (i = arg_size - 1; i >= 0; i--) { ArgumentMap arg = state.raw_pop(); if (!is_argument(arg)) continue; if (!is_arg_stack(arg)) { // arguments have already been recognized as escaping } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { set_method_escape(arg); must_record_dependencies = true; } else { set_global_escape(arg); } } // record dependencies if at least one parameter retained stack-allocatable if (must_record_dependencies) { if(code==Bytecodes::_invokeinterface||(code==Bytecodes::_invokevirtual&&!target->is_final_method())){ _dependencies.append(actual_recv); _dependencies.append(inline_target); } _dependencies.appendAll(analyzer.dependencies()); } } else { TRACE_BCEA(1, tty->print_cr("[EA] virtual method %s is not monomorphic.", target->name()->as_utf8())); // conservatively mark all actual parameters as escaping globally for (i = 0; i < arg_size; i++) { ArgumentMap arg = state.raw_pop(); if (!is_argument(arg)) continue; set_global_escape(arg); } } }
void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars) { clear_bits(vars, _arg_local); clear_bits(vars, _arg_stack); if (vars.contains_allocated()) _allocated_escapes = true; }
bool UnitTestDriver::run_tests(std::vector<UnitTest *>& tests_to_run, const ArgumentMap& kwargs) { std::time_t start_time = std::time(0); bool verbose = kwargs.count("verbose"); bool concise = kwargs.count("concise"); std::vector< TestResult > test_results; if (verbose && concise) { std::cout << "--verbose and --concise cannot be used together" << std::endl; exit(EXIT_FAILURE); } if (!concise) std::cout << "Running " << tests_to_run.size() << " unit tests." << std::endl; for(size_t i = 0; i < tests_to_run.size(); i++){ UnitTest& test = *tests_to_run[i]; if (verbose) std::cout << "Running " << test.name << "..." << std::flush; try { // time the test std::clock_t start = std::clock(); // run the test test.run(); // test passed record_result(TestResult(Pass, std::clock() - start, test), test_results); } catch (unittest::UnitTestFailure& f) { record_result(TestResult(Failure, std::numeric_limits<std::clock_t>::max(), test, f.message), test_results); } catch (unittest::UnitTestKnownFailure& f) { record_result(TestResult(KnownFailure, std::numeric_limits<std::clock_t>::max(), test, f.message), test_results); } catch (std::bad_alloc& e) { record_result(TestResult(Error, std::numeric_limits<std::clock_t>::max(), test, e.what()), test_results); } catch (unittest::UnitTestError& e) { record_result(TestResult(Error, std::numeric_limits<std::clock_t>::max(), test, e.message), test_results); } // immediate report if (!concise) { if (verbose) { switch(test_results.back().status) { case Pass: std::cout << "\r[PASS] "; std::cout << std::setw(10) << 1000.f * float(test_results.back().elapsed) / CLOCKS_PER_SEC << " ms"; break; case Failure: std::cout << "\r[FAILURE] "; break; case KnownFailure: std::cout << "\r[KNOWN FAILURE] "; break; case Error: std::cout << "\r[ERROR] "; break; default: break; } std::cout << " " << test.name << std::endl; } else { switch(test_results.back().status) { case Pass: std::cout << "."; break; case Failure: std::cout << "F"; break; case KnownFailure: std::cout << "K"; break; case Error: std::cout << "E"; break; default: break; } } } if (!post_test_sanity_check(test, concise)) { return false; } std::cout.flush(); } double elapsed_minutes = double(std::time(0) - start_time) / 60; // summary report if (!concise) report_results(test_results, elapsed_minutes); // if any failures or errors return false for(size_t i = 0; i < test_results.size(); i++) if (test_results[i].status != Pass && test_results[i].status != KnownFailure) return false; // all tests pass or are known failures return true; }
int main(int argc, char *argv[]) { QCoreApplication app(argc,argv); ArgumentParser parser(argc, argv); parser.add_argument("--get", "store_true", "get"); parser.add_argument("--list", "store_true", "list"); parser.add_argument("--upload", "upload"); parser.add_argument("--delete", "store_true", "delete"); parser.add_argument("-h", "store_true", "help"); parser.add_argument("--help","store_true","help"); parser.add_notes(notes); ArgumentMap vm = parser.parse_args(); QStringList args = parser.get_args(); if (vm.count("help") > 0 || app.arguments().count() == 1) { parser.print_help(); app.exit(0); return 0; } if (parser.error != "") { qCritical() << parser.error; app.exit(1); return 1; } TemplateMgr tpl; if (vm.count("list") > 0) { QStringList temps = tpl.templates(); for(int i=0;i<temps.count();i++) { QOSystem::printerr(temps[i]); } } else if (vm.count("upload") > 0) { if (args.count() != 1) { QOSystem::printerr("Invalid number of arguments"); app.exit(1); } QString src = args[0]; QString val = vm["upload"]; QString data; if (!QFileManager::readfile(src, data)) { QOSystem::printerr("Could not read file"); app.exit(1); return 1; } if (!tpl.setTemplate(val, src, data)) { QOSystem::printerr("Could not set template"); app.exit(1); return 1; } app.exit(0); return 0; } else if (vm.count("delete") > 0) { if (!tpl.removeTemplate(args[0])) { QOSystem::printerr("Could not remove template"); app.exit(1); return 1; } } else if (vm.count("get") > 0) { TemplateItem item; QMap<QString,QString> dict; if (vm.count("env") > 0) { dict = QOSystem::getEnvDict(); } if (!tpl.getTemplate(args[0], item, dict)) { QOSystem::printerr("Could not get template"); app.exit(1); return 1; } QOSystem::printerr(item.name); if (!QFileManager::writefile(item.name, item.data)) { QOSystem::printerr("Could not write template"); app.exit(1); return 1; } } return 0; }