Список инструкций JVM с правилами проверки их безопасности

Материал из JavaCogito
Перейти к навигации Перейти к поиску

Список инструкций JVM с правилами проверки их безопасности - перевод на русский язык главы Спецификации виртуальной машины Java.


Перевод: Саянкин А.А.

aaload aaload


Инструкция aaload безопасна по типу тогда и только тогда, когда мы правомерно можем заменить тип int и массив с компонентами ComponentType, где ComponentType это подтип Object на ComponentType равный выходному состоянию типов.

instructionIsTypeSafe(aaload, Environment, _Offset, StackFrame,
			NextStackFrame, ExceptionStackFrame) :-
    nth1OperandStackIs(2, StackFrame, ArrayType),
    arrayComponentType(ArrayType, ComponentType),
    isBootstrapLoader(BL),
    validTypeTransition(Environment,
			  [int, arrayOf(class('java/lang/Object', BL))],
                        ComponentType, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).

Тип компонента массива X это X. Мы определяем тип компонента null равным null.

arrayComponentType(arrayOf(X), X).
arrayComponentType(null, null).







aastore aastore


Инструкция aastore безопасна по типу тогда и только тогда, когда мы правомерно можем считать из входящего стека операндов типы, соответствующие Object, int и массиву Object и после этого получить выходящее состояние типов.


