В чем разница между командами pop и pop2 в jvm? - PullRequest
0 голосов
/ 21 мая 2018

Я ссылаюсь на приведенный ниже документ Oracle jvm doc

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.pop

pop Операция Pop значение верхнего стека операнда

Формат

pop Forms pop = 87 (0x57)

Стек операнда ..., значение →

...

Описание Извлекает верхнее значение из операндаstack.

Команда pop не должна использоваться, если только значение не является значением вычислительного типа категории 1. (§2.11.1).

pop2 Операция Pop the topодно или два значения стека операндов

Формат

pop2 Формы pop2 = 88 (0x58)

Форма стека операндов 1:

..., value2,value1 →

...

, где каждое из value1 и value2 является значением вычислительного типа категории 1 (§2.11.1).

Форма 2:

..., значение →

...

где значение - это значение вычислительного типа категории 2 (§2.11.1).

ОписаниеВыдвиньте верхнее одно или два значения из стека операндов.

Что означает «извлечение одного или двух верхних значений из стека операндов»?Что будет примером, когда используется pop2?

Ответы [ 3 ]

0 голосов
/ 21 мая 2018

Что означает «извлечение одного или двух верхних значений из стека операндов»?

Подумайте об этом так 1 :

  • Байт-код POP выводит одно значение, которое занимает одно 32-битное словов стеке.

  • Байт-код POP2 либо выводит одно значение, которое занимает два x 32-битных слова, либо два значения, каждое из которых занимает одно x 32-битное слово.

Что может быть примером при использовании POP2?

  1. , получая значение long или double;например, чтобы отменить нежелательный long результат вызова метода или
  2. , извлекая два int значения.

Обратите внимание, что текущего поколения Oracle / OpenJDKjavac компиляторы не выдают POP2 значения pop 2.Если в стеке есть два 32-битных значения, которые нужно вытолкнуть, компилятор выдает две POP инструкции.Итак, я не могу привести пример случая №2 для обычного Java-кода.(Но сторонние компиляторы для Java или других языков могут использовать его. Или люди, создающие байт-коды другим способом.)

Я не знаю достаточно о внутренностях JVM, чтобы быть уверенным, но одна вероятная причина для POP2 вообще означает, что если вы использовали две POP инструкции, чтобы вытолкнуть (скажем) long, то часть пути через последовательность была бы в недопустимом состоянии.Это может вызвать ошибку проверки.


1 - Это не совсем правильно.Значения в стеке не являются строго 32 или 64 битами.Например, адрес ссылки или возврата на 64-битной машине равен 64 битам ... но он по-прежнему моделируется как значение категории 1.Объяснение этому заключается в том, что набор инструкций байт-кода был изначально разработан для интерпретации на 32-битных компьютерах.

0 голосов
/ 29 мая 2018

POP: извлекает верхний элемент из одного слова из стека и удаляет его.

POP2: удаляет два элемента из одного слова из стека (например, два целых числа, или целое число и ссылку на объект) илиодин элемент из двух слов (т. е. двойной или один за другим).

Тот же Javadoc, упомянутый в вопросе, содержит информацию ниже:

Таблица 2.3.Фактические и вычислительные типы в виртуальной машине Java

Actual type Computational type      Category


1. byte             int               1
2. char             int               1
3. short            int               1
4. int              int               1
5. float            float             1
6. reference        reference         1
7. returnAddress    returnAddress     1
8. boolean          int               1
9. long             long              2
10. double          double            2

Как вы можете видеть, только long и double относятся к категории 2. Это происходит потому, что все остальные являются 32-битными в вычислительном отношении, а long и double - 64-битными.

В приведенном ниже примере показано, как сделать это ясным.

public class PopVsPop2 {

public static int popint(){

    return  1;
}

public static long poplong() {
    return 1;
}


public static Long popLong() {
    return 1L;
}

public static void main(String[] args) {    

    popint();
    poplong();
    popLong();
}

Вышеуказанный javacode имеет следующий сгенерированный байт-код:

public static main(String[]) : void
   L0
    LINENUMBER 24 L0
    INVOKESTATIC PopVsPop2.popint () : int
    POP
   L1
    LINENUMBER 25 L1
    INVOKESTATIC PopVsPop2.poplong () : long
    POP2
   L2
    LINENUMBER 26 L2
    INVOKESTATIC PopVsPop2.popLong () : Long
    POP
   L3
    LINENUMBER 27 L3
    RETURN
   L4
    LOCALVARIABLE args String[] L0 L4 0
    MAXSTACK = 2
    MAXLOCALS = 1

Как вы можете видеть

popint () - POP -Потому что int относится к категории 1.

poplong () -POP2 - Потому что long относится к категории 2. То же самое будет для double.

popLong () - POP- Потому что здесьLong относится к java.lang.Long, который является ссылочным типом.Отсюда категория 1.

0 голосов
/ 21 мая 2018

Напишите небольшую Java-программу, содержащую метод main с

System.currentTimeMillis();

, не используйте результат этого вызова.Тогда байт-код выглядит так:

INVOKESTATIC java/lang/System.currentTimeMillis()J
POP2

System.currentTimeMillis() помещает длинное значение (шириной 64 бита) в стек.Тем не менее, это содержимое стека больше не используется, поэтому его нужно вытолкнуть так, чтобы было доступно другое содержимое стека.32-битный (нормальный размер) нужен простой POP, а 64-битный (широкий размер) нужен POP2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...