Вопрос про invokedynamic
От: elw00d Россия http://elwood.su
Дата: 27.05.15 09:15
Оценка:
Разбираюсь с сабжем, и непонятно вот что. Везде пишут, что invokedynamic — это изобретение в первую очередь для поддержки динамических вызовов. То есть например мы — разработчики компилятора/рантайма какого-то динамического языка. И у нас есть код навроде

var a = getSomeA(); // Тип переменной a заранее не известен
var b = getSomeB(); // Тип переменной b тоже заранее не известен
a.foo(123); // Дёргаем метод a.foo(int), если таковой имеется у объекта a
a.foo(b); // Дёргаем метод a.foo(type(b)), если таковой имеется


То есть при компиляции мы не знаем типов ни вызывающего объекта, ни аргументов. Как же в таком случае нам поможет инструкция invokedynamic, если первым её параметром в байт-коде является ссылка на константу InvokeDynamic в пуле констант. А константа InvokeDynamic в свою очередь ссылается на bootstrap method и на константу NameAndType.

В случае статически типизированных лямбд всё понятно:

Constant pool:
#5 = InvokeDynamic      #0:#41         // #0:apply:()Ljava/util/function/Function;
#41 = NameAndType        #59:#60        // apply:()Ljava/util/function/Function;
#59 = Utf8               apply
#60 = Utf8               ()Ljava/util/function/Function;

BootstrapMethods:
  0: #37 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #38 (Ljava/lang/Object;)Ljava/lang/Object;
      #39 invokestatic org/jcoro/Test.lambda$foo$2:(Ljava/lang/Integer;)Ljava/lang/Boolean;
      #40 (Ljava/lang/Integer;)Ljava/lang/Boolean;

public static void foo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=0
         0: new           #2                  // class java/util/ArrayList
         3: dup
         4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
         7: astore_0
         8: aload_0
         9: invokeinterface #4,  1            // InterfaceMethod java/util/List.stream:()Ljava/util/stream/Stream;
        14: invokedynamic #5,  0              // InvokeDynamic #0:apply:()Ljava/util/function/Function;
        19: invokeinterface #6,  2            // InterfaceMethod java/util/stream/Stream.map:(Ljava/util/function/Function;)Ljava/util/stream/Stream;
        24: invokestatic  #7                  // Method java/util/stream/Collectors.toList:()Ljava/util/stream/Collector;
        27: invokeinterface #8,  2            // InterfaceMethod java/util/stream/Stream.collect:(Ljava/util/stream/Collector;)Ljava/lang/Object;
        32: pop
        33: return
      LineNumberTable:
        line 13: 0
        line 14: 8
        line 16: 24
        line 17: 33
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            8      26     0  list   Ljava/util/List;
      LocalVariableTypeTable:
        Start  Length  Slot  Name   Signature
            8      26     0  list   Ljava/util/List<Ljava/lang/Integer;>;

private static java.lang.Boolean lambda$foo$2(java.lang.Integer);
...


А как это поможет в создании рантайма для динамически типизированных языков ? Ведь NameAndType фиксирован даже не как _аргумент_ инструкции (который можно на стек положить в зависимости от типа), а как параметр инструкции в байткоде ! То есть вот написали метод, который делает invokeDynamic для указанного типа+имени метода. А если тип другой ? И в каком месте выполнять свич по типам аргументов, фактически переданных методу ?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.