Главные 64-разрядные изменения

Когда различные части кода должны сотрудничать, они должны следовать, стандарт согласовал соглашения о том, как должен действовать код. Соглашения включают размер и формат типов общих данных, а также инструкции, используемые, когда одна часть кода вызывает другого. Компиляторы реализованы на основе этих соглашений так, чтобы они могли испустить сотрудничающий двоичный код. Коллективно, эти соглашения упоминаются как двоичный интерфейс приложений (ABI).

приложения для iOS полагаются на низкоуровневый двоичный интерфейс приложений и соглашения кодирования, установленные языком Objective C и системными платформами. Начиная с iOS 7 некоторые устройства на iOS используют 64-разрядные процессоры и предлагают и 32-разрядное и 64-разрядную среду выполнения. Для большинства приложений 64-разрядная среда выполнения отличается от 32-разрядной среды выполнения двумя значительными способами:

Изменения в типах данных

В C и языках Objective C, встроенные типы данных не имеют предопределенного размера или выравнивания в памяти. Вместо этого каждая платформа определяет характеристики встроенных типов. Это означает, что, в ограничениях, определенных в стандарте языка, платформа может использовать значения, лучше всего соответствующие используемое оборудование и операционную систему. 64-разрядное время выполнения на iOS изменяет размеры многих встроенных типов данных. В более высоком уровне также изменились много типов данных, используемых Сенсорными платформами Какао. В этом разделе описываются изменения в типах данных, обычно используемых в коде Objective C.

Два соглашения: ILP32 и LP64

32-разрядное время выполнения использует соглашение под названием ILP32, в который целые числа, long целые числа и указатели являются 32-разрядными количествами. 64-разрядное время выполнения использует соглашение LP64; целые числа являются 32-разрядными количествами, и long целые числа и указатели являются 64-разрядными количествами. Эти соглашения соответствуют ABI для приложений, работающих на OS X (и точно так же Сенсорные соглашения Какао соответствуют типы данных, используемые в Какао), упрощая писать взаимодействующий код между этими двумя операционными системами.

Таблица 1-1 описывает все целые типы, обычно используемые в коде Objective C. Каждая запись включает размер типа данных и его ожидаемого выравнивания в памяти. Выделенные записи таблицы указывают места, где соглашение LP64 отличается от соглашения ILP32. Эти различия в размере указывают места, где поведение Вашего кода изменяется, когда скомпилировано в течение 64-разрядного времени выполнения. Компилятор определяет __LP64__ макрос при компиляции в течение 64-разрядного времени выполнения.

Табличный 1-1  Размер и выравнивание целочисленных типов данных в OS X и iOS

Целочисленный тип данных

Размер ILP32

Выравнивание ILP32

Размер LP64

Выравнивание LP64

char

1 байт

1 байт

1 байт

1 байт

BOOL, bool

1 байт

1 байт

1 байт

1 байт

short

2 байта

2 байта

2 байта

2 байта

int

4 байта

4 байта

4 байта

4 байта

long

4 байта

4 байта

8 байтов

8 байтов

long long

8 байтов

4 байта

8 байтов

8 байтов

указатель

4 байта

4 байта

8 байтов

8 байтов

size_t

4 байта

4 байта

8 байтов

8 байтов

time_t

4 байта

4 байта

8 байтов

8 байтов

NSInteger

4 байта

4 байта

8 байтов

8 байтов

CFIndex

4 байта

4 байта

8 байтов

8 байтов

fpos_t

8 байтов

4 байта

8 байтов

8 байтов

off_t

8 байтов

4 байта

8 байтов

8 байтов

Суммировать изменения:

  • Размер указателей увеличился с 4 байтов до 8 байтов.

  • Размер long целые числа увеличились с 4 байтов до 8 байтов. size_t, CFIndex, и NSInteger типы также увеличились с 4 байтов до 8 байтов.

  • Выравнивание long long целые числа и типы данных на основе его (fpos_t, off_t) увеличился с 4 байтов до 8 байтов. Все другие типы используют естественное выравнивание, означая, что элементы данных в структуре выровненные с промежутками соответствие ширине базового типа данных.

Таблица 1-2 показывает типы с плавающей точкой, обычно используемые в iOS и OS X. Несмотря на то, что встроенные типы данных не изменяются в размере в 64-разрядное время выполнения CGFloat введите изменения от a float к a double, обеспечение большего диапазона и точности для этих значений в Кварце и в других платформах, использующих Базовые Графические типы. (Типы с плавающей точкой всегда используют естественное выравнивание.)

Табличный 1-2  Размер типов данных с плавающей точкой в OS X и iOS

Тип с плавающей точкой

Размер ILP32

Размер LP64

float

4 байта

4 байта

double

8 байтов

8 байтов

CGFloat

4 байта

8 байтов

64-разрядная среда ARM использует среду с прямым порядком байтов; это соответствует 32-разрядное время выполнения iOS, используемое устройствами с процессорами ARM, поддерживающими архитектуру ARMv7.

Влияние типа данных изменяется на Вашем приложении

Когда Вы компилируете свое приложение и для 32-разрядных и для 64-разрядных сред выполнения, имеете в виду, что поведение Вашего приложения отличается согласно среде, это работает в и может привести к различиям в производительности или серьезным проблемам совместимости. Вот некоторые вещи, которые необходимо рассмотреть:

  • Увеличенное давление памяти

    Поскольку столько фундаментальных типов увеличилось в размере, 64-разрядная версия Вашего приложения использует больше памяти, чем 32-разрядная версия. Например, даже что-то столь простое, как связанный список является более дорогим, когда скомпилировано в течение 64-разрядного времени выполнения. Ожидайте проводить больше времени, оптимизируя производительность 64-разрядной версии Вашего приложения. Вы, возможно, также должны рассмотреть различные стратегии при разработке структур данных приложения, включая переменные экземпляра, используемые в классах Objective C. Для некоторых примеров посмотрите Производительность Памяти Оптимизации.

  • Обмен данными между 64-разрядным и 32-разрядным программным обеспечением

    При поставке и 32-разрядного и 64-разрядного программного обеспечения иногда обе версии должны взаимодействовать на тех же данных. Например, пользователь мог бы получить доступ к файлу, хранившему в iCloud и от 32-разрядных и от 64-разрядных устройств. Или Вы могли бы создавать игру, отправляющую сетевые данные между устройствами. В оба времени выполнения удостоверьтесь, что считанные данные или записанное использование расположение общей памяти, означая, что размеры и смещения каждого элемента данных идентичны.

  • Вычисления могли бы привести к различным результатам

    64-разрядное целое число поддерживает значительно больший диапазон возможных значений, чем 32-разрядное целое число поддерживает. Если Ваше приложение использует целый тип, изменившийся с 32 битов до 64 битов, результаты могли бы отличаться в 64-разрядной версии Вашего приложения. В частности, вычисление, превышающее максимальное значение 32-разрядные целочисленные переполнения на 32-разрядном целом числе, но не на 64-разрядном целом числе. Другие такие граничные случаи существуют.

  • Когда данные копируются от большего типа данных до меньшего типа данных, значения могут быть усеченными

    Некоторые приложения предполагают, что два типа данных являются тем же вместо того, чтобы безопасно преобразовать между ними. В 64-разрядное время выполнения предыдущие предположения о типах данных больше могут не быть корректными. Например, присвоение NSInteger оцените int введите работы в 32-разрядное время выполнения, потому что оба типа являются 32-разрядными целыми числами. Но в 64-разрядное время выполнения, эти два не являются тем же типом и таким образом, могут быть потеряны данные.

Изменения в функциональном вызове

Когда вызов функции сделан, компилятор испускает код для передачи параметров от вызывающей стороны до вызываемого. Например, ABI мог бы указать, что вызывающая сторона помещает свои параметры в регистры, или она могла бы указать, что вызывающая сторона продвигает значения на штабель в памяти. Обычно, если Вы не пишете ассемблер, соглашения о вызовах редко важны. Но в 64-разрядное время выполнения, иногда необходимо знать, как вызваны функции. Функции, принимающие переменное число параметров (variadic функции) вызваны с помощью различного набора соглашений, чем вызовы к функциям, принимающим фиксированный набор параметров.

Влияние вызова функции изменяется на Вашем приложении

При кодировании приложения, предназначающегося для 64-разрядного времени выполнения, приложение должно всегда вызывать функцию с помощью своего точного определения. В результате:

  • Каждая функция должна иметь прототип.

  • При кастинге функции необходимо быть осторожными, что версия броска функции имеет ту же подпись как исходная функция. В частности избегите бросать функцию к форме, берущей различный набор параметров (таких как кастинг указателя функции, берущего variadic образец к тому, берущему постоянное число параметров). Если Ваш код непосредственно вызывает функции передачи сообщений во время выполнения Objective C, дополнительные правила применяются. (См., что сообщения Objective C Отгрузки Используют Прототип Функции Метода.)

Изменения в Objective C

Если Вы пишете низкоуровневый код, предназначающийся для времени выполнения Objective C непосредственно, Вы больше не можете получать доступ к объекту isa указатель непосредственно. Вместо этого необходимо использовать функции времени выполнения для доступа к той информации.

Другие изменения в 64-разрядном времени выполнения

64-разрядная система команд ARM существенно отличается от 32-разрядной системы команд. Если Ваше приложение включает какой-либо код ассемблера, необходимо переписать его для использования новой системы команд. Вам также нужно более подробное описание 64-разрядных соглашений о вызовах в iOS, потому что соглашения точно не соответствуют стандарт ARM. Для получения дополнительной информации посмотрите iOS Руководство по Вызову функции ABI.

Сводка

На высоком уровне, для создания кода 64-разрядным чистый необходимо сделать следующее: