openjdk.ruOpenJDK на русском

JEP 306: Restore Always-Strict Floating-Point Semantics

Возврат к всегда строгой семантике операций с плавающей точкой

ОтветственныйJoe Darcy
ТипFeature
ОбластьSE
СтатусClosed / Delivered
Выпуск17
Компонентspecification / language
Обсуждениеhotspot dash dev at openjdk dot java dot net, core dash libs dash dev at openjdk dot java dot net
ТрудоёмкостьM
ДлительностьS
РецензентыBrian Goetz, John Rose, Mikael Vidstedt
ОдобренMikael Vidstedt
Создан2017/02/27 15:51
Обновлён2024/01/03 01:48
Задача8175916

Аннотация

Сделать операции с плавающей точкой всегда строгими вместо того, чтобы иметь одновременно строгую семантику операций с плавающей точкой (strictfp) и немного отличающуюся от неё семантику по умолчанию. Так в язык и VM вернётся исходная семантика операций с плавающей точкой — та, что действовала до появления строгого режима и режима по умолчанию в Java SE 1.2.

Цели

  • Упростить разработку библиотек, чувствительных к точности численных вычислений, в том числе java.lang.Math и java.lang.StrictMath.

  • Сделать более единообразным один из непростых аспектов платформы.

Что не является целью

Определять какой-либо «fast-fp» или «loose-fp» (ср. JSR 84: Floating Point Extensions) не является целью.

Мотивация

В конце 1990-х годов семантику операций с плавающей точкой по умолчанию на платформе изменили из-за неудачного взаимодействия исходной семантики языка Java и JVM с некоторыми досадными особенностями набора инструкций сопроцессора x87 популярной архитектуры x86. Чтобы точно соблюдать семантику операций с плавающей точкой во всех случаях, включая субнормальные операнды и результаты, требовались большие накладные расходы на дополнительные инструкции. Совпадения результатов при отсутствии переполнения или потери значимости можно было добиться с гораздо меньшими накладными расходами, и примерно это допускает пересмотренная семантика операций с плавающей точкой по умолчанию, введённая в Java SE 1.2.

Однако расширения SSE2 (Streaming SIMD Extensions 2), которые появились в процессорах Pentium 4 и более поздних примерно с 2001 года, позволяли поддерживать строгие операции с плавающей точкой JVM простым способом и без чрезмерных накладных расходов.

Поскольку и Intel, и AMD давно поддерживают SSE2 и более поздние расширения, которые естественным образом обеспечивают строгую семантику операций с плавающей точкой, технической причины иметь семантику по умолчанию, отличную от строгой, больше нет.

Описание

Этот JEP затронет Java Language Specification в части выражений с плавающей точкой (см. разделы JLS 4.2.3 Floating-Point Types, Formats, and Values, 5.1.13 *Value Set Conversion, 15.4 FP-strict Expressions, множество небольших изменений в других разделах далее в главе 15) и аналогичные разделы Java Virtual Machine Specification (JVMS 2.3.2 Floating-Point Types, Values Sets, and Values, раздел 2.8.2 Floating-Point Modes, 2.8.3 Value Set Conversion и множество небольших изменений в описаниях отдельных инструкций с плавающей точкой). Понятия наборов значений и преобразования наборов значений будут удалены из JLS и JVMS. Изменения реализации в JDK будут включать доработку виртуальной машины HotSpot, чтобы она никогда не работала в режиме операций с плавающей точкой, допускающем набор значений с расширенной экспонентой (наличие такого режима обязательно для операций strictfp), и доработку javac, чтобы он выдавал новые lint-предупреждения о лишнем использовании модификатора strictfp.

Тестирование

Все существующие численные тесты после этого изменения останутся корректными, поскольку в нём всегда используется один из режимов работы, допустимых сейчас.

Существующие тесты на исходном коде Java, использующие strictfp, можно продублировать без этого модификатора.

Риски и допущения

Предлагаемые изменения спецификаций несут низкий риск: в основном удаляется текст и обновляются обзорные разделы об операциях с плавающей точкой в JLS и JVMS. Восстанавливается исходная семантика платформы, а реализация только строгого режима всегда была допустимым вариантом. Поэтому риск нарушения совместимости поведения из-за изменений этого JEP пренебрежимо мал. Даже на платформах, где могло происходить нестрогое выполнение, не было приёма, чтобы принудительно включить нестрогое вычисление. Чтобы быть надёжным, код всегда должен был корректно работать при строгом выполнении, которое снова станет единственным вариантом.