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 fix_file (const std::wstring& in, const std::wstring& out) { std::wcout << L"in:" << in << L"\nout:" << out << L'\n'; rsc::istream fsin(in); rsc::ostream fsout(out); int count = 0; bool quote = false; char16_t before = L'\0'; char16_t current, after; fsin.get(current); while (!fsin.eof()) { fsin.get(after); if (is_double_quote(current)) quote = !quote; if (!quote) { // not in quote, do nothing } else if (is_floating_vowel(current)) { if (is_long_tail(before)) { count++; current = move_floating_left(current); } } else if (is_floating_vowel(current)) { if (is_long_tail(before)) { count++; current = move_floating_left(current); } } else if (is_tone_marker(current)) { if (is_floating_vowel(before)) { if (is_long_tail(before)) { count++; current = move_tone_marker_left_height(current); } } else if (is_long_tail(before)) { if (is_backward_floating_vowel(after)) { count++; current = move_tone_marker_left_height(current); } else { count++; current = move_tone_marker_left_low(current); } } else if (!is_backward_floating_vowel(after)) { count++; current = move_tone_marker_low(current); } } else if (is_lower_foot(current)) { if (is_lower_vowel(after)) { count++; current = strip_lower_foot(current); } } else if (is_lower_vowel(current)) { if (is_lower_tail(before)) { count++; current = move_lower_vowel_left(current); } } fsout.put(current); if (!quote) { } else if (is_digit(current)) { if (is_argument(before) && is_argument(after)) { count++; fsout.put(argument_prefix()); } } before = current; current = after; } // while if (count > 0) std::wcout << L'\n'; std::wcout << L"fixed:" << count << std::endl; }
/* * config_reader_get_scenarios -- return scenarios from config file * * This function reads the config file and returns a list of scenarios. * Each scenario contains a list of key/value arguments. * The scenario's arguments are merged with arguments from global section. */ int config_reader_get_scenarios(struct config_reader *cr, struct scenarios **scenarios) { /* * Read all groups. * The config file must have at least one group, otherwise * it is considered as invalid. */ gsize ngroups; gsize g; gchar **groups = g_key_file_get_groups(cr->key_file, &ngroups); assert(nullptr != groups); if (!groups) return -1; /* * Check if global section is present and read keys from it. */ int ret = 0; int has_global = g_key_file_has_group(cr->key_file, SECTION_GLOBAL) == TRUE; gsize ngkeys; gchar **gkeys = nullptr; struct scenarios *s; if (has_global) { gkeys = g_key_file_get_keys(cr->key_file, SECTION_GLOBAL, &ngkeys, nullptr); assert(nullptr != gkeys); if (!gkeys) { ret = -1; goto err_groups; } } s = scenarios_alloc(); assert(nullptr != s); if (!s) { ret = -1; goto err_gkeys; } for (g = 0; g < ngroups; g++) { /* * Check whether a group is a scenario * or global section. */ if (!is_scenario(groups[g])) continue; /* * Check for KEY_BENCHMARK which contains benchmark name. * If not present the benchmark name is the same as the * name of the section. */ struct scenario *scenario = nullptr; if (g_key_file_has_key(cr->key_file, groups[g], KEY_BENCHMARK, nullptr) == FALSE) { scenario = scenario_alloc(groups[g], groups[g]); assert(scenario != nullptr); } else { gchar *benchmark = g_key_file_get_value(cr->key_file, groups[g], KEY_BENCHMARK, nullptr); assert(benchmark != nullptr); if (!benchmark) { ret = -1; goto err_scenarios; } scenario = scenario_alloc(groups[g], benchmark); assert(scenario != nullptr); free(benchmark); } gsize k; if (has_global) { /* * Merge key/values from global section. */ for (k = 0; k < ngkeys; k++) { if (g_key_file_has_key(cr->key_file, groups[g], gkeys[k], nullptr) == TRUE) continue; if (!is_argument(gkeys[k])) continue; char *value = g_key_file_get_value( cr->key_file, SECTION_GLOBAL, gkeys[k], nullptr); assert(nullptr != value); if (!value) { ret = -1; goto err_scenarios; } struct kv *kv = kv_alloc(gkeys[k], value); assert(nullptr != kv); free(value); if (!kv) { ret = -1; goto err_scenarios; } TAILQ_INSERT_TAIL(&scenario->head, kv, next); } } /* check for group name */ if (g_key_file_has_key(cr->key_file, groups[g], KEY_GROUP, nullptr) != FALSE) { gchar *group = g_key_file_get_value( cr->key_file, groups[g], KEY_GROUP, nullptr); assert(group != nullptr); scenario_set_group(scenario, group); } else if (g_key_file_has_key(cr->key_file, SECTION_GLOBAL, KEY_GROUP, nullptr) != FALSE) { gchar *group = g_key_file_get_value(cr->key_file, SECTION_GLOBAL, KEY_GROUP, nullptr); scenario_set_group(scenario, group); } gsize nkeys; gchar **keys = g_key_file_get_keys(cr->key_file, groups[g], &nkeys, nullptr); assert(nullptr != keys); if (!keys) { ret = -1; goto err_scenarios; } /* * Read key/values from the scenario's section. */ for (k = 0; k < nkeys; k++) { if (!is_argument(keys[k])) continue; char *value = g_key_file_get_value( cr->key_file, groups[g], keys[k], nullptr); assert(nullptr != value); if (!value) { ret = -1; g_strfreev(keys); goto err_scenarios; } struct kv *kv = kv_alloc(keys[k], value); assert(nullptr != kv); free(value); if (!kv) { g_strfreev(keys); ret = -1; goto err_scenarios; } TAILQ_INSERT_TAIL(&scenario->head, kv, next); } g_strfreev(keys); TAILQ_INSERT_TAIL(&s->head, scenario, next); } g_strfreev(gkeys); g_strfreev(groups); *scenarios = s; return 0; err_scenarios: scenarios_free(s); err_gkeys: g_strfreev(gkeys); err_groups: g_strfreev(groups); return ret; }
/* * config_reader_get_scenarios -- return scenarios from config file * * This function reads the config file and returns a list of scenarios. * Each scenario contains a list of key/value arguments. * The scenario's arguments are merged with arguments from global section. */ int config_reader_get_scenarios(struct config_reader *cr, struct scenarios **scenarios) { /* * Read all groups. * The config file must have at least one group, otherwise * it is considered as invalid. */ int ret = 0; TCHAR *sections = (TCHAR *)malloc(sizeof(TCHAR) * SIZEOF_SECTION); if (!sections) return -1; GetPrivateProfileSectionNames(sections, SIZEOF_SECTION, cr->lpFileName); if (NULL_LIST_EMPTY(sections)) { ret = -1; goto err_sections; } /* * Check if global section is present and read it. */ TCHAR *global = (TCHAR *)malloc(sizeof(TCHAR) * SIZEOF_SECTION); if (!global) return -1; GetPrivateProfileSection(SECTION_GLOBAL, global, SIZEOF_SECTION, cr->lpFileName); KV_LIST global_kv = KV_LIST_INIT(global); int has_global = !KV_LIST_EMPTY(global_kv); struct scenarios *s = scenarios_alloc(); assert(NULL != s); if (!s) { ret = -1; goto err_gkeys; } LPTSTR global_group = NULL; for (KV_LIST it = global_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { if (_tcscmp(KV_LIST_KEY(it), KEY_GROUP) == 0) { global_group = KV_LIST_VALUE(it); break; } } TCHAR *section; for (LPTSTR group_name = sections; !NULL_LIST_EMPTY(group_name); group_name = NULL_LIST_NEXT(group_name)) { /* * Check whether a group is a scenario * or global section. */ if (!is_scenario(group_name)) continue; /* * Check for KEY_BENCHMARK which contains benchmark name. * If not present the benchmark name is the same as the * name of the section. */ section = (TCHAR *)malloc(sizeof(TCHAR) * SIZEOF_SECTION); if (!section) ret = -1; GetPrivateProfileSection(group_name, section, SIZEOF_SECTION, cr->lpFileName); KV_LIST section_kv = KV_LIST_INIT(section); struct scenario *scenario = NULL; LPTSTR name = NULL; LPTSTR group = NULL; for (KV_LIST it = section_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { if (_tcscmp(KV_LIST_KEY(it), KEY_BENCHMARK) == 0) { name = KV_LIST_VALUE(it); } if (_tcscmp(KV_LIST_KEY(it), KEY_GROUP) == 0) { group = KV_LIST_VALUE(it); } } if (name == NULL) { scenario = scenario_alloc((const char *)group_name, (const char *)group_name); } else { scenario = scenario_alloc((const char *)group_name, (const char *)name); } assert(scenario != NULL); if (has_global) { /* * Merge key/values from global section. */ for (KV_LIST it = global_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { LPTSTR key = KV_LIST_KEY(it); if (!is_argument(key)) continue; LPTSTR value = KV_LIST_VALUE(it); assert(NULL != value); if (!value) { ret = -1; goto err_scenarios; } struct kv *kv = kv_alloc((const char *)key, (const char *)value); assert(NULL != kv); if (!kv) { ret = -1; goto err_scenarios; } TAILQ_INSERT_TAIL(&scenario->head, kv, next); } } /* check for group name */ if (group) { scenario_set_group(scenario, (const char *)group); } else if (global_group) { scenario_set_group(scenario, (const char *)global_group); } for (KV_LIST it = section_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { LPTSTR key = KV_LIST_KEY(it); if (!is_argument(key)) continue; LPTSTR value = KV_LIST_VALUE(it); assert(NULL != value); if (!value) { ret = -1; goto err_scenarios; } struct kv *kv = kv_alloc((const char *)key, (const char *)value); assert(NULL != kv); if (!kv) { ret = -1; goto err_scenarios; } TAILQ_INSERT_TAIL(&scenario->head, kv, next); } TAILQ_INSERT_TAIL(&s->head, scenario, next); free(section); } *scenarios = s; free(global); free(sections); return 0; err_scenarios: free(section); scenarios_free(s); err_gkeys: free(global); err_sections: free(sections); return ret; }