Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Werden Instruktionen durch OPAL zusammengefaßt? #60

Open
PKTUDO opened this issue Jan 19, 2022 · 3 comments
Open

Werden Instruktionen durch OPAL zusammengefaßt? #60

PKTUDO opened this issue Jan 19, 2022 · 3 comments
Assignees
Labels
framework Issue related to the framework itself, as opposed to actual metric implementations question Further information is requested

Comments

@PKTUDO
Copy link
Collaborator

PKTUDO commented Jan 19, 2022

Wenn man von Hand zählt kommt wie erwartet 4 raus:
In Zeile 23 soll gegebenenfalls nach Zeile 62 gesprungen werden
In Zeile 62 wird stets nach Zeile 9 gesprungen
Wenn ich im IntelliJ-Debugger die Metrik durchsteppe zeigt er mir für Zeile nicht if_"icmpge 62" an
sondern "if_icmpge 23-14= 9" an
Es werden also unerwarteterweise 2 Instruktionen zusammengefaßt. Durch den unerwarteten Rücksprung verrechnet sich die Metrik

int test8();
    Code:
       0: sipush        255
       3: istore_1
       4: bipush        20
       6: istore_2
       7: iconst_1
       8: istore_3
       9: iload_3
      10: ifeq          65
      13: iload_2
      14: iload_1
      15: iadd
      16: istore_2
      17: iconst_0
      18: istore        4
      20: iload         4
      22: iload_1
      23: if_icmpge     62
      26: bipush        10
      28: istore        5
      30: iload         5
      32: iload_1
      33: iload_1
      34: imul
      35: if_icmpge     56
      38: iload         5
      40: iload_1
      41: iload_1
      42: imul
      43: iconst_1
      44: isub
      45: if_icmpne     50
      48: iconst_0
      49: istore_3
      50: iinc          5, 1
      53: goto          30
      56: iinc          4, 1
      59: goto          20
      62: goto          9
      65: iload_2
      66: ireturn



Originally posted by @PKTUDO in #57 (comment)

@PKTUDO PKTUDO added the question Further information is requested label Jan 19, 2022
@PKTUDO
Copy link
Collaborator Author

PKTUDO commented Jan 20, 2022

//Java-Quelltext für die Herstellung von MaximumNestingCompanion-1.0-SNAPSHOT.jar
public class start {

    public static void main(String[] args) {
        System.out.println("Hallo Welt");
    }

    //max Tiefe:2
    int test1(int zahl1, int zahl2, int zahl3) {
        if (zahl1 > zahl2) {
            if (zahl3 == zahl2) {
                return 78;
            }
            return zahl1;
        }
        if (zahl1 * 2 > zahl3) {
            return 345;
        }
        return zahl2;
    }

    //max Tiefe:3
    int test2(int zahl1, int zahl2, int zahl3) {
        int ergebnis = 0;
        for (int i = 0; i < zahl3; i++) {
            if (zahl1 > zahl2) {
                if (zahl3 == zahl2) {
                    ergebnis = ergebnis + 78;
                } else {
                    ergebnis -= 1;
                }
            }
            if (zahl1 * 2 > zahl3) {
                ergebnis = zahl2;
            } else {
                ergebnis -= 10;
            }
        }
        for (int i = 2; i < zahl1; i++) {
            ergebnis += 2;
        }
        return ergebnis;
    }

    //max Tiefe: 2
    int test3(int zahl1, int zahl2) {
        int ergebnis = 10;
        switch (zahl1) {
            case 0:
                ergebnis = 1;
            case 1:
                ergebnis = zahl1;
            case 2: {
                if (zahl2 * 10 == 100) {
                    zahl1 += 1;
                }
                ergebnis = zahl1 * zahl1;
            }
            case 3:
                ergebnis = 3;
            case 4:
                ergebnis = 25;
            default:
                ergebnis = zahl1 + 1;
        }

        for (int i = 10; i < 100; i++) {
            ergebnis += zahl2 - i * i;
        }
        return ergebnis;
    }


    //max Tiefe: 3
    int test4(int zahl1, int zahl2) {
        int ergebnis = 10;
        switch (zahl1) {
            case 0:
                ergebnis = 1;
            case 1:
                ergebnis = zahl1;
            case 2: {
                if (zahl2 * 10 == 100) {
                    zahl1 += 1;
                    if (zahl1 + zahl2 > 53) {
                        zahl1 = zahl1 + 2 * zahl2;
                    }
                }
                ergebnis = zahl1 * zahl1;
            }
            case 3:
                ergebnis = 3;
            case 4:
                ergebnis = 25;
            default:
                ergebnis = zahl1 + 1;
        }

        for (int i = 10; i < 100; i++) {
            ergebnis += zahl2 - i * i;
        }
        return ergebnis;
    }


