Esempio n. 1
0
TEST(Type, CanRunDtor) {
  TypeSet types = allTypes();
  auto expectTrue = [&](Type t) {
    EXPECT_TRUE(t.canRunDtor()) << t.toString() << ".canRunDtor() == true";
    types.erase(t);
  };
  expectTrue(Type::Arr);
  expectTrue(Type::CountedArr);
  expectTrue(Type::Obj);
  expectTrue(Type::Res);
  expectTrue(Type::Counted);
  expectTrue(Type::BoxedArr);
  expectTrue(Type::BoxedCountedArr);
  expectTrue(Type::BoxedObj);
  expectTrue(Type::BoxedRes);
  expectTrue(Type::BoxedCell);
  expectTrue(Type::Cell);
  expectTrue(Type::Gen);
  expectTrue(Type::Ctx);
  expectTrue(Type::Obj | Type::Func);
  expectTrue(Type::Init);
  expectTrue(Type::Top);
  expectTrue(Type::StackElem);
  expectTrue(Type::AnyObj);
  expectTrue(Type::AnyRes);
  expectTrue(Type::AnyArr);
  expectTrue(Type::AnyCountedArr);
  expectTrue(Type::AnyCell);

  for (Type t : types) {
    EXPECT_FALSE(t.canRunDtor()) << t.toString() << ".canRunDtor == false";
  }
}
bool
TypeInferenceOracle::canEnterInlinedFunction(HandleScript caller, jsbytecode *pc, JSFunction *target)
{
    AssertCanGC();
    RootedScript targetScript(cx, target->nonLazyScript());
    if (!targetScript->hasAnalysis() || !targetScript->analysis()->ranInference())
        return false;

    if (!targetScript->analysis()->ionInlineable())
        return false;

    if (targetScript->analysis()->usesScopeChain())
        return false;

    if (target->getType(cx)->unknownProperties())
        return false;

    JSOp op = JSOp(*pc);
    TypeSet *returnTypes = TypeScript::ReturnTypes(targetScript);
    TypeSet *callReturn = getCallReturn(caller, pc);
    if (op == JSOP_NEW) {
        if (!returnTypes->isSubsetIgnorePrimitives(callReturn))
            return false;
    } else {
        if (!returnTypes->isSubset(callReturn))
            return false;
    }

    // TI calls ObjectStateChange to trigger invalidation of the caller.
    HeapTypeSet::WatchObjectStateChange(cx, target->getType(cx));
    return true;
}
Esempio n. 3
0
  void StyleConfig::GetAreaTypesWithMag(double mag,
                                        TypeSet& types) const
  {
    types.Reset(areaMag.size());

    for (size_t i=0; i<areaMag.size(); i++) {
      if (mag>=areaMag[i]) {
        types.SetType(i);
      }
    }
  }
Esempio n. 4
0
TypeSet getGreatestCommonSubtypes(const TypeSet& set) {

    // handle the empty set
    if (set.empty()) return set;

    // handle the all set => empty set (since no common sub-type)
    if (set.isAll()) return TypeSet();

    TypeSet res;
    auto it = set.begin();
    res.insert(*it);
    ++it;

    // refine sub-set step by step
    for(;it != set.end(); ++it) {
        TypeSet tmp;
        for(const Type& cur : res) {
            tmp.insert(getGreatestCommonSubtypes(cur, *it));
        }
        res = tmp;
    }

    // done
    return res;
}
Esempio n. 5
0
bool
TypeInferenceOracle::canEnterInlinedFunction(RawScript caller, jsbytecode *pc, RawFunction target)
{
    RootedScript targetScript(cx, target->nonLazyScript());

    // Make sure empty script has type information, to allow inlining in more cases.
    if (targetScript->length == 1) {
        if (!targetScript->ensureRanInference(cx))
            return false;
    }

    if (!targetScript->hasAnalysis() ||
        !targetScript->analysis()->ranInference() ||
        !targetScript->analysis()->ranSSA())
    {
        return false;
    }

    if (!targetScript->analysis()->ionInlineable())
        return false;

    if (targetScript->needsArgsObj())
        return false;

    if (!targetScript->compileAndGo)
        return false;

    if (targetScript->analysis()->usesScopeChain())
        return false;

    types::TypeObject *targetType = target->getType(cx);
    if (!targetType || targetType->unknownProperties())
        return false;

    JSOp op = JSOp(*pc);
    TypeSet *returnTypes = TypeScript::ReturnTypes(targetScript);
    TypeSet *callReturn = getCallReturn(caller, pc);
    if (op == JSOP_NEW) {
        if (!returnTypes->isSubsetIgnorePrimitives(callReturn))
            return false;
    } else {
        if (!returnTypes->isSubset(callReturn))
            return false;
    }

    // TI calls ObjectStateChange to trigger invalidation of the caller.
    HeapTypeSet::WatchObjectStateChange(cx, targetType);
    return true;
}
Esempio n. 6
0
 void visit(const Type& type) const {
     if (isSubtypeOf(type, b)) {
         res.insert(type);
     } else {
         TypeVisitor<void>::visit(type);
     }
 }
