src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java

Print this page




2196      *
2197      * @return the method emitter
2198      */
2199     MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
2200         debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
2201         final String signature = getDynamicSignature(returnType, request.getArity());
2202         debug("   signature", signature);
2203         method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
2204         pushType(returnType);
2205 
2206         return this;
2207     }
2208 
2209     /**
2210      * Generate dynamic getter. Pop scope from stack. Push result
2211      *
2212      * @param valueType type of the value to set
2213      * @param name      name of property
2214      * @param flags     call site flags
2215      * @param isMethod  should it prefer retrieving methods
2216      *
2217      * @return the method emitter
2218      */
2219     MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
2220         if (name.length() > LARGE_STRING_THRESHOLD) { // use getIndex for extremely long names
2221             return load(name).dynamicGetIndex(valueType, flags, isMethod);
2222         }
2223 
2224         debug("dynamic_get", name, valueType, getProgramPoint(flags));
2225 
2226         Type type = valueType;
2227         if (type.isObject() || type.isBoolean()) {
2228             type = Type.OBJECT; //promote e.g strings to object generic setter
2229         }
2230 
2231         popType(Type.SCOPE);
2232         method.visitInvokeDynamicInsn((isMethod ? "dyn:getMethod|getProp|getElem:" : "dyn:getProp|getElem|getMethod:") +
2233                 NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
2234 
2235         pushType(type);
2236         convert(valueType); //most probably a nop
2237 
2238         return this;
2239     }
2240 
2241     /**
2242      * Generate dynamic setter. Pop receiver and property from stack.
2243      *
2244      * @param name  name of property
2245      * @param flags call site flags

2246      */
2247     void dynamicSet(final String name, final int flags) {
2248         if (name.length() > LARGE_STRING_THRESHOLD) { // use setIndex for extremely long names
2249             load(name).swap().dynamicSetIndex(flags);
2250             return;
2251         }
2252 
2253         assert !isOptimistic(flags);
2254         debug("dynamic_set", name, peekType());
2255 
2256         Type type = peekType();
2257         if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
2258             type = Type.OBJECT;
2259             convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
2260         }
2261         popType(type);
2262         popType(Type.SCOPE);
2263 
2264         method.visitInvokeDynamicInsn("dyn:setProp|setElem:" + NameCodec.encode(name), methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);

2265     }
2266 
2267      /**
2268      * Dynamic getter for indexed structures. Pop index and receiver from stack,
2269      * generate appropriate signatures based on types
2270      *
2271      * @param result result type for getter
2272      * @param flags call site flags for getter
2273      * @param isMethod should it prefer retrieving methods
2274      *
2275      * @return the method emitter
2276      */
2277     MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) {
2278         assert result.getTypeClass().isPrimitive() || result.getTypeClass() == Object.class;
2279         debug("dynamic_get_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags));
2280 
2281         Type resultType = result;
2282         if (result.isBoolean()) {
2283             resultType = Type.OBJECT; // INT->OBJECT to avoid another dimension of cross products in the getters. TODO
2284         }
2285 
2286         Type index = peekType();
2287         if (index.isObject() || index.isBoolean()) {
2288             index = Type.OBJECT; //e.g. string->object
2289             convert(Type.OBJECT);
2290         }
2291         popType();
2292 
2293         popType(Type.OBJECT);
2294 
2295         final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index);
2296 
2297         method.visitInvokeDynamicInsn(isMethod ? "dyn:getMethod|getElem|getProp" : "dyn:getElem|getProp|getMethod", signature, LINKERBOOTSTRAP, flags);
2298         pushType(resultType);
2299 
2300         if (result.isBoolean()) {
2301             convert(Type.BOOLEAN);
2302         }
2303 
2304         return this;
2305     }
2306 
2307     private static String getProgramPoint(final int flags) {
2308         if((flags & CALLSITE_OPTIMISTIC) == 0) {
2309             return "";
2310         }
2311         return "pp=" + String.valueOf((flags & (-1 << CALLSITE_PROGRAM_POINT_SHIFT)) >> CALLSITE_PROGRAM_POINT_SHIFT);
2312     }
2313 
2314     /**
2315      * Dynamic setter for indexed structures. Pop value, index and receiver from
2316      * stack, generate appropriate signature based on types
2317      *


2489         while(next != null) {
2490             final Symbol symbol = next.getSymbol();
2491             if(next.isLive()) {
2492                 emitLocalVariableConversion(next, true);
2493             } else {
2494                 markDeadLocalVariable(symbol);
2495             }
2496             next = next.getNext();
2497         }
2498     }
2499 
2500     void beforeTry(final TryNode tryNode, final Label recovery) {
2501         LocalVariableConversion next = tryNode.getLocalVariableConversion();
2502         while(next != null) {
2503             if(next.isLive()) {
2504                 final Type to = emitLocalVariableConversion(next, false);
2505                 recovery.getStack().onLocalStore(to, next.getSymbol().getSlot(to), true);
2506             }
2507             next = next.getNext();
2508         }












2509     }
2510 
2511     private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) {
2512         final Type from = conversion.getFrom();
2513         final Type to = conversion.getTo();
2514         final Symbol symbol = conversion.getSymbol();
2515         assert symbol.isBytecodeLocal();
2516         if(from == Type.UNDEFINED) {
2517             loadUndefined(to);
2518         } else {
2519             load(symbol, from).convert(to);
2520         }
2521         store(symbol, to, onlySymbolLiveValue);
2522         return to;
2523     }
2524 
2525     /*
2526      * Debugging below
2527      */
2528 




