JEP draft: unboxed argument lists for method handles
списки аргументов без упаковки для method handles
| Ответственный | John Rose |
| Тип | Feature |
| Область | JDK |
| Статус | Draft |
| Компонент | core-libs / java.lang.invoke |
| Создан | 2017/06/26 06:28 |
| Обновлён | 2017/06/26 06:31 |
| Задача | 8182862 |
Аннотация
Добавить в java.lang.invoke точки API для работы со списками аргументов без упаковки.
Цели
Типичная задача при работе с java.lang.invoke — преобразование вызовов, которые работают со списками аргументов переменной длины, особенно типа Object[] или List<Object>. Такие списки часто служат динамически типизированной заменой более строго типизированного набора аргументов, который может описываться MethodType. Однородный список аргументов на основе ссылок упаковывает примитивы, а в будущем будет упаковывать и value types. Эта упаковка, как и сам содержащий аргументы массив, снижает эффективность.
Коренная причина неэффективности — несоответствие между тем, чем на самом деле является список аргументов, и оболочкой (однородным массивом или списком), в которой он передаётся. Мы устраним эту неэффективность, добавив новый value-based класс ArgumentList, который будет полиморфно «упаковывать» любой допустимый список аргументов в один узел в куче.
Когда появятся value types, этот класс может быть преобразован в интерфейс, реализуемый value types. Это позволит буферизовать произвольные списки аргументов на стеке без какой-либо активности в куче.
Критерии успеха
В случае успеха эта возможность позволит программистам, для которых важна производительность, использовать ArgumentList вместо однородных списков или массивов при работе с сигнатурным полиморфизмом method handles.
Эта возможность также будет полезна как вспомогательный тип для ad hoc наборов значений данных, например тех, что создаются API «экстракторов» (extractor) для Pattern Matching (сопоставление с образцом), которые сейчас разрабатываются.
Мотивация
Проектирование новых API на основе method handles (например, для Pattern Matching) иногда блокируется или ограничивается потерями производительности из-за упаковки групп из нескольких значений. По мере распространения value types упаковки станет больше.
Существующий код, использующий method handles, в некоторых случаях можно сделать эффективнее, если заменить упакованные массивы varargs альтернативами без упаковки (или с минимальной упаковкой).
Более удачная оболочка для списка аргументов позволит нам разработать более эффективные механизмы «varargs» для языка Java. (Набросок приведён ниже, но он не входит в этот JEP.)
Описание
Тип ArgumentList — это либо value-based класс, либо интерфейс к семейству закрытых value-based классов.
Экземпляр списка аргументов представляет неизменный набор из не более чем 255 значений, каждое из которых соответствует связанному с ним (неизменному) типу времени выполнения (объекту java.lang.Class).
API списка аргументов позволяет извлекать отдельные аргументы как со статическими, так и с динамическими типами. Динамическую типизацию обеспечивает представление типа List<Object>, с помощью которого также можно получить массив ссылок на объекты, возможно упакованные. Статическая типизация реализуется через method handles.
Вложенный тип ArgumentList.Type предоставляет API для запроса типа списка аргументов. Между различными типами списков аргументов и MethodType существует взаимно однозначное (1-1) соответствие, если не учитывать возвращаемые типы. (По соглашению возвращаемым типом считается void.) Каждый тип списка аргументов предоставляет список method handles, рассчитанных на экземпляры ArgumentList этого типа, чтобы эффективно извлекать каждый аргумент из списка аргументов без накладных расходов на упаковку, которых требует динамически типизированное представление.
Тип списка аргументов также предоставит method handle для эффективного сбора списка аргументов (соответствующих статических типов) в экземпляр ArgumentList.
Для точек API в java.lang.invoke, которые сейчас работают со списками аргументов переменной арности (invokeWithArguments, asSpreader) или с другими группами аргументов (insertArguments), появятся дополнительные точки API, работающие с параметрами ArgumentList, как альтернатива существующим API в стиле varargs.
Также будут предоставлены один или несколько фабричных методов для списков аргументов. Это публичные точки API, с помощью которых можно создавать списки аргументов с произвольными типами компонентов, заданными пользователем. Такие точки API будут сигнатурно полиморфными в том же смысле, в каком сигнатурно полиморфны точки вызова MethodHandle и VarHandle. Вероятно, такой точкой API будет ArgumentList.of.
Возможные будущие расширения varargs
В одном из последующих JEP сам механизм varargs в языке Java может быть доработан, чтобы разрешить полиморфные вызовы с разнородными списками аргументов — включая полный сигнатурный полиморфизм, которым обладают API method handles, а также более ограниченные шаблоны, например чередующийся список аргументов ключ/значение для фабричного метода Map.
Ключевая идея здесь в том, что точка API с переменной арностью должна задавать для группы аргументов и внутренний тип, и внешний способ объединения. Внутренний тип — это то, что метод «видит» после вызова, а внешний способ объединения используется вызывающей стороной, чтобы собрать полиморфно типизированную группу аргументов в один аргумент. Кроме того, invokedynamic может играть роль посредника.
В текущем состоянии языка Java внутренний тип обязан быть типом массива, а способом объединения обязано быть создание нового массива этого типа. Эти процедуры можно и нужно обобщить.
Сигнатурно полиморфная точка API для построения списков аргументов (предлагаемая в этом JEP) — это исходный строительный блок для способа объединения varargs, и такие способы объединения можно строить также поверх других способов объединения. В итоге разработчики библиотек и даже конечные пользователи смогут создавать новые виды строго типизированных обобщённых точек API с переменной арностью.
Возможное использование с комбинаторами Pattern Matching
Pattern Matching состоит в том, чтобы исследовать одно значение, сравнить его с заданным пользователем шаблоном и дать ответ «да», если оно совпадает. Ответ «да» может сопровождаться набором значений диапазона (range values), извлечённых из тех мест шаблона, которые соответствуют «подстановочным знакам» или «связанным переменным». Это также похоже на «группы» регулярных выражений, подстроки которых можно запросить после успешного совпадения.
Объектно-ориентированный API для Pattern Matching должен (каким-то образом) уметь возвращать значения и/или расположение любого числа значений диапазона, выраженных шаблоном. Иногда это возможно с помощью статического набора локаторов (например, method handles), которые «выбирают» значения диапазона из исходного сопоставленного объекта.
Но в общем случае операции Pattern Matching иногда нужно буферизовать значения диапазона в ad hoc кортеж или запись. В общем случае сопоставляемая структура данных может быть изменяемой, и запись должна зафиксировать состояние, которое совпало, несмотря на то что микросекундой позже это состояние может уже не совпадать.
В любом случае ad hoc запись совпавших значений можно в точности представить списком аргументов из этих значений, и её удобно передать следующему вычислению в цепочке простым вызовом invokeWithArguments. Поэтому API списков аргументов, вероятно, станет полезным компонентом универсального API сопоставления.
Риски и допущения
Совместимое расширение API java.lang.invoke с низким риском.
Есть небольшой риск, что путь развития — от класса объектов к интерфейсу и далее к полиморфному value-классу — окажется заблокирован. В худшем случае придётся добавить новый value type, взаимно преобразуемый с классом объектов ArgumentList. Это риск того же рода, что и у java.lang.Integer и java.util.Optional с появлением value types.
Зависимости
Нет.