Список инструкций JVM с правилами проверки их безопасности
Список инструкций 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 только тогда, когда справедливо одно из следующих утверждений:
|
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 безопасна по типу тогда и только тогда, когда справедливы все следующие условия:
|
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 безопасна по типу тогда и только тогда, когда справедливы все следующие условия:
|
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 безопасна по типу тогда и только тогда, когда справедливы все следующие условия:
Либо:
|
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). |
Либо:
|
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 безопасна по типу тогда и только тогда, когда справедливы все следующие условия:
|
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 безопасна по типу тогда и только тогда, когда справедливы все следующие условия:
|
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 и вдобавок либо:
|
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). |