Разница между командой MSIL "ceq" и объектом. InternalEquals - PullRequest
3 голосов
/ 08 марта 2011

Я копался в ILDASM и Reflector и обнаружил, что:

  1. == скомпилировано в команду "ceq"
  2. object.Equals оставлено как есть
  3. object.Equals вызывает object.InternalEquals

Этот вопрос показал мне, как узнать, как InternalEquals может быть реализован, например, в классе .cpp (или где-то ещеCLR).

Мой вопрос:

Чем становится ceq?Другой метод в другом классе .cpp?Т.е. они совершенно разные кусочки кода?Таким образом, хотя поведение по умолчанию == и Equals выглядит одинаково, это другой код?

Ответы [ 3 ]

18 голосов
/ 08 марта 2011

Оператор == не всегда переводится в ceq. Тип может перегрузить его с помощью оператора == (). Например, System.Decimal делает это, перегружая все операторы, поскольку их реализация нетривиальна, а джиттер не имеет специальных знаний о типе (компилятор делает).

Вы найдете его с Reflector как метод Decimal.op_Equality (). Что приводит вас к FCallCompare, методу, который приписывается MethodImplOptions.InternalCall. Эти методы особенные, у джиттера есть секретное знание о них. Вы можете найти их реализацию через файл исходного кода clr / src / vm / ecall.cpp в Rotor. Он содержит таблицу всех внутренних функций вызова, джиттер ищет запись в таблице по имени метода. Затем компилирует адрес соответствующей функции C ++, как указано в таблице, в инструкцию вызова. Помните, что имя функции было изменено с момента выпуска Rotor, найдите FCallAdd, это следующая запись в таблице. Что приводит вас к COMDecimal :: Compare. Что приведет вас к файлу исходного кода comdecimal.cpp.

Jitters x86 и x64 знают, как преобразовать код операции ceq в машинный код напрямую, без использования вспомогательной функции, он генерирует встроенные машинные инструкции. Фактически сгенерированный код зависит от типа сравниваемых значений. И цель, джиттер x64 использует инструкции SSE, x86 использует инструкции FPU для сравнения значений с плавающей запятой. Другие дрожания будут реализовывать их по-другому, но, конечно же.

Вспомогательная функция, такая как Object.InternalEquals (), также является внутренним методом, как и FCallCompare. Вы бы использовали ту же стратегию, чтобы найти реализацию.

4 голосов
/ 08 марта 2011

Вы видите ceq, потому что нет перегруженного == - выполняется прямое сравнение ссылок. Для этого все, что нужно сделать, это напрямую сравнить два числа в стеке; это самое быстрое, что он может сделать.

object.Equals неоднозначен; их два;

x.Equals (y) - это виртуальный метод, поэтому он может быть переопределен. В зависимости от типа будет производиться виртуальный вызов, статический или ограниченный вызов, который может иметь пользовательскую реализацию.

object.Equals (x, y) - статический метод, который сначала проверяет наличие нулей; 2 null = true, 1 null = false, 0 null - вызов x.Equals (y).

Но чтобы сосредоточиться на этом вопросе, логически a == для родных целых чисел; в большинстве JIT я хотел бы надеяться, что это остается == против двух целочисленных типов (возможно, указателей), но JIT различаются (или могут даже не существовать - MF является интерпретатором).

2 голосов
/ 08 марта 2011

Да, они запускают другой код.

  • Equals - это метод экземпляра.
  • == является статическим оператором.

Оба могут быть переопределены для пользовательских типов.

...