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