// // Reclaim all unused buckets. // void DependencyContext::expunge_stale_entries() { assert_locked_or_safepoint(CodeCache_lock); if (!has_stale_entries()) { assert(!find_stale_entries(), "inconsistent info"); return; } nmethodBucket* first = dependencies(); nmethodBucket* last = NULL; int removed = 0; for (nmethodBucket* b = first; b != NULL;) { assert(b->count() >= 0, "bucket count: %d", b->count()); nmethodBucket* next = b->next(); if (b->count() == 0) { if (last == NULL) { first = next; } else { last->set_next(next); } removed++; delete b; // last stays the same. } else { last = b; } b = next; } set_dependencies(first); set_has_stale_entries(false); if (UsePerfData && removed > 0) { _perf_total_buckets_deallocated_count->inc(removed); _perf_total_buckets_stale_count->dec(removed); } }
void on_property_deleted(iproperty* Property) { dependencies_t::iterator dependency = dependencies.find(Property); if(dependency != dependencies.end()) { if(state_recorder && state_recorder->current_change_set()) { dependencies_t old_dependencies; old_dependencies.insert(*dependency); state_recorder->current_change_set()->record_old_state(new set_dependencies_container(*this, old_dependencies)); state_recorder->current_change_set()->record_new_state(new delete_property_container(*this, Property)); } dependencies.erase(dependency); } m_delete_connections[Property].disconnect(); m_delete_connections.erase(Property); dependencies_t new_dependencies; for(dependencies_t::iterator dependency = dependencies.begin(); dependency != dependencies.end(); ++dependency) { if(dependency->second == Property) { dependency->first->property_set_dependency(0); new_dependencies.insert(std::make_pair(dependency->first, static_cast<iproperty*>(0))); } } new_dependencies[Property] = 0; set_dependencies(new_dependencies); }
void DependencyContext::wipe() { assert_locked_or_safepoint(CodeCache_lock); nmethodBucket* b = dependencies(); set_dependencies(NULL); set_has_stale_entries(false); while (b != NULL) { nmethodBucket* next = b->next(); delete b; b = next; } }
// // Add an nmethod to the dependency context. // It's possible that an nmethod has multiple dependencies on a klass // so a count is kept for each bucket to guarantee that creation and // deletion of dependencies is consistent. // void DependencyContext::add_dependent_nmethod(nmethod* nm, bool expunge) { assert_lock_strong(CodeCache_lock); for (nmethodBucket* b = dependencies(); b != NULL; b = b->next()) { if (nm == b->get_nmethod()) { b->increment(); return; } } set_dependencies(new nmethodBucket(nm, dependencies())); if (UsePerfData) { _perf_total_buckets_allocated_count->inc(); } if (expunge) { // Remove stale entries from the list. expunge_stale_entries(); } }
// // Remove an nmethod dependency from the context. // Decrement count of the nmethod in the dependency list and, optionally, remove // the bucket completely when the count goes to 0. This method must find // a corresponding bucket otherwise there's a bug in the recording of dependencies. // Can be called concurrently by parallel GC threads. // void DependencyContext::remove_dependent_nmethod(nmethod* nm, bool expunge) { assert_locked_or_safepoint(CodeCache_lock); nmethodBucket* first = dependencies(); nmethodBucket* last = NULL; for (nmethodBucket* b = first; b != NULL; b = b->next()) { if (nm == b->get_nmethod()) { int val = b->decrement(); guarantee(val >= 0, "Underflow: %d", val); if (val == 0) { if (expunge) { if (last == NULL) { set_dependencies(b->next()); } else { last->set_next(b->next()); } delete b; if (UsePerfData) { _perf_total_buckets_deallocated_count->inc(); } } else { // Mark the context as having stale entries, since it is not safe to // expunge the list right now. set_has_stale_entries(true); if (UsePerfData) { _perf_total_buckets_stale_count->inc(); _perf_total_buckets_stale_acc_count->inc(); } } } if (expunge) { // Remove stale entries from the list. expunge_stale_entries(); } return; } last = b; } #ifdef ASSERT tty->print_raw_cr("### can't find dependent nmethod"); nm->print(); #endif // ASSERT ShouldNotReachHere(); }
// // Invalidate all dependencies in the context int DependencyContext::remove_all_dependents() { assert_locked_or_safepoint(CodeCache_lock); nmethodBucket* b = dependencies(); set_dependencies(NULL); int marked = 0; int removed = 0; while (b != NULL) { nmethod* nm = b->get_nmethod(); if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) { nm->mark_for_deoptimization(); marked++; } nmethodBucket* next = b->next(); removed++; delete b; b = next; } set_has_stale_entries(false); if (UsePerfData && removed > 0) { _perf_total_buckets_deallocated_count->inc(removed); } return marked; }
void pipeline::connect(iproperty& From, iproperty& To) { dependencies_t dependencies; dependencies.insert(std::make_pair(&To, &From)); set_dependencies(dependencies); }
int main (int argc, char **argv) { int command_number = 1; bool print_tree = false; bool time_travel = false; int **dependencies; int i, j, status, wait_val; pid_t* pids; bool can_run, finished; command_t* commands; program_name = argv[0]; for (;;) switch (getopt (argc, argv, "pt")) { case 'p': print_tree = true; break; case 't': time_travel = true; break; default: usage (); break; case -1: goto options_exhausted; } options_exhausted:; // There must be exactly one file argument. if (optind != argc - 1) usage (); script_name = argv[optind]; FILE *script_stream = fopen (script_name, "r"); if (! script_stream) error (1, errno, "%s: cannot open", script_name); command_stream_t command_stream = make_command_stream (get_next_byte, script_stream); if (time_travel) { commands = command_stream->commands; dependencies = set_dependencies(commands, command_stream->num_commands); pids = (pid_t*) checked_malloc(sizeof(pid_t) * command_stream->num_commands); for (i = 0; i <command_stream->num_commands; i++) pids[i] = -1; } command_t last_command = NULL; command_t command; if (print_tree || !time_travel) { while ((command = read_command_stream (command_stream))) { if (print_tree) { printf ("# %d\n", command_number++); print_command (command); } else { last_command = command; execute_command (command); } } } else { for(;;) { finished = true; for (i = 0; i < command_stream->num_commands; i++) { if (pids[i] == -1) { can_run = true; for (j = 0; dependencies[i][j] != -1; j++) if (commands[dependencies[i][j]]->status == -1) { can_run = false; break; } if (can_run) { pids[i] = fork(); if (pids[i]== -1) error(1, errno, "Error forking process"); if (pids[i] == 0) { execute_command(commands[i]); exit(commands[i]->status); } } } } for (i = 0; i < command_stream->num_commands; i++) { if (pids[i] != -1) { wait_val = waitpid(pids[i], &status, WNOHANG); if (wait_val == 0) finished = false; else commands[i]->status = WEXITSTATUS(status); } else finished = false; } if (finished) { last_command = commands[command_stream->num_commands-1]; break; } } } free_stream(command_stream); if (time_travel) { free(pids); for (i = 0; i<command_stream->num_commands; i++) free(dependencies[i]); free(dependencies); } return print_tree || !last_command ? 0 : command_status (last_command); }