    //max Tiefe: 6
    int test5(int zahl1, int zahl2) {
        int ergebnis = 10;
        switch (zahl1) {
            case 0:
                ergebnis = 1;
                break;
            case 1:
                ergebnis = zahl1;
                break;
            case 2: {
                if (zahl2 * 10 == 100) {
                    zahl1 += 1;
                    if (zahl1 + zahl2 > 53) {
                        zahl1 = zahl1 + 2 * zahl2;
                        for (int i = 10; i < 100; i++) {
                            ergebnis += zahl2 - i * i;
                            switch (ergebnis) {
                                case 1:
                                    zahl1 = 1;
                                    break;
                                case 2:
                                    zahl2 = 10;
                                    break;
                                case 3:
                                    if (zahl2 > zahl1) {
                                        zahl2 = 100;
                                    } else {
                                        zahl2 = 50;
                                    }
                                    break;
                                default:
                                    zahl1 = 15;
                                    break;
                            }
                        }
                    }
                }
                ergebnis = zahl1 * zahl1;
            }
            break;
            case 3:
                ergebnis = 3;
            case 4:
                ergebnis = 25;
            default:
                ergebnis = zahl1 + 1;
        }

        for (int i = 10; i < 100; i++) {
            ergebnis += zahl2 - i * i;
        }
        return ergebnis;
    }

    //max Tiefe: 2
    int test6(int zahl1, int zahl2, int zahl3) {
        if (zahl1 > zahl2) {
            if (zahl3 == zahl2) {
                return 78;
            } else if (zahl3 > zahl2) {
                zahl1 = zahl2 + 10;
            }
            return zahl1;
        }
        if (zahl1 * 2 > zahl3) {
            return 345;
        }
        return zahl2;
    }

    //max Tiefe: 6
    int test7(int zahl1, int zahl2) {
        int ergebnis = 10;
        switch (zahl1) {
            case 0:
                ergebnis = 1;
                break;
            case 1:
                ergebnis = zahl1;
                break;
            case 2: {
                if (zahl2 * 10 == 100) {
                    zahl1 += 1;
                    if (zahl1 + zahl2 > 53) {
                        zahl1 = zahl1 + 2 * zahl2;
                        for (int i = 10; i < 100; i++) {
                            ergebnis += zahl2 - i * i;
                            switch (ergebnis) {
                                case 1:
                                    zahl1 = 1;
                                    break;
                                case 2:
                                    zahl2 = 10;
                                    break;
                                case 3:
                                    if (zahl2 > zahl1) {
                                        zahl2 = 100;
                                    } else {
                                        zahl2 = 50;
                                    }
                                    break;
                                default:
                                    zahl1 = 15;
                                    break;
                            }
                        }
                    }
                }
                ergebnis = zahl1 * zahl1;
            }
            break;
            case 3:
                ergebnis = 3;
            case 4:
                ergebnis = 25;
            default:
                ergebnis = zahl1 + 1;
        }
        return ergebnis;
    }

    int test8()
    {
        int max = 255;
        int ergebnis = 20;
        boolean loop = true;
        while(loop)
        {
            ergebnis += max;
            for(int i = 0; i < max; i++)
            {
                for(int j = 10; j < max * max; j++)
                {
                    if(j == max * max -1)
                    {
                        loop = false;
                    }
                }
            }
        }
        return ergebnis;
    }

    int test9(int zahl1, int zahl2)
    {
        if(zahl1 >= zahl2)
        {
            if(zahl1 > zahl2)
                return zahl1;
        }
        return zahl2;
    }

    int test10(int zahl1, int zahl2)
    {
        if(zahl1 >= zahl2 && zahl1 > zahl2)
        {
                return zahl1;
        }
        return zahl2;
    }

}

@johannesduesing
Copy link
Member

Ich hatte jetzt endlich mal Zeit mir das Problem genauer anzugucken. Leider war ich wenig erfolgreich: Ich komme zu genau dem gleichen Ergebnis. Sowohl nach dem Kompilieren als auch nach dem Verpacken in eine JAR (jeweils per CLI) liefert mir javap in Zeile 23 das gewünschte Ergebnis 23: if_icmpge 62. In OPAL wird aber immer 23: IF_ICMPGE(-14) angegeben. Alles Testen lief unter Java 1.8.0 Update 311 auf der HotSpot VM.

Das ist tatsächlich schon beim Laden der Classfiles, also bevor das OPAL Project erstellt wird, der Fall. Ich habe mich länger durch OPAL-Code gedebuggt und bin schließlich im org.opalj.bi.reader.ClassFileReader angekommen, der in Zeile 269 die Methoden einliest. Und schon hier wird das Offeset im Body mit -14 angegeben. Leider komme ich von da partout nicht weiter, da wird durch Scala-Magie das Method-Objekt inklusive Code erzeugt, und ich kann nicht rausfinden ob da noch eine Zusammenfassung / Optimierung geschieht.

Ich werde bei Gelegenheit nochmal weitergucken woran das Problem genau liegt, aber für die Implementationsphase müssen wir wohl leider damit leben.

@PKTUDO
Copy link
Collaborator Author

PKTUDO commented Jan 24, 2022

Es ist schon mal gut zu wissen, dass die Existenz des Effekts wirklich vorliegt 😃

@johannesduesing johannesduesing added the framework Issue related to the framework itself, as opposed to actual metric implementations label Jan 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
framework Issue related to the framework itself, as opposed to actual metric implementations question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants