Myślę, że większość z was wie, że goto
jest to zastrzeżone słowo kluczowe w języku Java, ale tak naprawdę nie jest używane. Prawdopodobnie wiesz również, że goto
jest to kod operacyjny Java Virtual Machine (JVM). Sądzę wszystkich skomplikowanych struktur przepływu kontrola Java, Scala i Kotlin są na poziomie JVM, realizowane przy użyciu niektórych kombinacji goto
i ifeq
, ifle
, iflt
, itd.
Patrząc na specyfikację JVM https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto_w Widzę, że istnieje również goto_w
kod operacyjny. Podczas gdy goto
przyjmuje 2-bajtowe przesunięcie gałęzi, goto_w
przyjmuje 4-bajtowe przesunięcie gałęzi. Specyfikacja mówi, że
Chociaż instrukcja goto_w przyjmuje 4-bajtowe przesunięcie gałęzi, inne czynniki ograniczają rozmiar metody do 65535 bajtów (§4.11). Limit ten może zostać podniesiony w przyszłej wersji wirtualnej maszyny Java.
To brzmi dla mnie jak goto_w
jest przyszłość pokryć, jak niektóre inne *_w
rozkazy. Ale zdaje mi się, że możegoto_w
może można by go użyć z dwoma bardziej znaczącymi bajtami wyzerowanymi i dwoma mniej znaczącymi bajtami takimi samymi jak dla goto
, z koniecznymi zmianami.
Na przykład, biorąc pod uwagę ten Java Switch-Case (lub Scala Match-Case):
12: lookupswitch {
112785: 48 // case "red"
3027034: 76 // case "green"
98619139: 62 // case "blue"
default: 87
}
48: aload_2
49: ldc #17 // String red
51: invokevirtual #18
// Method java/lang/String.equals:(Ljava/lang/Object;)Z
54: ifeq 87
57: iconst_0
58: istore_3
59: goto 87
62: aload_2
63: ldc #19 // String green
65: invokevirtual #18
// Method java/lang/String.equals:(Ljava/lang/Object;)Z
68: ifeq 87
71: iconst_1
72: istore_3
73: goto 87
76: aload_2
77: ldc #20 // String blue
79: invokevirtual #18
// etc.
moglibyśmy przepisać to jako
12: lookupswitch {
112785: 48
3027034: 78
98619139: 64
default: 91
}
48: aload_2
49: ldc #17 // String red
51: invokevirtual #18
// Method java/lang/String.equals:(Ljava/lang/Object;)Z
54: ifeq 91 // 00 5B
57: iconst_0
58: istore_3
59: goto_w 91 // 00 00 00 5B
64: aload_2
65: ldc #19 // String green
67: invokevirtual #18
// Method java/lang/String.equals:(Ljava/lang/Object;)Z
70: ifeq 91
73: iconst_1
74: istore_3
75: goto_w 91
79: aload_2
81: ldc #20 // String blue
83: invokevirtual #18
// etc.
Tak naprawdę nie próbowałem tego, ponieważ prawdopodobnie popełniłem błąd, zmieniając „numery linii”, aby uwzględnić goto_w
s. Ale ponieważ jest to w specyfikacji, powinno być to możliwe.
Moje pytanie brzmi, czy istnieje powód, dla którego kompilator lub inny generator kodu bajtowego mógłby użyć goto_w
przy obecnym limicie 65535, aby pokazać, że można to zrobić?
// ... repeat 10K times ...
To się kompiluje? Wiem, że istnieje limit wielkości pojedynczej klasy źródłowej ... ale nie wiem, co to dokładnie jest (generowanie kodu to jedyny raz, kiedy widziałem, że coś w to uderzyło).