Esempio n. 7
0
bool
TypeInferenceOracle::callReturnTypeSetMatches(RawScript callerScript, jsbytecode *callerPc,
                                              RawFunction callee)
{
    RootedScript targetScript(cx, callee->nonLazyScript());

    JSOp op = JSOp(*callerPc);
    TypeSet *returnTypes = TypeScript::ReturnTypes(targetScript);
    TypeSet *callReturn = getCallReturn(callerScript, callerPc);
    if (op == JSOP_NEW) {
        if (!returnTypes->isSubsetIgnorePrimitives(callReturn))
            return false;
    } else {
        if (!returnTypes->isSubset(callReturn))
            return false;
    }

    return true;
}
Esempio n. 8
0
/*******************************************************************
* Function:	ArrayIndexAnalysis::getTypeInfo
* Purpose : Get an array dimensions' information
* Initial : Nurudeen A. Lameed on July 21, 2009
********************************************************************
Revisions and bug fixes:
*/
inline TypeInfo ArrayIndexAnalysis::getTypeInfo(const IIRNode* node, const SymbolExpr* symbol) const
{
    // retrieve the type set
    TypeInfoMap post = typeInferenceInfo->postTypeMap;
    TypeSet tSet = (post[node])[symbol];

    // look for one with bounds information
    // if none has the info, return an empty type info.
    for (TypeSet::const_iterator it = tSet.begin(), iEnd = tSet.end(); it != iEnd; ++it)
    {
        TypeInfo typ = *it;

        if ( typ.getSizeKnown() )
        {
            return *it;
        }
    }

    return TypeInfo(); // return an empty type info
}
void IConnectionLoader::addConnection(
        VertexMap& vertices, SystemTypeGetter* info,
        int from, int to, TypeSet tags)
{
	TypeSet toType, fromType;

	toType.insert(info->getType(to));
	toType.insert(tags.begin(), tags.end());
	fromType.insert(info->getType(from));
	fromType.insert(tags.begin(), tags.end());

    //Add vertices if they dont exists already
    //this will fail if it already exists
    vertices.insert(std::make_pair(from, Vertex(from))); 
    vertices.insert(std::make_pair(to, Vertex(to)));

    //Add edges to the vertices
    vertices.find(from)->second.addEdge(to, toType);
	vertices.find(to)->second.addEdge(from, fromType);
}
Esempio n. 10
0
/**
 * Move all single impl in a single impl method signature to next pass.
 * We make a single optimization per pass over any given single impl so
 * I1, I2 and void I1.m(I2)
 * the first optimization (I1 or I2) moves the other interface to next pass.
 * That is not the case for methods on non optimizable classes, so for
 * I1, I2 and void C.m(I1, I2)
 * then m is changed in a single pass for both I1 and I2.
 */
