Думаю, більшість із вас знає, що goto
це ключове слово на мові Java, але воно фактично не використовується. І ви, мабуть, також знаєте, що goto
це опкод Java Virtual Machine (JVM). Я вважаю , всі складні структури потоку управління Java, Scala і Котлин є, на рівні віртуальної машини Java, реалізовані з використанням деякої комбінації goto
і ifeq
, ifle
, iflt
і т.д.
Дивлячись на специфікацію JVM https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto_w, я бачу, що існує також goto_w
опкод. Тоді goto
як 2-байтний зсув гілки goto_w
приймає 4-байтове зміщення гілки. Специфікація стверджує, що
Хоча інструкція goto_w приймає 4-байтове зміщення гілки, інші фактори обмежують розмір методу до 65535 байт (§4.11). Ця межа може бути підвищена в майбутньому випуску віртуальної машини Java.
Мені це здається, що це впевненість у goto_w
майбутньому, як і деякі інші *_w
опкоди. Але мені також здається, що, можливо, goto_w
можна було б використовувати два більш значущих байти, нульові і два менш значні байти такі ж, як і для goto
, з необхідними коригуваннями.
Наприклад, враховуючи цей Java-перемикач (або 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.
ми могли б переписати це як
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.
Я насправді цього не пробував, оскільки я, мабуть, помилився, змінивши "номери рядків" для розміщення goto_w
s. Але оскільки це в специфікації, це має бути можливо зробити.
Моє запитання: чи є причина, яку компілятор або інший генератор байт-коду може використовувати goto_w
з поточним обмеженням 65535, крім того, щоб показати, що це можна зробити?
// ... repeat 10K times ...
Що компілює? Я знаю, що існує обмеження на розмір одного класу джерел ... але я не знаю, що це саме (генерація коду - це єдиний раз, коли я бачив, що щось насправді вдарило).