instructionIsTypeSafe(aastore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    isBootstrapLoader(BL),
    canPop(StackFrame,
           [class('java/lang/Object', BL),
           int,
           arrayOf(class('java/lang/Object', BL))],
           NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).







aconst_null aconst_null


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


instructionIsTypeSafe(aconst_null, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [], null, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







aload aload


Инструкция aload с операндом Index безопасна по типу и приводит к выходящему состоянию типов NextStackFrame, если инструкция загрузки с операндом Index и типом reference является безопасной по типу и приводит к выходящему состоянию типов NextStackFrame.


instructionIsTypeSafe(aload(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
     loadIsTypeSafe(Environment, Index, reference,
     StackFrame,  NextStackFrame),
     exceptionStackFrame(StackFrame, ExceptionStackFrame).







aload_<n> aload_<n>


Инструкции aload_<n> для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция aload безопасна по типу.


instructionHasEquivalentTypeRule(aload_0,aload(0)).
instructionHasEquivalentTypeRule(aload_1,aload(1)).
instructionHasEquivalentTypeRule(aload_2,aload(2)).
instructionHasEquivalentTypeRule(aload_3,aload(3)).







anewarray anewarray


Инструкция anewarray с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего либо класс, либо массив и можно правомерно заменить тип int во входящем стеке операндов на массив с компонентами CP и при этом получить выходящее состояние типов.


instructionIsTypeSafe(anewarray(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    (CP = class(_, _) ; CP = arrayOf(_)),
    validTypeTransition(Environment, [int], arrayOf(CP),
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







areturn areturn


Инструкция areturn безопасна по типу тогда и только тогда, когда метод, в котором она находится имеет тип возвращаемого значения ReturnType равный типу reference и допустимо считать тип соответствующий ReturnType из входящего стека операндов.


instructionIsTypeSafe(areturn, Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    thisMethodReturnType(Environment, ReturnType),
    isAssignable(ReturnType, reference),
    canPop(StackFrame, [ReturnType], _PoppedStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







arraylength arraylength


Инструкция arraylength безопасна по типу тогда и только тогда, когда допустимо заменить тип массива во входящем стеке операндов на тип int и при этом получить выходное состояние типов.


instructionIsTypeSafe(arraylength, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    nth1OperandStackIs(1, StackFrame, ArrayType),
    arrayComponentType(ArrayType, _),
    validTypeTransition(Environment, [top], int, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







astore astore


Инструкция astore с операндом Index безопасна по типу и приводит к результирующему состоянию типов NextStackFrame, если инструкция сохранения с операндом Index и типом reference безопасна по типам и приводит к результирующему состоянию типов NextStackFrame.


instructionIsTypeSafe(astore(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    storeIsTypeSafe(Environment, Index, reference, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







astore_<n> astore_<n>


Инструкции astore_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция astore также безопасна по типу.


instructionHasEquivalentTypeRule(astore_0, astore(0)).
instructionHasEquivalentTypeRule(astore_1, astore(1)).
instructionHasEquivalentTypeRule(astore_2, astore(2)).
instructionHasEquivalentTypeRule(astore_3, astore(3)).







athrow athrow


Инструкция athrow безопасна по типу тогда и только тогда, когда на вершине стека операндов находится элемент, соответствующий Throwable.


instructionIsTypeSafe(athrow, _Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    isBootstrapLoader(BL),
    canPop(StackFrame, [class('java/lang/Throwable', BL)], _PoppedStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







baload baload


Инструкция baload безопасна по типу тогда и только тогда, когда допустимо заменить типы, соответствующие int и массиву «малых» типов во входящем стеке операндов на тип int и после замены получить выходное состояние типов.

Массив является массивом «малых» типов если это массив из типов byte, либо boolean, либо null.


instructionIsTypeSafe(baload, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :
    nth1OperandStackIs(2, StackFrame, Array),
    isSmallArray(Array),
    validTypeTransition(Environment, [int, top], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).

isSmallArray(arrayOf(byte)).
isSmallArray(arrayOf(boolean)).
isSmallArray(null).







bastore bastore


Инструкция bastore безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие int, int и массиву «малых» типов и после считывания получить выходное состояние типов.


instructionIsTypeSafe(bastore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    nth1OperandStackIs(3, StackFrame, Array),
    isSmallArray(Array),
    canPop(StackFrame, [int, int, top], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







bipush bipush


Инструкция bastore безопасна по типу тогда и только тогда, когда эквивалентная инструкция sipush также безопасна по типу.


instructionHasEquivalentTypeRule(bipush(Value), sipush(Value)).







caload caload


Инструкция caload безопасна по типу тогда и только тогда, когда допустимо заменить типы, соответствующие int и массиву типов char во входящем стеке операндов на тип int и после замены получить выходное состояние типов.


instructionIsTypeSafe(caload, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, arrayOf(char)], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







castore castore


Инструкция castore безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие int, int и массиву типов char и после считывания получить выходное состояние типов.


instructionIsTypeSafe(castore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [int, int, arrayOf(char)], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







checkcast checkcast


Инструкция checkcast с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего либо класс либо массив и допустимо заменить тип Object на вершине входящего стека операндов на тип, обозначенный через CP, и при этом получить выходящее состояние типов.


instructionIsTypeSafe(checkcast(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    (CP = class(_, _) ; CP = arrayOf(_)),
    isBootstrapLoader(BL),
    validTypeTransition(Environment, [class('java/lang/Object', BL)], CP,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







d2f d2f


Инструкция d2f безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип double, заменить его на float и после получить выходное состояние типов.


instructionIsTypeSafe(d2f, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [double], float,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







d2i d2i


Инструкция d2i безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип double, заменить его на int и после получить выходное состояние типов.


instructionIsTypeSafe(d2i, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [double], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







d2l d2l


Инструкция d2l безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип double, заменить его на long и после получить выходное состояние типов.


instructionIsTypeSafe(d2l, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
     validTypeTransition(Environment, [double], long,
                         StackFrame, NextStackFrame),
     exceptionStackFrame(StackFrame, ExceptionStackFrame).







dadd dadd


Инструкция dadd безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие double и double, на double, и после замены получить выходное состояние типов.


instructionIsTypeSafe(dadd, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
     validTypeTransition(Environment, [double, double], double,
                         StackFrame, NextStackFrame),
     exceptionStackFrame(StackFrame, ExceptionStackFrame).







daload daload


Инструкция daload безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие int и массиву double, на double, и после замены получить выходное состояние типов.


instructionIsTypeSafe(daload, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, arrayOf(double)], double,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







dastore dastore


Инструкция dastore безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие double, int и массиву типов double и после считывания получить выходное состояние типов.


instructionIsTypeSafe(dastore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [double, int, arrayOf(double)], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







dcmp<op> dcmp<op>


Инструкция dcmpg безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие double и double, на int, и после замены получить выходное состояние типов.


instructionIsTypeSafe(dcmpg, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [double, double], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция dcmpl безопасна по типу тогда и только тогда, когда эквивалентная инструкция dcmpg также безопасна.


instructionHasEquivalentTypeRule(dcmpl, dcmpg).







dconst_<d> dconst_<d>


Инструкция dconst_0 безопасна по типу тогда и только тогда, когда допустимо записать во входящий стек операндов тип, соответствующий double, и после записи получить выходное состояние типов.


instructionIsTypeSafe(dconst_0, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [], double, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция dconst_1 безопасна по типу тогда и только тогда, когда эквивалентная инструкция dconst_0 также безопасна.


instructionHasEquivalentTypeRule(dconst_1, dconst_0).







ddiv ddiv


Инструкция ddiv безопасна по типу тогда и только тогда, когда эквивалентная инструкция dadd также безопасна.


instructionHasEquivalentTypeRule(ddiv, dadd).







dload dload


Инструкция dload с операндом Index безопасна по типу и приводит к выходящему состоянию типов NextStackFrame, если инструкция загрузки с операндом Index и типом double является безопасной по типу и приводит к выходящему состоянию типов NextStackFrame.


instructionIsTypeSafe(dload(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    loadIsTypeSafe(Environment, Index, double, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







dload_<n> dload_<n>


Инструкции dload_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция dload также безопасна.


instructionHasEquivalentTypeRule(dload_0, dload(0)).
instructionHasEquivalentTypeRule(dload_1, dload(1)).
instructionHasEquivalentTypeRule(dload_2, dload(2)).
instructionHasEquivalentTypeRule(dload_3, dload(3)).







dmul dmul


Инструкция dmul безопасна по типу тогда и только тогда, когда эквивалентная инструкция dadd также безопасна.


instructionHasEquivalentTypeRule(dmul, dadd).







dneg dneg


Инструкция dneg безопасна по типу тогда и только тогда, когда во входящем стеке находится тип, соответствующие double. Инструкция dneg не меняет состояние типов.


instructionIsTypeSafe(dneg, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [double], double,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







drem drem


Инструкция drem безопасна по типу тогда и только тогда, когда эквивалентная инструкция dadd также безопасна.


instructionHasEquivalentTypeRule(drem, dadd).







dreturn dreturn


Инструкция dreturn безопасна по типу тогда и только тогда, когда метод, в котором она находится имеет тип возвращаемого значения double и допустимо считать тип соответствующий double из входящего стека операндов.


instructionIsTypeSafe(dreturn, Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    thisMethodReturnType(Environment, double),
    canPop(StackFrame, [double], _PoppedStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







dstore dstore


Инструкция dstore с операндом Index безопасна по типу и приводит к результирующему состоянию типов NextStackFrame, если инструкция сохранения с операндом Index и типом double безопасна по типам и приводит к результирующему состоянию типов NextStackFrame.


instructionIsTypeSafe(dstore(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    storeIsTypeSafe(Environment, Index, double, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







dstore_<n> dstore_<n>


Инструкции dstore_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция dstore также безопасна.


instructionHasEquivalentTypeRule(dstore_0, dstore(0)).
instructionHasEquivalentTypeRule(dstore_1, dstore(1)).
instructionHasEquivalentTypeRule(dstore_2, dstore(2)).
instructionHasEquivalentTypeRule(dstore_3, dstore(3)).







dsub dsub


Инструкция dsub безопасна по типу тогда и только тогда, когда эквивалентная инструкция dadd также безопасна.


instructionHasEquivalentTypeRule(dsub, dadd).







dup dup


Инструкция dup безопасна по типу тогда и только тогда, когда допустимо заменить тип Type, принадлежащий категории 1 на типы Type , Type и после замены получить выходное состояние типов.


instructionIsTypeSafe(dup, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, InputOperandStack, Flags),
    popCategory1(InputOperandStack, Type, _),
    canSafelyPush(Environment, InputOperandStack, Type, OutputOperandStack),
    NextStackFrame = frame(Locals, OutputOperandStack, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







dup_x1 dup_x1


Инструкция dup_x1 безопасна по типу тогда и только тогда, когда допустимо заменить два типа Type1 и Type2, принадлежащие категории 1 на типы Type1, Type2, Type1 и после замены получить выходное состояние типов.


instructionIsTypeSafe(dup_x1, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, InputOperandStack, Flags),
    popCategory1(InputOperandStack, Type1, Stack1),
    popCategory1(Stack1, Type2, Rest),
    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],
                      OutputOperandStack),
    NextStackFrame = frame(Locals, OutputOperandStack, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







dup_x2 dup_x2


Инструкция dup_x2 безопасна по типу тогда и только тогда, когда она представляет собой одну из безопасных по типу форм этой инструкции:


instructionIsTypeSafe(dup_x2, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, InputOperandStack, Flags),
    dup_x2SomeFormIsTypeSafe(Environment, InputOperandStack,
                             OutputOperandStack),
    NextStackFrame = frame(Locals, OutputOperandStack, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция dup_x2 является безопасной по типу формой инструкции dup_x2 только тогда, когда она является формой 1 инструкции dup_x2 или формой 2 этой инструкции.


dup_x2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

dup_x2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).


Инструкция dup_x2 является безопасной по типу формой 1 инструкции dup_x2 тогда и только тогда, когда допустимо заменить три типа Type1, Type2 и Type3, принадлежащие категории 1 на типы Type1, Type2, Type3, Type1 и после замены получить выходное состояние типов.


dup_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory1(InputOperandStack, Type1, Stack1),
    popCategory1(Stack1, Type2, Stack2),
    popCategory1(Stack2, Type3, Rest),
    canSafelyPushList(Environment, Rest, [Type1, Type3, Type2, Type1],
                      OutputOperandStack).


Инструкция dup_x2 является безопасной по типу формой 2 инструкции dup_x2 тогда и только тогда, когда допустимо заменить тип Type1, принадлежащий категории 1, и тип Type2, принадлежащий категории 2, на типы Type1, Type2, Type1 и после замены получить выходное состояние типов.


dup_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory1(InputOperandStack, Type1, Stack1),
    popCategory2(Stack1, Type2, Rest),
    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],
                      OutputOperandStack).







dup2 dup2


Инструкция dup2 безопасна по типу тогда и только тогда, когда она представляет собой одну из безопасных по типу форм этой инструкции:


instructionIsTypeSafe(dup2, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, InputOperandStack, Flags),
    dup2SomeFormIsTypeSafe(Environment,InputOperandStack, OutputOperandStack),
    NextStackFrame = frame(Locals, OutputOperandStack, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция dup2 является безопасной по типу формой инструкции dup2 только тогда, когда она является формой 1 инструкции dup2 или формой 2 этой инструкции.


dup2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2Form1IsTypeSafe(Environment,InputOperandStack, OutputOperandStack).

dup2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2Form2IsTypeSafe(Environment,InputOperandStack, OutputOperandStack).


Инструкция dup2 является безопасной по типу формой 1 инструкции dup2 тогда и только тогда, когда допустимо заменить два типа Type1 и Type2 принадлежащие категории 1 на типы Type1, Type2, Type1, Type2 и после замены получить выходное состояние типов.


dup2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack):-
    popCategory1(InputOperandStack, Type1, TempStack),
    popCategory1(TempStack, Type2, _),
    canSafelyPushList(Environment, InputOperandStack, [Type1, Type2],
                      OutputOperandStack).


Инструкция dup2 является безопасной по типу формой 2 инструкции dup2 тогда и только тогда, когда допустимо заменить тип Type, принадлежащий категории 2, на типы Type, Type и после замены получить выходное состояние типов.


dup2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack):-
    popCategory2(InputOperandStack, Type, _),
    canSafelyPush(Environment, InputOperandStack, Type, OutputOperandStack).







dup2_x1 dup2_x1


Инструкция dup2_x1 безопасна по типу тогда и только тогда, когда она представляет собой одну из безопасных по типу форм этой инструкции:


instructionIsTypeSafe(dup2_x1, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, InputOperandStack, Flags),
    dup2_x1SomeFormIsTypeSafe(Environment, InputOperandStack,
                              OutputOperandStack),
    NextStackFrame = frame(Locals, OutputOperandStack, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция dup2_x1 является безопасной по типу формой инструкции dup2_x1 только тогда, когда она является формой 1 инструкции dup2_x1 или формой 2 этой инструкции.


up2_x1SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2_x1Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

dup2_x1SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2_x1Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).


Инструкция dup2_x1 является безопасной по типу формой 1 инструкции dup2_x1 тогда и только тогда, когда допустимо заменить три типа Type1, Type2 и Type3 принадлежащие категории 1 на типы Type1, Type2, Type3, Type1, Type2 и после замены получить выходное состояние типов.


dup2_x1Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory1(InputOperandStack, Type1, Stack1),
    popCategory1(Stack1, Type2, Stack2),
    popCategory1(Stack2, Type3, Rest),
    canSafelyPushList(Environment, Rest, [Type2, Type1, Type3, Type2, Type1],
                      OutputOperandStack).


Инструкция dup2_x1 является безопасной по типу формой 2 инструкции dup2_x1 тогда и только тогда, когда допустимо заменить тип Type1, принадлежащий категории 2, и тип Type2, принадлежащий категории 1 на типы Type1, Type2, Type1 и после замены получить выходное состояние типов.


dup2_x1Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory2(InputOperandStack, Type1, Stack1),
    popCategory1(Stack1, Type2, Rest),
    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],
                      OutputOperandStack).







dup2_x2 dup2_x2


Инструкция dup2_x2 безопасна по типу тогда и только тогда, когда она представляет собой одну из безопасных по типу форм этой инструкции:


instructionIsTypeSafe(dup2_x2, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, InputOperandStack, Flags),
    dup2_x2SomeFormIsTypeSafe(Environment, InputOperandStack,
                              OutputOperandStack),
    NextStackFrame = frame(Locals, OutputOperandStack, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция dup2_x2 является безопасной по типу формой инструкции dup2_x2 только тогда, когда справедливо одно из следующих утверждений:

  • она является безосной по типу формой 1 инструкции dup2_x2.
  • она является безосной по типу формой 2 инструкции dup2_x2.
  • она является безосной по типу формой 3 инструкции dup2_x2.
  • она является безосной по типу формой 4 инструкции dup2_x2.


dup2_x2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

dup2_x2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

dup2_x2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2_x2Form3IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).

dup2_x2SomeFormIsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    dup2_x2Form4IsTypeSafe(Environment, InputOperandStack, OutputOperandStack).


Инструкция dup2_x2 является безопасной по типу формой 1 инструкции dup2_x2 тогда и только тогда, когда допустимо заменить четыре типа Type1, Type2, Type3 и Type4 принадлежащие категории 1 на типы Type1, Type2, Type3, Type4, Type1, Type2 и после замены получить выходное состояние типов.


dup2_x2Form1IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory1(InputOperandStack, Type1, Stack1),
    popCategory1(Stack1, Type2, Stack2),
    popCategory1(Stack2, Type3, Stack3),
    popCategory1(Stack3, Type4, Rest),
    canSafelyPushList(Environment, Rest,
                      [Type2, Type1, Type4, Type3, Type2, Type1],
                      OutputOperandStack).


Инструкция dup2_x2 является безопасной по типу формой 2 инструкции dup2_x2 тогда и только тогда, когда допустимо заменить тип Type1, принадлежащий категории 2, и два типа Type2, Type3, принадлежащий категории 1 на типы Type1, Type2, Type3, Type1 и после замены получить выходное состояние типов.


dup2_x2Form2IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory2(InputOperandStack, Type1, Stack1),
    popCategory1(Stack1, Type2, Stack2),
    popCategory1(Stack2, Type3, Rest),
    canSafelyPushList(Environment, Rest,
                      [Type1, Type3, Type2, Type1],
                      OutputOperandStack).


Инструкция dup2_x2 является безопасной по типу формой 3 инструкции dup2_x2 тогда и только тогда, когда допустимо заменить два типа Type1, Type2, принадлежащие категории 1, и тип Type3, принадлежащий категории 2, на типы Type1, Type2, Type3, Type1, Type2 и после замены получить выходное состояние типов.


dup2_x2Form3IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory1(InputOperandStack, Type1, Stack1),
    popCategory1(Stack1, Type2, Stack2),
    popCategory2(Stack2, Type3, Rest),
    canSafelyPushList(Environment, Rest,
                      [Type2, Type1, Type3, Type2, Type1],
                      OutputOperandStack).


Инструкция dup2_x2 является безопасной по типу формой 4 инструкции dup2_x2 тогда и только тогда, когда допустимо заменить два типа Type1, Type2, принадлежащие категории 2, на типы Type1, Type2, Type1, и после замены получить выходное состояние типов.


dup2_x2Form4IsTypeSafe(Environment, InputOperandStack, OutputOperandStack) :-
    popCategory2(InputOperandStack, Type1, Stack1),
    popCategory2(Stack1, Type2, Rest),
    canSafelyPushList(Environment, Rest, [Type1, Type2, Type1],
                      OutputOperandStack).







f2d f2d


Инструкция f2d безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип, соответствующий float, и заменить его на double и после замены получить выходное состояние типов.


instructionIsTypeSafe(f2d, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [float], double,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







f2i f2i


Инструкция f2i безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип, соответствующий float, и заменить его на int и после замены получить выходное состояние типов.


instructionIsTypeSafe(f2i, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [float], int,
                    StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







f2l f2l


Инструкция f2l безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип, соответствующий float, и заменить его на long и после замены получить выходное состояние типов.


instructionIsTypeSafe(f2l, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [float], long,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







fadd fadd


Инструкция fadd безопасна по типу тогда и только тогда, когда допустимо заменить во входящем стеке операндов типы, соответствующие float и float, на float и после замены получить выходное состояние типов.


instructionIsTypeSafe(fadd, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [float, float], float,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







faload faload


Инструкция faload безопасна по типу тогда и только тогда, когда допустимо заменить во входящем стеке операндов типы, соответствующие int и массиву float, на float и после замены получить выходное состояние типов.


instructionIsTypeSafe(faload, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, arrayOf(float)], float,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







fastore fastore


Инструкция fastore безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие float, int и массиву float, и после считывания получить выходное состояние типов.


instructionIsTypeSafe(fastore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [float, int, arrayOf(float)], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







fcmp<op> fcmp<op>


Инструкция fcmpg безопасна по типу тогда и только тогда, когда допустимо заменить во входящем стеке операндов типы, соответствующие float и float, на int и после замены получить выходное состояние типов.


instructionIsTypeSafe(fcmpg, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [float, float], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция fcmpl безопасна по типу тогда и только тогда, когда эквивалентная инструкция fcmpg также безопасна по типу.


instructionHasEquivalentTypeRule(fcmpl, fcmpg).







fconst_<f> fconst_<f>


Инструкция fconst_0 безопасна по типу тогда и только тогда, когда допустимо записать во входящий стек операндов тип, соответствующий float и после записи получить выходное состояние типов.


instructionIsTypeSafe(fconst_0, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [], float, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Правила для остальных вариантов инструкции fconst эквивалентны.


instructionHasEquivalentTypeRule(fconst_1, fconst_0).
instructionHasEquivalentTypeRule(fconst_2, fconst_0).







fdiv fdiv


Инструкция fdiv безопасна по типу тогда и только тогда, когда эквивалентная инструкция fadd также безопасна.


instructionHasEquivalentTypeRule(fdiv, fadd).







fload fload


Инструкция fload с операндом Index безопасна по типу и приводит к выходящему состоянию типов NextStackFrame, если инструкция загрузки с операндом Index и типом float является безопасной по типу и приводит к выходящему состоянию типов NextStackFrame.


instructionIsTypeSafe(fload(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    loadIsTypeSafe(Environment, Index, float, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







fload_<n> fload_<n>


Инструкции fload_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция fload также безопасна.


instructionHasEquivalentTypeRule(fload_0, fload(0)).
instructionHasEquivalentTypeRule(fload_1, fload(1)).
instructionHasEquivalentTypeRule(fload_2, fload(2)).
instructionHasEquivalentTypeRule(fload_3, fload(3)).







fmul fmul


Инструкция fmul безопасна по типу тогда и только тогда, когда эквивалентная инструкция fadd также безопасна.


instructionHasEquivalentTypeRule(fmul, fadd).







fneg fneg


Инструкция fneg безопасна по типу тогда и только тогда, когда во входящем стеке находится тип, соответствующие float. Инструкция fneg не меняет состояние типов.


instructionIsTypeSafe(fneg, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [float], float,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







frem frem


Инструкция frem безопасна по типу тогда и только тогда, когда эквивалентная инструкция fadd также безопасна.


instructionHasEquivalentTypeRule(frem, fadd).







freturn freturn


Инструкция freturn безопасна по типу тогда и только тогда, когда метод, в котором она находится имеет тип возвращаемого значения float и допустимо считать тип соответствующий float из входящего стека операндов.


instructionIsTypeSafe(freturn, Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    thisMethodReturnType(Environment, float),
    canPop(StackFrame, [float], _PoppedStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







fstore fstore


Инструкция fstore с операндом Index безопасна по типу и приводит к результирующему состоянию типов NextStackFrame, если инструкция сохранения с операндом Index и типом float безопасна по типам и приводит к результирующему состоянию типов NextStackFrame.


instructionIsTypeSafe(fstore(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    storeIsTypeSafe(Environment, Index, float, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







fstore_<n> fstore_<n>


Инструкции fstore_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция fstore также безопасна.


instructionHasEquivalentTypeRule(fstore_0, fstore(0)).
instructionHasEquivalentTypeRule(fstore_1, fstore(1)).
instructionHasEquivalentTypeRule(fstore_2, fstore(2)).
instructionHasEquivalentTypeRule(fstore_3, fstore(3)).







fsub fsub


Инструкция fsub безопасна по типу тогда и только тогда, когда эквивалентная инструкция fadd также безопасна.


instructionHasEquivalentTypeRule(fsub, fadd).







getfield getfield


Инструкция getfield с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего поле, чей объявленный тип равен FieldType, в классе FieldClass и допустимо заменить во входящем стеке операндов тип, соответствующий FieldClass на тип FieldType и после замены получить выходящее состояние типов. FieldClass не должен быть массивом. Поля с модификатором доступа protected обсуждаются ниже.


instructionIsTypeSafe(getfield(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = field(FieldClass, FieldName, FieldDescriptor),
    parseFieldDescriptor(FieldDescriptor, FieldType),
    passesProtectedCheck(Environment, FieldClass, FieldName,
                         FieldDescriptor, StackFrame),
    validTypeTransition(Environment, [class(FieldClass)], FieldType,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Проверка для модификатора protected применима только к членам данным классов предков текущего класса. Остальные случаи вступают в силу при выполнении проверок во время разрешения ссылок. Если имя текущего класса не совпадает с именем класса предка, то такой случай может быть безопасно проигнорирован.


passesProtectedCheck(Environment, MemberClassName, MemberName,
                     MemberDescriptor, StackFrame) :-
    thisClass(Environment, class(CurrentClassName, CurrentLoader)),
    superclassChain(CurrentClassName, CurrentLoader, Chain),
    notMember(class(MemberClassName, _), Chain).


Использование членов данных, которые не являются protected тривиально и является корректным.

Если MemberClassName такой же как и имя класса предка, то класс, чьё разрешение сейчас происходит, может быть на самом деле классом предком. В этом случае, если в другом пакете времени выполнения отсутствует класс предок с именем MemberClassName, который имеет член с модификатором protected, именем MemberName и дескриптором MemberDescriptor, то нет необходимости применять проверку для protected.

Так происходит потому, что класс, разрешение которого в данный момент происходит, будет одним из тех классов предков, для которых мы знаем, что либо это тот же пакет времени выполнения и доступ в этом случае может быть предоставлен; либо член данное, о котором идёт речь, не является protected и проверка не применяется; либо он будет классом наследником, и в этом случае проверка закончится успешно всегда; либо он будет каким-либо другим классом в том же пакете времени выполнения и это значит доступ может быть предоставлен, а в проверке нет необходимости; либо верификатор считает, что нет необходимости отмечать эту ситуацию как проблемную, поскольку она будет все равно перехвачена аварийно завершившегося разрешения.


passesProtectedCheck(Environment, MemberClassName, MemberName,
                     MemberDescriptor, StackFrame) :-
    thisClass(Environment, class(CurrentClassName, CurrentLoader)),
    superclassChain(CurrentClassName, CurrentLoader, Chain),
    member(class(MemberClassName, _), Chain),
    classesInOtherPkgWithProtectedMember(
      class(CurrentClassName, CurrentLoader),
      MemberName, MemberDescriptor, MemberClassName, Chain, []).


Если в классе предке существует член с модификатором protected в другом пакете времени выполнения, выполняется загрузка MemberClassName; если член данное не является protected, то проверка не выполняется.


passesProtectedCheck(Environment, MemberClassName, MemberName,
                     MemberDescriptor,

                     frame(_Locals, [Target | Rest], _Flags)) :-
    thisClass(Environment, class(CurrentClassName, CurrentLoader)),
    superclassChain(CurrentClassName, CurrentLoader, Chain),
    member(class(MemberClassName, _), Chain),
    classesInOtherPkgWIthProtectedMember(
      class(CurrentClassName, CurrentLoader),
      MemberName, MemberDescriptor, MemberClassName, Chain, List),
    List /= [],
    loadedClass(MemberClassName, CurrentLoader, ReferencedClass),
    isNotProtected(ReferencedClass, MemberName, MemberDescriptor).


В противном случае использование члена с типом Target требует того, чтобы Target можно было присвоить типу в текущем классе.


passesProtectedCheck(Environment, MemberClassName, MemberName,
                     MemberDescriptor,
    frame(_Locals, [Target | Rest], _Flags)) :-
    thisClass(Environment, class(CurrentClassName, CurrentLoader)),
    superclassChain(CurrentClassName, CurrentLoader, Chain),
    member(class(MemberClassName, _), Chain),
    classesInOtherPkgWithProtectedMember(
      class(CurrentClassName, CurrentLoader),
      MemberName, MemberDescriptor, MemberClassName, Chain, List),
  List /= [],
  loadedClass(MemberClassName, CurrentLoader, ReferencedClass),
  isProtected(ReferencedClass, MemberName, MemberDescriptor),
  isAssignable(Target, class(CurrentClassName, CurrentLoader)).


Предикат classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Chain, List) является истинным, если List — это набор классов цепи Chain с находящимся в нем именем MemberClassName, причём класс MemberClassName расположен в отличном пакете времени выполнения, чем класс Class, который имеет член данное MemberName с модификатором protected и дескриптором MemberDescriptor.


classesInOtherPkgWithProtectedMember(_, _, _, _, [], []).

classesInOtherPkgWithProtectedMember(Class, MemberName,
                                     MemberDescriptor, MemberClassName,
                                     [class(MemberClassName, L) | Tail],
                                     [class(MemberClassName, L) | T]) :-
    differentRuntimePackage(Class, class(MemberClassName, L)),
    loadedClass(MemberClassName, L, Super),
    isProtected(Super, MemberName, MemberDescriptor),
    classesInOtherPkgWithProtectedMember(
      Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).

classesInOtherPkgWithProtectedMember(Class, MemberName,
                                     MemberDescriptor, MemberClassName,
                                     [class(MemberClassName, L) | Tail],
                                     T) :-
   differentRuntimePackage(Class, class(MemberClassName, L)),
   loadedClass(MemberClassName, L, Super),
   isNotProtected(Super, MemberName, MemberDescriptor),
   classesInOtherPkgWithProtectedMember(
     Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).

classesInOtherPkgWithProtectedMember(Class, MemberName,
                                     MemberDescriptor, MemberClassName,
                                     [class(MemberClassName, L) | Tail],
                                     T] :-
    sameRuntimePackage(Class, class(MemberClassName, L)),
    classesInOtherPkgWithProtectedMember(
      Class, MemberName, MemberDescriptor, MemberClassName, Tail, T).







getstatic getstatic


Инструкция getstatic с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего поле, чей объявленный тип равен FieldType, и допустимо записать во входящий стек операндов тип, соответствующий FieldType и после записи получить выходящее состояние типов.


instructionIsTypeSafe(getstatic(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = field(_FieldClass, _FieldName, FieldDescriptor),
    parseFieldDescriptor(FieldDescriptor, FieldType),
    validTypeTransition(Environment, [], FieldType,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







goto goto


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


instructionIsTypeSafe(goto(Target), Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    targetIsTypeSafe(Environment, StackFrame, Target),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







goto_w goto_w


Инструкция goto_w безопасна по типу тогда и только тогда, когда эквивалентная ей инструкция goto также безопасна по типу.


instructionHasEquivalentTypeRule(goto_w(Target), goto(Target)).







i2b i2b


Инструкция i2b безопасна по типу тогда и только тогда, когда эквивалентная ей инструкция ineg также безопасна по типу.


instructionHasEquivalentTypeRule(i2b, ineg).







i2c i2c


Инструкция i2c безопасна по типу тогда и только тогда, когда эквивалентная ей инструкция ineg также безопасна по типу.


instructionHasEquivalentTypeRule(i2c, ineg).







i2d i2d


Инструкция i2d безопасна по типу тогда и только тогда, когда допустимо во входящем стеке операндов считать тип, соответствующий int, затем записать туда double и после замены получить выходящее состояние типов.


instructionIsTypeSafe(i2d, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int], double,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







i2f i2f


Инструкция i2f безопасна по типу тогда и только тогда, когда допустимо во входящем стеке операндов считать тип, соответствующий int, затем записать туда float и после замены получить выходящее состояние типов.


instructionIsTypeSafe(i2f, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int], float,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







i2l i2l


Инструкция i2f безопасна по типу тогда и только тогда, когда допустимо во входящем стеке операндов считать тип, соответствующий int, затем записать туда long и после замены получить выходящее состояние типов.


instructionIsTypeSafe(i2l, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int], long,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







i2s i2s


Инструкция i2s безопасна по типу тогда и только тогда, когда эквивалентная ей инструкция ineg также безопасна по типу.


instructionHasEquivalentTypeRule(i2s, ineg).







iadd iadd


Инструкция iadd безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие int и int, на int, и после замены получить выходное состояние типов.


instructionIsTypeSafe(iadd, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, int], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







iaload iaload


Инструкция iaload безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие int и массиву int, на int, и после замены получить выходное состояние типов.


instructionIsTypeSafe(iaload, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, arrayOf(int)], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







iand iand


Инструкция iand безопасна по типу тогда и только тогда, когда эквивалентная ей инструкция iadd также безопасна по типу.


instructionHasEquivalentTypeRule(iand, iadd).







iastore iastore


Инструкция iastore безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие int, int и массиву типов int и после считывания получить выходное состояние типов.


instructionIsTypeSafe(iastore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [int, int, arrayOf(int)], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







if_acmp<cond> if_acmp<cond>


Инструкция if_acmpeq безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие reference и reference и после считывания получить выходное состояние типов NextStackFrame, причём операнд Target инструкции if_acmpeq является допустимой целью для перехода, принимая во внимание NextStackFrame как входящее состояние типов.


instructionIsTypeSafe(if_acmpeq(Target), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [reference, reference], NextStackFrame),
    targetIsTypeSafe(Environment, NextStackFrame, Target),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).



Правило для if_acmpne идентично.


instructionHasEquivalentTypeRule(if_acmpne(Target), if_acmpeq(Target)).







if_icmp<cond> if_icmp<cond>


Инструкция if_icmpeq безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие int и int и после считывания получить выходное состояние типов NextStackFrame, причём операнд Target инструкции if_icmpeq является допустимой целью для перехода, принимая во внимание NextStackFrame как входящее состояние типов.


instructionIsTypeSafe(if_icmpeq(Target), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [int, int], NextStackFrame),
    targetIsTypeSafe(Environment, NextStackFrame, Target),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).



Правила для остальных вариантов инструкции if_icmp<cond> идентичны.


instructionHasEquivalentTypeRule(if_icmpge(Target), if_icmpeq(Target)).
instructionHasEquivalentTypeRule(if_icmpgt(Target), if_icmpeq(Target)).
instructionHasEquivalentTypeRule(if_icmple(Target), if_icmpeq(Target)).
instructionHasEquivalentTypeRule(if_icmplt(Target), if_icmpeq(Target)).
instructionHasEquivalentTypeRule(if_icmpne(Target), if_icmpeq(Target)).







if<cond> if<cond>


Инструкция ifeq безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип, соответствующий int и после считывания получить выходное состояние типов NextStackFrame, причём операнд Target инструкции ifeq является допустимой целью для перехода, принимая во внимание NextStackFrame как входящее состояние типов.


instructionIsTypeSafe(ifeq(Target), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [int], NextStackFrame),
    targetIsTypeSafe(Environment, NextStackFrame, Target),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Правила для остальных вариантов инструкции if<cond> идентичны.


instructionHasEquivalentTypeRule(ifge(Target), ifeq(Target)).
instructionHasEquivalentTypeRule(ifgt(Target), ifeq(Target)).
instructionHasEquivalentTypeRule(ifle(Target), ifeq(Target)).
instructionHasEquivalentTypeRule(iflt(Target), ifeq(Target)).
instructionHasEquivalentTypeRule(ifne(Target), ifeq(Target)).







ifnonnull ifnonnull


Инструкция ifnonnull безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип, соответствующий reference и после считывания получить выходное состояние типов NextStackFrame, причём операнд Target инструкции ifnonnull является допустимой целью для перехода, принимая во внимание NextStackFrame как входящее состояние типов.


instructionIsTypeSafe(ifnonnull(Target), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [reference], NextStackFrame),
    targetIsTypeSafe(Environment, NextStackFrame, Target),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







ifnull ifnull


Инструкция ifnull безопасна по типу тогда и только тогда, когда эквивалентная ей инструкция ifnonnull также безопасна по типу.


instructionHasEquivalentTypeRule(ifnull(Target), ifnonnull(Target)).







iinc iinc


Инструкция iinc с первым операндом Index безопасна по типу тогда и только тогда, когда LIndex имеет тип int. Инструкция iinc не меняет состояние типов.


instructionIsTypeSafe(iinc(Index, _Value), _Environment, _Offset,
                     StackFrame, StackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, _OperandStack, _Flags),
    nth0(Index, Locals, int),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







iload iload


Инструкция iload с операндом Index безопасна по типу и приводит к выходящему состоянию типов NextStackFrame, если инструкция загрузки с операндом Index и типом int является безопасной по типу и приводит к выходящему состоянию типов NextStackFrame.


instructionIsTypeSafe(iload(Index), Environment, _Offset, StackFrame,
NextStackFrame, ExceptionStackFrame) :-
loadIsTypeSafe(Environment, Index, int, StackFrame, NextStackFrame),
exceptionStackFrame(StackFrame, ExceptionStackFrame).







iload_<n> iload_<n>


Инструкции iload_<n>, где 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная им инструкция iload также безопасна по типу.


instructionHasEquivalentTypeRule(iload_0, iload(0)).
instructionHasEquivalentTypeRule(iload_1, iload(1)).
instructionHasEquivalentTypeRule(iload_2, iload(2)).
instructionHasEquivalentTypeRule(iload_3, iload(3)).







imul imul


Инструкция imul безопасна по типу тогда и только тогда, когда эквивалентная ей инструкция iadd также безопасна по типу.


instructionHasEquivalentTypeRule(imul, iadd).







ineg ineg


Инструкция ineg безопасна по типу тогда и только тогда, когда во входящем стеке операндов находится тип, соответствующий int. Инструкция ineg не меняет состояние типов.


instructionIsTypeSafe(ineg, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int], int, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







instanceof instanceof


Инструкция instanceof с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего либо класс либо массив и допустимо заменить тип Object на вершине входящего стека операндов на тип int, и при этом получить выходящее состояние типов.


instructionIsTypeSafe(instanceof(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    (CP = class(_, _) ; CP = arrayOf(_)),
    isBootstrapLoader(BL),
    validTypeTransition(Environment, [class('java/lang/Object'), BL], int,
                        StackFrame,NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







invokedynamic invokedynamic


Инструкция invokedynamic безопасна по типу тогда и только тогда, когда справедливы все следующие условия:


  • Её первый операнд CP ссылается на элемент константного пула, обозначающего узел динамического вызова с именем CallSiteName и дескриптором Descriptor.
  • CallSiteName не является <init>.
  • CallSiteName не является <clinit>.
  • Во входящем стеке операндов допустимо заменить типы, соответствующие типам аргументов представленных в Descriptor на тип возвращаемого значения, представленного в Descriptor и в результате замены получить выходящее состояние типов.


instructionIsTypeSafe(invokedynamic(CP,0,0), Environment, _Offset,
                      StackFrame, NextStackFrame, ExceptionStackFrame) :-
    CP = dmethod(CallSiteName, Descriptor),
    CallSiteName \= ' <init> ',
    CallSiteName \= ' <clinit> ',
    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
    reverse(OperandArgList, StackArgList),
    validTypeTransition(Environment, StackArgList, ReturnType,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







invokeinterface invokeinterface


Инструкция invokeinterface безопасна по типу тогда и только тогда, когда справедливы все следующие условия:


  • Её первый операнд CP ссылается на элемент константного пула, обозначающего метод интерфейса с именем MethodName и дескриптором Descriptor, который является членом интерфейса с именем MethodIntfName.
  • CallSiteName не является <init>.
  • CallSiteName не является <clinit>.
  • Её второй операнд Count является действительным счётчиком (см ниже).
  • Во входящем стеке операндов допустимо заменить тип, соответствующий MethodIntfName и типы, соответствующие типам аргументов представленных в Descriptor на тип возвращаемого значения, представленного в Descriptor и в результате замены получить выходящее состояние типов.


instructionIsTypeSafe(invokeinterface(CP, Count, 0), Environment, _Offset,
                      StackFrame, NextStackFrame, ExceptionStackFrame) :-
    CP = imethod(MethodIntfName, MethodName, Descriptor),
    MethodName \= ' <init> ',
    MethodName \= ' <clinit> ',
    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
    currentClassLoader(Environment, L),
    reverse([class(MethodIntfName, L) | OperandArgList], StackArgList),
    canPop(StackFrame, StackArgList, TempFrame),
    validTypeTransition(Environment, [], ReturnType, TempFrame, NextStackFrame),
    countIsValid(Count, StackFrame, TempFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Операнд Count инструкции invokeinterface является действительным, если он равен количеству аргументов инструкции. Количество аргументов равно разнице размеров InputFrame и OutputFrame.


countIsValid(Count, InputFrame, OutputFrame) :-
    InputFrame = frame(_Locals1, OperandStack1, _Flags1),
    OutputFrame = frame(_Locals2, OperandStack2, _Flags2),
    length(OperandStack1, Length1),
    length(OperandStack2, Length2),
    Count =:= Length1 - Length2.







invokespecial invokespecial


Инструкция invokespecial безопасна по типу тогда и только тогда, когда справедливы все следующие условия:

  • Её первый операнд CP ссылается на элемент константного пула, обозначающего метод с именем MethodName и дескриптором Descriptor, который является членом класса с именем MethodClassName.

Либо:

  • MethodName не является <init>.
  • MethodName не является <clinit>.
  • Во входящем стеке операндов допустимо заменить тип, соответствующий текущему классу и типы, соответствующие типам аргументов представленных в Descriptor на тип возвращаемого значения, представленного в Descriptor и в результате замены получить выходящее состояние типов.
  • Во входящем стеке операндов допустимо заменить тип, соответствующий классу MethodClassName и типы, соответствующие типам аргументов представленных в Descriptor на тип возвращаемого значения, представленного в Descriptor и в результате замены получить выходящее состояние типов.


instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = method(MethodClassName, MethodName, Descriptor),
    MethodName \= ' <init> ',
    MethodName \= ' <clinit> ',
    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
    thisClass(Environment, CurrentClass),
    reverse([CurrentClass | OperandArgList], StackArgList),
    validTypeTransition(Environment, StackArgList, ReturnType,
                        StackFrame, NextStackFrame),
    currentClassLoader(Environment, L),
    reverse([class(MethodClassName, L) | OperandArgList], StackArgList2),
    validTypeTransition(Environment, StackArgList2, ReturnType,
                        StackFrame, _ResultStackFrame),
    isAssignable(class(CurrentClassName, L), class(MethodClassName, L)).
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Либо:

  • MethodName является <init>.
  • В дескрипторе Descriptor определен тип возвращаемого значения как void.
  • Во входящем стеке операндов допустимо считать типы, соответствующие типам аргументов представленных в Descriptor и неинициализированный тип UninitializedArg и в результате считывания получить OperandStack.
  • Исходящее состояние типов поличается их входящего заменой, во-первых, входящего стека операндов на OperandStack и, во-вторых, заменой всех экземпляров UninitializedArg на тип экземпляра, который инициализируется.


instructionIsTypeSafe(invokespecial(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = method(MethodClassName, ' <init> ', Descriptor),
    parseMethodDescriptor(Descriptor, OperandArgList, void),
    reverse(OperandArgList, StackArgList),
    canPop(StackFrame, StackArgList, TempFrame),
    TempFrame = frame(Locals, FullOperandStack, Flags),
    FullOperandStack = [UninitializedArg | OperandStack],
    currentClassLoader(Environment, CurrentLoader),
    rewrittenUninitializedType(UninitializedArg, Environment,
                               class(MethodClassName, CurrentLoader), This),
    rewrittenInitializationFlags(UninitializedArg, Flags, NextFlags),
    substitute(UninitializedArg, This, OperandStack, NextOperandStack),
    substitute(UninitializedArg, This, Locals, NextLocals),
    NextStackFrame = frame(NextLocals, NextOperandStack, NextFlags),
    ExceptionStackFrame = frame(NextLocals, [], Flags),
    passesProtectedCheck(Environment, MethodClassName, ' <init> ',
    Descriptor, NextStackFrame).


Специальное правило для invokespecial <init> метода.

Это правило является единственной причиной для возврата явного исключения в стеке фреймов. Предположим что invokespecial может привести к вызову <init> метода в классе предке и вызов закончиться аварийно, оставляя this не инициализированным. Данная ситуация не может быть создана с использованием исходного кода на языке программирования Java, но может быть воссоздана непосредственно с помощью байт-кода.

Исходный фрейм содержит неинициализированный объект в локальных переменных а также флаг uninitializedThis. Нормальное завершение invokespecial инициализирует неинициализированный объект и сбрасывает флаг uninitializedThis. Но если вызов метода <init> приводит к исключению, то неинициализированный объект может пребывать в частично инициализированном состоянии и требовать того, чтобы его обозначили как не готового к использованию. Это достигается тем, что в фрейм исключения содержит неверный объект (новое значение локальной переменной) и флаг uninitializedThis (старый флаг). Поскольку нет возможности получить из частично инициализированного объекта, содержащего флаг uninitializedThis полностью инициализированный объект, так что объект помечается как не готовый к использованию. Для других случаев стековый фрейм исключения может быть таким же, как входящий стековый фрейм.


rewrittenUninitializedType(uninitializedThis, Environment,
                           _MethodClass, This) :-
    thisClass(Environment, This).

rewrittenUninitializedType(uninitialized(Address), Environment,
                           MethodClass, MethodClass) :-
    allInstructions(Environment, Instructions),
    member(instruction(Address, new(MethodClass)), Instructions).


Вычисляем к какому типу тип неинициализированного аргумента должен быть приведён. Есть два случая:

Первый случай. Если мы инициализируем объект внутри конструктора, то его тип изначально равен uninitializedThis. Он будет замене на тип класса, которому принадлежит метод <init>.

Второй случай. Мы инициализируем объект с помощью операции new. Тогда тип неинициализированного аргумента должен быть равным MethodClass — типу, содержащему метод <init>. Мы также проверяем действительно ли по адресу Address находится инструкция new.


rewrittenInitializationFlags(uninitializedThis, _Flags, []).
rewrittenInitializationFlags(uninitialized(_), Flags, Flags).

substitute(_Old, _New, [], []).
	substitute(Old, New, [Old | FromRest], [New | ToRest]) :
    substitute(Old, New, FromRest, ToRest).
substitute(Old, New, [From1 | FromRest], [From1 | ToRest]) :-
    From1 \= Old,
    substitute(Old, New, FromRest, ToRest).







invokestatic invokestatic


Инструкция invokestatic безопасна по типу тогда и только тогда, когда справедливы все следующие условия:

  • Её первый операнд CP ссылается на элемент константного пула, обозначающего метод с именем MethodName и дескриптором Descriptor.
  • MethodName не является <init>.
  • MethodName не является <clinit>.
  • Во входящем стеке операндов допустимо заменить типы, соответствующие типам аргументов представленных в Descriptor на тип возвращаемого значения, представленного в Descriptor и в результате замены получить выходящее состояние типов.


instructionIsTypeSafe(invokestatic(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = method(_MethodClassName, MethodName, Descriptor),
    MethodName \= ' <init> ',
    MethodName \= ' <clinit> ',
    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
    reverse(OperandArgList, StackArgList),
    validTypeTransition(Environment, StackArgList, ReturnType,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







invokevirtual invokevirtual


Инструкция invokevirtual безопасна по типу тогда и только тогда, когда справедливы все следующие условия:

  • Её первый операнд CP ссылается на элемент константного пула, обозначающего метод с именем MethodName и дескриптором Descriptor, причем метод принадлежит классу MethodClassName.
  • MethodName не является <init>.
  • MethodName не является <clinit>.
  • Во входящем стеке операндов допустимо заменить тип, соответствующий MethodClassName и типы, соответствующие типам аргументов представленных в Descriptor на тип возвращаемого значения, представленного в Descriptor и в результате замены получить выходящее состояние типов.
  • Если метод является protected использование согласуется с правилами, описывающими доступ к членам данным с модификатором protected.


instructionIsTypeSafe(invokevirtual(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = method(MethodClassName, MethodName, Descriptor),
    MethodName \= ' <init> ',
    MethodName \= ' <clinit> ',
    parseMethodDescriptor(Descriptor, OperandArgList, ReturnType),
    reverse(OperandArgList, ArgList),
    currentClassLoader(Environment, L),
    reverse([class(MethodClassName, L) | OperandArgList], StackArgList),
    validTypeTransition(Environment, StackArgList, ReturnType,
                        StackFrame, NextStackFrame),
    canPop(StackFrame, ArgList, PoppedFrame),
    passesProtectedCheck(Environment, MethodClassName, MethodName,
    Descriptor, PoppedFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







ior ior


Инструкция ior безопасна по типу тогда и только тогда, когда эквивалентная инструкция iadd также безопасна.


instructionHasEquivalentTypeRule(ior, iadd).







irem irem


Инструкция irem безопасна по типу тогда и только тогда, когда эквивалентная инструкция iadd также безопасна.


instructionHasEquivalentTypeRule(irem, iadd).







ireturn ireturn


Инструкция ireturn безопасна по типу тогда и только тогда, когда метод, в котором она находится имеет тип возвращаемого значения int и допустимо считать тип соответствующий int из входящего стека операндов.


instructionIsTypeSafe(ireturn, Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    thisMethodReturnType(Environment, int),
    canPop(StackFrame, [int], _PoppedStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







ishl ishl


Инструкция ishl безопасна по типу тогда и только тогда, когда эквивалентная инструкция iadd также безопасна.


instructionHasEquivalentTypeRule(ishl, iadd).







ishr ishr


Инструкция ishr безопасна по типу тогда и только тогда, когда эквивалентная инструкция iadd также безопасна.


instructionHasEquivalentTypeRule(ishr, iadd).







istore istore


Инструкция istore с операндом Index безопасна по типу и приводит к результирующему состоянию типов NextStackFrame, если инструкция сохранения с операндом Index и типом int безопасна по типам и приводит к результирующему состоянию типов NextStackFrame.


instructionIsTypeSafe(istore(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    storeIsTypeSafe(Environment, Index, int, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







istore_<n> istore_<n>


Инструкции istore_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция istore также безопасна.


instructionHasEquivalentTypeRule(istore_0, istore(0)).
instructionHasEquivalentTypeRule(istore_1, istore(1)).
instructionHasEquivalentTypeRule(istore_2, istore(2)).
instructionHasEquivalentTypeRule(istore_3, istore(3)).







isub isub


Инструкция isub безопасна по типу тогда и только тогда, когда эквивалентная инструкция iadd также безопасна.


instructionHasEquivalentTypeRule(isub, iadd).







iushr iushr


Инструкция iushr безопасна по типу тогда и только тогда, когда эквивалентная инструкция iadd также безопасна.


instructionHasEquivalentTypeRule(iushr, iadd).







ixor ixor


Инструкция ixor безопасна по типу тогда и только тогда, когда эквивалентная инструкция iadd также безопасна.


instructionHasEquivalentTypeRule(ixor, iadd).







l2d l2d


Инструкция l2d безопасна по типу тогда и только тогда, когда допустимо во входящем стеке операндов считать тип, соответствующий long, затем записать туда double и после замены получить выходящее состояние типов.


instructionIsTypeSafe(l2d, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [long], double,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







l2f l2f


Инструкция l2f безопасна по типу тогда и только тогда, когда допустимо во входящем стеке операндов считать тип, соответствующий long, затем записать туда float и после замены получить выходящее состояние типов.


instructionIsTypeSafe(l2f, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [long], float,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







l2i l2i


Инструкция l2i безопасна по типу тогда и только тогда, когда допустимо во входящем стеке операндов считать тип, соответствующий long, затем записать туда float и после замены получить выходящее состояние типов.


instructionIsTypeSafe(l2i, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [long], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







ladd ladd


Инструкция ladd безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие long и long, на long, и после замены получить выходное состояние типов.


instructionIsTypeSafe(ladd, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [long, long], long,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







laload laload


Инструкция laload безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие int и массиву long, на long, и после замены получить выходное состояние типов.


instructionIsTypeSafe(laload, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, arrayOf(long)], long,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







land land


Инструкция land безопасна по типу тогда и только тогда, когда эквивалентная инструкция ladd также безопасна.


instructionHasEquivalentTypeRule(land, ladd).







lastore lastore


Инструкция lastore безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие long, int и массиву типов long и после считывания получить выходное состояние типов.


instructionIsTypeSafe(lastore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [long, int, arrayOf(long)], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lcmp lcmp


Инструкция lcmp безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие long и long, на int, и после замены получить выходное состояние типов.


instructionIsTypeSafe(lcmp, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [long, long], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lconst_<l> lconst_<l>


Инструкция lconst_0 безопасна по типу тогда и только тогда, когда допустимо записать во входящий стек операндов тип, соответствующий long, и после записи получить выходное состояние типов.


instructionIsTypeSafe(lconst_0, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [], long, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция lconst_1 безопасна по типу тогда и только тогда, когда эквивалентная инструкция lconst_0 также безопасна.


instructionHasEquivalentTypeRule(lconst_1, lconst_0).







ldc ldc


Инструкция ldc с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего элемент Type, где Type это либо int, float, String, Class, java.lang.invoke.MethodType, либо java.lang.invoke.MethodHandle и допустимо записать во входящий стек операндов на тип Type, и при этом получить выходящее состояние типов.


instructionIsTypeSafe(ldc(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    functor(CP, Tag, _),
    isBootstrapLoader(BL),
    member([Tag, Type], [
       [int, int],
       [float, float],
       [string, class('java/lang/String', BL)],
       [classConst, class('java/lang/Class', BL)],
       [methodTypeConst, class('java/lang/invoke/MethodType', BL)],
       [methodHandleConst, class('java/lang/invoke/MethodHandle', BL)],
    ]),
    validTypeTransition(Environment, [], Type, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







ldc_w ldc_w


Инструкция ldc_w безопасна по типу тогда и только тогда, когда эквивалентная инструкция ldc также безопасна.


instructionHasEquivalentTypeRule(ldc_w(CP), ldc(CP)).







ldc2_w ldc2_w


Инструкция ldc2_w с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего элемент Tag, где Tag это либо long либо double и допустимо записать во входящий стек операндов на тип Tag, и при этом получить выходящее состояние типов.


instructionIsTypeSafe(ldc2_w(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    functor(CP, Tag, _),
    member(Tag, [long, double]),
    validTypeTransition(Environment, [], Tag, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







ldiv ldiv


Инструкция ldiv безопасна по типу тогда и только тогда, когда эквивалентная инструкция ladd также безопасна.


instructionHasEquivalentTypeRule(ldiv, ladd).







lload lload


Инструкция lload с операндом Index безопасна по типу и приводит к выходящему состоянию типов NextStackFrame, если инструкция загрузки с операндом Index и типом long является безопасной по типу и приводит к выходящему состоянию типов NextStackFrame.


instructionIsTypeSafe(lload(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    loadIsTypeSafe(Environment, Index, long, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lload_<n> lload_<n>


Инструкции lload_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция lload также безопасна.


instructionHasEquivalentTypeRule(lload_0, lload(0)).
instructionHasEquivalentTypeRule(lload_1, lload(1)).
instructionHasEquivalentTypeRule(lload_2, lload(2)).
instructionHasEquivalentTypeRule(lload_3, lload(3)).







lmul lmul


Инструкция lmul безопасна по типу тогда и только тогда, когда эквивалентная инструкция ladd также безопасна.


instructionHasEquivalentTypeRule(lmul, ladd).







lneg lneg


Инструкция lneg безопасна по типу тогда и только тогда, когда во входящем стеке операндов находится тип, соответствующий long. Инструкция lneg не меняет состояние типов.


instructionIsTypeSafe(lneg, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [long], long,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lookupswitch lookupswitch


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


instructionIsTypeSafe(lookupswitch(Targets, Keys), Environment, _, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    sort(Keys, Keys),
    canPop(StackFrame, [int], BranchStackFrame),
    checklist(targetIsTypeSafe(Environment, BranchStackFrame), Targets),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lor lor


Инструкция lor безопасна по типу тогда и только тогда, когда эквивалентная инструкция ladd также безопасна.


instructionHasEquivalentTypeRule(lor, ladd).







lrem lrem


Инструкция lrem безопасна по типу тогда и только тогда, когда эквивалентная инструкция ladd также безопасна.


instructionHasEquivalentTypeRule(lrem, ladd).







lreturn lreturn


Инструкция lreturn безопасна по типу тогда и только тогда, когда метод, в котором она находится имеет тип возвращаемого значения long и допустимо считать тип соответствующий long из входящего стека операндов.


instructionIsTypeSafe(lreturn, Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    thisMethodReturnType(Environment, long),
    canPop(StackFrame, [long], _PoppedStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lshl lshl


Инструкция lshl безопасна по типу тогда и только тогда, когда допустимо заменить во входящем стеке операндов типы, соответствующие int и long на long, и после замены получить выходное состояние типов.


instructionIsTypeSafe(lshl, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, long], long,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lshr lshr


Инструкция lshr безопасна по типу тогда и только тогда, когда эквивалентная инструкция lshl также безопасна.


instructionHasEquivalentTypeRule(lshr, lshl).







lstore lstore


Инструкция lstore с операндом Index безопасна по типу и приводит к результирующему состоянию типов NextStackFrame, если инструкция сохранения с операндом Index и типом long безопасна по типам и приводит к результирующему состоянию типов NextStackFrame.


instructionIsTypeSafe(lstore(Index), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    storeIsTypeSafe(Environment, Index, long, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







lstore_<n> lstore_<n>


Инструкции lstore_<n>, для 0 ≤ n ≤ 3 безопасны по типу тогда и только тогда, когда эквивалентная инструкция lstore также безопасна.


instructionHasEquivalentTypeRule(lstore_0, lstore(0)).
instructionHasEquivalentTypeRule(lstore_1, lstore(1)).
instructionHasEquivalentTypeRule(lstore_2, lstore(2)).
instructionHasEquivalentTypeRule(lstore_3, lstore(3)).







lsub lsub


Инструкция lsub безопасна по типу тогда и только тогда, когда эквивалентная инструкция ladd также безопасна.


instructionHasEquivalentTypeRule(lsub, ladd).







lushr lushr


Инструкция lushr безопасна по типу тогда и только тогда, когда эквивалентная инструкция lshl также безопасна.


instructionHasEquivalentTypeRule(lushr, lshl).







lxor lxor


Инструкция lxor безопасна по типу тогда и только тогда, когда эквивалентная инструкция ladd также безопасна.


instructionHasEquivalentTypeRule(lxor, ladd).







monitorenter monitorenter


Инструкция monitorenter безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов тип, соответствующий reference и после считывания получить выходное состояние типов.


instructionIsTypeSafe(monitorenter, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [reference], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







monitorexit monitorexit


Инструкция monitorexit безопасна по типу тогда и только тогда, когда эквивалентная инструкция monitorenter также безопасна.


instructionHasEquivalentTypeRule(monitorexit, monitorenter).







multianewarray multianewarray


Инструкция multianewarray с операндами CP и Dim безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего массив, чья размерность больше либо равна Dim, Dim строго больше нуля, и допустимо заменить во входящем стеке операндов типы Dim int на тип обозначенный CP и при этом получить выходящее состояние типов.


instructionIsTypeSafe(multianewarray(CP, Dim), Environment, _Offset,
                      StackFrame, NextStackFrame, ExceptionStackFrame) :-
    CP = arrayOf(_),
    classDimension(CP, Dimension),
    Dimension >= Dim,
    Dim > 0,
    /* Make a list of Dim ints */
    findall(int, between(1, Dim, _), IntList),
    validTypeTransition(Environment, IntList, CP, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Размерность массива, чью компоненты также являются массивами, на один больше чем размерность самих компонентов.


classDimension(arrayOf(X), Dimension) :-
    classDimension(X, Dimension1),
    Dimension is Dimension1 + 1.

classDimension(_, Dimension) :-
    Dimension = 0.







new new


Инструкция new с операндом CP и смещением Offset безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего класс, тип uninitialized(Offset) не появляется во входящем стеке операндов и допустимо записать uninitialized(Offset) во входящий стек операндов и заменить uninitialized(Offset) на top во входящих локальных переменных и при этом получить выходящее состояние типов.


instructionIsTypeSafe(new(CP), Environment, Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, OperandStack, Flags),
    CP = class(_, _),
    NewItem = uninitialized(Offset),
    notMember(NewItem, OperandStack),
    substitute(NewItem, top, Locals, NewLocals),
    validTypeTransition(Environment, [], NewItem,
                        frame(NewLocals, OperandStack, Flags),
                        NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







newarray newarray


Инструкция newarray с операндом TypeCode безопасна по типу тогда и только тогда, когда TypeCode соответствует элементарному типу ElementType и допустимо заменить тип int во входящем стеке операндов на «массив ElementType» и при этом получить выходящее состояние типов.


nstructionIsTypeSafe(newarray(TypeCode), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    primitiveArrayInfo(TypeCode, _TypeChar, ElementType, _VerifierType),
    validTypeTransition(Environment, [int], arrayOf(ElementType),
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Соответствие между кодом типа и самим примитивным типом определено следующими предикатами:


primitiveArrayInfo(4,  0'Z, boolean, int).
PrimitiveArrayInfo(5,  0'C, char,    int).
PrimitiveArrayInfo(6,  0'F, float,   float).
PrimitiveArrayInfo(7,  0'D, double,  double).
PrimitiveArrayInfo(8,  0'B, byte,    int).
PrimitiveArrayInfo(9,  0'S, short,   int).
primitiveArrayInfo(10, 0'I, int,     int).
primitiveArrayInfo(11, 0'J, long,    long).







nop nop


Инструкция nop всегда безопасна по типу. Инструкция nop не влияет на состояние типов.


instructionIsTypeSafe(nop, _Environment, _Offset, StackFrame,
                      StackFrame, ExceptionStackFrame) :-
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







pop pop


Инструкция pop безопасна по типу тогда и только тогда, когда допустимо считать тип категории 1 из входящего стека операндов и при этом получить выходящее состояние типов.


instructionIsTypeSafe(pop, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, [Type | Rest], Flags),
    Type \= top,
    sizeOf(Type, 1),
    NextStackFrame = frame(Locals, Rest, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







pop2 pop2


Инструкция pop2 безопасна по типу тогда и только тогда, когда она является безопасной по типу формой инструкции pop2.


instructionIsTypeSafe(pop2, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, InputOperandStack, Flags),
    pop2SomeFormIsTypeSafe(InputOperandStack, OutputOperandStack),
    NextStackFrame = frame(Locals, OutputOperandStack, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).


Инструкция pop2 является безопасной по типу формой инструкции pop2, когда она представляет собой безопасную по типу форму 1 инструкции pop2 либо безопасную по типу форму 2 инструкции pop2.


pop2SomeFormIsTypeSafe(InputOperandStack, OutputOperandStack) :-
    pop2Form1IsTypeSafe(InputOperandStack, OutputOperandStack).

pop2SomeFormIsTypeSafe(InputOperandStack, OutputOperandStack) :-
    pop2Form2IsTypeSafe(InputOperandStack, OutputOperandStack).


Инструкция pop2 является безопасной по типу формой 1 инструкции pop2 тогда и только тогда, когда допустимо считать из входящего стека операндов два типа размера 1 и при этом получить выходящее состояние типов.


pop2Form1IsTypeSafe([Type1, Type2 | Rest], Rest) :-
    sizeOf(Type1, 1),
    sizeOf(Type2, 1).


Инструкция pop2 является безопасной по типу формой 2 инструкции pop2 тогда и только тогда, когда допустимо считать из входящего стека операндов тип размера 2 и при этом получить выходящее состояние типов.


pop2Form2IsTypeSafe([top, Type | Rest], Rest) :- sizeOf(Type, 2).







putfield putfield


Инструкция putfield с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего поле, чей объявленный тип это FieldType, причём поле находится в классе FieldClass и допустимо считать из входящего стека операндов типы, соответствующие FieldType и FieldClass, и при этом получить выходящее состояние типов.


instructionIsTypeSafe(putfield(CP), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = field(FieldClass, FieldName, FieldDescriptor),
    parseFieldDescriptor(FieldDescriptor, FieldType),
    canPop(StackFrame, [FieldType], PoppedFrame),
    passesProtectedCheck(Environment, FieldClass, FieldName,
                         FieldDescriptor, PoppedFrame),
    currentClassLoader(Environment, CurrentLoader),
    canPop(StackFrame, [FieldType, class(FieldClass, CurrentLoader)],
           NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







putstatic putstatic


Инструкция putstatic с операндом CP безопасна по типу тогда и только тогда, когда CP ссылается на элемент константного пула, обозначающего поле, чей объявленный тип это FieldType, и допустимо считать из входящего стека операндов тип, соответствующий FieldType и при этом получить выходящее состояние типов.


instructionIsTypeSafe(putstatic(CP), _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    CP = field(_FieldClass, _FieldName, FieldDescriptor),
    parseFieldDescriptor(FieldDescriptor, FieldType),
    canPop(StackFrame, [FieldType], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







return return


Инструкция return безопасна по типу тогда и только тогда, когда метод, в котором она находится имеет тип возвращаемого значения void и вдобавок либо:


  • метод, в котором находится инструкция не является <init> методом либо
  • this полностью инициализирована в той точке кода, где помещена инструкция.


instructionIsTypeSafe(return, Environment, _Offset, StackFrame,
                      afterGoto, ExceptionStackFrame) :-
    thisMethodReturnType(Environment, void),
    StackFrame = frame(_Locals, _OperandStack, Flags),
    notMember(flagThisUninit, Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







saload saload


Инструкция saload безопасна по типу тогда и только тогда, когда допустимо заменить из входящего стека операндов типы, соответствующие int и массиву short, на int, и после замены получить выходное состояние типов.


instructionIsTypeSafe(saload, Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [int, arrayOf(short)], int,
                        StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







sastore sastore


Инструкция sastore безопасна по типу тогда и только тогда, когда допустимо считать из входящего стека операндов типы, соответствующие int, int и массиву типов short и после считывания получить выходное состояние типов.


instructionIsTypeSafe(sastore, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    canPop(StackFrame, [int, int, arrayOf(short)], NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







sipush sipush


Инструкция sipush безопасна по типу тогда и только тогда, когда допустимо записать тип int во входящий стек операндов и после записи получить выходное состояние типов.


instructionIsTypeSafe(sipush(_Value), Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    validTypeTransition(Environment, [], int, StackFrame, NextStackFrame),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







swap swap


Инструкция swap безопасна по типу тогда и только тогда, когда допустимо заменить два типа категории 1 Type1 и Type2 на типы Type2 и Type1 во входящем стеке операндов и после замены получить выходное состояние типов.


instructionIsTypeSafe(swap, _Environment, _Offset, StackFrame,
                      NextStackFrame, ExceptionStackFrame) :-
    StackFrame = frame(_Locals, [Type1, Type2 | Rest], _Flags),
    sizeOf(Type1, 1),
    sizeOf(Type2, 1),
    NextStackFrame = frame(_Locals, [Type2, Type1 | Rest], _Flags),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







tableswitch tableswitch


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


instructionIsTypeSafe(tableswitch(Targets, Keys), Environment, _Offset,
                      StackFrame, afterGoto, ExceptionStackFrame) :-
    sort(Keys, Keys),
    canPop(StackFrame, [int], BranchStackFrame),
    checklist(targetIsTypeSafe(Environment, BranchStackFrame), Targets),
    exceptionStackFrame(StackFrame, ExceptionStackFrame).







wide wide


Инструкция wide подчинена тем же самым правилам, что и инструкция, которую она расширяет.


instructionHasEquivalentTypeRule(wide(WidenedInstruction),
                                 WidenedInstruction).


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


exceptionStackFrame(StackFrame, ExceptionStackFrame) :-
    StackFrame = frame(Locals, _OperandStack, Flags),
    ExceptionStackFrame = frame(Locals, [], Flags).


Большинство правил для типов в данной спецификации зависят от понимания корректного преобразования типов.

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


validTypeTransition(Environment, ExpectedTypesOnStack, ResultType,
                    frame(Locals, InputOperandStack, Flags),
                    frame(Locals, NextOperandStack, Flags)) :-
    popMatchingList(InputOperandStack, ExpectedTypesOnStack, InterimOperandStack),
    pushOperandStack(InterimOperandStack, ResultType, NextOperandStack),
    operandStackHasLegalLength(Environment, NextOperandStack).


Доступ к I-тому элементу стека операндов.


nth1OperandStackIs(I, frame(_Locals, OperandStack, _Flags), Element) :-
    nth1(I, OperandStack, Element).