Fork me on GitHub
#portkey
<
2017-08-10
>
cgrand08:08:16

UCInterpreter.merge is responsible for merging UCValues

cgrand08:08:07

together they are a join semi-lattice https://en.wikipedia.org/wiki/Semilattice

cgrand08:08:48

currently merge is bugged and can create cycles

cgrand08:08:38

asm Analyzer takes a method and returns an array of Frames, one frame per instruction.

viesti08:08:52

SemiLattice for a class name would have been neat šŸ˜„

cgrand08:08:58

a Frame represents the (abstract) state of the VM at a given instruction: it contains abstract values for all locals and the stack

cgrand08:08:33

frames[0] is initialized with an empty stack, and abstract arguments (created only from their type). Unitiliazed locals are abstracted to whatever Interpreter.newValue(null) returns. This value is also used for padding of double-word values (longs and doubles).

cgrand08:08:18

starting from frame[0] the analyzer interprets the bytecode and produces next frames

cgrand08:08:48

when a jump occurs to a previously visited instruction then the new frame and the old frames are merged and subsequent frames will be recomputed.

cgrand08:08:22

for this process to terminate it must converge

cgrand08:08:53

the semilattice properties assures that progress is made, convergence involves the interpreter not creating ever ā€œgreaterā€ abstract values.

cgrand09:08:52

Here are the kind of abstract values we try to represent: ā€¢ constants (strings, numbers, classes for a start) as their own value ā€¢ uninitialized ā€¢ instances with their types

viesti09:08:45

hmm so what happens in merge with different sized Values?

viesti09:08:25

looking at

@Override
    public Value merge(final Value v, final Value w) {
        // is this enough?
        if (v.equals(w)) return v;
        if (((UCValue) v).type == null && w.getSize() == 1) return w;
        if (((UCValue) w).type == null && v.getSize() == 1) return v;
        return UCValue.UNINITIALIZED_VALUE;
    }

viesti09:08:44

UCValue.UNINITIALIZED_VALUE is returned I guess

viesti10:08:07

switched to Idea+Cursive for Java land browsing, seems that I have to renew Cursive license

cgrand10:08:04

these 4 lines of code are baaaaad (well #2 and #3)

viesti10:08:20

thought so šŸ™‚

viesti10:08:32

or innocent at least, they need friends šŸ™‚

viesti10:08:22

good friends

cgrand10:08:32

Iā€™m not even sure that in legal bytecode you could have that case (merging different sizes)

cgrand10:08:16

reuse of space happens but between different points in the program

cgrand10:08:29

merge occur at the same place in a program

cgrand10:08:31

it makes no sense to say ā€œat instruction #42, local #1 and #2 are one double or two object references.

cgrand10:08:20

ā€œone double or one longā€ (no diff in size) seems already wrong

cgrand10:08:41

the only case where it may happen is when an ā€œunitializedā€ slot is merged with a double-word one

cgrand11:08:30

and this kind of merge should not happen (from my current understanding of the analyzer) with ā€œnot initializedā€ values (cf access arrays)

viesti11:08:17

so hmm, did the problematic behavior of merge surface only after these two commits? https://github.com/cgrand/portkey/commit/217acd4e6eae54ee995363861f362135b1e197b3 5b651877291c165e807a39e29133f1612473f30a

cgrand11:08:19

these two commits allowed to go further and reach problematic code