1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime.linker;
  27 
  28 import java.lang.invoke.MethodHandles;
  29 import java.lang.invoke.MethodHandles.Lookup;
  30 import java.lang.invoke.MethodType;
  31 import java.lang.ref.Reference;
  32 import java.lang.ref.WeakReference;
  33 import java.security.AccessControlContext;
  34 import java.security.AccessController;
  35 import java.security.PrivilegedAction;
  36 import java.util.Collections;
  37 import java.util.Map;
  38 import java.util.WeakHashMap;
  39 import java.util.concurrent.ConcurrentHashMap;
  40 import java.util.concurrent.ConcurrentMap;
  41 import java.util.stream.Stream;
  42 import jdk.dynalink.CallSiteDescriptor;
  43 import jdk.dynalink.CompositeOperation;
  44 import jdk.dynalink.NamedOperation;
  45 import jdk.dynalink.Operation;
  46 import jdk.dynalink.StandardOperation;
  47 import jdk.nashorn.internal.ir.debug.NashornTextifier;
  48 import jdk.nashorn.internal.runtime.AccessControlContextFactory;
  49 import jdk.nashorn.internal.runtime.ScriptRuntime;
  50 
  51 /**
  52  * Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}.
  53  * The reason we have our own subclass is that we're storing flags in an
  54  * additional primitive field. The class also exposes some useful utilities in
  55  * form of static methods.
  56  */
  57 public final class NashornCallSiteDescriptor extends CallSiteDescriptor {
  58     // Lowest three bits describe the operation
  59     /** Property getter operation {@code obj.prop} */
  60     public static final int GET_PROPERTY        = 0;
  61     /** Element getter operation {@code obj[index]} */
  62     public static final int GET_ELEMENT         = 1;
  63     /** Property getter operation, subsequently invoked {@code obj.prop()} */
  64     public static final int GET_METHOD_PROPERTY = 2;
  65     /** Element getter operation, subsequently invoked {@code obj[index]()} */
  66     public static final int GET_METHOD_ELEMENT  = 3;
  67     /** Property setter operation {@code obj.prop = value} */
  68     public static final int SET_PROPERTY        = 4;
  69     /** Element setter operation {@code obj[index] = value} */
  70     public static final int SET_ELEMENT         = 5;
  71     /** Call operation {@code fn(args...)} */
  72     public static final int CALL                = 6;
  73     /** New operation {@code new Constructor(args...)} */
  74     public static final int NEW                 = 7;
  75 
  76     private static final int OPERATION_MASK = 7;
  77 
  78     // Correspond to the operation indices above.
  79     private static final Operation[] OPERATIONS = new Operation[] {
  80         new CompositeOperation(StandardOperation.GET_PROPERTY, StandardOperation.GET_ELEMENT, StandardOperation.GET_METHOD),
  81         new CompositeOperation(StandardOperation.GET_ELEMENT, StandardOperation.GET_PROPERTY, StandardOperation.GET_METHOD),
  82         new CompositeOperation(StandardOperation.GET_METHOD, StandardOperation.GET_PROPERTY, StandardOperation.GET_ELEMENT),
  83         new CompositeOperation(StandardOperation.GET_METHOD, StandardOperation.GET_ELEMENT, StandardOperation.GET_PROPERTY),
  84         new CompositeOperation(StandardOperation.SET_PROPERTY, StandardOperation.SET_ELEMENT),
  85         new CompositeOperation(StandardOperation.SET_ELEMENT, StandardOperation.SET_PROPERTY),
  86         StandardOperation.CALL,
  87         StandardOperation.NEW
  88     };
  89 
  90     /** Flags that the call site references a scope variable (it's an identifier reference or a var declaration, not a
  91      * property access expression. */
  92     public static final int CALLSITE_SCOPE         = 1 << 3;
  93     /** Flags that the call site is in code that uses ECMAScript strict mode. */
  94     public static final int CALLSITE_STRICT        = 1 << 4;
  95     /** Flags that a property getter or setter call site references a scope variable that is located at a known distance
  96      * in the scope chain. Such getters and setters can often be linked more optimally using these assumptions. */
  97     public static final int CALLSITE_FAST_SCOPE    = 1 << 5;
  98     /** Flags that a callsite type is optimistic, i.e. we might get back a wider return value than encoded in the
  99      * descriptor, and in that case we have to throw an UnwarrantedOptimismException */
 100     public static final int CALLSITE_OPTIMISTIC    = 1 << 6;
 101     /** Is this really an apply that we try to call as a call? */
 102     public static final int CALLSITE_APPLY_TO_CALL = 1 << 7;
 103     /** Does this a callsite for a variable declaration? */
 104     public static final int CALLSITE_DECLARE       = 1 << 8;
 105 
 106     /** Flags that the call site is profiled; Contexts that have {@code "profile.callsites"} boolean property set emit
 107      * code where call sites have this flag set. */
 108     public static final int CALLSITE_PROFILE         = 1 << 9;
 109     /** Flags that the call site is traced; Contexts that have {@code "trace.callsites"} property set emit code where
 110      * call sites have this flag set. */
 111     public static final int CALLSITE_TRACE           = 1 << 10;
 112     /** Flags that the call site linkage miss (and thus, relinking) is traced; Contexts that have the keyword
 113      * {@code "miss"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
 114     public static final int CALLSITE_TRACE_MISSES    = 1 << 11;
 115     /** Flags that entry/exit to/from the method linked at call site are traced; Contexts that have the keyword
 116      * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
 117     public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 12;
 118     /** Flags that values passed as arguments to and returned from the method linked at call site are traced; Contexts
 119      * that have the keyword {@code "values"} in their {@code "trace.callsites"} property emit code where call sites
 120      * have this flag set. */
 121     public static final int CALLSITE_TRACE_VALUES    = 1 << 13;
 122 
 123     //we could have more tracing flags here, for example CALLSITE_TRACE_SCOPE, but bits are a bit precious
 124     //right now given the program points
 125 
 126     /**
 127      * Number of bits the program point is shifted to the left in the flags (lowest bit containing a program point).
 128      * Always one larger than the largest flag shift. Note that introducing a new flag halves the number of program
 129      * points we can have.
 130      * TODO: rethink if we need the various profile/trace flags or the linker can use the Context instead to query its
 131      * trace/profile settings.
 132      */
 133     public static final int CALLSITE_PROGRAM_POINT_SHIFT = 14;
 134 
 135     /**
 136      * Maximum program point value. We have 18 bits left over after flags, and
 137      * it should be plenty. Program points are local to a single function. Every
 138      * function maps to a single JVM bytecode method that can have at most 65535
 139      * bytes. (Large functions are synthetically split into smaller functions.)
 140      * A single invokedynamic is 5 bytes; even if a method consists of only
 141      * invokedynamic instructions that leaves us with at most 65535/5 = 13107
 142      * program points for the largest single method; those can be expressed on
 143      * 14 bits. It is true that numbering of program points is independent of
 144      * bytecode representation, but if a function would need more than ~14 bits
 145      * for the program points, then it is reasonable to presume splitter
 146      * would've split it into several smaller functions already.
 147      */
 148     public static final int MAX_PROGRAM_POINT_VALUE = (1 << 32 - CALLSITE_PROGRAM_POINT_SHIFT) - 1;
 149 
 150     /**
 151      * Flag mask to get the program point flags
 152      */
 153     public static final int FLAGS_MASK = (1 << CALLSITE_PROGRAM_POINT_SHIFT) - 1;
 154 
 155     private static final ClassValue<ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor>> canonicals =
 156             new ClassValue<ConcurrentMap<NashornCallSiteDescriptor,NashornCallSiteDescriptor>>() {
 157         @Override
 158         protected ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> computeValue(final Class<?> type) {
 159             return new ConcurrentHashMap<>();
 160         }
 161     };
 162 
 163     private static final AccessControlContext GET_LOOKUP_PERMISSION_CONTEXT =
 164             AccessControlContextFactory.createAccessControlContext(CallSiteDescriptor.GET_LOOKUP_PERMISSION_NAME);
 165 
 166     @SuppressWarnings("unchecked")
 167     private static final Map<String, Reference<NamedOperation>>[] NAMED_OPERATIONS =
 168             Stream.generate(() -> Collections.synchronizedMap(new WeakHashMap<>()))
 169             .limit(OPERATIONS.length).toArray(Map[]::new);
 170 
 171     private final int flags;
 172 
 173     /**
 174      * Function used by {@link NashornTextifier} to represent call site flags in
 175      * human readable form
 176      * @param flags call site flags
 177      * @param sb the string builder
 178      */
 179     public static void appendFlags(final int flags, final StringBuilder sb) {
 180         final int pp = flags >> CALLSITE_PROGRAM_POINT_SHIFT;
 181         if (pp != 0) {
 182             sb.append(" pp=").append(pp);
 183         }
 184         if ((flags & CALLSITE_SCOPE) != 0) {
 185             if ((flags & CALLSITE_FAST_SCOPE) != 0) {
 186                 sb.append(" fastscope");
 187             } else {
 188                 sb.append(" scope");
 189             }
 190             if ((flags & CALLSITE_DECLARE) != 0) {
 191                 sb.append(" declare");
 192             }
 193         } else {
 194             assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope";
 195         }
 196         if ((flags & CALLSITE_APPLY_TO_CALL) != 0) {
 197             sb.append(" apply2call");
 198         }
 199         if ((flags & CALLSITE_STRICT) != 0) {
 200             sb.append(" strict");
 201         }
 202     }
 203 
 204     /**
 205      * Given call site flags, returns the operation name encoded in them.
 206      * @param flags flags
 207      * @return the operation name
 208      */
 209     public static String getOperationName(final int flags) {
 210         switch(flags & OPERATION_MASK) {
 211         case 0: return "GET_PROPERTY";
 212         case 1: return "GET_ELEMENT";
 213         case 2: return "GET_METHOD_PROPERTY";
 214         case 3: return "GET_METHOD_ELEMENT";
 215         case 4: return "SET_PROPERTY";
 216         case 5: return "SET_ELEMENT";
 217         case 6: return "CALL";
 218         case 7: return "NEW";
 219         default: throw new AssertionError();
 220         }
 221     }
 222 
 223     /**
 224      * Retrieves a Nashorn call site descriptor with the specified values. Since call site descriptors are immutable
 225      * this method is at liberty to retrieve canonicalized instances (although it is not guaranteed it will do so).
 226      * @param lookup the lookup describing the script
 227      * @param name the name at the call site. Can not be null, but it can be empty.
 228      * @param methodType the method type at the call site
 229      * @param flags Nashorn-specific call site flags
 230      * @return a call site descriptor with the specified values.
 231      */
 232     public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name,
 233             final MethodType methodType, final int flags) {
 234         final int opIndex = flags & OPERATION_MASK;
 235         final Operation baseOp = OPERATIONS[opIndex];
 236         final String decodedName = NameCodec.decode(name);
 237         final Operation op = decodedName.isEmpty() ? baseOp : getNamedOperation(decodedName, opIndex, baseOp);
 238         return get(lookup, op, methodType, flags);
 239     }
 240 
 241     private static NamedOperation getNamedOperation(final String name, final int opIndex, final Operation baseOp) {
 242         final Map<String, Reference<NamedOperation>> namedOps = NAMED_OPERATIONS[opIndex];
 243         final Reference<NamedOperation> ref = namedOps.get(name);
 244         if (ref != null) {
 245             final NamedOperation existing = ref.get();
 246             if (existing != null) {
 247                 return existing;
 248             }
 249         }
 250         final NamedOperation newOp = new NamedOperation(baseOp, name);
 251         namedOps.put(name, new WeakReference<>(newOp));
 252         return newOp;
 253     }
 254 
 255     private static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final Operation operation, final MethodType methodType, final int flags) {
 256         final NashornCallSiteDescriptor csd = new NashornCallSiteDescriptor(lookup, operation, methodType, flags);
 257         // Many of these call site descriptors are identical (e.g. every getter for a property color will be
 258         // "GET_PROPERTY:color(Object)Object", so it makes sense canonicalizing them. Make an exception for
 259         // optimistic call site descriptors, as they also carry a program point making them unique.
 260         if (csd.isOptimistic()) {
 261             return csd;
 262         }
 263         final NashornCallSiteDescriptor canonical = canonicals.get(lookup.lookupClass()).putIfAbsent(csd, csd);
 264         return canonical != null ? canonical : csd;
 265     }
 266 
 267     private NashornCallSiteDescriptor(final MethodHandles.Lookup lookup, final Operation operation, final MethodType methodType, final int flags) {
 268         super(lookup, operation, methodType);
 269         this.flags = flags;
 270     }
 271 
 272     static Lookup getLookupInternal(final CallSiteDescriptor csd) {
 273         if (csd instanceof NashornCallSiteDescriptor) {
 274             return ((NashornCallSiteDescriptor)csd).getLookupPrivileged();
 275         }
 276         return AccessController.doPrivileged((PrivilegedAction<Lookup>)()->csd.getLookup(), GET_LOOKUP_PERMISSION_CONTEXT);
 277     }
 278 
 279     @Override
 280     public boolean equals(final Object obj) {
 281         return super.equals(obj) && flags == ((NashornCallSiteDescriptor)obj).flags;
 282     }
 283 
 284     @Override
 285     public int hashCode() {
 286         return super.hashCode() ^ flags;
 287     }
 288 
 289     /**
 290      * Returns the named operand in this descriptor's operation. Equivalent to
 291      * {@code ((NamedOperation)getOperation()).getName().toString()} for call
 292      * sites with a named operand. For call sites without named operands returns null.
 293      * @return the named operand in this descriptor's operation.
 294      */
 295     public String getOperand() {
 296         return getOperand(this);
 297     }
 298 
 299     /**
 300      * Returns the named operand in the passed descriptor's operation.
 301      * Equivalent to
 302      * {@code ((NamedOperation)desc.getOperation()).getName().toString()} for
 303      * descriptors with a named operand. For descriptors without named operands
 304      * returns null.
 305      * @param desc the call site descriptors
 306      * @return the named operand in this descriptor's operation.
 307      */
 308     public static String getOperand(final CallSiteDescriptor desc) {
 309         final Operation operation = desc.getOperation();
 310         return operation instanceof NamedOperation ? ((NamedOperation)operation).getName().toString() : null;
 311     }
 312 
 313     /**
 314      * Returns the first operation in this call site descriptor's potentially
 315      * composite operation. E.g. if this call site descriptor has a composite
 316      * operation {@code GET_PROPERTY|GET_METHOD|GET_ELEM}, it will return
 317      * {@code GET_PROPERTY}. Nashorn - being a ECMAScript engine - does not
 318      * distinguish between property, element, and method namespace; ECMAScript
 319      * objects just have one single property namespace for all these, therefore
 320      * it is largely irrelevant what the composite operation is structured like;
 321      * if the first operation can't be satisfied, neither can the others. The
 322      * first operation is however sometimes used to slightly alter the
 323      * semantics; for example, a distinction between {@code GET_PROPERTY} and
 324      * {@code GET_METHOD} being the first operation can translate into whether
 325      * {@code "__noSuchProperty__"} or {@code "__noSuchMethod__"} will be
 326      * executed in case the property is not found. Note that if a call site
 327      * descriptor comes from outside of Nashorn, its class will be different,
 328      * and there is no guarantee about the way it composes its operations. For
 329      * that reason, for potentially foreign call site descriptors you should use
 330      * {@link #getFirstStandardOperation(CallSiteDescriptor)} instead.
 331      * @return the first operation in this call site descriptor. Note this will
 332      * always be a {@code StandardOperation} as Nashorn internally only uses
 333      * standard operations.
 334      */
 335     public StandardOperation getFirstOperation() {
 336         final Operation base = NamedOperation.getBaseOperation(getOperation());
 337         if (base instanceof CompositeOperation) {
 338             return (StandardOperation)((CompositeOperation)base).getOperation(0);
 339         }
 340         return (StandardOperation)base;
 341     }
 342 
 343     /**
 344      * Returns the first standard operation in the (potentially composite)
 345      * operation of the passed call site descriptor.
 346      * @param desc the call site descriptor.
 347      * @return Returns the first standard operation in the (potentially
 348      * composite) operation of the passed call site descriptor. Can return null
 349      * if the call site contains no standard operations.
 350      */
 351     public static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) {
 352         final Operation base = NamedOperation.getBaseOperation(desc.getOperation());
 353         if (base instanceof StandardOperation) {
 354             return (StandardOperation)base;
 355         } else if (base instanceof CompositeOperation) {
 356             final CompositeOperation cop = (CompositeOperation)base;
 357             for(int i = 0; i < cop.getOperationCount(); ++i) {
 358                 final Operation op = cop.getOperation(i);
 359                 if (op instanceof StandardOperation) {
 360                     return (StandardOperation)op;
 361                 }
 362             }
 363         }
 364         return null;
 365     }
 366 
 367     /**
 368      * Returns true if the passed call site descriptor's operation contains (or
 369      * is) the specified standard operation.
 370      * @param desc the call site descriptor.
 371      * @param operation the operation whose presence is tested.
 372      * @return Returns true if the call site descriptor's operation contains (or
 373      * is) the specified standard operation.
 374      */
 375     public static boolean contains(final CallSiteDescriptor desc, final StandardOperation operation) {
 376         return CompositeOperation.contains(NamedOperation.getBaseOperation(desc.getOperation()), operation);
 377     }
 378 
 379     /**
 380      * Returns the error message to be used when CALL or NEW is used on a non-function.
 381      *
 382      * @param obj object on which CALL or NEW is used
 383      * @return error message
 384      */
 385     public String getFunctionErrorMessage(final Object obj) {
 386         final String funcDesc = getOperand();
 387         return funcDesc != null? funcDesc : ScriptRuntime.safeToString(obj);
 388     }
 389 
 390     /**
 391      * Returns the error message to be used when CALL or NEW is used on a non-function.
 392      *
 393      * @param desc call site descriptor
 394      * @param obj object on which CALL or NEW is used
 395      * @return error message
 396      */
 397     public static String getFunctionErrorMessage(final CallSiteDescriptor desc, final Object obj) {
 398         return desc instanceof NashornCallSiteDescriptor ?
 399                 ((NashornCallSiteDescriptor)desc).getFunctionErrorMessage(obj) :
 400                 ScriptRuntime.safeToString(obj);
 401     }
 402 
 403     /**
 404      * Returns the Nashorn-specific flags for this call site descriptor.
 405      * @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
 406      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
 407      * generated outside of Nashorn.
 408      * @return the Nashorn-specific flags for the call site, or 0 if the passed descriptor is not a Nashorn call site
 409      * descriptor.
 410      */
 411     public static int getFlags(final CallSiteDescriptor desc) {
 412         return desc instanceof NashornCallSiteDescriptor ? ((NashornCallSiteDescriptor)desc).flags : 0;
 413     }
 414 
 415     /**
 416      * Returns true if this descriptor has the specified flag set, see {@code CALLSITE_*} constants in this class.
 417      * @param flag the tested flag
 418      * @return true if the flag is set, false otherwise
 419      */
 420     private boolean isFlag(final int flag) {
 421         return (flags & flag) != 0;
 422     }
 423 
 424     /**
 425      * Returns true if this descriptor has the specified flag set, see {@code CALLSITE_*} constants in this class.
 426      * @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
 427      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
 428      * generated outside of Nashorn.
 429      * @param flag the tested flag
 430      * @return true if the flag is set, false otherwise (it will be false if the descriptor is not a Nashorn call site
 431      * descriptor).
 432      */
 433     private static boolean isFlag(final CallSiteDescriptor desc, final int flag) {
 434         return (getFlags(desc) & flag) != 0;
 435     }
 436 
 437     /**
 438      * Returns true if this descriptor is a Nashorn call site descriptor and has the {@link  #CALLSITE_SCOPE} flag set.
 439      * @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
 440      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
 441      * generated outside of Nashorn.
 442      * @return true if the descriptor is a Nashorn call site descriptor, and the flag is set, false otherwise.
 443      */
 444     public static boolean isScope(final CallSiteDescriptor desc) {
 445         return isFlag(desc, CALLSITE_SCOPE);
 446     }
 447 
 448     /**
 449      * Returns true if this descriptor is a Nashorn call site descriptor and has the {@link  #CALLSITE_FAST_SCOPE} flag set.
 450      * @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
 451      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
 452      * generated outside of Nashorn.
 453      * @return true if the descriptor is a Nashorn call site descriptor, and the flag is set, false otherwise.
 454      */
 455     public static boolean isFastScope(final CallSiteDescriptor desc) {
 456         return isFlag(desc, CALLSITE_FAST_SCOPE);
 457     }
 458 
 459     /**
 460      * Returns true if this descriptor is a Nashorn call site descriptor and has the {@link  #CALLSITE_STRICT} flag set.
 461      * @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
 462      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
 463      * generated outside of Nashorn.
 464      * @return true if the descriptor is a Nashorn call site descriptor, and the flag is set, false otherwise.
 465      */
 466     public static boolean isStrict(final CallSiteDescriptor desc) {
 467         return isFlag(desc, CALLSITE_STRICT);
 468     }
 469 
 470     /**
 471      * Returns true if this is an apply call that we try to call as
 472      * a "call"
 473      * @param desc descriptor
 474      * @return true if apply to call
 475      */
 476     public static boolean isApplyToCall(final CallSiteDescriptor desc) {
 477         return isFlag(desc, CALLSITE_APPLY_TO_CALL);
 478     }
 479 
 480     /**
 481      * Is this an optimistic call site
 482      * @param desc descriptor
 483      * @return true if optimistic
 484      */
 485     public static boolean isOptimistic(final CallSiteDescriptor desc) {
 486         return isFlag(desc, CALLSITE_OPTIMISTIC);
 487     }
 488 
 489     /**
 490      * Does this callsite contain a declaration for its target?
 491      * @param desc descriptor
 492      * @return true if contains declaration
 493      */
 494     public static boolean isDeclaration(final CallSiteDescriptor desc) {
 495         return isFlag(desc, CALLSITE_DECLARE);
 496     }
 497 
 498     /**
 499      * Returns true if {@code flags} has the {@link  #CALLSITE_STRICT} bit set.
 500      * @param flags the flags
 501      * @return true if the flag is set, false otherwise.
 502      */
 503     public static boolean isStrictFlag(final int flags) {
 504         return (flags & CALLSITE_STRICT) != 0;
 505     }
 506 
 507     /**
 508      * Returns true if {@code flags} has the {@link  #CALLSITE_SCOPE} bit set.
 509      * @param flags the flags
 510      * @return true if the flag is set, false otherwise.
 511      */
 512     public static boolean isScopeFlag(final int flags) {
 513         return (flags & CALLSITE_SCOPE) != 0;
 514     }
 515 
 516     /**
 517      * Get a program point from a descriptor (must be optimistic)
 518      * @param desc descriptor
 519      * @return program point
 520      */
 521     public static int getProgramPoint(final CallSiteDescriptor desc) {
 522         assert isOptimistic(desc) : "program point requested from non-optimistic descriptor " + desc;
 523         return getFlags(desc) >> CALLSITE_PROGRAM_POINT_SHIFT;
 524     }
 525 
 526     boolean isProfile() {
 527         return isFlag(CALLSITE_PROFILE);
 528     }
 529 
 530     boolean isTrace() {
 531         return isFlag(CALLSITE_TRACE);
 532     }
 533 
 534     boolean isTraceMisses() {
 535         return isFlag(CALLSITE_TRACE_MISSES);
 536     }
 537 
 538     boolean isTraceEnterExit() {
 539         return isFlag(CALLSITE_TRACE_ENTEREXIT);
 540     }
 541 
 542     boolean isTraceObjects() {
 543         return isFlag(CALLSITE_TRACE_VALUES);
 544     }
 545 
 546     boolean isOptimistic() {
 547         return isFlag(CALLSITE_OPTIMISTIC);
 548     }
 549 
 550     @Override
 551     public CallSiteDescriptor changeMethodTypeInternal(final MethodType newMethodType) {
 552         return get(getLookupPrivileged(), getOperation(), newMethodType, flags);
 553     }
 554 }