void OptimizationImpl::drop_single_impl_collision(DexType* intf,
                                                  SingleImplData& data,
                                                  DexMethod* method) {
  auto check_type = [&](DexType* type) {
    if (type != intf && single_impls->is_single_impl(type) &&
        !single_impls->is_escaped(type)) {
      single_impls->escape_interface(type, NEXT_PASS);
      assert(optimized.find(type) == optimized.end());
    }
  };

  auto owner = method->get_class();
  if (!single_impls->is_single_impl(owner)) return;
  check_type(owner);
  auto proto = method->get_proto();
  check_type(proto->get_rtype());
  auto args_list = proto->get_args();
  for (auto arg : args_list->get_type_list()) {
    check_type(arg);
  }
}
Esempio n. 11
0
TypeSet getLeastCommonSupertypes(const Type& a, const Type& b) {

    // make sure they are in the same type environment
    assert(a.getTypeEnvironment().isType(a) && a.getTypeEnvironment().isType(b));

    // if they are equal it is easy
    if (a == b) {
        return TypeSet(a);
    }

    // equally simple - check whether one is a sub-type of the other
    if (isSubtypeOf(a,b)) {
        return TypeSet(b);
    }
    if (isSubtypeOf(b,a)) {
        return TypeSet(a);
    }

    // harder: no obvious relation => hard way
    TypeSet superTypes;
    TypeSet all = a.getTypeEnvironment().getAllTypes();
    for(const Type& cur : all) {
        if (isSubtypeOf(a, cur) && isSubtypeOf(b, cur)) {
            superTypes.insert(cur);
        }
    }

    // filter out non-least super types
    TypeSet res;
    for(const Type& cur : superTypes) {
        bool least = !any_of(superTypes, [&](const Type& t) {
                return t != cur && isSubtypeOf(t, cur);
                });
        if (least) res.insert(cur);
    }

    return res;

}
Esempio n. 12
0
void RenameClassesPass::run_pass(DexStoresVector& stores,
                                 ConfigFiles& cfg,
                                 PassManager& mgr) {
  const JsonWrapper& json_cfg = cfg.get_json_config();
  if (json_cfg.get("emit_name_based_locators", false)) {
    // TODO: Purge the old RenameClassesPass entirely everywhere.
    fprintf(stderr,
            "[RenameClassesPass] error: Configuration option "
            "emit_locator_strings is not compatible with RenameClassesPass. "
            "Upgrade to RenameClassesPassV2 instead.\n");
    exit(EXIT_FAILURE);
  }

  auto scope = build_class_scope(stores);
  ClassHierarchy ch = build_type_hierarchy(scope);
  std::unordered_set<const DexType*> untouchables;
  for (const auto& base : m_untouchable_hierarchies) {
    auto base_type = DexType::get_type(base.c_str());
    if (base_type != nullptr) {
      untouchables.insert(base_type);
      TypeSet children;
      get_all_children(ch, base_type, children);
      untouchables.insert(children.begin(), children.end());
    }
  }
  mgr.incr_metric(METRIC_CLASSES_IN_SCOPE, scope.size());
  rename_classes(
      scope, m_pre_filter_whitelist, m_post_filter_whitelist,
      untouchables, m_rename_annotations, mgr);
  TRACE(RENAME, 1,
      "renamed classes: %d anon classes, %d from single char patterns, "
      "%d from multi char patterns\n",
      match_inner,
      match_short,
      match_long);
  TRACE(RENAME, 1, "String savings, at least %d bytes \n",
      base_strings_size - ren_strings_size);
}
Esempio n. 13
0
/**
 * Run an optimization step.
 */
