void Store::resolve(Value& val) const { if(val.id() != Value::UNKNOWN_ID) return; // lookup strings val.ensureLexical(); if(val.isTyped() && val.datatypeLex().null()) { Value v = lookupValue(val.datatypeId()); val.datatypeLex(String(v.lexical())); } val.ensureDirectStrings(*this); val.ensureResolvedStrings(*this); // look for pages containing the hash Hash::hash_t hash = val.hash(); Cursor cur = values_.index->lookup(hash); if(!cur.valid()) { val.id(0); return; } // scan all candidates in the collision list Cursor end = db_.pageEnd(cur); while(cur != end) { if(cur.readInt() != hash) break; Value::id_t id = cur.readInt(); Value v = lookupValue(id); if(v == val) { val.id(id); return; } } val.id(0); }
void ValueStack::store_local(StoreLocal* x, int bci) { int i = x->java_index(); Value instr = _stores.at(i); if (instr != NULL) { StoreLocal* store = instr->as_StoreLocal(); assert(store != NULL, "just checking"); store->set_eliminated(true); if (PrintStoreElimination) { tty->print_cr("store local %d (index %d) eliminated %d @ %d", x->id(), x->java_index(), instr->id(), bci); } } // NOTE: currently we only allow store elimination for arguments of // inlined methods -- which is where most of the inefficiency was // being generated anyway. Running Java2Demo with // PrintStoreElimination and // CompileOnly=GradientPaintContext.\<init\> (at least the JDK 1.4 // version) shows a situation where the store elimination algorithm // is incorrect. In general we can not know whether the right hand // side of the store either has side effects or must be evaluated // (i.e., it is a LoadLocal which must be executed before subsequent // instructions overwrite the local, and unpinning the StoreLocal // causes it to be skipped). if (x->is_inline_argument()) { _stores.at_put(i, x); } }
ValueRange Store::eqClass(const Value& val) const { if(val.id() > 0) return eqClass(val.id()); assert(val.interpreted()); // costly binary search for equivalent value Value::id_t left = 1; Value::id_t right = values_.count + 1; while(left != right) { Value::id_t middle = left + (right - left) / 2; Value mVal = lookupValue(middle); mVal.ensureInterpreted(*this); if(mVal.compare(val) == 0) return eqClass(middle); if(mVal < val) left = middle + 1; else right = middle; } ValueRange result = {left, left - 1}; return result; }
void ValueMap::print() { tty->print_cr("(size %d, entries %d, nesting %d)", size(), entry_count(), nesting()); int entries = 0; for (int i = 0; i < size(); i++) { if (entry_at(i) != NULL) { tty->print(" %2d: ", i); for (ValueMapEntry* entry = entry_at(i); entry != NULL; entry = entry->next()) { Value value = entry->value(); tty->print("%s %c%d (%s%d) -> ", value->name(), value->type()->tchar(), value->id(), is_killed(value) ? "x" : "", entry->nesting()); entries++; } tty->print_cr("NULL"); } } _killed_values.print(); assert(entry_count() == entries, "entry_count incorrect"); }
extern string value_to_str(const Value &value) { string str(""); str.append(value.id()); str.append("~~"); if (value.has_indegree()) { str.append(num_to_str<long>(value.indegree())); } else { str.append("noindegree"); } str.append("~~"); if (value.parents_size() > 0) { for (int i = 0; i < value.parents_size(); i++) { str.append(value.parents(i)); str.append("??"); } } else { str.append("noparents"); } str.append("~~"); if (value.children_size() > 0) { for (int i = 0; i < value.children_size(); i++) { str.append(value.children(i)); str.append("??"); } } else { str.append("nochildren"); } str.append("~~"); if (value.datanamelist_size() > 0) { for (int i = 0; i < value.datanamelist_size(); i++) { str.append(value.datanamelist(i)); str.append("??"); } } else { str.append("nodataname"); } str.append("~~"); if (value.datasize_size() > 0) { for (int i = 0; i < value.datasize_size(); i++) { str.append(num_to_str<long>(value.datasize(i))); str.append("??"); } } else { str.append("nodatasize"); } str.append("~~"); if (value.has_alldatasize()) { str.append(num_to_str<long>(value.alldatasize())); } else { str.append("noalldatasize"); } str.append("~~"); if (value.has_tasklength()) str.append(num_to_str<long>(value.tasklength())); else str.append("notasklength"); str.append("~~"); if (value.has_numtaskfin()) { str.append(num_to_str<long>(value.numtaskfin())); } else { str.append("nonumtaskfin"); } str.append("~~"); if (value.has_numworksteal()) { str.append(num_to_str<long>(value.numworksteal())); } else { str.append("nonumworksteal"); } str.append("~~"); if (value.has_numworkstealfail()) { str.append(num_to_str<long>(value.numworkstealfail())); } else { str.append("nonumworkstealfail"); } str.append("~~"); if (value.has_numtaskwait()) { str.append(num_to_str<int>(value.numtaskwait())); } else { str.append("nonumtaskwait"); } str.append("~~"); if (value.has_numtaskready()) { str.append(num_to_str<int>(value.numtaskready())); } else { str.append("nonumtaskready"); } str.append("~~"); if (value.has_numcoreavilable()) { str.append(num_to_str<int>(value.numcoreavilable())); } else { str.append("nonumcoreavail"); } str.append("~~"); if (value.has_numallcore()) { str.append(num_to_str<int>(value.numallcore())); } else { str.append("nonumallcore"); } str.append("~~"); if (value.has_outputsize()) str.append(num_to_str<long>(value.outputsize())); else str.append("nooutputsize"); str.append("~~"); if (value.has_submittime()) str.append(num_to_str<long>(value.submittime())); else str.append("nosubmittime"); str.append("~~"); return str; }
void InstructionPrinter::print_temp(Value value) { tty->print("%c%d", value->type()->tchar(), value->id()); }
Value ValueMap::find_insert(Value x) { const intx hash = x->hash(); if (hash != 0) { // 0 hash means: exclude from value numbering NOT_PRODUCT(_number_of_finds++); for (ValueMapEntry* entry = entry_at(entry_index(hash, size())); entry != NULL; entry = entry->next()) { if (entry->hash() == hash) { Value f = entry->value(); if (!is_killed(f) && f->is_equal(x)) { NOT_PRODUCT(_number_of_hits++); TRACE_VALUE_NUMBERING(tty->print_cr("Value Numbering: %s %c%d equal to %c%d (size %d, entries %d, nesting-diff %d)", x->name(), x->type()->tchar(), x->id(), f->type()->tchar(), f->id(), size(), entry_count(), nesting() - entry->nesting())); if (entry->nesting() != nesting() && f->as_Constant() == NULL) { // non-constant values of of another block must be pinned, // otherwise it is possible that they are not evaluated f->pin(Instruction::PinGlobalValueNumbering); } assert(x->type()->tag() == f->type()->tag(), "should have same type"); return f; } } } // x not found, so insert it if (entry_count() >= size_threshold()) { increase_table_size(); } int idx = entry_index(hash, size()); _entries.at_put(idx, new ValueMapEntry(hash, x, nesting(), entry_at(idx))); _entry_count++; TRACE_VALUE_NUMBERING(tty->print_cr("Value Numbering: insert %s %c%d (size %d, entries %d, nesting %d)", x->name(), x->type()->tchar(), x->id(), size(), entry_count(), nesting())); } return x; }
inline void ValueSet::remove(Value x) { _map.clear_bit(x->id()); }
inline void ValueSet::put(Value x) { _map.set_bit(x->id()); }
inline bool ValueSet::contains(Value x) { return _map.at(x->id()); }