Mercurial > hg > truffle
view graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java @ 8952:ef450d176a20
fixed bug in transformation of a type check profile into type check hints
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 09 Apr 2013 17:38:33 +0200 |
parents | 06e08471949e |
children | 38d7b55f87b0 |
line wrap: on
line source
/* * Copyright (c) 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.api.code; import static com.oracle.graal.api.meta.MetaUtil.*; import static java.lang.reflect.Modifier.*; import java.util.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; /** * Utility for deriving hint types for a type check instruction (e.g. checkcast or instanceof) based * on the target type of the check and any profiling information available for the instruction. */ public class TypeCheckHints { /** * A receiver type profiled in a type check instruction. */ public static class Hint { /** * A type seen while profiling a type check instruction. */ public final ResolvedJavaType type; /** * Specifies if {@link #type} was a sub-type of the checked type. */ public final boolean positive; Hint(ResolvedJavaType type, boolean positive) { this.type = type; this.positive = positive; } } private static final Hint[] NO_HINTS = {}; /** * If true, then {@link #hints} contains the only possible type that could pass the type check * because the target of the type check is a final class or has been speculated to be a final * class. */ public final boolean exact; /** * The most likely types that the type check instruction will see. */ public final Hint[] hints; /** * Derives hint information for use when generating the code for a type check instruction. * * @param targetType the target type of the type check * @param profile the profiling information available for the instruction (if any) * @param assumptions the object in which speculations are recorded. This is null if * speculations are not supported. * @param minHintHitProbability if the probability that the type check will hit one of the * profiled types (up to {@code maxHints}) is below this value, then {@link #hints} * will be null * @param maxHints the maximum length of {@link #hints} */ public TypeCheckHints(ResolvedJavaType targetType, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) { if (targetType != null && !canHaveSubtype(targetType)) { hints = new Hint[]{new Hint(targetType, true)}; exact = true; } else { ResolvedJavaType uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { hints = new Hint[]{new Hint(uniqueSubtype, true)}; if (assumptions.useOptimisticAssumptions()) { assumptions.recordConcreteSubtype(targetType, uniqueSubtype); exact = true; } else { exact = false; } } else { exact = false; Hint[] hintsBuf = NO_HINTS; JavaTypeProfile typeProfile = profile; if (typeProfile != null) { double notRecordedTypes = typeProfile.getNotRecordedProbability(); ProfiledType[] ptypes = typeProfile.getTypes(); if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) { hintsBuf = new Hint[ptypes.length]; int hintCount = 0; double totalHintProbability = 0.0d; for (ProfiledType ptype : ptypes) { if (targetType != null) { ResolvedJavaType hintType = ptype.getType(); hintsBuf[hintCount++] = new Hint(hintType, targetType.isAssignableFrom(hintType)); totalHintProbability += ptype.getProbability(); } } if (totalHintProbability >= minHintHitProbability) { if (hintsBuf.length != hintCount || hintCount > maxHints) { hintsBuf = Arrays.copyOf(hintsBuf, Math.min(maxHints, hintCount)); } } else { hintsBuf = NO_HINTS; } } } this.hints = hintsBuf; } } } /** * Determines if a given type can have subtypes other than itself. This analysis is purely * static; no assumptions are made. * * @return true if {@code type} can have subtypes */ public static boolean canHaveSubtype(ResolvedJavaType type) { return !isFinal(getElementalType(type).getModifiers()); } }