ฉันคิดว่าคุณส่วนใหญ่รู้ว่าgoto
เป็นคำหลักที่สงวนไว้ในภาษา Java แต่ไม่ได้ใช้จริง และคุณก็อาจจะรู้ว่าgoto
เป็น opcode Java Virtual Machine (JVM) ฉันคิดว่าทุกคนที่มีความซับซ้อนของโครงสร้างการควบคุมการไหลของ Java, Scala และ Kotlin กำลังที่ระดับ JVM, ดำเนินการโดยใช้การรวมกันของบางgoto
และifeq
, ifle
, iflt
ฯลฯ
ดูที่ข้อกำหนด JVM https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.goto_wฉันเห็นว่ามันมีgoto_w
opcode เช่นกัน ในขณะที่goto
ออฟเซ็ตสาขา 2 ไบต์goto_w
จะใช้ออฟเซ็ตสาขา4 ไบต์ สเป็คระบุว่า
แม้ว่าคำสั่งgoto_wใช้ออฟเซ็ตสาขา 4 ไบต์ปัจจัยอื่น ๆ จำกัด ขนาดของวิธีการเป็น 65535 ไบต์ (§4.11) ขีด จำกัด นี้อาจเพิ่มใน Java Virtual Machine รุ่นที่วางจำหน่ายในอนาคต
เสียงที่ฉันชอบgoto_w
คือการพิสูจน์ในอนาคตเหมือนกับ*_w
opcodes อื่น ๆ แต่ก็ยังเกิดขึ้นกับผมว่าอาจจะgoto_w
สามารถนำมาใช้กับทั้งสองไบต์สำคัญมากพุ่งออกมาและทั้งสองไบต์อย่างมีนัยสำคัญน้อยลงเช่นเดียวกับgoto
ที่มีการปรับเปลี่ยนตามความจำเป็น
ตัวอย่างเช่นกำหนด Java Switch-Case (หรือ 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
ของ แต่เนื่องจากมันอยู่ในสเป็คมันควรจะเป็นไปได้ที่จะทำมัน
คำถามของฉันคือว่ามีเหตุผลที่คอมไพเลอร์หรือตัวกำเนิดอื่น ๆ ของ bytecode อาจใช้goto_w
กับวงเงิน 65535 ปัจจุบันนอกเหนือจากที่แสดงว่าสามารถทำได้หรือไม่
// ... repeat 10K times ...
รวบรวมว่า? ฉันรู้ว่ามีการ จำกัด ขนาดของคลาสซอร์สเดี่ยว ... แต่ฉันไม่รู้ว่ามันแม่นยำเพียงใด (การสร้างโค้ดเป็นครั้งเดียวที่ฉันเห็นบางสิ่งที่กระทบจริง ๆ )