Comments 15
Ох, не надо, пусть indy остается только для лямбд — там фиксированный шаблон, можно статически скомпилировать, все хорошо. А то ведь произвольный indy — ад для AOT компиляторов. :(
Но это так, о наболевшем. :)
Почему ад? Можно же просто вставлять в соответствующих местах вызов JIT...
Ну так напиши в мейлинг-лист о своём наболевшем :-) Как я понимаю, AOT-компиляция Oracle тоже интересует.
не совсем понятно как один статический MULT заменяет несколько статических полей, каждое упоминание MULT создает новое поле?
Каждое упоминание Intrinsics.invokedynamic
вставляет инструкцию invokedynamic
, а она уже сохраняет точку вызова, привязанную к конкретному месту в байткоде, что по большому счёту есть лениво инициализируемое статическое поле в этом классе.
MULT для удобства сделан, можно его заинлайнить в точки использования, эффект будет тот же, только ещё больше энтерпрайза.
К сожалению, в подобном сценарии использования это все равно неприменимо. Ну не буду же я везде писать "(BigInteger) Intrinsics.invokedynamic(MULT, "foo", bigNum, bigNum)"! А вынести в метод нельзя.
Да, в текущем прототипе есть такая проблема. Но ведь никто не сказал, что так и будет всегда. Если есть идеи лучше, высказывайтесь в мейлинг-листе! От Intrinsics.
уже сейчас легко избавиться статическим импортом. Я пытаюсь протолкнуть мысль, что BootstrapSpecifier
может быть параметризован возвращаемым типом, и тогда удастся обойтись без каста, что уже полдела. Пока не проталкивается.
Так даже "invokedynamic(MULT, "foo", bigNum, bigNum)" не выглядит хорошим для пользовательского кода. Так что я считаю что пока не будет чего-то подобного async из c# (т.е. что полная сигнатура метода при реализации одна, а при вызове другая) особого улучшения от возможности писать indy через джаву не появится. Основной плюс данной инструкции именно в том, что можно во многих разных местах кода получить разный CallSite. А если таких мест всего 2-3, то я и руками могу разные методы вызвать.
Т.е. я говорю про что-нибудь в духе
//в библиотеке
bootstrap public static CallSite multiplyFactory(MethodHandles.Lookup lookup, String name, MethodType type) {
return new MultiplyCallSite(type);
}
//а вызывать в коде его как будто это простой метод:
BigInteger res = multiplyFactory(num1, num2);
Но такой штуки не будет абсолютно точно (как минимум, совершенно неясно откуда брать сигнатуру метода).
Ну методы с полиморфной сигнатурой уже существуют. Если разрешить определять такие пользовательские методы и инлайнить их во время компиляции, то можно как-то это решить. Понятно, что красивое решение придумать сложно. Но вот задача сообщества в том и состоит, чтобы придумывать красивые решения и продавливать их.
Полиморфная сигнатура — это все-таки другое. Там я могу вызвать метод с любыми аргументами и он просто так будет записан. Здесь же мне нужна конкретная сигнатура. Разве что добавить еще аннотацию.
@MethodSignature(parameterTypes = {long.class, long.class}, returnType = BigInteger.class)
В данном случае, если вы требуете конкретную сигнатуру, как раз лучше сделать инлайнинг, чем мутные аннотации:
inline BigInteger multiply(long x, long y) throws Throwable {
return (BigInteger)Intrinsics.invokedynamic(MULT, "foo", x, y);
}
Однако часть рулезности invokedynamic ещё и в самой полиморфной сигнатуре. К примеру то самое, о чём я писал — если переданы два инта, то можно дополнительно оптимизировать, а здесь получится, что они сразу расширятся до лонгов.
Если уж сравнивать с C#, то не с async
, а с dynamic
надо сравнивать...
Что там с JEP-303 или изобретаем invokedynamic