blob: f3e6f4d747e712dfb80aa981f0f1b32dcbd604cd [file] [log] [blame]
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.lib.jittester;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeSet;
import jdk.test.lib.jittester.factories.Factory;
import jdk.test.lib.jittester.utils.PseudoRandom;
/**
* The Rule. A helper to perform production.
*/
public class Rule<T extends IRNode> extends Factory<T> implements Comparable<Rule<T>> {
private final String name;
private final TreeSet<RuleEntry> variants;
private Integer limit = -1;
@Override
public int compareTo(Rule<T> rule) {
return name.compareTo(rule.name);
}
public Rule(String name) {
this.name = name;
variants = new TreeSet<>();
}
public void add(String ruleName, Factory<? extends T> factory) {
add(ruleName, factory, 1.0);
}
public void add(String ruleName, Factory<? extends T> factory, double weight) {
variants.add(new RuleEntry(ruleName, factory, weight));
}
public int size() {
return variants.size();
}
@Override
public T produce() throws ProductionFailedException {
if (!variants.isEmpty()) {
// Begin production.
LinkedList<RuleEntry> rulesList = new LinkedList<>(variants);
PseudoRandom.shuffle(rulesList);
while (!rulesList.isEmpty() && (limit == -1 || limit > 0)) {
double sum = rulesList.stream()
.mapToDouble(r -> r.weight)
.sum();
double rnd = PseudoRandom.random() * sum;
Iterator<RuleEntry> iterator = rulesList.iterator();
RuleEntry ruleEntry;
double weightAccumulator = 0;
do {
ruleEntry = iterator.next();
weightAccumulator += ruleEntry.weight;
if (weightAccumulator >= rnd) {
break;
}
} while (iterator.hasNext());
try {
return ruleEntry.produce();
} catch (ProductionFailedException e) {
}
iterator.remove();
if (limit != -1) {
limit--;
}
}
//throw new ProductionFailedException();
}
// should probably throw exception here..
//return getChildren().size() > 0 ? getChild(0).produce() : null;
throw new ProductionFailedException();
}
private class RuleEntry extends Factory<T> implements Comparable<RuleEntry> {
private final double weight;
private final Factory<? extends T> factory;
private final String name;
private RuleEntry(String name, Factory<? extends T> factory, double weight) {
this.name = name;
this.weight = weight;
this.factory = factory;
}
@Override
public T produce() throws ProductionFailedException {
return factory.produce();
}
@Override
public int compareTo(RuleEntry entry) {
return name.compareTo(entry.name);
}
}
}