size_t OptimizationImpl::optimize(Scope& scope) {
  TypeList to_optimize;
  single_impls->get_interfaces(to_optimize);
  for (auto intf : to_optimize) {
    auto& intf_data = single_impls->get_single_impl_data(intf);
    TRACE(INTF, 3, "(OPT) %s => %s\n", SHOW(intf), SHOW(intf_data.cls));
    if (intf_data.is_escaped()) continue;
    auto escape = can_optimize(intf, intf_data);
    if (escape != EscapeReason::NO_ESCAPE) {
      single_impls->escape_interface(intf, escape);
      continue;
    }
    do_optimize(intf, intf_data);
    optimized.insert(intf);
  }
  // make a new scope deleting all single impl interfaces
  Scope new_scope;
  for (auto cls : scope) {
    if (optimized.find(cls->get_type()) != optimized.end()) continue;
    new_scope.push_back(cls);
  }
  scope.swap(new_scope);
  return optimized.size();
}
Esempio n. 14
0
TypeSet getGreatestCommonSubtypes(const Type& a, const Type& b) {

    // make sure they are in the same type environment
    assert(a.getTypeEnvironment().isType(a) && a.getTypeEnvironment().isType(b));

    // if they are equal it is easy
    if (a == b) {
        return TypeSet(a);
    }

    // equally simple - check whether one is a sub-type of the other
    if (isSubtypeOf(a,b)) {
        return TypeSet(a);
    }
    if (isSubtypeOf(b,a)) {
        return TypeSet(b);
    }

    // last option: if both are unions with common sub-types
    TypeSet res;
    if (isUnion(a) && isUnion(b)) {
        // collect common sub-types of union types

        struct collector : public TypeVisitor<void> {
            const Type& b;
            TypeSet& res;
            collector(const Type& b, TypeSet& res) : b(b), res(res) {}
            void visit(const Type& type) const {
                if (isSubtypeOf(type, b)) {
                    res.insert(type);
                } else {
                    TypeVisitor<void>::visit(type);
                }
            }
            void visitUnionType(const UnionType& type) const {
                for(const auto& cur : type.getElementTypes()) visit(*cur);
            }
        };

        // collect all common sub-types
        collector(b,res).visit(a);
    }

    // otherwise there is no common super type
    return res;
}
Esempio n. 15
0
void RemoveInterfacePass::remove_interfaces_for_root(
    const Scope& scope,
    const DexStoresVector& stores,
    const DexType* root,
    const TypeSystem& type_system) {
  TRACE(RM_INTF, 5, "Processing root %s\n", SHOW(root));
  TypeSet interfaces;
  type_system.get_all_interface_children(root, interfaces);
  include_parent_interfaces(root, interfaces);

  m_total_num_interface += interfaces.size();
  m_num_interface_excluded += exclude_unremovables(
      scope, stores, type_system, m_skip_multiple_targets_roots,
      m_include_primary_dex, interfaces);

  TRACE(RM_INTF, 5, "removable interfaces %ld\n", interfaces.size());
  TypeSet removed =
      remove_leaf_interfaces(scope, root, interfaces, type_system);

  while (removed.size() > 0) {
    for (const auto intf : removed) {
      interfaces.erase(intf);
      m_removed_interfaces.insert(intf);
    }
    TRACE(RM_INTF, 5, "non-leaf removable interfaces %ld\n", interfaces.size());
    removed = remove_leaf_interfaces(scope, root, interfaces, type_system);
  }

  // Update type reference to removed interfaces all at once.
  remove_interface_references(scope, type_system, root, m_removed_interfaces);

  if (traceEnabled(RM_INTF, 9)) {
    TypeSystem updated_ts(scope);
    for (const auto intf : interfaces) {
      TRACE(RM_INTF, 9, "unremoved interface %s\n", SHOW(intf));
      TypeSet children;
      updated_ts.get_all_interface_children(intf, children);
      for (const auto cintf : children) {
        TRACE(RM_INTF, 9, "  child %s\n", SHOW(cintf));
      }
    }
  }
}
Esempio n. 16
0
TypeSet getGreatestCommonSubtypes(const TypeSet& a, const TypeSet& b) {

    // special cases
    if (a.empty()) return a;
    if (b.empty()) return b;

    if (a.isAll()) return b;
    if (b.isAll()) return a;

    // compute pairwise greatest common sub types
    TypeSet res;
    for(const Type& x : a) {
        for(const Type& y : b) {
            res.insert(getGreatestCommonSubtypes(x,y));
        }
    }
    return res;
}
Esempio n. 17
0
  bool AreaAreaIndex::GetOffsets(const TypeConfigRef& typeConfig,
                                 double minlon,
                                 double minlat,
                                 double maxlon,
                                 double maxlat,
                                 size_t maxLevel,
                                 const TypeSet& types,
                                 size_t maxCount,
                                 std::vector<FileOffset>& offsets) const
  {
    std::vector<CellRef>    cellRefs;     // cells to scan in this level
    std::vector<CellRef>    nextCellRefs; // cells to scan for the next level
    std::vector<FileOffset> newOffsets;   // offsets collected in the current level

    minlon+=180;
    maxlon+=180;
    minlat+=90;
    maxlat+=90;

    // Clear result datastructures
    offsets.clear();

    // Make the vector preallocate memory for the expected data size
    // This should void reallocation
    offsets.reserve(std::min(100000u,(uint32_t)maxCount));
    newOffsets.reserve(std::min(100000u,(uint32_t)maxCount));

    cellRefs.reserve(1000);

    nextCellRefs.reserve(1000);

    cellRefs.push_back(CellRef(topLevelOffset,0,0));

    // For all levels:
    // * Take the tiles and offsets of the last level
    // * Calculate the new tiles and offsets that still interfere with given area
    // * Add the new offsets to the list of offsets and finish if we have
    //   reached maxLevel or maxAreaCount.
    // * copy no, ntx, nty to ctx, cty, co and go to next iteration
    bool stopArea=false;
    for (uint32_t level=0;
         !stopArea &&
         level<=this->maxLevel &&
         level<=maxLevel &&
         !cellRefs.empty();
         level++) {
      nextCellRefs.clear();

      newOffsets.clear();

      for (size_t i=0; !stopArea && i<cellRefs.size(); i++) {
        size_t               cx;
        size_t               cy;
        IndexCache::CacheRef cell;

        if (!GetIndexCell(*typeConfig,
                          level,
                          cellRefs[i].offset,
                          cell)) {
          log.Error() << "Cannot find offset " << cellRefs[i].offset << " in level " << level << " in file '" << scanner.GetFilename() << "'";
          return false;
        }

        if (offsets.size()+
            newOffsets.size()+
            cell->value.areas.size()>=maxCount) {
          stopArea=true;
          continue;
        }

        for (const auto entry : cell->value.areas) {
          if (types.IsTypeSet(entry.type)) {
            newOffsets.push_back(entry.offset);
          }
        }

        cx=cellRefs[i].x*2;
        cy=cellRefs[i].y*2;

        if (cell->value.children[0]!=0) {
          // top left
          double x=cx*cellWidth[level+1];
          double y=(cy+1)*cellHeight[level+1];

          if (!(x>maxlon+cellWidth[level+1]/2 ||
                y>maxlat+cellHeight[level+1]/2 ||
                x+cellWidth[level+1]<minlon-cellWidth[level+1]/2 ||
                y+cellHeight[level+1]<minlat-cellHeight[level+1]/2)) {
            nextCellRefs.push_back(CellRef(cell->value.children[0],cx,cy+1));
          }
        }

        if (cell->value.children[1]!=0) {
          // top right
          double x=(cx+1)*cellWidth[level+1];
          double y=(cy+1)*cellHeight[level+1];

          if (!(x>maxlon+cellWidth[level+1]/2 ||
                y>maxlat+cellHeight[level+1]/2 ||
                x+cellWidth[level+1]<minlon-cellWidth[level+1]/2 ||
                y+cellHeight[level+1]<minlat-cellHeight[level+1]/2)) {
            nextCellRefs.push_back(CellRef(cell->value.children[1],cx+1,cy+1));
          }
        }

        if (cell->value.children[2]!=0) {
          // bottom left
          double x=cx*cellWidth[level+1];
          double y=cy*cellHeight[level+1];

          if (!(x>maxlon+cellWidth[level+1]/2 ||
                y>maxlat+cellHeight[level+1]/2 ||
                x+cellWidth[level+1]<minlon-cellWidth[level+1]/2 ||
                y+cellHeight[level+1]<minlat-cellHeight[level+1]/2)) {
            nextCellRefs.push_back(CellRef(cell->value.children[2],cx,cy));
          }
        }

        if (cell->value.children[3]!=0) {
          // bottom right
          double x=(cx+1)*cellWidth[level+1];
          double y=cy*cellHeight[level+1];

          if (!(x>maxlon+cellWidth[level+1]/2 ||
                y>maxlat+cellHeight[level+1]/2 ||
                x+cellWidth[level+1]<minlon-cellWidth[level+1]/2 ||
                y+cellHeight[level+1]<minlat-cellHeight[level+1]/2)) {
            nextCellRefs.push_back(CellRef(cell->value.children[3],cx+1,cy));
          }
        }
      }

      if (!stopArea) {
        offsets.insert(offsets.end(),newOffsets.begin(),newOffsets.end());
      }

      std::swap(cellRefs,nextCellRefs);
    }

    return true;
  }