2196      *
2197      * @return the method emitter
2198      */
2199     MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
2200         debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
2201         final String signature = getDynamicSignature(returnType, request.getArity());
2202         debug("   signature", signature);
2203         method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
2204         pushType(returnType);
2205 
2206         return this;
2207     }
2208 
2209     /**
2210      * Generate dynamic getter. Pop scope from stack. Push result
2211      *
2212      * @param valueType type of the value to set
2213      * @param name      name of property
2214      * @param flags     call site flags
2215      * @param isMethod  should it prefer retrieving methods
2216      * @param isIndex   is this an index operation?
2217      * @return the method emitter
2218      */
2219     MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod, final boolean isIndex) {
2220         if (name.length() > LARGE_STRING_THRESHOLD) { // use getIndex for extremely long names
2221             return load(name).dynamicGetIndex(valueType, flags, isMethod);
2222         }
2223 
2224         debug("dynamic_get", name, valueType, getProgramPoint(flags));
2225 
2226         Type type = valueType;
2227         if (type.isObject() || type.isBoolean()) {
2228             type = Type.OBJECT; //promote e.g strings to object generic setter
2229         }
2230 
2231         popType(Type.SCOPE);
2232         method.visitInvokeDynamicInsn(dynGetOperation(isMethod, isIndex) + ':' + NameCodec.encode(name),
2233                 Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
2234 
2235         pushType(type);
2236         convert(valueType); //most probably a nop
2237 
2238         return this;
2239     }
2240 
2241     /**
2242      * Generate dynamic setter. Pop receiver and property from stack.
2243      *
2244      * @param name  name of property
2245      * @param flags call site flags
2246      * @param isIndex is this an index operation?
2247      */
2248     void dynamicSet(final String name, final int flags, final boolean isIndex) {
2249         if (name.length() > LARGE_STRING_THRESHOLD) { // use setIndex for extremely long names
2250             load(name).swap().dynamicSetIndex(flags);
2251             return;
2252         }
2253 
2254         assert !isOptimistic(flags);
2255         debug("dynamic_set", name, peekType());
2256 
2257         Type type = peekType();
2258         if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
2259             type = Type.OBJECT;
2260             convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
2261         }
2262         popType(type);
2263         popType(Type.SCOPE);
2264 
2265         method.visitInvokeDynamicInsn(dynSetOperation(isIndex) + ':' + NameCodec.encode(name),
2266                 methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
2267     }
2268 
2269      /**
2270      * Dynamic getter for indexed structures. Pop index and receiver from stack,
2271      * generate appropriate signatures based on types
2272      *
2273      * @param result result type for getter
2274      * @param flags call site flags for getter
2275      * @param isMethod should it prefer retrieving methods
2276      *
2277      * @return the method emitter
2278      */
2279     MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) {
2280         assert result.getTypeClass().isPrimitive() || result.getTypeClass() == Object.class;
2281         debug("dynamic_get_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags));
2282 
2283         Type resultType = result;
2284         if (result.isBoolean()) {
2285             resultType = Type.OBJECT; // INT->OBJECT to avoid another dimension of cross products in the getters. TODO
2286         }
2287 
2288         Type index = peekType();
2289         if (index.isObject() || index.isBoolean()) {
2290             index = Type.OBJECT; //e.g. string->object
2291             convert(Type.OBJECT);
2292         }
2293         popType();
2294 
2295         popType(Type.OBJECT);
2296 
2297         final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index);
2298 
2299         method.visitInvokeDynamicInsn(dynGetOperation(isMethod, true), signature, LINKERBOOTSTRAP, flags);
2300         pushType(resultType);
2301 
2302         if (result.isBoolean()) {
2303             convert(Type.BOOLEAN);
2304         }
2305 
2306         return this;
2307     }
2308 
2309     private static String getProgramPoint(final int flags) {
2310         if((flags & CALLSITE_OPTIMISTIC) == 0) {
2311             return "";
2312         }
2313         return "pp=" + String.valueOf((flags & (-1 << CALLSITE_PROGRAM_POINT_SHIFT)) >> CALLSITE_PROGRAM_POINT_SHIFT);
2314     }
2315 
2316     /**
2317      * Dynamic setter for indexed structures. Pop value, index and receiver from
2318      * stack, generate appropriate signature based on types
2319      *


2491         while(next != null) {
2492             final Symbol symbol = next.getSymbol();
2493             if(next.isLive()) {
2494                 emitLocalVariableConversion(next, true);
2495             } else {
2496                 markDeadLocalVariable(symbol);
2497             }
2498             next = next.getNext();
2499         }
2500     }
2501 
2502     void beforeTry(final TryNode tryNode, final Label recovery) {
2503         LocalVariableConversion next = tryNode.getLocalVariableConversion();
2504         while(next != null) {
2505             if(next.isLive()) {
2506                 final Type to = emitLocalVariableConversion(next, false);
2507                 recovery.getStack().onLocalStore(to, next.getSymbol().getSlot(to), true);
2508             }
2509             next = next.getNext();
2510         }
2511     }
2512 
2513     private static String dynGetOperation(final boolean isMethod, final boolean isIndex) {
2514         if (isMethod) {
2515             return isIndex ? "dyn:getMethod|getElem|getProp" : "dyn:getMethod|getProp|getElem";
2516         } else {
2517             return isIndex ? "dyn:getElem|getProp|getMethod" : "dyn:getProp|getElem|getMethod";
2518         }
2519     }
2520 
2521     private static String dynSetOperation(final boolean isIndex) {
2522         return isIndex ? "dyn:setElem|setProp" : "dyn:setProp|setElem";
2523     }
2524 
2525     private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) {
2526         final Type from = conversion.getFrom();
2527         final Type to = conversion.getTo();
2528         final Symbol symbol = conversion.getSymbol();
2529         assert symbol.isBytecodeLocal();
2530         if(from == Type.UNDEFINED) {
2531             loadUndefined(to);
2532         } else {
2533             load(symbol, from).convert(to);
2534         }
2535         store(symbol, to, onlySymbolLiveValue);
2536         return to;
2537     }
2538 
2539     /*
2540      * Debugging below
2541      */
2542