Mercurial > hg > graal-compiler
view graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/TypeFeedbackCache.java @ 5540:a891c53a295b
Renaming RiKind => Kind.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Fri, 08 Jun 2012 23:47:42 +0200 |
parents | 426c605c9d3c |
children | b4c406861c33 |
line wrap: on
line source
/* * Copyright (c) 2012, 2012, 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 com.oracle.graal.compiler.types; import java.util.*; import java.util.Map.Entry; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.types.*; public class TypeFeedbackCache implements TypeFeedbackTool, Cloneable { public static final boolean NO_OBJECT_TYPES = false; public static final boolean NO_SCALAR_TYPES = false; private final RiRuntime runtime; private final StructuredGraph graph; private final HashMap<ValueNode, ScalarTypeFeedbackStore> scalarTypeFeedback; private final HashMap<ValueNode, ObjectTypeFeedbackStore> objectTypeFeedback; private final TypeFeedbackChanged changed; private final boolean negated; public TypeFeedbackCache(RiRuntime runtime, StructuredGraph graph, TypeFeedbackChanged changed) { this.runtime = runtime; this.graph = graph; scalarTypeFeedback = new HashMap<>(); objectTypeFeedback = new HashMap<>(); negated = false; this.changed = changed; } public TypeFeedbackCache(RiRuntime runtime, StructuredGraph graph, HashMap<ValueNode, ScalarTypeFeedbackStore> scalarTypeFeedback, HashMap<ValueNode, ObjectTypeFeedbackStore> objectTypeFeedback, boolean negated, TypeFeedbackChanged changed) { this.runtime = runtime; this.graph = graph; this.scalarTypeFeedback = scalarTypeFeedback; this.objectTypeFeedback = objectTypeFeedback; this.negated = negated; this.changed = changed; } @Override public ScalarTypeFeedbackTool addScalar(ValueNode value) { assert value.kind() == Kind.Int || value.kind() == Kind.Long || value.kind() == Kind.Float || value.kind() == Kind.Double; ScalarTypeFeedbackStore result = scalarTypeFeedback.get(value); if (result == null) { if (value.stamp().scalarType() != null) { result = value.stamp().scalarType().store().clone(); } else { result = new ScalarTypeFeedbackStore(value.kind(), changed); } scalarTypeFeedback.put(value, result); } return negated ? new NegateScalarTypeFeedback(result) : result; } @Override public ObjectTypeFeedbackTool addObject(ValueNode value) { assert value.kind() == Kind.Object; ObjectTypeFeedbackStore result = objectTypeFeedback.get(value); if (result == null) { if (value.stamp().objectType() != null) { result = value.stamp().objectType().store().clone(); } else { result = new ObjectTypeFeedbackStore(changed); } objectTypeFeedback.put(value, result); } return negated ? new NegateObjectTypeFeedback(result) : result; } @Override public TypeFeedbackTool negate() { return new TypeFeedbackCache(runtime, graph, scalarTypeFeedback, objectTypeFeedback, !negated, changed); } @Override public RiRuntime runtime() { return runtime; } @Override public TypeFeedbackCache clone() { return new TypeFeedbackCache(runtime, graph, deepClone(scalarTypeFeedback), deepClone(objectTypeFeedback), negated, changed); } @SuppressWarnings("unchecked") private static <KeyT, ValueT extends CloneableTypeFeedback> HashMap<KeyT, ValueT> deepClone(HashMap<KeyT, ValueT> map) { HashMap<KeyT, ValueT> result = new HashMap<>(); for (Map.Entry<KeyT, ValueT> entry : map.entrySet()) { if (entry.getValue() == null) { System.out.println(entry.getKey()); } else { result.put(entry.getKey(), (ValueT) entry.getValue().clone()); } } return result; } @Override public String toString() { StringBuilder str = new StringBuilder().append("types [\n"); for (Map.Entry<ValueNode, ScalarTypeFeedbackStore> entry : scalarTypeFeedback.entrySet()) { if (!entry.getValue().isEmpty()) { str.append(" ").append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); } } for (Map.Entry<ValueNode, ObjectTypeFeedbackStore> entry : objectTypeFeedback.entrySet()) { if (!entry.getValue().isEmpty()) { str.append(" ").append(entry.getKey()).append(": ").append(entry.getValue()).append("\n"); } } str.setLength(str.length() - 1); return str.append(" ]").toString(); } public static TypeFeedbackCache meet(TypeFeedbackCache[] cacheList, Iterable<PhiNode> phis) { TypeFeedbackCache result = new TypeFeedbackCache(cacheList[0].runtime, cacheList[0].graph, cacheList[0].changed); for (int i = 1; i < cacheList.length; i++) { assert result.runtime == cacheList[i].runtime; assert !result.negated && !cacheList[i].negated : "cannot meet negated type feedback caches"; } // meet the scalar types for (Entry<ValueNode, ScalarTypeFeedbackStore> entry : cacheList[0].scalarTypeFeedback.entrySet()) { ScalarTypeFeedbackStore[] types = new ScalarTypeFeedbackStore[cacheList.length]; for (int i = 0; i < cacheList.length; i++) { types[i] = cacheList[i].scalarTypeFeedback.get(entry.getKey()); } ScalarTypeFeedbackStore scalar = ScalarTypeFeedbackStore.meet(types); if (scalar != null && !scalar.isEmpty()) { result.scalarTypeFeedback.put(entry.getKey(), scalar); } } // meet the object types for (Entry<ValueNode, ObjectTypeFeedbackStore> entry : cacheList[0].objectTypeFeedback.entrySet()) { ObjectTypeFeedbackStore[] types = new ObjectTypeFeedbackStore[cacheList.length]; for (int i = 0; i < cacheList.length; i++) { types[i] = cacheList[i].objectTypeFeedback.get(entry.getKey()); } ObjectTypeFeedbackStore object = ObjectTypeFeedbackStore.meet(types); if (object != null && !object.isEmpty()) { result.objectTypeFeedback.put(entry.getKey(), object); } } // meet the phi nodes for (PhiNode phi : phis) { assert phi.valueCount() == cacheList.length; if (phi.kind() == Kind.Int || phi.kind() == Kind.Long) { ScalarTypeFeedbackStore[] types = new ScalarTypeFeedbackStore[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) { ScalarTypeFeedbackStore other = cacheList[i].scalarTypeFeedback.get(phi.valueAt(i)); if (other == null && phi.valueAt(i).stamp().scalarType() != null) { other = phi.valueAt(i).stamp().scalarType().store(); } types[i] = other; } ScalarTypeFeedbackStore scalar = ScalarTypeFeedbackStore.meet(types); if (scalar != null && !scalar.isEmpty()) { result.scalarTypeFeedback.put(phi, scalar); // phi.setStamp(StampFactory.forKind(phi.kind(), scalar.query(), null)); } } else if (phi.kind() == Kind.Object) { ObjectTypeFeedbackStore[] types = new ObjectTypeFeedbackStore[phi.valueCount()]; for (int i = 0; i < phi.valueCount(); i++) { ObjectTypeFeedbackStore other = cacheList[i].objectTypeFeedback.get(phi.valueAt(i)); if (other == null && phi.valueAt(i).stamp().objectType() != null) { other = phi.valueAt(i).stamp().objectType().store(); } types[i] = other; } ObjectTypeFeedbackStore object = ObjectTypeFeedbackStore.meet(types); if (object != null && !object.isEmpty()) { result.objectTypeFeedback.put(phi, object); // phi.setStamp(StampFactory.forKind(phi.kind(), null, object.query())); } } } return result; } @Override public ScalarTypeQuery queryScalar(ValueNode value) { assert value.kind() == Kind.Int || value.kind() == Kind.Long || value.kind() == Kind.Float || value.kind() == Kind.Double; if (NO_SCALAR_TYPES) { return new ScalarTypeFeedbackStore(value.kind(), changed).query(); } ScalarTypeFeedbackStore result = scalarTypeFeedback.get(value); if (result == null) { if (value.stamp().scalarType() != null) { return value.stamp().scalarType(); } result = new ScalarTypeFeedbackStore(value.kind(), changed); scalarTypeFeedback.put(value, result); } return result.query(); } @Override public ObjectTypeQuery queryObject(ValueNode value) { assert value != null; assert value.kind() == Kind.Object; if (NO_OBJECT_TYPES) { return new ObjectTypeFeedbackStore(changed).query(); } ObjectTypeFeedbackStore result = objectTypeFeedback.get(value); if (result == null) { if (value.stamp().objectType() != null) { return value.stamp().objectType(); } result = new ObjectTypeFeedbackStore(changed); objectTypeFeedback.put(value, result); } return result.query(); } }