Esempio n. 18
0
TypeSet TypeEnvironment::getAllTypes() const {
    TypeSet res;
    for(const auto& cur : types) res.insert(*cur.second);
    return res;
}
Esempio n. 19
0
bool isRecordType(const TypeSet& s) {
    return !s.empty() && !s.isAll() && all_of(s, (bool(*)(const Type&))&isRecordType);
}
Esempio n. 20
0
bool CalculateAmplitudes::process() {
    //_ui.btnOK->setEnabled(false);

    _processors.clear();
    _ui.table->setRowCount(0);

    Core::TimeWindow acTimeWindow;

    if ( !_origin || (_recomputeAmplitudes && !_thread) )
        return false;

    if ( _amplitudeTypes.empty() )
        return false;

    _timeWindow = Core::TimeWindow();

    /*
    TypeSet wantedAmpTypes;

    wantedAmpTypes.insert("MLv");
    wantedAmpTypes.insert("mb");
    wantedAmpTypes.insert("mB");
    wantedAmpTypes.insert("Mwp");

    try {
    	vector<string> amps = SCApp->configGetStrings("amplitudes");
    	wantedAmpTypes.clear();
    	wantedAmpTypes.insert(amps.begin(), amps.end());
    }
    catch (...) {}
    */

    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

    if ( _thread )
        _thread->connect();

    typedef pair<PickCPtr, double> PickStreamEntry;

    // Typedef a pickmap that maps a streamcode to a pick
    typedef map<string, PickStreamEntry> PickStreamMap;

    // This map is needed to find the earliest P pick of
    // a certain stream
    PickStreamMap pickStreamMap;

    for ( size_t i = 0; i < _origin->arrivalCount(); ++i ) {
        Arrival *ar = _origin->arrival(i);

        double weight = 1.;
        try {
            weight = ar->weight();
        }
        catch (Seiscomp::Core::ValueException) {}

        if ( Util::getShortPhaseName(ar->phase().code()) != 'P' || weight < 0.5 ) {
            continue;
        }

        Pick *pick = Pick::Find(ar->pickID());
        if ( !pick ) {
// 			cerr << " - Skipping arrival " << i << " -> no pick found" << endl;
            continue;
        }

        double dist = -1;

        try {
            dist = ar->distance();
        }
        catch ( Core::ValueError &e ) {
            try {
                Client::StationLocation loc;
                double azi1, azi2;

                loc = Client::Inventory::Instance()->stationLocation(pick->waveformID().networkCode(), pick->waveformID().stationCode(), pick->time().value());
                Math::Geo::delazi(loc.latitude, loc.longitude, _origin->latitude(), _origin->longitude(), &dist, &azi1, &azi2);
            }
            catch ( Core::GeneralException &e ) {}
        }


        DataModel::WaveformStreamID wfid = pick->waveformID();
        // Strip the component code because every AmplitudeProcessor
        // will use its own component to pick the amplitude on
        wfid.setChannelCode(wfid.channelCode().substr(0,2));

        string streamID = waveformIDToStdString(wfid);
        PickStreamEntry &e = pickStreamMap[streamID];

        // When there is already a pick registered for this stream which has
        // been picked earlier, ignore the current pick
        if ( e.first && e.first->time().value() < pick->time().value() )
            continue;

        e.first = pick;
        e.second = dist;
    }

    for ( PickStreamMap::iterator it = pickStreamMap.begin(); it != pickStreamMap.end(); ++it ) {
        PickCPtr pick = it->second.first;
        double dist = it->second.second;

        _ui.comboFilterType->clear();
        _ui.comboFilterType->addItem("- Any -");
        for ( TypeSet::iterator ita = _amplitudeTypes.begin(); ita != _amplitudeTypes.end(); ++ita )
            _ui.comboFilterType->addItem(ita->c_str());

        if ( _recomputeAmplitudes ) {
            for ( TypeSet::iterator ita = _amplitudeTypes.begin(); ita != _amplitudeTypes.end(); ++ita )
                addProcessor(*ita, pick.get(), dist);
        }
        else {
            string streamID = waveformIDToStdString(pick->waveformID());

            TypeSet usedTypes;

            if ( !_amplitudes.empty() ) {
                iterator_range itp;
                itp = _amplitudes.equal_range(pick->publicID());

                for ( iterator it = itp.first; it != itp.second; ) {
                    AmplitudePtr amp = it->second.first;

                    // The amplitude type is not one of the wanted types
                    if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) {
                        ++it;
                        continue;
                    }

                    // Already has an amplitude of this type processed
                    if ( usedTypes.find(amp->type()) != usedTypes.end() ) {
                        ++it;
                        continue;
                    }

                    usedTypes.insert(amp->type());

                    int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type());
                    setMessage(row, "read from cache");
                    setValue(row, amp->amplitude().value());

                    ++it;
                }
            }

            bool foundAmplitudes = false;
            if ( _externalAmplitudeCache ) {
                iterator_range itp;
                itp = _externalAmplitudeCache->equal_range(pick->publicID());

                for ( iterator ita = itp.first; ita != itp.second; ++ita ) {
                    AmplitudePtr amp = ita->second.first;

                    // The amplitude type is not one of the wanted types
                    if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() )
                        continue;

                    // Already has an amplitude of this type processed
                    if ( usedTypes.find(amp->type()) != usedTypes.end() ) {
                        checkPriority(ita->second);
                        continue;
                    }

                    usedTypes.insert(amp->type());

                    int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type());
                    setMessage(row, "read from cache");
                    setValue(row, amp->amplitude().value());

                    _amplitudes.insert(PickAmplitudeMap::value_type(ita->first, ita->second));
                }
            }

            if ( _query && !foundAmplitudes ) {
                DatabaseIterator it = _query->getAmplitudesForPick(pick->publicID());
                for ( ; *it; ++it ) {
                    AmplitudePtr amp = Amplitude::Cast(*it);
                    if ( !amp ) continue;

                    foundAmplitudes = true;

                    // The amplitude type is not one of the wanted types
                    if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) continue;

                    // Already has an amplitude of this type processed
                    if ( usedTypes.find(amp->type()) != usedTypes.end() ) {
                        checkPriority(AmplitudeEntry(amp, false));
                        continue;
                    }

                    usedTypes.insert(amp->type());

                    int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type());
                    setMessage(row, "read from database");
                    setValue(row, amp->amplitude().value());
                    _amplitudes.insert(PickAmplitudeMap::value_type(pick->publicID(), AmplitudeEntry(amp, false)));
                }
            }

            if ( !foundAmplitudes ) {
                EventParameters *ep = EventParameters::Cast(PublicObject::Find("EventParameters"));
                if ( ep ) {
                    for ( size_t i = 0; i < ep->amplitudeCount(); ++i ) {
                        Amplitude *amp = ep->amplitude(i);
                        if ( amp->pickID() != pick->publicID() ) continue;

                        // The amplitude type is not one of the wanted types
                        if ( _amplitudeTypes.find(amp->type()) == _amplitudeTypes.end() ) continue;

                        // Already has an amplitude of this type processed
                        if ( usedTypes.find(amp->type()) != usedTypes.end() ) {
                            checkPriority(AmplitudeEntry(amp, false));
                            continue;
                        }

                        usedTypes.insert(amp->type());

                        int row = addProcessingRow(waveformIDToStdString(amp->waveformID()), amp->type());
                        setMessage(row, "read from memory");
                        setValue(row, amp->amplitude().value());
                        _amplitudes.insert(PickAmplitudeMap::value_type(pick->publicID(), AmplitudeEntry(amp, false)));
                    }
                }
            }

            TypeSet remainingTypes;
            set_difference(_amplitudeTypes.begin(), _amplitudeTypes.end(),
                           usedTypes.begin(), usedTypes.end(),
                           inserter(remainingTypes, remainingTypes.begin()));

            for ( TypeSet::iterator ita = remainingTypes.begin(); ita != remainingTypes.end(); ++ita ) {
                if ( _thread )
                    addProcessor(*ita, pick.get(), dist);
                else {
                    int row = addProcessingRow(streamID, *ita);
                    setError(row, "missing");
                }
            }
        }
    }

    _ui.table->resizeColumnsToContents();
    _ui.table->resizeRowsToContents();

    if ( _thread && _timeWindow ) {
        _thread->setTimeWindow(_timeWindow);
        _thread->start();
    }
    //else
    //	_ui.btnOK->setEnabled(true);

    QApplication::restoreOverrideCursor();

    return true;
}